From bcb6592af5496f17417f71924fbf0bcbbd03fe06 Mon Sep 17 00:00:00 2001 From: iphydf Date: Sat, 13 Jan 2024 13:43:01 +0000 Subject: [PATCH] test: Add C++ classes wrapping system interfaces. These are more convenient and safer than the manual vtables we have in the fuzzer support code. We can override individual member functions, and C++ will take care of correctly casting and offsetting this-pointers when needed. --- CMakeLists.txt | 2 + testing/fuzzing/CMakeLists.txt | 2 +- toxcore/BUILD.bazel | 53 ++++++++++++++----- toxcore/DHT_test.cc | 5 +- toxcore/group_announce_fuzz_test.cc | 3 +- toxcore/group_announce_test.cc | 3 +- toxcore/group_moderation_fuzz_test.cc | 4 +- toxcore/group_moderation_test.cc | 57 +++++++++++++------- toxcore/mem_test_util.cc | 26 ++++++++++ toxcore/mem_test_util.hh | 39 ++++++++++++++ toxcore/mono_time_test.cc | 10 ++-- toxcore/network_test.cc | 9 ++++ toxcore/network_test_util.cc | 75 +++++++++++++++++++++++++++ toxcore/network_test_util.hh | 54 +++++++++++++++++++ toxcore/ping_array_test.cc | 21 ++++---- toxcore/test_util.hh | 14 +++++ 16 files changed, 323 insertions(+), 54 deletions(-) create mode 100644 toxcore/mem_test_util.cc create mode 100644 toxcore/mem_test_util.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index 42211dce..f8688a30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -481,6 +481,8 @@ add_library(test_util STATIC toxcore/DHT_test_util.hh toxcore/crypto_core_test_util.cc toxcore/crypto_core_test_util.hh + toxcore/mem_test_util.cc + toxcore/mem_test_util.hh toxcore/network_test_util.cc toxcore/network_test_util.hh toxcore/test_util.cc diff --git a/testing/fuzzing/CMakeLists.txt b/testing/fuzzing/CMakeLists.txt index 6e928d0b..7efbb8c5 100644 --- a/testing/fuzzing/CMakeLists.txt +++ b/testing/fuzzing/CMakeLists.txt @@ -12,7 +12,7 @@ function(fuzz_test target source_dir) set(CORPUS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/toktok-fuzzer/corpus/${target}_fuzz_test) file(GLOB CORPUS "${CORPUS_DIR}/*") add_executable(${target}_fuzz_test ${source_dir}/${target}_fuzz_test.cc) - target_link_libraries(${target}_fuzz_test PRIVATE toxcore_fuzz fuzz_support ${LIBFUZZER_LINKER_FLAGS}) + target_link_libraries(${target}_fuzz_test PRIVATE fuzz_support test_util toxcore_fuzz ${LIBFUZZER_LINKER_FLAGS}) if(CORPUS) add_test(NAME ${target}_fuzz COMMAND ${CROSSCOMPILING_EMULATOR} ${target}_fuzz_test -max_total_time=10 ${CORPUS}) set_property(TEST ${target}_fuzz PROPERTY ENVIRONMENT "LLVM_PROFILE_FILE=${target}.profraw;srcdir=${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index 081a5b11..1232bf62 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -1,6 +1,5 @@ -load("@rules_cc//cc:defs.bzl", "cc_test") +load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test") -load("//tools:no_undefined.bzl", "cc_library") exports_files( srcs = [ @@ -12,6 +11,7 @@ exports_files( cc_library( name = "test_util", + testonly = True, srcs = ["test_util.cc"], hdrs = ["test_util.hh"], ) @@ -52,6 +52,17 @@ cc_library( ], ) +cc_library( + name = "mem_test_util", + testonly = True, + srcs = ["mem_test_util.cc"], + hdrs = ["mem_test_util.hh"], + deps = [ + ":mem", + ":test_util", + ], +) + cc_test( name = "mem_test", size = "small", @@ -162,6 +173,7 @@ cc_library( cc_library( name = "crypto_core_test_util", + testonly = True, srcs = ["crypto_core_test_util.cc"], hdrs = ["crypto_core_test_util.hh"], deps = [ @@ -240,6 +252,7 @@ cc_test( size = "small", srcs = ["mono_time_test.cc"], deps = [ + ":mem_test_util", ":mono_time", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", @@ -292,6 +305,7 @@ cc_library( cc_library( name = "network_test_util", + testonly = True, srcs = ["network_test_util.cc"], hdrs = ["network_test_util.hh"], deps = [ @@ -307,6 +321,7 @@ cc_test( srcs = ["network_test.cc"], deps = [ ":network", + ":network_test_util", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], @@ -341,6 +356,7 @@ cc_test( size = "small", srcs = ["ping_array_test.cc"], deps = [ + ":mem_test_util", ":mono_time", ":ping_array", "@com_google_googletest//:gtest", @@ -399,6 +415,7 @@ cc_library( cc_library( name = "DHT_test_util", + testonly = True, srcs = ["DHT_test_util.cc"], hdrs = ["DHT_test_util.hh"], deps = [ @@ -418,6 +435,7 @@ cc_test( ":DHT", ":DHT_test_util", ":crypto_core", + ":mem_test_util", ":network_test_util", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", @@ -468,7 +486,7 @@ cc_fuzz_test( name = "forwarding_fuzz_test", size = "small", srcs = ["forwarding_fuzz_test.cc"], - #corpus = ["//tools/toktok-fuzzer/corpus:forwarding_fuzz_test"], + corpus = ["//tools/toktok-fuzzer/corpus:forwarding_fuzz_test"], deps = [ ":forwarding", "//c-toxcore/testing/fuzzing:fuzz_support", @@ -641,12 +659,26 @@ cc_test( srcs = ["group_announce_test.cc"], deps = [ ":group_announce", + ":mem_test_util", ":mono_time", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], ) +cc_fuzz_test( + name = "group_announce_fuzz_test", + size = "small", + testonly = True, + srcs = ["group_announce_fuzz_test.cc"], + corpus = ["//tools/toktok-fuzzer/corpus:group_announce_fuzz_test"], + deps = [ + ":group_announce", + ":mem_test_util", + "//c-toxcore/testing/fuzzing:fuzz_support", + ], +) + cc_library( name = "group_onion_announce", srcs = ["group_onion_announce.c"], @@ -663,17 +695,6 @@ cc_library( ], ) -cc_fuzz_test( - name = "group_announce_fuzz_test", - size = "small", - srcs = ["group_announce_fuzz_test.cc"], - #corpus = ["//tools/toktok-fuzzer/corpus:group_announce_fuzz_test"], - deps = [ - ":group_announce", - "//c-toxcore/testing/fuzzing:fuzz_support", - ], -) - cc_library( name = "onion_client", srcs = ["onion_client.c"], @@ -759,8 +780,10 @@ cc_test( srcs = ["group_moderation_test.cc"], deps = [ ":crypto_core", + ":crypto_core_test_util", ":group_moderation", ":logger", + ":mem_test_util", ":util", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", @@ -770,10 +793,12 @@ cc_test( cc_fuzz_test( name = "group_moderation_fuzz_test", size = "small", + testonly = True, srcs = ["group_moderation_fuzz_test.cc"], corpus = ["//tools/toktok-fuzzer/corpus:group_moderation_fuzz_test"], deps = [ ":group_moderation", + ":mem_test_util", "//c-toxcore/testing/fuzzing:fuzz_support", ], ) diff --git a/toxcore/DHT_test.cc b/toxcore/DHT_test.cc index 95812582..34841c74 100644 --- a/toxcore/DHT_test.cc +++ b/toxcore/DHT_test.cc @@ -11,6 +11,7 @@ #include "DHT_test_util.hh" #include "crypto_core.h" #include "crypto_core_test_util.hh" +#include "mem_test_util.hh" #include "network_test_util.hh" namespace { @@ -326,8 +327,8 @@ TEST(Request, CreateAndParse) TEST(AnnounceNodes, SetAndTest) { Test_Random rng; - const Network *ns = system_network(); - const Memory *mem = system_memory(); + Test_Memory mem; + Test_Network ns; Logger *log = logger_new(); ASSERT_NE(log, nullptr); diff --git a/toxcore/group_announce_fuzz_test.cc b/toxcore/group_announce_fuzz_test.cc index 051a10bd..eba5e877 100644 --- a/toxcore/group_announce_fuzz_test.cc +++ b/toxcore/group_announce_fuzz_test.cc @@ -6,6 +6,7 @@ #include #include "../testing/fuzzing/fuzz_support.h" +#include "mem_test_util.hh" namespace { @@ -48,7 +49,7 @@ void TestUnpackPublicAnnounce(Fuzz_Data &input) void TestDoGca(Fuzz_Data &input) { - const Memory *mem = system_memory(); + Test_Memory mem; std::unique_ptr logger(logger_new(), logger_kill); uint64_t clock = 1; diff --git a/toxcore/group_announce_test.cc b/toxcore/group_announce_test.cc index 6252e426..89452672 100644 --- a/toxcore/group_announce_test.cc +++ b/toxcore/group_announce_test.cc @@ -2,13 +2,14 @@ #include +#include "mem_test_util.hh" #include "mono_time.h" namespace { struct Announces : ::testing::Test { protected: - const Memory *mem_ = system_memory(); + Test_Memory mem_; uint64_t clock_ = 1000; Mono_Time *mono_time_ = nullptr; GC_Announces_List *gca_ = nullptr; diff --git a/toxcore/group_moderation_fuzz_test.cc b/toxcore/group_moderation_fuzz_test.cc index 281536a6..9edca19d 100644 --- a/toxcore/group_moderation_fuzz_test.cc +++ b/toxcore/group_moderation_fuzz_test.cc @@ -1,13 +1,15 @@ #include "group_moderation.h" #include "../testing/fuzzing/fuzz_support.h" +#include "mem_test_util.hh" namespace { void TestModListUnpack(Fuzz_Data &input) { CONSUME1_OR_RETURN(const uint16_t, num_mods, input); - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; mod_list_unpack(&mods, input.data(), input.size(), num_mods); mod_list_cleanup(&mods); } diff --git a/toxcore/group_moderation_test.cc b/toxcore/group_moderation_test.cc index 3524abef..24e32ba2 100644 --- a/toxcore/group_moderation_test.cc +++ b/toxcore/group_moderation_test.cc @@ -7,7 +7,9 @@ #include #include "crypto_core.h" +#include "crypto_core_test_util.hh" #include "logger.h" +#include "mem_test_util.hh" #include "util.h" namespace { @@ -18,7 +20,8 @@ using ModerationHash = std::array; TEST(ModList, PackedSizeOfEmptyModListIsZero) { - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; EXPECT_EQ(mod_list_packed_size(&mods), 0); uint8_t byte = 1; @@ -28,14 +31,16 @@ TEST(ModList, PackedSizeOfEmptyModListIsZero) TEST(ModList, UnpackingZeroSizeArrayIsNoop) { - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; const uint8_t byte = 1; EXPECT_EQ(mod_list_unpack(&mods, &byte, 0, 0), 0); } TEST(ModList, AddRemoveMultipleMods) { - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; uint8_t sig_pk1[32] = {1}; uint8_t sig_pk2[32] = {2}; EXPECT_TRUE(mod_list_add_entry(&mods, sig_pk1)); @@ -47,7 +52,8 @@ TEST(ModList, AddRemoveMultipleMods) TEST(ModList, PackingAndUnpackingList) { using ModListEntry = std::array; - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; EXPECT_TRUE(mod_list_add_entry(&mods, ModListEntry{}.data())); std::vector packed(mod_list_packed_size(&mods)); @@ -55,7 +61,7 @@ TEST(ModList, PackingAndUnpackingList) EXPECT_TRUE(mod_list_remove_entry(&mods, ModListEntry{}.data())); - Moderation mods2{system_memory()}; + Moderation mods2{mem}; EXPECT_EQ(mod_list_unpack(&mods2, packed.data(), packed.size(), 1), packed.size()); EXPECT_TRUE(mod_list_remove_entry(&mods2, ModListEntry{}.data())); } @@ -63,13 +69,14 @@ TEST(ModList, PackingAndUnpackingList) TEST(ModList, UnpackingTooManyModsFails) { using ModListEntry = std::array; - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; EXPECT_TRUE(mod_list_add_entry(&mods, ModListEntry{}.data())); std::vector packed(mod_list_packed_size(&mods)); mod_list_pack(&mods, packed.data()); - Moderation mods2{system_memory()}; + Moderation mods2{mem}; EXPECT_EQ(mod_list_unpack(&mods2, packed.data(), packed.size(), 2), -1); EXPECT_TRUE(mod_list_remove_entry(&mods, ModListEntry{}.data())); } @@ -78,16 +85,17 @@ TEST(ModList, UnpackingFromEmptyBufferFails) { std::vector packed(1); - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; EXPECT_EQ(mod_list_unpack(&mods, packed.data(), 0, 1), -1); } TEST(ModList, HashOfEmptyModListZeroesOutBuffer) { - const Random *rng = system_random(); - ASSERT_NE(rng, nullptr); + Test_Memory mem; + Test_Random rng; - Moderation mods{system_memory()}; + Moderation mods{mem}; // Fill with random data, check that it's zeroed. ModerationHash hash; @@ -98,21 +106,24 @@ TEST(ModList, HashOfEmptyModListZeroesOutBuffer) TEST(ModList, RemoveIndexFromEmptyModListFails) { - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; EXPECT_FALSE(mod_list_remove_index(&mods, 0)); EXPECT_FALSE(mod_list_remove_index(&mods, UINT16_MAX)); } TEST(ModList, RemoveEntryFromEmptyModListFails) { - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; uint8_t sig_pk[32] = {0}; EXPECT_FALSE(mod_list_remove_entry(&mods, sig_pk)); } TEST(ModList, ModListRemoveIndex) { - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; uint8_t sig_pk[32] = {1}; EXPECT_TRUE(mod_list_add_entry(&mods, sig_pk)); EXPECT_TRUE(mod_list_remove_index(&mods, 0)); @@ -120,20 +131,23 @@ TEST(ModList, ModListRemoveIndex) TEST(ModList, CleanupOnEmptyModsIsNoop) { - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; mod_list_cleanup(&mods); } TEST(ModList, EmptyModListCannotVerifyAnySigPk) { - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; uint8_t sig_pk[32] = {1}; EXPECT_FALSE(mod_list_verify_sig_pk(&mods, sig_pk)); } TEST(ModList, ModListAddVerifyRemoveSigPK) { - Moderation mods{system_memory()}; + Test_Memory mem; + Moderation mods{mem}; uint8_t sig_pk[32] = {1}; EXPECT_TRUE(mod_list_add_entry(&mods, sig_pk)); EXPECT_TRUE(mod_list_verify_sig_pk(&mods, sig_pk)); @@ -143,7 +157,8 @@ TEST(ModList, ModListAddVerifyRemoveSigPK) TEST(ModList, ModListHashCheck) { - Moderation mods1{system_memory()}; + Test_Memory mem; + Moderation mods1{mem}; uint8_t sig_pk1[32] = {1}; std::array hash1; @@ -165,7 +180,8 @@ TEST(SanctionsList, PackingIntoUndersizedBufferFails) TEST(SanctionsList, PackUnpackSanctionsCreds) { - Moderation mod{system_memory()}; + Test_Memory mem; + Moderation mod{mem}; std::array packed; EXPECT_EQ(sanctions_creds_pack(&mod.sanctions_creds, packed.data()), MOD_SANCTIONS_CREDS_SIZE); EXPECT_EQ( @@ -177,7 +193,8 @@ protected: ExtPublicKey pk; ExtSecretKey sk; Logger *log = logger_new(); - Moderation mod{system_memory()}; + Test_Memory mem; + Moderation mod{mem}; Mod_Sanction sanctions[2] = {}; const uint8_t sanctioned_pk1[32] = {1}; diff --git a/toxcore/mem_test_util.cc b/toxcore/mem_test_util.cc new file mode 100644 index 00000000..874bc66b --- /dev/null +++ b/toxcore/mem_test_util.cc @@ -0,0 +1,26 @@ +#include "mem_test_util.hh" + +#include + +Memory_Funcs const Memory_Class::vtable = { + Method::invoke<&Memory_Class::malloc>, + Method::invoke<&Memory_Class::calloc>, + Method::invoke<&Memory_Class::realloc>, + Method::invoke<&Memory_Class::free>, +}; + +Memory_Class::~Memory_Class() = default; + +void *Test_Memory::malloc(void *obj, uint32_t size) { return mem->funcs->malloc(mem->obj, size); } + +void *Test_Memory::calloc(void *obj, uint32_t nmemb, uint32_t size) +{ + return mem->funcs->calloc(mem->obj, nmemb, size); +} + +void *Test_Memory::realloc(void *obj, void *ptr, uint32_t size) +{ + return mem->funcs->realloc(mem->obj, ptr, size); +} + +void Test_Memory::free(void *obj, void *ptr) { return mem->funcs->free(mem->obj, ptr); } diff --git a/toxcore/mem_test_util.hh b/toxcore/mem_test_util.hh new file mode 100644 index 00000000..6d1773d1 --- /dev/null +++ b/toxcore/mem_test_util.hh @@ -0,0 +1,39 @@ +#ifndef C_TOXCORE_TOXCORE_MEM_TEST_UTIL_H +#define C_TOXCORE_TOXCORE_MEM_TEST_UTIL_H + +#include "mem.h" +#include "test_util.hh" + +struct Memory_Class { + static Memory_Funcs const vtable; + Memory const self; + + operator Memory const *() const { return &self; } + + Memory_Class(Memory_Class const &) = default; + Memory_Class() + : self{&vtable, this} + { + } + + virtual ~Memory_Class(); + virtual mem_malloc_cb malloc = 0; + virtual mem_calloc_cb calloc = 0; + virtual mem_realloc_cb realloc = 0; + virtual mem_free_cb free = 0; +}; + +/** + * Base test Memory class that just forwards to system_memory. Can be + * subclassed to override individual (or all) functions. + */ +class Test_Memory : public Memory_Class { + const Memory *mem = REQUIRE_NOT_NULL(system_memory()); + + void *malloc(void *obj, uint32_t size) override; + void *calloc(void *obj, uint32_t nmemb, uint32_t size) override; + void *realloc(void *obj, void *ptr, uint32_t size) override; + void free(void *obj, void *ptr) override; +}; + +#endif // C_TOXCORE_TOXCORE_MEM_TEST_UTIL_H diff --git a/toxcore/mono_time_test.cc b/toxcore/mono_time_test.cc index 3a649b7b..0334f323 100644 --- a/toxcore/mono_time_test.cc +++ b/toxcore/mono_time_test.cc @@ -5,11 +5,13 @@ #include #include +#include "mem_test_util.hh" + namespace { TEST(MonoTime, UnixTimeIncreasesOverTime) { - const Memory *mem = system_memory(); + Test_Memory mem; Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); ASSERT_NE(mono_time, nullptr); @@ -28,7 +30,7 @@ TEST(MonoTime, UnixTimeIncreasesOverTime) TEST(MonoTime, IsTimeout) { - const Memory *mem = system_memory(); + Test_Memory mem; Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); ASSERT_NE(mono_time, nullptr); @@ -46,7 +48,7 @@ TEST(MonoTime, IsTimeout) TEST(MonoTime, IsTimeoutReal) { - const Memory *mem = system_memory(); + Test_Memory mem; Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); ASSERT_NE(mono_time, nullptr); @@ -67,7 +69,7 @@ TEST(MonoTime, IsTimeoutReal) TEST(MonoTime, CustomTime) { - const Memory *mem = system_memory(); + Test_Memory mem; Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); ASSERT_NE(mono_time, nullptr); diff --git a/toxcore/network_test.cc b/toxcore/network_test.cc index 98b97a5b..a86436c8 100644 --- a/toxcore/network_test.cc +++ b/toxcore/network_test.cc @@ -2,8 +2,17 @@ #include +#include "network_test_util.hh" + namespace { +TEST(TestUtil, ProducesNonNullNetwork) +{ + Test_Network net; + const Network *ns = net; + EXPECT_NE(ns, nullptr); +} + TEST(IpNtoa, DoesntWriteOutOfBounds) { Ip_Ntoa ip_str; diff --git a/toxcore/network_test_util.cc b/toxcore/network_test_util.cc index 82f3b872..1f34e086 100644 --- a/toxcore/network_test_util.cc +++ b/toxcore/network_test_util.cc @@ -2,6 +2,81 @@ #include +Network_Funcs const Network_Class::vtable = { + Method::invoke<&Network_Class::close>, + Method::invoke<&Network_Class::accept>, + Method::invoke<&Network_Class::bind>, + Method::invoke<&Network_Class::listen>, + Method::invoke<&Network_Class::recvbuf>, + Method::invoke<&Network_Class::recv>, + Method::invoke<&Network_Class::recvfrom>, + Method::invoke<&Network_Class::send>, + Method::invoke<&Network_Class::sendto>, + Method::invoke<&Network_Class::socket>, + Method::invoke<&Network_Class::socket_nonblock>, + Method::invoke<&Network_Class::getsockopt>, + Method::invoke<&Network_Class::setsockopt>, + Method::invoke<&Network_Class::getaddrinfo>, + Method::invoke<&Network_Class::freeaddrinfo>, +}; + +int Test_Network::close(void *obj, int sock) { return net->funcs->close(net->obj, sock); } +int Test_Network::accept(void *obj, int sock) { return net->funcs->accept(net->obj, sock); } +int Test_Network::bind(void *obj, int sock, const Network_Addr *addr) +{ + return net->funcs->bind(net->obj, sock, addr); +} +int Test_Network::listen(void *obj, int sock, int backlog) +{ + return net->funcs->listen(net->obj, sock, backlog); +} +int Test_Network::recvbuf(void *obj, int sock) { return net->funcs->recvbuf(net->obj, sock); } +int Test_Network::recv(void *obj, int sock, uint8_t *buf, size_t len) +{ + return net->funcs->recv(net->obj, sock, buf, len); +} +int Test_Network::recvfrom(void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) +{ + return net->funcs->recvfrom(net->obj, sock, buf, len, addr); +} +int Test_Network::send(void *obj, int sock, const uint8_t *buf, size_t len) +{ + return net->funcs->send(net->obj, sock, buf, len); +} +int Test_Network::sendto( + void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr) +{ + return net->funcs->sendto(net->obj, sock, buf, len, addr); +} +int Test_Network::socket(void *obj, int domain, int type, int proto) +{ + return net->funcs->socket(net->obj, domain, type, proto); +} +int Test_Network::socket_nonblock(void *obj, int sock, bool nonblock) +{ + return net->funcs->socket_nonblock(net->obj, sock, nonblock); +} +int Test_Network::getsockopt( + void *obj, int sock, int level, int optname, void *optval, size_t *optlen) +{ + return net->funcs->getsockopt(net->obj, sock, level, optname, optval, optlen); +} +int Test_Network::setsockopt( + void *obj, int sock, int level, int optname, const void *optval, size_t optlen) +{ + return net->funcs->setsockopt(net->obj, sock, level, optname, optval, optlen); +} +int Test_Network::getaddrinfo(void *obj, int family, Network_Addr **addrs) +{ + return net->funcs->getaddrinfo(net->obj, family, addrs); +} +int Test_Network::freeaddrinfo(void *obj, Network_Addr *addrs) +{ + return net->funcs->freeaddrinfo(net->obj, addrs); +} + +Network_Class::~Network_Class() = default; + IP_Port increasing_ip_port::operator()() { IP_Port ip_port; diff --git a/toxcore/network_test_util.hh b/toxcore/network_test_util.hh index 86663251..ede8397d 100644 --- a/toxcore/network_test_util.hh +++ b/toxcore/network_test_util.hh @@ -7,6 +7,60 @@ #include "network.h" #include "test_util.hh" +struct Network_Class { + static Network_Funcs const vtable; + Network const self; + + operator Network const *() const { return &self; } + + Network_Class(Network_Class const &) = default; + Network_Class() + : self{&vtable, this} + { + } + + virtual ~Network_Class(); + virtual net_close_cb close = 0; + virtual net_accept_cb accept = 0; + virtual net_bind_cb bind = 0; + virtual net_listen_cb listen = 0; + virtual net_recvbuf_cb recvbuf = 0; + virtual net_recv_cb recv = 0; + virtual net_recvfrom_cb recvfrom = 0; + virtual net_send_cb send = 0; + virtual net_sendto_cb sendto = 0; + virtual net_socket_cb socket = 0; + virtual net_socket_nonblock_cb socket_nonblock = 0; + virtual net_getsockopt_cb getsockopt = 0; + virtual net_setsockopt_cb setsockopt = 0; + virtual net_getaddrinfo_cb getaddrinfo = 0; + virtual net_freeaddrinfo_cb freeaddrinfo = 0; +}; + +/** + * Base test Network class that just forwards to system_network. Can be + * subclassed to override individual (or all) functions. + */ +class Test_Network : public Network_Class { + const Network *net = REQUIRE_NOT_NULL(system_network()); + + int close(void *obj, int sock) override; + int accept(void *obj, int sock) override; + int bind(void *obj, int sock, const Network_Addr *addr) override; + int listen(void *obj, int sock, int backlog) override; + int recvbuf(void *obj, int sock) override; + int recv(void *obj, int sock, uint8_t *buf, size_t len) override; + int recvfrom(void *obj, int sock, uint8_t *buf, size_t len, Network_Addr *addr) override; + int send(void *obj, int sock, const uint8_t *buf, size_t len) override; + int sendto(void *obj, int sock, const uint8_t *buf, size_t len, const Network_Addr *addr) override; + int socket(void *obj, int domain, int type, int proto) override; + int socket_nonblock(void *obj, int sock, bool nonblock) override; + int getsockopt(void *obj, int sock, int level, int optname, void *optval, size_t *optlen) override; + int setsockopt(void *obj, int sock, int level, int optname, const void *optval, size_t optlen) override; + int getaddrinfo(void *obj, int family, Network_Addr **addrs) override; + int freeaddrinfo(void *obj, Network_Addr *addrs) override; +}; + template <> struct Deleter : Function_Deleter { }; diff --git a/toxcore/ping_array_test.cc b/toxcore/ping_array_test.cc index 8ce55709..6f6f4c21 100644 --- a/toxcore/ping_array_test.cc +++ b/toxcore/ping_array_test.cc @@ -4,6 +4,7 @@ #include +#include "mem_test_util.hh" #include "mono_time.h" namespace { @@ -15,7 +16,7 @@ struct Ping_Array_Deleter { using Ping_Array_Ptr = std::unique_ptr; struct Mono_Time_Deleter { - Mono_Time_Deleter(const Memory *mem) + Mono_Time_Deleter(const Test_Memory &mem) : mem_(mem) { } @@ -29,21 +30,21 @@ using Mono_Time_Ptr = std::unique_ptr; TEST(PingArray, MinimumTimeoutIsOne) { - const Memory *mem = system_memory(); + Test_Memory mem; EXPECT_EQ(ping_array_new(mem, 1, 0), nullptr); EXPECT_NE(Ping_Array_Ptr(ping_array_new(mem, 1, 1)), nullptr); } TEST(PingArray, MinimumArraySizeIsOne) { - const Memory *mem = system_memory(); + Test_Memory mem; EXPECT_EQ(ping_array_new(mem, 0, 1), nullptr); EXPECT_NE(Ping_Array_Ptr(ping_array_new(mem, 1, 1)), nullptr); } TEST(PingArray, ArraySizeMustBePowerOfTwo) { - const Memory *mem = system_memory(); + Test_Memory mem; Ping_Array_Ptr arr; arr.reset(ping_array_new(mem, 2, 1)); @@ -59,7 +60,7 @@ TEST(PingArray, ArraySizeMustBePowerOfTwo) TEST(PingArray, StoredDataCanBeRetrieved) { - const Memory *mem = system_memory(); + Test_Memory mem; Ping_Array_Ptr const arr(ping_array_new(mem, 2, 1)); Mono_Time_Ptr const mono_time(mono_time_new(mem, nullptr, nullptr), mem); @@ -78,7 +79,7 @@ TEST(PingArray, StoredDataCanBeRetrieved) TEST(PingArray, RetrievingDataWithTooSmallOutputBufferHasNoEffect) { - const Memory *mem = system_memory(); + Test_Memory mem; Ping_Array_Ptr const arr(ping_array_new(mem, 2, 1)); Mono_Time_Ptr const mono_time(mono_time_new(mem, nullptr, nullptr), mem); @@ -101,7 +102,7 @@ TEST(PingArray, RetrievingDataWithTooSmallOutputBufferHasNoEffect) TEST(PingArray, ZeroLengthDataCanBeAdded) { - const Memory *mem = system_memory(); + Test_Memory mem; Ping_Array_Ptr const arr(ping_array_new(mem, 2, 1)); Mono_Time_Ptr const mono_time(mono_time_new(mem, nullptr, nullptr), mem); @@ -118,7 +119,7 @@ TEST(PingArray, ZeroLengthDataCanBeAdded) TEST(PingArray, PingId0IsInvalid) { - const Memory *mem = system_memory(); + Test_Memory mem; Ping_Array_Ptr const arr(ping_array_new(mem, 2, 1)); Mono_Time_Ptr const mono_time(mono_time_new(mem, nullptr, nullptr), mem); @@ -131,7 +132,7 @@ TEST(PingArray, PingId0IsInvalid) // Protection against replay attacks. TEST(PingArray, DataCanOnlyBeRetrievedOnce) { - const Memory *mem = system_memory(); + Test_Memory mem; Ping_Array_Ptr const arr(ping_array_new(mem, 2, 1)); Mono_Time_Ptr const mono_time(mono_time_new(mem, nullptr, nullptr), mem); @@ -149,7 +150,7 @@ TEST(PingArray, DataCanOnlyBeRetrievedOnce) TEST(PingArray, PingIdMustMatchOnCheck) { - const Memory *mem = system_memory(); + Test_Memory mem; Ping_Array_Ptr const arr(ping_array_new(mem, 1, 1)); Mono_Time_Ptr const mono_time(mono_time_new(mem, nullptr, nullptr), mem); diff --git a/toxcore/test_util.hh b/toxcore/test_util.hh index 615e3cc4..08bc9482 100644 --- a/toxcore/test_util.hh +++ b/toxcore/test_util.hh @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -66,4 +68,16 @@ Container sorted(Container arr, Less less) return arr; } +template +T *require_not_null(const char *file, int line, T *ptr) +{ + if (ptr == nullptr) { + std::fprintf(stderr, "unexpected null pointer at %s:%d\n", file, line); + std::exit(7); + } + return ptr; +} + +#define REQUIRE_NOT_NULL(ptr) require_not_null(__FILE__, __LINE__, ptr) + #endif // C_TOXCORE_TOXCORE_TEST_UTIL_H