From 8d46ee85f19e20f56c6a383c8624fb03d2a65626 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 13 Jun 2014 01:00:46 +0200 Subject: [PATCH] Add test for BinaryHeap --- CMakeLists.txt | 11 +- UnitTests/DataStructures/BinaryHeapTest.cpp | 154 ++++++++++++++++++++ UnitTests/datastructure_tests.cpp | 8 + 3 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 UnitTests/DataStructures/BinaryHeapTest.cpp create mode 100644 UnitTests/datastructure_tests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7467dc08b..557a0b95c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,8 +41,9 @@ add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp FingerPrint.c VERBATIM) add_custom_target(FingerPrintConfigure DEPENDS ${CMAKE_SOURCE_DIR}/Util/FingerPrint.cpp) +add_custom_target(tests DEPENDS datastructure-tests) -set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread) +set(BOOST_COMPONENTS date_time filesystem iostreams program_options regex system thread unit_test_framework) configure_file( ${CMAKE_SOURCE_DIR}/Util/GitDescription.cpp.in @@ -65,6 +66,7 @@ file(GLOB CoordinateGlob DataStructures/Coordinate.cpp) file(GLOB AlgorithmGlob Algorithms/*.cpp) file(GLOB HttpGlob Server/Http/*.cpp) file(GLOB LibOSRMGlob Library/*.cpp) +file(GLOB DataStructureTestsGlob UnitTests/DataStructures/*.cpp) set( OSRMSources @@ -84,6 +86,9 @@ add_dependencies(FINGERPRINT FingerPrintConfigure) add_executable(osrm-routed routed.cpp ${ServerGlob}) add_executable(osrm-datastore datastore.cpp) +# Unit tests +add_executable(datastructure-tests EXCLUDE_FROM_ALL UnitTests/datastructure_tests.cpp ${DataStructureTestsGlob}) + # Check the release mode if(NOT CMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_BUILD_TYPE Release) @@ -114,6 +119,8 @@ if(CMAKE_BUILD_TYPE MATCHES Release) endif (HAS_LTO_FLAG) endif() +add_definitions(-DBOOST_TEST_DYN_LINK) + # Configuring compilers if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # using Clang @@ -190,6 +197,8 @@ target_link_libraries(osrm-prepare ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION target_link_libraries(osrm-routed ${Boost_LIBRARIES} ${OPTIONAL_SOCKET_LIBS} OSRM FINGERPRINT GITDESCRIPTION) target_link_libraries(osrm-datastore ${Boost_LIBRARIES} FINGERPRINT GITDESCRIPTION COORDLIB) +target_link_libraries(datastructure-tests ${Boost_LIBRARIES}) + find_package(Threads REQUIRED) target_link_libraries(osrm-extract ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(osrm-datastore ${CMAKE_THREAD_LIBS_INIT}) diff --git a/UnitTests/DataStructures/BinaryHeapTest.cpp b/UnitTests/DataStructures/BinaryHeapTest.cpp new file mode 100644 index 000000000..f4b200a1d --- /dev/null +++ b/UnitTests/DataStructures/BinaryHeapTest.cpp @@ -0,0 +1,154 @@ +#include "../../DataStructures/BinaryHeap.h" +#include "../../typedefs.h" + +#include +#include +#include + +#include + +BOOST_AUTO_TEST_SUITE(binary_heap) + +struct TestData +{ + unsigned value; +}; + +typedef NodeID TestNodeID; +typedef int TestKey; +typedef int TestWeight; +typedef boost::mpl::list, + MapStorage, + UnorderedMapStorage> storage_types; + + +template +struct RandomDataFixture +{ + RandomDataFixture() + { + for (unsigned i = 0; i < NUM_ELEM; i++) + { + data.push_back(TestData {i*3}); + weights.push_back((i+1)*100); + ids.push_back(i); + order.push_back(i); + } + + // Choosen by a fair W20 dice roll + std::mt19937 g(15); + + std::shuffle(order.begin(), order.end(), g); + } + + std::vector data; + std::vector weights; + std::vector ids; + std::vector order; +}; + +constexpr unsigned NUM_NODES = 100; + +BOOST_FIXTURE_TEST_CASE_TEMPLATE(insert_test, T, storage_types, RandomDataFixture) +{ + BinaryHeap heap(NUM_NODES); + + TestWeight min_weight = std::numeric_limits::max(); + TestNodeID min_id; + + for (unsigned idx : order) + { + BOOST_CHECK(!heap.WasInserted(ids[idx])); + + heap.Insert(ids[idx], weights[idx], data[idx]); + + BOOST_CHECK(heap.WasInserted(ids[idx])); + + if (weights[idx] < min_weight) + { + min_weight = weights[idx]; + min_id = ids[idx]; + } + BOOST_CHECK_EQUAL(min_id, heap.Min()); + } + + for (auto id : ids) + { + const auto& d = heap.GetData(id); + BOOST_CHECK_EQUAL(d.value, data[id].value); + + const auto& w = heap.GetKey(id); + BOOST_CHECK_EQUAL(w, weights[id]); + } +} + +BOOST_FIXTURE_TEST_CASE_TEMPLATE(delete_min_test, T, storage_types, RandomDataFixture) +{ + BinaryHeap heap(NUM_NODES); + + for (unsigned idx : order) + { + heap.Insert(ids[idx], weights[idx], data[idx]); + } + + for (auto id : ids) + { + BOOST_CHECK(!heap.WasRemoved(id)); + + BOOST_CHECK_EQUAL(heap.Min(), id); + BOOST_CHECK_EQUAL(id, heap.DeleteMin()); + if (id+1 < NUM_NODES) + BOOST_CHECK_EQUAL(heap.Min(), id+1); + + BOOST_CHECK(heap.WasRemoved(id)); + } +} + +BOOST_FIXTURE_TEST_CASE_TEMPLATE(delete_all_test, T, storage_types, RandomDataFixture) +{ + BinaryHeap heap(NUM_NODES); + + for (unsigned idx : order) + { + heap.Insert(ids[idx], weights[idx], data[idx]); + } + + heap.DeleteAll(); + + BOOST_CHECK(heap.Empty()); +} + +BOOST_FIXTURE_TEST_CASE_TEMPLATE(decrease_key_test, T, storage_types, RandomDataFixture<10>) +{ + BinaryHeap heap(10); + + for (unsigned idx : order) + { + heap.Insert(ids[idx], weights[idx], data[idx]); + } + + std::vector rids(ids); + std::reverse(rids.begin(), rids.end()); + + for (auto id : rids) + { + TestNodeID min_id = heap.Min(); + TestWeight min_weight = heap.GetKey(min_id); + + // decrease weight until we reach min weight + while (weights[id] > min_weight) + { + heap.DecreaseKey(id, weights[id]); + BOOST_CHECK_EQUAL(heap.Min(), min_id); + weights[id]--; + } + + // make weight smaller than min + weights[id] -= 2; + heap.DecreaseKey(id, weights[id]); + BOOST_CHECK_EQUAL(heap.Min(), id); + } +} + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/UnitTests/datastructure_tests.cpp b/UnitTests/datastructure_tests.cpp new file mode 100644 index 000000000..2f7f6593b --- /dev/null +++ b/UnitTests/datastructure_tests.cpp @@ -0,0 +1,8 @@ +#define BOOST_TEST_MODULE datastructure tests + +#include + +/* + * This file will contain an automatically generated main function. + */ +