From 08233d44a6cfde878d7e10bca38ae935ed1c8fd5 Mon Sep 17 00:00:00 2001 From: Mauro Date: Wed, 30 Jun 2021 07:57:22 +0000 Subject: [HICN-713] Transport Library Major Refactoring 2 Co-authored-by: Luca Muscariello Co-authored-by: Michele Papalini Co-authored-by: Olivier Roques Co-authored-by: Giulio Grassi Signed-off-by: Mauro Sardara Change-Id: I5b2c667bad66feb45abdb5effe22ed0f6c85d1c2 --- libtransport/src/test/CMakeLists.txt | 55 ++-- libtransport/src/test/fec_reed_solomon.cc | 154 ---------- libtransport/src/test/fec_rely.cc | 156 ---------- libtransport/src/test/main.cc | 22 ++ libtransport/src/test/test_auth.cc | 162 +++++++++-- .../src/test/test_consumer_producer_rtc.cc | 15 +- libtransport/src/test/test_core_manifest.cc | 19 +- libtransport/src/test/test_event_thread.cc | 11 +- libtransport/src/test/test_fec_reedsolomon.cc | 184 +++++------- libtransport/src/test/test_fec_rely_wrapper.cc | 232 +++++++++++++++ libtransport/src/test/test_indexer.cc | 322 +++++++++++++++++++++ libtransport/src/test/test_interest.cc | 5 - libtransport/src/test/test_packet.cc | 9 - libtransport/src/test/test_transport_producer.cc | 66 ----- 14 files changed, 834 insertions(+), 578 deletions(-) delete mode 100644 libtransport/src/test/fec_reed_solomon.cc delete mode 100644 libtransport/src/test/fec_rely.cc create mode 100644 libtransport/src/test/main.cc create mode 100644 libtransport/src/test/test_fec_rely_wrapper.cc create mode 100644 libtransport/src/test/test_indexer.cc delete mode 100644 libtransport/src/test/test_transport_producer.cc (limited to 'libtransport/src/test') diff --git a/libtransport/src/test/CMakeLists.txt b/libtransport/src/test/CMakeLists.txt index dd3d1d923..26fe7aee1 100644 --- a/libtransport/src/test/CMakeLists.txt +++ b/libtransport/src/test/CMakeLists.txt @@ -13,27 +13,40 @@ include(BuildMacros) -list(APPEND TESTS - test_auth - test_consumer_producer_rtc - test_core_manifest - test_event_thread - test_fec_reedsolomon - test_interest - test_packet +list(APPEND TESTS_SRC + main.cc + test_auth.cc + test_consumer_producer_rtc.cc + test_core_manifest.cc + test_event_thread.cc + test_fec_reedsolomon.cc + test_indexer.cc + test_interest.cc + test_packet.cc ) -foreach(test ${TESTS}) - build_executable(${test} - NO_INSTALL - SOURCES ${test}.cc - LINK_LIBRARIES ${LIBTRANSPORT_SHARED} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} - INCLUDE_DIRS ${LIBTRANSPORT_INCLUDE_DIRS} ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} - DEPENDS gtest ${LIBTRANSPORT_SHARED} - COMPONENT lib${LIBTRANSPORT} - DEFINITIONS "${COMPILER_DEFINITIONS}" - LINK_FLAGS ${LINK_FLAGS} - ) +if (ENABLE_RELY) + list(APPEND TESTS_SRC + test_fec_rely_wrapper.cc + ) +endif() - add_test_internal(${test}) -endforeach() +build_executable(unit_tests + NO_INSTALL + SOURCES ${TESTS_SRC} + LINK_LIBRARIES + ${LIBRARIES} + ${LIBTRANSPORT_STATIC} + ${GTEST_LIBRARIES} + INCLUDE_DIRS + ${LIBTRANSPORT_INCLUDE_DIRS} + ${LIBHICN_INCLUDE_DIRS} + ${LIBTRANSPORT_INTERNAL_INCLUDE_DIRS} + ${GTEST_INCLUDE_DIRS} + DEPENDS gtest ${LIBTRANSPORT_SHARED} + COMPONENT ${LIBTRANSPORT_COMPONENT} + DEFINITIONS "${COMPILER_DEFINITIONS}" + LINK_FLAGS ${LINK_FLAGS} +) + +add_test_internal(unit_tests) diff --git a/libtransport/src/test/fec_reed_solomon.cc b/libtransport/src/test/fec_reed_solomon.cc deleted file mode 100644 index 36543c531..000000000 --- a/libtransport/src/test/fec_reed_solomon.cc +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace transport { -namespace interface { - -namespace { - -class ConsumerProducerTest : public ::testing::Test, - public ConsumerSocket::ReadCallback { - static const constexpr char prefix[] = "b001::1/128"; - static const constexpr char name[] = "b001::1"; - static const constexpr double prod_rate = 1.0e6; - static const constexpr size_t payload_size = 1200; - static constexpr std::size_t receive_buffer_size = 1500; - static const constexpr double prod_interval_microseconds = - double(payload_size) * 8 * 1e6 / prod_rate; - - public: - ConsumerProducerTest() - : io_service_(), - rtc_timer_(io_service_), - consumer_(TransportProtocolAlgorithms::RTC, io_service_), - producer_(ProductionProtocolAlgorithms::RTC_PROD, io_service_), - producer_prefix_(prefix), - consumer_name_(name), - packets_sent_(0), - packets_received_(0) { - global_config::IoModuleConfiguration config; - config.name = "loopback_module"; - config.set(); - } - - virtual ~ConsumerProducerTest() { - // You can do clean-up work that doesn't throw exceptions here. - } - - // If the constructor and destructor are not enough for setting up - // and cleaning up each test, you can define the following methods: - - virtual void SetUp() override { - // Code here will be called immediately after the constructor (right - // before each test). - - auto ret = consumer_.setSocketOption( - ConsumerCallbacksOptions::READ_CALLBACK, this); - ASSERT_EQ(ret, SOCKET_OPTION_SET); - - consumer_.connect(); - producer_.registerPrefix(producer_prefix_); - producer_.connect(); - } - - virtual void TearDown() override { - // Code here will be called immediately after each test (right - // before the destructor). - } - - void setTimer() { - using namespace std::chrono; - rtc_timer_.expires_from_now( - microseconds(unsigned(prod_interval_microseconds))); - rtc_timer_.async_wait(std::bind(&ConsumerProducerTest::produceRTCPacket, - this, std::placeholders::_1)); - } - - void produceRTCPacket(const std::error_code &ec) { - if (ec) { - FAIL() << "Failed to schedule packet production"; - io_service_.stop(); - } - - producer_.produceDatagram(consumer_name_, payload_, payload_size); - packets_sent_++; - setTimer(); - } - - // Consumer callback - bool isBufferMovable() noexcept override { return false; } - - void getReadBuffer(uint8_t **application_buffer, - size_t *max_length) override { - *application_buffer = receive_buffer_; - *max_length = receive_buffer_size; - } - - void readDataAvailable(std::size_t length) noexcept override {} - - size_t maxBufferSize() const override { return receive_buffer_size; } - - void readError(const std::error_code ec) noexcept override { - FAIL() << "Error while reading from RTC socket"; - io_service_.stop(); - } - - void readSuccess(std::size_t total_size) noexcept override { - packets_received_++; - } - - asio::io_service io_service_; - asio::steady_timer rtc_timer_; - ConsumerSocket consumer_; - ProducerSocket producer_; - core::Prefix producer_prefix_; - core::Name consumer_name_; - uint8_t payload_[payload_size]; - uint8_t receive_buffer_[payload_size]; - - uint64_t packets_sent_; - uint64_t packets_received_; -}; - -const char ConsumerProducerTest::prefix[]; -const char ConsumerProducerTest::name[]; - -} // namespace - -TEST_F(ConsumerProducerTest, EndToEnd) { - produceRTCPacket(std::error_code()); - consumer_.consume(consumer_name_); - - io_service_.run(); -} - -} // namespace interface - -} // namespace transport - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/libtransport/src/test/fec_rely.cc b/libtransport/src/test/fec_rely.cc deleted file mode 100644 index e7745bae5..000000000 --- a/libtransport/src/test/fec_rely.cc +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2021 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -namespace transport { -namespace interface { - -namespace { - -class ConsumerProducerTest : public ::testing::Test, - public ConsumerSocket::ReadCallback { - static const constexpr char prefix[] = "b001::1/128"; - static const constexpr char name[] = "b001::1"; - static const constexpr double prod_rate = 1.0e6; - static const constexpr size_t payload_size = 1200; - static constexpr std::size_t receive_buffer_size = 1500; - static const constexpr double prod_interval_microseconds = - double(payload_size) * 8 * 1e6 / prod_rate; - - public: - ConsumerProducerTest() - : io_service_(), - rtc_timer_(io_service_), - consumer_(TransportProtocolAlgorithms::RTC, io_service_), - producer_(ProductionProtocolAlgorithms::RTC_PROD, io_service_), - producer_prefix_(prefix), - consumer_name_(name), - packets_sent_(0), - packets_received_(0) { - global_config::IoModuleConfiguration config; - config.name = "loopback_module"; - config.set(); - } - - virtual ~ConsumerProducerTest() { - // You can do clean-up work that doesn't throw exceptions here. - } - - // If the constructor and destructor are not enough for setting up - // and cleaning up each test, you can define the following methods: - - virtual void SetUp() override { - // Code here will be called immediately after the constructor (right - // before each test). - - auto ret = consumer_.setSocketOption( - ConsumerCallbacksOptions::READ_CALLBACK, this); - ASSERT_EQ(ret, SOCKET_OPTION_SET); - - consumer_.connect(); - producer_.registerPrefix(producer_prefix_); - producer_.connect(); - } - - virtual void TearDown() override { - // Code here will be called immediately after each test (right - // before the destructor). - } - - void setTimer() { - using namespace std::chrono; - rtc_timer_.expires_from_now( - microseconds(unsigned(prod_interval_microseconds))); - rtc_timer_.async_wait(std::bind(&ConsumerProducerTest::produceRTCPacket, - this, std::placeholders::_1)); - } - - void produceRTCPacket(const std::error_code &ec) { - if (ec) { - FAIL() << "Failed to schedule packet production"; - io_service_.stop(); - } - - producer_.produceDatagram(consumer_name_, payload_, payload_size); - packets_sent_++; - setTimer(); - } - - // Consumer callback - bool isBufferMovable() noexcept override { return false; } - - void getReadBuffer(uint8_t **application_buffer, - size_t *max_length) override { - *application_buffer = receive_buffer_; - *max_length = receive_buffer_size; - } - - void readDataAvailable(std::size_t length) noexcept override {} - - size_t maxBufferSize() const override { return receive_buffer_size; } - - void readError(const std::error_code ec) noexcept override { - FAIL() << "Error while reading from RTC socket"; - io_service_.stop(); - } - - void readSuccess(std::size_t total_size) noexcept override { - packets_received_++; - } - - asio::io_service io_service_; - asio::steady_timer rtc_timer_; - ConsumerSocket consumer_; - ProducerSocket producer_; - core::Prefix producer_prefix_; - core::Name consumer_name_; - uint8_t payload_[payload_size]; - uint8_t receive_buffer_[payload_size]; - - uint64_t packets_sent_; - uint64_t packets_received_; -}; - -const char ConsumerProducerTest::prefix[]; -const char ConsumerProducerTest::name[]; - -} // namespace - -TEST_F(ConsumerProducerTest, EndToEnd) { - produceRTCPacket(std::error_code()); - consumer_.consume(consumer_name_); - - io_service_.run(); -} - -} // namespace interface - -} // namespace transport - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/libtransport/src/test/main.cc b/libtransport/src/test/main.cc new file mode 100644 index 000000000..a4d7ce1b3 --- /dev/null +++ b/libtransport/src/test/main.cc @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +int main(int argc, char **argv) { + srand(time(0)); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/libtransport/src/test/test_auth.cc b/libtransport/src/test/test_auth.cc index 976981cce..db1c3b52f 100644 --- a/libtransport/src/test/test_auth.cc +++ b/libtransport/src/test/test_auth.cc @@ -14,7 +14,7 @@ */ #include -#include +#include #include #include #include @@ -45,14 +45,15 @@ TEST_F(AuthTest, VoidVerifier) { // Verify that VoidVerifier validates the packet std::shared_ptr verifier = std::make_shared(); - ASSERT_EQ(verifier->verifyPacket(&packet), true); - ASSERT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT); + EXPECT_EQ(verifier->verifyPacket(&packet), true); + EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT); } -TEST_F(AuthTest, RSAVerifier) { +TEST_F(AuthTest, AsymmetricRSA) { // Create the RSA signer from an Identity object Identity identity("test_rsa.p12", PASSPHRASE, CryptoSuite::RSA_SHA256, 1024u, 30, "RSAVerifier"); + std::shared_ptr signer = identity.getSigner(); // Create a content object @@ -66,21 +67,125 @@ TEST_F(AuthTest, RSAVerifier) { signer->signPacket(&packet); // Create the RSA verifier - PARCKey *key = parcSigner_CreatePublicKey(signer->getParcSigner()); std::shared_ptr verifier = - std::make_shared(key); + std::make_shared(identity.getCertificate()); + + EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH); + EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256); + EXPECT_EQ(signer->getSuite(), CryptoSuite::RSA_SHA256); + EXPECT_EQ(signer->getSignatureSize(), 128u); + EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT); +} + +TEST_F(AuthTest, AsymmetricBufferRSA) { + // Create the RSA signer from an Identity object + Identity identity("test_rsa.p12", PASSPHRASE, CryptoSuite::RSA_SHA256, 1024u, + 30, "RSAVerifier"); + + std::shared_ptr signer = identity.getSigner(); + std::string payload = "bonjour"; - ASSERT_EQ(packet.getFormat(), HF_INET6_TCP_AH); - ASSERT_EQ(signer->getCryptoHashType(), CryptoHashType::SHA_256); - ASSERT_EQ(signer->getCryptoSuite(), CryptoSuite::RSA_SHA256); - ASSERT_EQ(signer->getSignatureSize(), 128u); - ASSERT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT); + std::vector buffer(payload.begin(), payload.end()); + signer->signBuffer(buffer); + std::vector sig = signer->getSignature(); - // Release PARC objects - parcKey_Release(&key); + std::shared_ptr cert = identity.getCertificate(); + AsymmetricVerifier verif(cert); + bool res = verif.verifyBuffer( + buffer, std::vector(sig.data(), sig.data() + sig.size()), + CryptoHashType::SHA256); + EXPECT_EQ(res, true); } -TEST_F(AuthTest, HMACVerifier) { +TEST_F(AuthTest, AsymmetricBufferDSA) { + // Create the DSA signer from an Identity object + Identity identity("test_dsa.p12", PASSPHRASE, CryptoSuite::DSA_SHA256, 1024u, + 30, "DSAVerifier"); + + std::shared_ptr signer = identity.getSigner(); + std::string payload = "bonjour"; + + std::vector buffer(payload.begin(), payload.end()); + signer->signBuffer(buffer); + std::vector sig = signer->getSignature(); + + std::shared_ptr cert = identity.getCertificate(); + AsymmetricVerifier verif(cert); + bool res = verif.verifyBuffer( + buffer, std::vector(sig.data(), sig.data() + sig.size()), + CryptoHashType::SHA256); + EXPECT_EQ(res, true); +} + +TEST_F(AuthTest, AsymmetricVerifierDSA) { + // Create the DSA signer from an Identity object + Identity identity("test_dsa.p12", PASSPHRASE, CryptoSuite::DSA_SHA256, 1024u, + 30, "DSAVerifier"); + + std::shared_ptr signer = identity.getSigner(); + + // Create a content object + core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize()); + + // Fill it with bogus data + uint8_t buffer[256] = {0}; + packet.appendPayload(buffer, 256); + // this test has to be done before the signature is compute + // EXPECT_EQ(signer->getSignatureSize(), 256u); + signer->signPacket(&packet); + std::shared_ptr verifier = + std::make_shared(identity.getCertificate()); + + EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH); + EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256); + EXPECT_EQ(signer->getSuite(), CryptoSuite::DSA_SHA256); + EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT); +} + +TEST_F(AuthTest, AsymmetricBufferECDSA) { + // Create the ECDSA signer from an Identity object + Identity identity("test_ecdsa.p12", PASSPHRASE, CryptoSuite::ECDSA_SHA256, + 256u, 30, "ECDSAVerifier"); + + std::shared_ptr signer = identity.getSigner(); + std::string payload = "bonjour"; + + std::vector buffer(payload.begin(), payload.end()); + signer->signBuffer(buffer); + std::vector sig = signer->getSignature(); + + std::shared_ptr cert = identity.getCertificate(); + AsymmetricVerifier verif(cert); + bool res = verif.verifyBuffer( + buffer, std::vector(sig.data(), sig.data() + sig.size()), + CryptoHashType::SHA256); + EXPECT_EQ(res, true); +} + +TEST_F(AuthTest, AsymmetricVerifierECDSA) { + Identity identity("test_ecdsa.p12", PASSPHRASE, CryptoSuite::ECDSA_SHA256, + 256u, 30, "ECDSAVerifier"); + + std::shared_ptr signer = identity.getSigner(); + std::shared_ptr verifier = + std::make_shared(identity.getCertificate()); + // Create a content object + for (int i = 0; i < 100; i++) { + core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize()); + + // Fill it with bogus data + uint8_t buffer[256] = {0}; + packet.appendPayload(buffer, 256); + signer->signPacket(&packet); + + EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH); + EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256); + EXPECT_EQ(signer->getSuite(), CryptoSuite::ECDSA_SHA256); + EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT); + } +} + +TEST_F(AuthTest, HMACbuffer) { // Create the HMAC signer from a passphrase std::shared_ptr signer = std::make_shared(CryptoSuite::HMAC_SHA256, PASSPHRASE); @@ -88,6 +193,25 @@ TEST_F(AuthTest, HMACVerifier) { // Create a content object core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize()); + std::string payload = "bonjour"; + std::vector buffer(payload.begin(), payload.end()); + signer->signBuffer(buffer); + std::vector sig = signer->getSignature(); + SymmetricVerifier hmac(PASSPHRASE); + bool res = hmac.verifyBuffer( + buffer, std::vector(sig.data(), sig.data() + sig.size()), + CryptoHashType::SHA256); + EXPECT_EQ(res, true); +} + +TEST_F(AuthTest, HMACVerifier) { + // Create the HMAC signer from a passphrase + std::shared_ptr signer = + std::make_shared(CryptoSuite::HMAC_SHA256, PASSPHRASE); + + // Create a content object + core::ContentObject packet(HF_INET6_TCP_AH, signer->getSignatureSize()); + // Fill it with bogus data uint8_t buffer[256] = {0}; packet.appendPayload(buffer, 256); @@ -99,11 +223,11 @@ TEST_F(AuthTest, HMACVerifier) { std::shared_ptr verifier = std::make_shared(PASSPHRASE); - ASSERT_EQ(packet.getFormat(), HF_INET6_TCP_AH); - ASSERT_EQ(signer->getCryptoHashType(), CryptoHashType::SHA_256); - ASSERT_EQ(signer->getCryptoSuite(), CryptoSuite::HMAC_SHA256); - ASSERT_EQ(signer->getSignatureSize(), 32u); - ASSERT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT); + EXPECT_EQ(packet.getFormat(), HF_INET6_TCP_AH); + EXPECT_EQ(signer->getHashType(), CryptoHashType::SHA256); + EXPECT_EQ(signer->getSuite(), CryptoSuite::HMAC_SHA256); + EXPECT_EQ(signer->getSignatureSize(), 32u); + EXPECT_EQ(verifier->verifyPackets(&packet), VerificationPolicy::ACCEPT); } } // namespace auth diff --git a/libtransport/src/test/test_consumer_producer_rtc.cc b/libtransport/src/test/test_consumer_producer_rtc.cc index 87385971a..8541a9e1a 100644 --- a/libtransport/src/test/test_consumer_producer_rtc.cc +++ b/libtransport/src/test/test_consumer_producer_rtc.cc @@ -14,14 +14,12 @@ */ #include +#include #include #include #include #include -#include -#include - namespace transport { namespace interface { @@ -151,7 +149,7 @@ const char ConsumerProducerTest::name[]; } // namespace -TEST_F(ConsumerProducerTest, EndToEnd) { +TEST_F(ConsumerProducerTest, DISABLED_EndToEnd) { produceRTCPacket(std::error_code()); consumer_.consume(consumer_name_); setStopTimer(); @@ -165,12 +163,3 @@ TEST_F(ConsumerProducerTest, EndToEnd) { } // namespace interface } // namespace transport - -int main(int argc, char **argv) { -#if 0 - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -#else - return 0; -#endif -} \ No newline at end of file diff --git a/libtransport/src/test/test_core_manifest.cc b/libtransport/src/test/test_core_manifest.cc index f98147d43..93f4e87cb 100644 --- a/libtransport/src/test/test_core_manifest.cc +++ b/libtransport/src/test/test_core_manifest.cc @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include @@ -124,9 +124,9 @@ TEST_F(ManifestTest, SetManifestType) { TEST_F(ManifestTest, SetHashAlgorithm) { manifest1_.clear(); - auth::CryptoHashType hash1 = auth::CryptoHashType::SHA_512; - auth::CryptoHashType hash2 = auth::CryptoHashType::CRC32C; - auth::CryptoHashType hash3 = auth::CryptoHashType::SHA_256; + auth::CryptoHashType hash1 = auth::CryptoHashType::SHA512; + auth::CryptoHashType hash2 = auth::CryptoHashType::BLAKE2B512; + auth::CryptoHashType hash3 = auth::CryptoHashType::SHA256; manifest1_.setHashAlgorithm(hash1); auto type_returned1 = manifest1_.getHashAlgorithm(); @@ -191,9 +191,9 @@ TEST_F(ManifestTest, SetSuffixList) { data[i].resize(32); std::generate(std::begin(data[i]), std::end(data[i]), std::ref(rbe)); suffixes[i] = idis(eng); - entries[i] = std::make_pair( - suffixes[i], auth::CryptoHash(data[i].data(), data[i].size(), - auth::CryptoHashType::SHA_256)); + entries[i] = std::make_pair(suffixes[i], + auth::CryptoHash(data[i].data(), data[i].size(), + auth::CryptoHashType::SHA256)); manifest1_.addSuffixHash(entries[i].first, entries[i].second); } @@ -223,8 +223,3 @@ TEST_F(ManifestTest, SetSuffixList) { } // namespace core } // namespace transport - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/libtransport/src/test/test_event_thread.cc b/libtransport/src/test/test_event_thread.cc index e66b49f10..549ff9c1a 100644 --- a/libtransport/src/test/test_event_thread.cc +++ b/libtransport/src/test/test_event_thread.cc @@ -71,7 +71,7 @@ double stdDeviation(const unsigned long samples[], int size) { } // namespace -TEST_F(EventThreadTest, SchedulingDelay) { +TEST_F(EventThreadTest, DISABLED_SchedulingDelay) { using namespace std::chrono; const size_t size = 1000000; std::vector samples(size); @@ -95,12 +95,3 @@ TEST_F(EventThreadTest, SchedulingDelay) { } } // namespace utils - -int main(int argc, char **argv) { -#if 0 - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -#else - return 0; -#endif -} \ No newline at end of file diff --git a/libtransport/src/test/test_fec_reedsolomon.cc b/libtransport/src/test/test_fec_reedsolomon.cc index 3b10b7307..c7e10d111 100644 --- a/libtransport/src/test/test_fec_reedsolomon.cc +++ b/libtransport/src/test/test_fec_reedsolomon.cc @@ -14,21 +14,21 @@ * limitations under the License. */ -#include #include #include #include +#include #include #include #include namespace transport { -namespace core { +namespace protocol { -double ReedSolomonTest(int k, int n, int size) { - fec::encoder encoder(k, n); - fec::decoder decoder(k, n); +double ReedSolomonTest(int k, int n, int seq_offset, int size) { + fec::RSEncoder encoder(k, n, seq_offset); + fec::RSDecoder decoder(k, n, seq_offset); std::vector tx_block(k); std::vector rx_block(k); @@ -36,27 +36,31 @@ double ReedSolomonTest(int k, int n, int size) { int run = 0; int iterations = 100; - auto &packet_manager = PacketManager<>::getInstance(); - - encoder.setFECCallback([&tx_block](std::vector &repair_packets) { - for (auto &p : repair_packets) { - // Append repair symbols to tx_block - tx_block.emplace_back(std::move(p)); - } - }); + auto &packet_manager = core::PacketManager<>::getInstance(); + + encoder.setFECCallback( + [&tx_block]( + std::vector> &repair_packets) { + for (auto &p : repair_packets) { + // Append repair symbols to tx_block + tx_block.emplace_back(std::move(p).second); + } + }); - decoder.setFECCallback([&](std::vector &source_packets) { - for (int i = 0; i < k; i++) { - // Compare decoded source packets with original transmitted packets. - if (*tx_block[i] != *source_packets[i]) { - count++; - } - } - }); + decoder.setFECCallback( + [&](std::vector> &source_packets) { + for (int i = 0; i < k; i++) { + // Compare decoded source packets with original transmitted packets. + if (*tx_block[i] != *source_packets[i].second) { + count++; + } + } + }); do { // Discard eventual packet appended in previous callback call tx_block.erase(tx_block.begin() + k, tx_block.end()); + auto _seq_offet = seq_offset; // Initialization. Feed encoder with first k source packets for (int i = 0; i < k; i++) { @@ -74,8 +78,8 @@ double ReedSolomonTest(int k, int n, int size) { std::generate(packet->writableData(), packet->writableTail(), rand); std::fill(packet->writableData(), packet->writableTail(), i + 1); - // Set first byte of payload to i, to reorder at receiver side - packet->writableData()[0] = uint8_t(i); + // Set first byte of payload to seq_offset, to reorder at receiver side + packet->writableData()[0] = uint8_t(_seq_offet++); // Store packet in tx buffer and clear rx buffer tx_block[i] = std::move(packet); @@ -99,10 +103,11 @@ double ReedSolomonTest(int k, int n, int size) { rx_block[rxi++] = tx_block[i]; if (i < k) { // Source packet - decoder.consume(rx_block[rxi - 1], rx_block[rxi - 1]->data()[0]); + decoder.consumeSource(rx_block[rxi - 1], + rx_block[rxi - 1]->data()[0]); } else { // Repair packet - decoder.consume(rx_block[rxi - 1]); + decoder.consumeRepair(rx_block[rxi - 1]); } } @@ -118,10 +123,10 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) { int n = 24; int size = 1000; - fec::encoder encoder(k, n); - fec::decoder decoder(k, n); + fec::RSEncoder encoder(k, n); + fec::RSDecoder decoder(k, n); - auto &packet_manager = PacketManager<>::getInstance(); + auto &packet_manager = core::PacketManager<>::getInstance(); std::vector> tx_block; std::vector> rx_block; @@ -133,28 +138,31 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) { int tx_packets = k * n_sourceblocks; unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); - encoder.setFECCallback([&](std::vector &repair_packets) { - for (auto &p : repair_packets) { - // Append repair symbols to tx_block - tx_block.emplace_back(std::move(p), ++i); - } + encoder.setFECCallback( + [&](std::vector> &repair_packets) { + for (auto &p : repair_packets) { + // Append repair symbols to tx_block + tx_block.emplace_back(std::move(p.second), ++i); + } - EXPECT_EQ(tx_block.size(), size_t(n)); + EXPECT_EQ(tx_block.size(), size_t(n)); - // Select k packets to send, including at least one symbol. We start from - // the end for this reason. - for (int j = n - 1; j > n - k - 1; j--) { - rx_block.emplace_back(std::move(tx_block[j])); - } + // Select k packets to send, including at least one symbol. We start + // from the end for this reason. + for (int j = n - 1; j > n - k - 1; j--) { + rx_block.emplace_back(std::move(tx_block[j])); + } - // Clear tx block for next source block - tx_block.clear(); - encoder.clear(); - }); + // Clear tx block for next source block + tx_block.clear(); + encoder.clear(); + }); // The decode callback must be called exactly n_sourceblocks times decoder.setFECCallback( - [&](std::vector &source_packets) { count++; }); + [&](std::vector> &source_packets) { + count++; + }); // Produce n * n_sourceblocks // - ( k ) * n_sourceblocks source packets @@ -194,10 +202,10 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) { int index = p.second % n; if (index < k) { // Source packet - decoder.consume(p.first, p.second); + decoder.consumeSource(p.first, p.second); } else { // Repair packet - decoder.consume(p.first); + decoder.consumeRepair(p.first); } } @@ -205,66 +213,22 @@ void ReedSolomonMultiBlockTest(int n_sourceblocks) { EXPECT_EQ(count, n_sourceblocks); } -TEST(ReedSolomonTest, RSk1n3) { - int k = 1; - int n = 3; - int size = 1000; - EXPECT_LE(ReedSolomonTest(k, n, size), 0); -} - -TEST(ReedSolomonTest, RSk6n10) { - int k = 6; - int n = 10; - int size = 1000; - EXPECT_LE(ReedSolomonTest(k, n, size), 0); -} - -TEST(ReedSolomonTest, RSk8n32) { - int k = 8; - int n = 32; - int size = 1000; - EXPECT_LE(ReedSolomonTest(k, n, size), 0); -} - -TEST(ReedSolomonTest, RSk16n24) { - int k = 16; - int n = 24; - int size = 1000; - EXPECT_LE(ReedSolomonTest(k, n, size), 0); -} - -TEST(ReedSolomonTest, RSk10n30) { - int k = 10; - int n = 30; - int size = 1000; - EXPECT_LE(ReedSolomonTest(k, n, size), 0); -} - -TEST(ReedSolomonTest, RSk10n40) { - int k = 10; - int n = 40; - int size = 1000; - EXPECT_LE(ReedSolomonTest(k, n, size), 0); -} - -TEST(ReedSolomonTest, RSk10n60) { - int k = 10; - int n = 60; - int size = 1000; - EXPECT_LE(ReedSolomonTest(k, n, size), 0); -} - -TEST(ReedSolomonTest, RSk10n90) { - int k = 10; - int n = 90; - int size = 1000; - EXPECT_LE(ReedSolomonTest(k, n, size), 0); -} - -TEST(ReedSolomonMultiBlockTest, RSMB1) { - int blocks = 1; - ReedSolomonMultiBlockTest(blocks); -} +/** + * @brief Use foreach_rs_fec_type to automatically generate the code of the + * tests and avoid copy/paste the same function. + */ +#define _(name, k, n) \ + TEST(ReedSolomonTest, RSK##k##N##n) { \ + int K = k; \ + int N = n; \ + int seq_offset = 0; \ + int size = 1000; \ + EXPECT_LE(ReedSolomonTest(K, N, seq_offset, size), 0); \ + seq_offset = 12345; \ + EXPECT_LE(ReedSolomonTest(K, N, seq_offset, size), 0); \ + } +foreach_rs_fec_type +#undef _ TEST(ReedSolomonMultiBlockTest, RSMB10) { int blocks = 10; @@ -281,11 +245,5 @@ TEST(ReedSolomonMultiBlockTest, RSMB1000) { ReedSolomonMultiBlockTest(blocks); } -int main(int argc, char **argv) { - srand(time(0)); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} - -} // namespace core +} // namespace protocol } // namespace transport diff --git a/libtransport/src/test/test_fec_rely_wrapper.cc b/libtransport/src/test/test_fec_rely_wrapper.cc new file mode 100644 index 000000000..c5b73f8d2 --- /dev/null +++ b/libtransport/src/test/test_fec_rely_wrapper.cc @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include + +namespace transport { +namespace protocol { + +std::string printMissing( + const std::map &missing) { + std::stringstream stream; + + for (auto &[seq, packet] : missing) { + stream << " " << seq; + } + + stream << "\n"; + + return stream.str(); +} + +/** + * @brief Test encode-decode operations performed using the wrapper for rely + * + * @param k Number of source symbols + * @param n Sum of source symbols and repair symbols + * @param max_packet_size The max packet size the decoder will expect. + * @param timeout The timeout used by rely + * https://rely.steinwurf.com/docs/6.1.0/design/timeout_configuration.html + * @param max_iterations The number of packets to send + * @param loss_rate The loss rate + */ +void testRelyEncoderDecoder(uint32_t k, uint32_t n, size_t max_packet_size, + int64_t timeout, uint32_t max_iterations, + int loss_rate) { + // Create 1 encoder and 1 decoder + fec::RelyEncoder _encoder(k, n); + fec::RelyDecoder _decoder(k, n); + + // Seed the pseudo-random with known value to always get same loss pattern + srand(k * n); + + // We will interact with rely encoder/decoder using the interface + fec::ProducerFEC &encoder = _encoder; + fec::ConsumerFEC &decoder = _decoder; + + // Initialize current iteration + uint32_t iterations = 0; + + // Packet allocator + auto &packet_manager = core::PacketManager<>::getInstance(); + + // Store packets to verify them in the decoder callback + std::map saved_packets; + + // Save repair packets here in encoder callback + std::queue pending_repair_packets; + + // Set callback called by encoder when a buffer is required. + encoder.setBufferCallback([](std::size_t size) -> fec::buffer { + auto ret = + core::PacketManager<>::getInstance().getPacket(); + ret->updateLength(size); + ret->append(size); + ret->trimStart(ret->headerSize()); + assert(ret->length() >= size); + + return ret; + }); + + // Set callback to be called by encoder when repair packets are ready + encoder.setFECCallback( + [&](std::vector> &packets) { + // We must get n - k symbols + EXPECT_EQ(packets.size(), n - k); + // TRANSPORT_LOGD("Got %zu symbols", packets.size()); + + // Save symbols in pending_repair_packets queue and increment iterations + for (auto &packet : packets) { + ++iterations; + pending_repair_packets.push(packet.second); + } + }); + + // Set callback to be called when decoder recover a packet + decoder.setFECCallback( + [&](std::vector> &packets) { + for (auto &packet : packets) { + // TRANSPORT_LOGD("Recovering packet %u", packet.first); + + // Ensure recovered packet is in packets actually produced by encoder + auto original = saved_packets.find(packet.first); + ASSERT_TRUE(original != saved_packets.end()); + auto &original_packet = *original->second; + + // Remove additional headers at the beginning of the packet. This may + // change in the future. + original_packet.trimStart(60 /* Ip + TCP */ + 28 /* Rely header */ + + 4 /* Packet size */); + + // Recovered packet should be equal to the original one + EXPECT_TRUE(original_packet == *packet.second); + + // Restore removed headers + original_packet.prepend(60 + 28 + 4); + + // Erase packet from saved packet list + saved_packets.erase(original); + } + }); + + // Send max_iterations packets from encoder to decoder + while (iterations < max_iterations) { + // Create a payload, the size is between 50 and 1350 bytes. + auto payload_size = 50 + (rand() % 1300); + uint8_t payload[max_packet_size]; + std::generate(payload, payload + payload_size, rand); + + // Get a packet from global pool and set name + auto buffer = packet_manager.getPacket(); + buffer->setName(core::Name("b001::abcd", iterations)); + + // Get offset + auto offset = buffer->headerSize(); + + // Copy payload into packet. We keep the payload to compare returned packet + // with original one (since rely encoder does modify the packet by adding + // its own header). + buffer->appendPayload(payload, payload_size); + + // Save packet in the saving_packets list + // TRANSPORT_LOGD("Saving packet with index %lu", iterations); + saved_packets.emplace(iterations, buffer); + + // Feed buffer into the encoder. This will eventually trigger a call to the + // FEC callback as soon as k packets are fed into the endocer. + encoder.onPacketProduced(*buffer, offset); + + // Check returned packet. We calculate the difference in size and we compare + // only the part of the returned packet corresponding to the original + // payload. Rely should only add a header and should not modify the actual + // payload content. If it does it, this check will fail. + auto diff = buffer->length() - payload_size - offset; + // TRANSPORT_LOGD("Difference is %zu", diff); + auto cmp = + std::memcmp(buffer->data() + offset + diff, payload, payload_size); + EXPECT_FALSE(cmp); + + // Drop condition. Id addition to the loss rate, we ensure that no drops are + // perfomed in the last 10% of the total iterations. This is done because + // rely uses a sliding-window mechanism to recover, and if we suddenly stop + // we may not be able to recover missing packets that would be recovered + // using future packets that are not created in the test. For this reason, + // we ensure the test ends without losses. +#define DROP_CONDITION(loss_rate, max_iterations) \ + (rand() % 100) >= loss_rate || iterations >= max_iterations * 0.9 + + // Handle the source packet to the decoder, id drop condition returns true + if (DROP_CONDITION(loss_rate, max_iterations)) { + // Pass packet to decoder + // TRANSPORT_LOGD("Passing packet %u to decoder", + // buffer->getName().getSuffix()); + decoder.onDataPacket(*buffer, offset); + } else { + // TRANSPORT_LOGD("Packet %u, dropped", buffer->getName().getSuffix()); + } + + // Check if previous call to encoder.consumer() generated repair packets, + // and if yes, feed them to the decoder. + while (pending_repair_packets.size()) { + // Also repair packets can be lost + if (DROP_CONDITION(loss_rate, max_iterations)) { + auto &packet = pending_repair_packets.front(); + // TRANSPORT_LOGD("Passing packet %u to decoder", iterations); + core::ContentObject &co = (core::ContentObject &)(*packet); + decoder.onDataPacket(co, 0); + } else { + // TRANSPORT_LOGD("Packet (repair) %u dropped", iterations); + } + + // Remove packet from the queue + pending_repair_packets.pop(); + } + + ++iterations; + } + + // We expect this test to terminate with a full recover of all the packets and + // 0.001 residual losses + EXPECT_LE(saved_packets.size(), iterations * 0.001) + << printMissing(saved_packets); + + // Reset seed + srand(time(0)); +} + +/** + * @brief Use foreach_rely_fec_type to automatically generate the code of the + * tests and avoid copy/paste the same function. + */ +#define _(name, k, n) \ + TEST(RelyTest, RelyK##k##N##n) { \ + int K = k; \ + int N = n; \ + uint32_t max_iterations = 1000; \ + int size = 1400; \ + int64_t timeout = 120; \ + int loss_rate = 10; \ + testRelyEncoderDecoder(K, N, size, timeout, max_iterations, loss_rate); \ + } +foreach_rely_fec_type +#undef _ + +} // namespace protocol +} // namespace transport diff --git a/libtransport/src/test/test_indexer.cc b/libtransport/src/test/test_indexer.cc new file mode 100644 index 000000000..9c12e2037 --- /dev/null +++ b/libtransport/src/test/test_indexer.cc @@ -0,0 +1,322 @@ + +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include + +namespace transport { +namespace protocol { + +class IncrementalIndexerTest : public ::testing::Test { + protected: + IncrementalIndexerTest() : indexer_(nullptr, nullptr) { + // You can do set-up work for each test here. + } + + virtual ~IncrementalIndexerTest() { + // You can do clean-up work that doesn't throw exceptions here. + } + + // If the constructor and destructor are not enough for setting up + // and cleaning up each test, you can define the following methods: + + virtual void SetUp() { + // Code here will be called immediately after the constructor (right + // before each test). + } + + virtual void TearDown() { + // Code here will be called immediately after each test (right + // before the destructor). + } + + IncrementalIndexer indexer_; +}; + +class RtcIndexerTest : public ::testing::Test { + protected: + RtcIndexerTest() : indexer_(nullptr, nullptr) { + // You can do set-up work for each test here. + } + + virtual ~RtcIndexerTest() { + // You can do clean-up work that doesn't throw exceptions here. + } + + // If the constructor and destructor are not enough for setting up + // and cleaning up each test, you can define the following methods: + + virtual void SetUp() { + // Code here will be called immediately after the constructor (right + // before each test). + indexer_.setFirstSuffix(0); + indexer_.reset(); + } + + virtual void TearDown() { + // Code here will be called immediately after each test (right + // before the destructor). + } + + static const constexpr uint32_t LIMIT = (1 << 31); + rtc::RtcIndexer indexer_; +}; + +void testIncrement(Indexer &indexer) { + // As a first index we should get zero + auto index = indexer.getNextSuffix(); + EXPECT_EQ(index, uint32_t(0)); + + // Check if the sequence works for consecutive incremental numbers + for (uint32_t i = 1; i < 4096; i++) { + index = indexer.getNextSuffix(); + EXPECT_EQ(index, i); + } + + index = indexer.getNextSuffix(); + EXPECT_NE(index, uint32_t(0)); +} + +void testJump(Indexer &indexer) { + // Fist suffix is 0 + auto index = indexer.getNextSuffix(); + EXPECT_EQ(index, uint32_t(0)); + + // Next suffix should be 1, but we jump to 12345 + uint32_t jump = 12345; + indexer.jumpToIndex(jump); + + // This takes place immediately + index = indexer.getNextSuffix(); + EXPECT_EQ(index, jump); +} + +TEST_F(IncrementalIndexerTest, TestReset) { + testIncrement(indexer_); + + // Reset the indexer + indexer_.reset(); + + // Now it should startfrom zero again + for (uint32_t i = 0; i < 4096; i++) { + auto index = indexer_.getNextSuffix(); + EXPECT_EQ(index, i); + } +} + +TEST_F(IncrementalIndexerTest, TestGetSuffix) { testIncrement(indexer_); } + +TEST_F(IncrementalIndexerTest, TestGetNextReassemblySegment) { + // Test suffixes for reassembly are not influenced by download suffixed + // increment + for (uint32_t i = 0; i < 4096; i++) { + auto index = indexer_.getNextSuffix(); + EXPECT_EQ(index, i); + } + + for (uint32_t i = 0; i < 4096; i++) { + auto index = indexer_.getNextReassemblySegment(); + EXPECT_EQ(index, i); + } +} + +TEST_F(IncrementalIndexerTest, TestJumpToIndex) { testJump(indexer_); } + +TEST_F(IncrementalIndexerTest, TestGetFinalSuffix) { + // Since final suffix hasn't been discovered, it should be invalid_index + auto final_suffix = indexer_.getFinalSuffix(); + ASSERT_EQ(final_suffix, Indexer::invalid_index); +} + +TEST_F(IncrementalIndexerTest, TestMaxLimit) { + // Jump to max value for uint32_t + indexer_.jumpToIndex(std::numeric_limits::max()); + auto ret = indexer_.getNextSuffix(); + ASSERT_EQ(ret, Indexer::invalid_index); + + // Now the indexer should always return invalid_index + for (uint32_t i = 0; i < 4096; i++) { + ret = indexer_.getNextSuffix(); + EXPECT_EQ(ret, Indexer::invalid_index); + } +} + +TEST_F(IncrementalIndexerTest, TestSetFirstSuffix) { + // Set first suffix before starting + uint32_t start = 1234567890; + indexer_.setFirstSuffix(1234567890); + + // The first suffix set should take place only after a reset + auto index = indexer_.getNextSuffix(); + EXPECT_EQ(index, uint32_t(0)); + + indexer_.reset(); + index = indexer_.getNextSuffix(); + EXPECT_EQ(index, start); +} + +TEST_F(IncrementalIndexerTest, TestIsFinalSuffixDiscovered) { + // Final suffix should not be discovererd + auto ret = indexer_.isFinalSuffixDiscovered(); + EXPECT_FALSE(ret); +} + +TEST_F(RtcIndexerTest, TestReset) { + // Without setting anything this indexer should behave exactly as the + // incremental indexer for the getNextSuffix() + testIncrement(indexer_); + + // Reset the indexer + indexer_.reset(); + + // Now it should startfrom zero again + for (uint32_t i = 0; i < 4096; i++) { + auto index = indexer_.getNextSuffix(); + EXPECT_EQ(index, i); + } +} + +TEST_F(RtcIndexerTest, TestGetNextSuffix) { + // Without setting anything this indexer should behave exactly as the + // incremental indexer for the getNextSuffix() + testIncrement(indexer_); +} + +TEST_F(RtcIndexerTest, TestGetNextReassemblySegment) { + // This indexer should not provide reassembly segments since they are not + // required for rtc + try { + indexer_.getNextReassemblySegment(); + // We should not reach this point + FAIL() << "Exception expected here"; + } catch (const errors::RuntimeException &exc) { + // OK correct exception + } catch (...) { + FAIL() << "Wrong exception thrown"; + } +} + +TEST_F(RtcIndexerTest, TestGetFinalSuffix) { + // Final suffix should be eqaul to LIMIT + ASSERT_EQ(indexer_.getFinalSuffix(), uint32_t(LIMIT)); +} + +TEST_F(RtcIndexerTest, TestJumpToIndex) { testJump(indexer_); } + +TEST_F(RtcIndexerTest, TestIsFinalSuffixDiscovered) { + // This method should always return true + EXPECT_TRUE(indexer_.isFinalSuffixDiscovered()); +} + +TEST_F(RtcIndexerTest, TestMaxLimit) { + // Once reached the LIMIT, this indexer should restart from 0 + + // Jump to max value for uint32_t + indexer_.jumpToIndex(LIMIT); + testIncrement(indexer_); +} + +TEST_F(RtcIndexerTest, TestEnableFec) { + // Here we enable the FEC and we check we receive indexes for souece packets + // only + indexer_.enableFec(fec::FECType::RS_K1_N3); + + // We did not set NFec, which should be zero. So we get only indexes for + // Source packets. + + // With this FEC type we should get one source packet every 3 (0 . . 3 . . 6) + auto index = indexer_.getNextSuffix(); + EXPECT_EQ(index, uint32_t(0)); + + index = indexer_.getNextSuffix(); + EXPECT_EQ(index, uint32_t(3)); + + index = indexer_.getNextSuffix(); + EXPECT_EQ(index, uint32_t(6)); + + // Change FEC Type + indexer_.enableFec(fec::FECType::RS_K10_N30); + + // With this FEC type we should get source packets from 7 to 9 + for (uint32_t i = 7; i < 10; i++) { + index = indexer_.getNextSuffix(); + EXPECT_EQ(index, i); + } + + // And then jump to 30 + index = indexer_.getNextSuffix(); + EXPECT_EQ(index, uint32_t(30)); + + // Let's now jump to a high value + indexer_.jumpToIndex(12365); + for (uint32_t i = 12365; i < 12369; i++) { + index = indexer_.getNextSuffix(); + EXPECT_EQ(index, i); + } +} + +TEST_F(RtcIndexerTest, TestSetNFec) { + // Here we enable the FEC and we set a max of 20 fec packets + indexer_.enableFec(fec::FECType::RS_K10_N90); + indexer_.setNFec(20); + + // We should get indexes up to 29 + uint32_t index; + for (uint32_t i = 0; i < 30; i++) { + index = indexer_.getNextSuffix(); + EXPECT_EQ(i, index); + } + + // Then it should jump to 90 + for (uint32_t i = 90; i < 99; i++) { + index = indexer_.getNextSuffix(); + EXPECT_EQ(i, index); + } + + // Let's set NFEC > 80 + indexer_.setNFec(150); +} + +TEST_F(RtcIndexerTest, TestSetNFecWithOffset) { + // Here we enable the FEC and we set a max of 20 fec packets + const constexpr uint32_t first_suffix = 7; + indexer_.setFirstSuffix(first_suffix); + indexer_.reset(); + indexer_.enableFec(fec::FECType::RS_K16_N24); + indexer_.setNFec(8); + + uint32_t index; + for (uint32_t i = first_suffix; i < 16 + first_suffix; i++) { + index = indexer_.getNextSuffix(); + EXPECT_FALSE(indexer_.isFec(index)); + EXPECT_EQ(i, index); + } + + for (uint32_t i = first_suffix + 16; i < 16 + 8 + first_suffix; i++) { + index = indexer_.getNextSuffix(); + EXPECT_TRUE(indexer_.isFec(index)); + EXPECT_EQ(i, index); + } +} + +} // namespace protocol +} // namespace transport diff --git a/libtransport/src/test/test_interest.cc b/libtransport/src/test/test_interest.cc index 0a835db24..8853563b0 100644 --- a/libtransport/src/test/test_interest.cc +++ b/libtransport/src/test/test_interest.cc @@ -260,8 +260,3 @@ TEST_F(InterestTest, AppendSuffixesEncodeAndIterate) { } // namespace core } // namespace transport - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/libtransport/src/test/test_packet.cc b/libtransport/src/test/test_packet.cc index 0ee140e2c..76ad352d6 100644 --- a/libtransport/src/test/test_packet.cc +++ b/libtransport/src/test/test_packet.cc @@ -47,10 +47,6 @@ class PacketForTest : public Packet { throw errors::NotImplementedException(); } - void setName(Name &&name) override { - throw errors::NotImplementedException(); - } - void setLifetime(uint32_t lifetime) override { throw errors::NotImplementedException(); } @@ -1040,8 +1036,3 @@ TEST_F(PacketTest, TestSetGetTTL) { } // namespace core } // namespace transport - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/libtransport/src/test/test_transport_producer.cc b/libtransport/src/test/test_transport_producer.cc deleted file mode 100644 index f711fb4bb..000000000 --- a/libtransport/src/test/test_transport_producer.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include - -#include "hicn/transport/interfaces/socket_producer.h" - -namespace transport { - -namespace interface { - -namespace { -// The fixture for testing class Foo. -class ProducerTest : public ::testing::Test { - protected: - ProducerTest() : name_("b001::123|321"), producer_() { - // You can do set-up work for each test here. - } - - virtual ~ProducerTest() { - // You can do clean-up work that doesn't throw exceptions here. - } - - // If the constructor and destructor are not enough for setting up - // and cleaning up each test, you can define the following methods: - - virtual void SetUp() { - // Code here will be called immediately after the constructor (right - // before each test). - } - - virtual void TearDown() { - // Code here will be called immediately after each test (right - // before the destructor). - } - - Name name_; - ProducerSocket producer_; -}; - -} // namespace - -TEST_F(ProducerTest, ProduceContent) { ASSERT_TRUE(true); } - -} // namespace interface - -} // namespace transport - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} \ No newline at end of file -- cgit 1.2.3-korg