From 56591772170cb2d9ebe3545815f21386499ddf52 Mon Sep 17 00:00:00 2001 From: King_DuckZ Date: Tue, 13 Sep 2016 00:38:40 +0200 Subject: [PATCH] Introduce rapidcheck and a basic test. --- .gitmodules | 6 +++ CMakeLists.txt | 45 +++++++++++++---- lib/gtest | 1 + lib/rapidcheck | 1 + src/find_redirections.cpp | 49 ++++++++++++++++++ src/find_redirections.hpp | 41 ++++++++++++++++ test/unit/CMakeLists.txt | 23 +++++++++ test/unit/test_upnp.cpp | 101 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 258 insertions(+), 9 deletions(-) create mode 160000 lib/gtest create mode 160000 lib/rapidcheck create mode 100644 src/find_redirections.cpp create mode 100644 src/find_redirections.hpp create mode 100644 test/unit/CMakeLists.txt create mode 100644 test/unit/test_upnp.cpp diff --git a/.gitmodules b/.gitmodules index 85252af..d5dfc46 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,9 @@ [submodule "lib/better-enums"] path = lib/better-enums url = https://github.com/aantron/better-enums +[submodule "lib/gtest"] + path = lib/gtest + url = https://github.com/google/googletest.git +[submodule "lib/rapidcheck"] + path = lib/rapidcheck + url = https://github.com/emil-e/rapidcheck.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 9db37fe..1d329e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,14 @@ cmake_minimum_required(VERSION 3.2 FATAL_ERROR) project(keepupnpup CXX) list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules) +set(CXX_STANDARD_REQUIRED ON) + option (USE_SYSTEM_MINIUPNP "Try to locate miniupnpc on the system and build against that" ON) +include(CTest) + +find_package(Boost 1.55.0 REQUIRED) + if (USE_SYSTEM_MINIUPNP) find_package(Miniupnpc 2.0 REQUIRED) else() @@ -17,35 +23,56 @@ else() set(UPNPC_BUILD_SHARED OFF CACHE BOOL "" FORCE) endif() set(UPNPC_BUILD_TESTS OFF CACHE BOOL "" FORCE) - set(CXX_STANDARD_REQUIRED ON) add_subdirectory(lib/miniupnp/miniupnpc) endif() add_executable(${PROJECT_NAME} src/main.cpp +) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_EXTENSIONS OFF) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14) +add_library(${PROJECT_NAME}_implem STATIC src/upnp.cpp src/upnpexceptions.cpp + src/find_redirections.cpp ) +set_property(TARGET ${PROJECT_NAME}_implem PROPERTY CXX_EXTENSIONS OFF) +set_property(TARGET ${PROJECT_NAME}_implem PROPERTY CXX_STANDARD 14) -target_include_directories(${PROJECT_NAME} - PRIVATE lib/better-enums +target_include_directories(${PROJECT_NAME}_implem + PUBLIC lib/better-enums +) +target_include_directories(${PROJECT_NAME}_implem SYSTEM + PUBLIC ${Boost_INCLUDE_DIRS} ) if (USE_SYSTEM_MINIUPNP) - target_include_directories(${PROJECT_NAME} SYSTEM + target_include_directories(${PROJECT_NAME}_implem SYSTEM PRIVATE ${MINIUPNP_INCLUDE_DIR} ) - target_link_libraries(${PROJECT_NAME} + target_link_libraries(${PROJECT_NAME}_implem PRIVATE ${MINIUPNP_LIBRARY} ) else() - target_include_directories(${PROJECT_NAME} + target_include_directories(${PROJECT_NAME}_implem PRIVATE lib/miniupnp/miniupnpc ) - target_link_libraries(${PROJECT_NAME} - libminiupnpc-${upnp_lib_type} + target_link_libraries(${PROJECT_NAME}_implem + PRIVATE libminiupnpc-${upnp_lib_type} ) endif() -set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14) +target_link_libraries(${PROJECT_NAME} + PRIVATE ${PROJECT_NAME}_implem +) + +if (BUILD_TESTING) + set(BUILD_GTEST ON CACHE BOOL "" FORCE) + set(BUILD_GMOCK OFF CACHE BOOL "" FORCE) + set(RC_ENABLE_GTEST ON CACHE BOOL "" FORCE) + + add_subdirectory(lib/gtest) + add_subdirectory(lib/rapidcheck) + add_subdirectory(test/unit) +endif() diff --git a/lib/gtest b/lib/gtest new file mode 160000 index 0000000..48ee8e9 --- /dev/null +++ b/lib/gtest @@ -0,0 +1 @@ +Subproject commit 48ee8e98abc950abd8541e15550b18f8f6cfb3a9 diff --git a/lib/rapidcheck b/lib/rapidcheck new file mode 160000 index 0000000..f5d3afa --- /dev/null +++ b/lib/rapidcheck @@ -0,0 +1 @@ +Subproject commit f5d3afa4f387ecf147faf98d96710a6edfa420f1 diff --git a/src/find_redirections.cpp b/src/find_redirections.cpp new file mode 100644 index 0000000..f07bd57 --- /dev/null +++ b/src/find_redirections.cpp @@ -0,0 +1,49 @@ +/* Copyright 2016, Michele Santullo + * This file is part of "keepupnpup". + * + * "keepupnpup" 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. + * + * "keepupnpup" 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 "keepupnpup". If not, see . + */ + +#include "find_redirections.hpp" +#include + +namespace kuu { + auto redirections_for_localaddr ( + const RedirectionsList& parRedirs, + const std::string& parAddr, + uint16_t parPort, + Protocol parProto + ) { + return parRedirs | boost::adaptors::filtered([=](const Redirection& parRedir) { + return parRedir.internal_port == parPort and + parRedir.protocol == parProto and + parRedir.internal_client == parAddr + ; + }); + } + + auto redirections_not_for_localaddr ( + const RedirectionsList& parRedirs, + const std::string& parAddr, + uint16_t parPort, + Protocol parProto + ) { + return parRedirs | boost::adaptors::filtered([=](const Redirection& parRedir) { + return parRedir.internal_port == parPort and + parRedir.protocol == parProto and + parRedir.internal_client != parAddr + ; + }); + } +} //namespace kuu diff --git a/src/find_redirections.hpp b/src/find_redirections.hpp new file mode 100644 index 0000000..5886b35 --- /dev/null +++ b/src/find_redirections.hpp @@ -0,0 +1,41 @@ +/* Copyright 2016, Michele Santullo + * This file is part of "keepupnpup". + * + * "keepupnpup" 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. + * + * "keepupnpup" 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 "keepupnpup". If not, see . + */ + +#pragma once + +#include "redirection.hpp" +#include +#include +#include + +namespace kuu { + using RedirectionsList = std::vector; + + auto redirections_for_localaddr ( + const RedirectionsList& parRedirs, + const std::string& parAddr, + uint16_t parPort, + Protocol parProto + ); + + auto redirections_not_for_localaddr ( + const RedirectionsList& parRedirs, + const std::string& parAddr, + uint16_t parPort, + Protocol parProto + ); +} //namespace kuu diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt new file mode 100644 index 0000000..d1ce180 --- /dev/null +++ b/test/unit/CMakeLists.txt @@ -0,0 +1,23 @@ +project(test_kuu CXX) + +add_executable(${PROJECT_NAME} + test_upnp.cpp +) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_EXTENSIONS OFF) +set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14) + +add_test( + NAME kuu + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${PROJECT_NAME} +) + +target_link_libraries(${PROJECT_NAME} + PRIVATE keepupnpup_implem + PRIVATE gtest + PRIVATE gtest_main + PRIVATE rapidcheck_gtest +) +target_include_directories(${PROJECT_NAME} + PRIVATE ${CMAKE_SOURCE_DIR}/src +) diff --git a/test/unit/test_upnp.cpp b/test/unit/test_upnp.cpp new file mode 100644 index 0000000..f493512 --- /dev/null +++ b/test/unit/test_upnp.cpp @@ -0,0 +1,101 @@ +/* Copyright 2016, Michele Santullo + * This file is part of "keepupnpup". + * + * "keepupnpup" 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. + * + * "keepupnpup" 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 "keepupnpup". If not, see . + */ + +#include "gtest/gtest.h" +#include "rapidcheck/gtest.h" +#include "redirection.hpp" +#include "find_redirections.hpp" +#include +#include +#include +#include + +namespace { + std::string make_ip(uint8_t parA, uint8_t parB, uint8_t parC, uint8_t parD) { + std::ostringstream oss; + oss << + static_cast(parA) << '.' << + static_cast(parB) << '.' << + static_cast(parC) << '.' << + static_cast(parD) + ; + return oss.str(); + } + + rc::Gen generate_lan_ip() { + using namespace rc; + + auto ip_any = gen::arbitrary(); + auto ip_pos = gen::positive(); + + std::vector> gens; + gens.push_back(gen::apply([](uint8_t c, uint8_t d) { return make_ip(192, 168, c, d); }, ip_any, ip_pos)); + gens.push_back(gen::apply([](uint8_t b, uint8_t c, uint8_t d) { return make_ip(10, b, c, d); }, ip_any, ip_any, ip_pos)); + gens.push_back(gen::apply([](uint8_t b, uint8_t c, uint8_t d) { return make_ip(172, b, c, d); }, gen::inRange(16, 31), ip_any, ip_pos)); + + return gen::join(gen::elementOf(gens)); + } + + rc::Gen generate_external_ip() { + using namespace rc; + auto ip_a = gen::suchThat(gen::inRange(1, 254), [](uint8_t v) { return 192 != v and 10 != v and 172 != v; }); + auto ip_b = gen::arbitrary(); + auto ip_c = gen::arbitrary(); + auto ip_d = gen::positive(); + + return gen::apply(&make_ip, ip_a, ip_b, ip_c, ip_d); + } + + rc::Gen generate_description() { + using namespace rc; + return gen::nonEmpty(gen::resize(80, gen::container(gen::inRange('a', 'z')))); + } +} //unnamed namespace + +namespace rc { + template <> + struct Arbitrary { + static Gen arbitrary() { + using kuu::Redirection; + + return gen::build( + gen::set(&Redirection::internal_client, generate_lan_ip()), + gen::set(&Redirection::remote_host, generate_external_ip()), + gen::set(&Redirection::desc, generate_description()), + gen::set(&Redirection::protocol, gen::element(kuu::Protocol::TCP, kuu::Protocol::UDP)), + gen::set(&Redirection::duration, gen::just(0)), + gen::set(&Redirection::internal_port), + gen::set(&Redirection::external_port), + gen::set(&Redirection::enabled, gen::just(true)) + ); + } + }; +} //namespace rc + +RC_GTEST_PROP(kuu, upnp, (const std::vector& parRedirections)) { + //for (auto& red : parRedirections) { + // std::cout << "internal_client: " << red.internal_client << '\n'; + // std::cout << "remote_host: " << red.remote_host << '\n'; + // std::cout << "desc: \"" << red.desc << "\" (" << red.desc.size() << ")\n"; + // std::cout << "protocol: " << red.protocol << '\n'; + // std::cout << "duration: " << red.duration << '\n'; + // std::cout << "internal_port: " << red.internal_port << '\n'; + // std::cout << "external_port: " << red.external_port << '\n'; + // std::cout << "enabled: " << red.enabled << '\n'; + // std::cout << "---------------------------------------------------------\n"; + //} +}