Move files in unit_tests around
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../data_structures/binary_heap.hpp"
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
#include <boost/mpl/list.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(binary_heap)
|
||||
|
||||
struct TestData
|
||||
{
|
||||
unsigned value;
|
||||
};
|
||||
|
||||
typedef NodeID TestNodeID;
|
||||
typedef int TestKey;
|
||||
typedef int TestWeight;
|
||||
typedef boost::mpl::list<ArrayStorage<TestNodeID, TestKey>,
|
||||
MapStorage<TestNodeID, TestKey>,
|
||||
UnorderedMapStorage<TestNodeID, TestKey>> storage_types;
|
||||
|
||||
template <unsigned NUM_ELEM> 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<TestData> data;
|
||||
std::vector<TestWeight> weights;
|
||||
std::vector<TestNodeID> ids;
|
||||
std::vector<unsigned> order;
|
||||
};
|
||||
|
||||
constexpr unsigned NUM_NODES = 100;
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE_TEMPLATE(insert_test, T, storage_types, RandomDataFixture<NUM_NODES>)
|
||||
{
|
||||
BinaryHeap<TestNodeID, TestKey, TestWeight, TestData, T> heap(NUM_NODES);
|
||||
|
||||
TestWeight min_weight = std::numeric_limits<TestWeight>::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<NUM_NODES>)
|
||||
{
|
||||
BinaryHeap<TestNodeID, TestKey, TestWeight, TestData, T> 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<NUM_NODES>)
|
||||
{
|
||||
BinaryHeap<TestNodeID, TestKey, TestWeight, TestData, T> 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<TestNodeID, TestKey, TestWeight, TestData, T> heap(10);
|
||||
|
||||
for (unsigned idx : order)
|
||||
{
|
||||
heap.Insert(ids[idx], weights[idx], data[idx]);
|
||||
}
|
||||
|
||||
std::vector<TestNodeID> 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);
|
||||
BOOST_CHECK_EQUAL(heap.MinKey(), min_weight);
|
||||
weights[id]--;
|
||||
}
|
||||
|
||||
// make weight smaller than min
|
||||
weights[id] -= 2;
|
||||
heap.DecreaseKey(id, weights[id]);
|
||||
BOOST_CHECK_EQUAL(heap.Min(), id);
|
||||
BOOST_CHECK_EQUAL(heap.MinKey(), weights[id]);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "../../algorithms/coordinate_calculation.hpp"
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// Regression test for bug captured in #1347
|
||||
BOOST_AUTO_TEST_CASE(regression_test_1347)
|
||||
{
|
||||
FixedPointCoordinate u(10 * COORDINATE_PRECISION, -100 * COORDINATE_PRECISION);
|
||||
FixedPointCoordinate v(10.001 * COORDINATE_PRECISION, -100.002 * COORDINATE_PRECISION);
|
||||
FixedPointCoordinate q(10.002 * COORDINATE_PRECISION, -100.001 * COORDINATE_PRECISION);
|
||||
|
||||
float d1 = coordinate_calculation::perpendicular_distance(u, v, q);
|
||||
|
||||
float ratio;
|
||||
FixedPointCoordinate nearest_location;
|
||||
float d2 = coordinate_calculation::perpendicular_distance(u, v, q, nearest_location, ratio);
|
||||
|
||||
BOOST_CHECK_LE(std::abs(d1 - d2), 0.01f);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../extractor/extraction_helper_functions.hpp"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(durations_are_valid)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(all_necessary_test)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(durationIsValid("00:01"), true);
|
||||
BOOST_CHECK_EQUAL(durationIsValid("00:01:01"), true);
|
||||
BOOST_CHECK_EQUAL(durationIsValid("PT15M"), true);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(common_durations_get_translated)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(parseDuration("00:01"), 60);
|
||||
BOOST_CHECK_EQUAL(parseDuration("00:01:01"), 61);
|
||||
BOOST_CHECK_EQUAL(parseDuration("01:01"), 3660);
|
||||
|
||||
// check all combinations of iso duration tokens
|
||||
BOOST_CHECK_EQUAL(parseDuration("PT1M1S"), 61);
|
||||
BOOST_CHECK_EQUAL(parseDuration("PT1H1S"), 3601);
|
||||
BOOST_CHECK_EQUAL(parseDuration("PT15M"), 900);
|
||||
BOOST_CHECK_EQUAL(parseDuration("PT15S"), 15);
|
||||
BOOST_CHECK_EQUAL(parseDuration("PT15H"), 54000);
|
||||
BOOST_CHECK_EQUAL(parseDuration("PT1H15M"), 4500);
|
||||
BOOST_CHECK_EQUAL(parseDuration("PT1H15M1S"), 4501);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(iso_8601_durations_case_insensitive)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(parseDuration("PT15m"), 900);
|
||||
BOOST_CHECK_EQUAL(parseDuration("PT1h15m"), 4500);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../data_structures/dynamic_graph.hpp"
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(dynamic_graph)
|
||||
|
||||
struct TestData
|
||||
{
|
||||
EdgeID id;
|
||||
};
|
||||
|
||||
typedef DynamicGraph<TestData> TestDynamicGraph;
|
||||
typedef TestDynamicGraph::InputEdge TestInputEdge;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(find_test)
|
||||
{
|
||||
/*
|
||||
* (0) -1-> (1)
|
||||
* ^ ^
|
||||
* 2 5
|
||||
* | |
|
||||
* (3) -3-> (4)
|
||||
* <-4-
|
||||
*/
|
||||
std::vector<TestInputEdge> input_edges = {
|
||||
TestInputEdge{0, 1, TestData{1}},
|
||||
TestInputEdge{3, 0, TestData{2}},
|
||||
TestInputEdge{3, 0, TestData{5}},
|
||||
TestInputEdge{3, 4, TestData{3}},
|
||||
TestInputEdge{4, 3, TestData{4}}
|
||||
};
|
||||
TestDynamicGraph simple_graph(5, input_edges);
|
||||
|
||||
auto eit = simple_graph.FindEdge(0, 1);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1);
|
||||
|
||||
eit = simple_graph.FindEdge(1, 0);
|
||||
BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID);
|
||||
|
||||
eit = simple_graph.FindEdgeInEitherDirection(1, 0);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1);
|
||||
|
||||
bool reverse = false;
|
||||
eit = simple_graph.FindEdgeIndicateIfReverse(1, 0, reverse);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1);
|
||||
BOOST_CHECK(reverse);
|
||||
|
||||
eit = simple_graph.FindEdge(3, 1);
|
||||
BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID);
|
||||
eit = simple_graph.FindEdge(0, 4);
|
||||
BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID);
|
||||
|
||||
eit = simple_graph.FindEdge(3, 4);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3);
|
||||
eit = simple_graph.FindEdgeInEitherDirection(3, 4);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3);
|
||||
|
||||
eit = simple_graph.FindEdge(3, 0);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../data_structures/range_table.hpp"
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
|
||||
#include <numeric>
|
||||
#include <stxxl/vector>
|
||||
|
||||
constexpr unsigned BLOCK_SIZE = 16;
|
||||
typedef RangeTable<BLOCK_SIZE, false> TestRangeTable;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(range_table)
|
||||
|
||||
void ConstructionTest(stxxl::vector<unsigned> lengths, std::vector<unsigned> offsets)
|
||||
{
|
||||
BOOST_ASSERT(lengths.size() == offsets.size() - 1);
|
||||
|
||||
TestRangeTable table(lengths);
|
||||
|
||||
for (unsigned i = 0; i < lengths.size(); i++)
|
||||
{
|
||||
auto range = table.GetRange(i);
|
||||
BOOST_CHECK_EQUAL(range.front(), offsets[i]);
|
||||
BOOST_CHECK_EQUAL(range.back() + 1, offsets[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeLengthsOffsets(stxxl::vector<unsigned> &lengths,
|
||||
std::vector<unsigned> &offsets,
|
||||
unsigned num)
|
||||
{
|
||||
lengths.resize(num);
|
||||
offsets.resize(num + 1);
|
||||
std::iota(lengths.begin(), lengths.end(), 1);
|
||||
offsets[0] = 0;
|
||||
std::partial_sum(lengths.begin(), lengths.end(), offsets.begin() + 1);
|
||||
|
||||
std::stringstream l_ss;
|
||||
l_ss << "Lengths: ";
|
||||
for (auto l : lengths)
|
||||
l_ss << l << ", ";
|
||||
BOOST_TEST_MESSAGE(l_ss.str());
|
||||
std::stringstream o_ss;
|
||||
o_ss << "Offsets: ";
|
||||
for (auto o : offsets)
|
||||
o_ss << o << ", ";
|
||||
BOOST_TEST_MESSAGE(o_ss.str());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(serialization_test)
|
||||
{
|
||||
stxxl::vector<unsigned> lengths;
|
||||
std::vector<unsigned> offsets;
|
||||
ComputeLengthsOffsets(lengths, offsets, (BLOCK_SIZE + 1) * 10);
|
||||
|
||||
TestRangeTable in_table(lengths);
|
||||
TestRangeTable out_table;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << in_table;
|
||||
ss >> out_table;
|
||||
|
||||
for (unsigned i = 0; i < lengths.size(); i++)
|
||||
{
|
||||
auto range = out_table.GetRange(i);
|
||||
BOOST_CHECK_EQUAL(range.front(), offsets[i]);
|
||||
BOOST_CHECK_EQUAL(range.back() + 1, offsets[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(construction_test)
|
||||
{
|
||||
// only offset empty block
|
||||
stxxl::vector<unsigned> empty_lengths;
|
||||
empty_lengths.push_back(1);
|
||||
ConstructionTest(empty_lengths, {0, 1});
|
||||
// first block almost full => sentinel is last element of block
|
||||
// [0] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, (16)}
|
||||
stxxl::vector<unsigned> almost_full_lengths;
|
||||
std::vector<unsigned> almost_full_offsets;
|
||||
ComputeLengthsOffsets(almost_full_lengths, almost_full_offsets, BLOCK_SIZE);
|
||||
ConstructionTest(almost_full_lengths, almost_full_offsets);
|
||||
|
||||
// first block full => sentinel is offset of new block, next block empty
|
||||
// [0] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
|
||||
// [(153)] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
stxxl::vector<unsigned> full_lengths;
|
||||
std::vector<unsigned> full_offsets;
|
||||
ComputeLengthsOffsets(full_lengths, full_offsets, BLOCK_SIZE + 1);
|
||||
ConstructionTest(full_lengths, full_offsets);
|
||||
|
||||
// first block full and offset of next block not sentinel, but the first differential value
|
||||
// [0] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
|
||||
// [153] {(17), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
stxxl::vector<unsigned> over_full_lengths;
|
||||
std::vector<unsigned> over_full_offsets;
|
||||
ComputeLengthsOffsets(over_full_lengths, over_full_offsets, BLOCK_SIZE + 2);
|
||||
ConstructionTest(over_full_lengths, over_full_offsets);
|
||||
|
||||
// test multiple blocks
|
||||
stxxl::vector<unsigned> multiple_lengths;
|
||||
std::vector<unsigned> multiple_offsets;
|
||||
ComputeLengthsOffsets(multiple_lengths, multiple_offsets, (BLOCK_SIZE + 1) * 10);
|
||||
ConstructionTest(multiple_lengths, multiple_offsets);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../data_structures/static_graph.hpp"
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(static_graph)
|
||||
|
||||
struct TestData
|
||||
{
|
||||
EdgeID id;
|
||||
};
|
||||
|
||||
typedef StaticGraph<TestData> TestStaticGraph;
|
||||
typedef TestStaticGraph::NodeArrayEntry TestNodeArrayEntry;
|
||||
typedef TestStaticGraph::EdgeArrayEntry TestEdgeArrayEntry;
|
||||
typedef TestStaticGraph::InputEdge TestInputEdge;
|
||||
|
||||
constexpr unsigned TEST_NUM_NODES = 100;
|
||||
constexpr unsigned TEST_NUM_EDGES = 500;
|
||||
// Chosen by a fair W20 dice roll (this value is completely arbitrary)
|
||||
constexpr unsigned RANDOM_SEED = 15;
|
||||
|
||||
template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomArrayEntryFixture
|
||||
{
|
||||
RandomArrayEntryFixture()
|
||||
{
|
||||
std::mt19937 g(RANDOM_SEED);
|
||||
|
||||
std::uniform_int_distribution<> edge_udist(0, NUM_EDGES - 1);
|
||||
std::vector<unsigned> offsets;
|
||||
for (unsigned i = 0; i < NUM_NODES; i++)
|
||||
{
|
||||
offsets.push_back(edge_udist(g));
|
||||
}
|
||||
std::sort(offsets.begin(), offsets.end());
|
||||
// add sentinel
|
||||
offsets.push_back(offsets.back());
|
||||
|
||||
// extract interval lengths
|
||||
for (unsigned i = 0; i < offsets.size() - 1; i++)
|
||||
{
|
||||
lengths.push_back(offsets[i + 1] - offsets[i]);
|
||||
}
|
||||
lengths.push_back(NUM_EDGES - offsets[NUM_NODES - 1]);
|
||||
|
||||
for (auto offset : offsets)
|
||||
{
|
||||
nodes.emplace_back(TestNodeArrayEntry{offset});
|
||||
}
|
||||
|
||||
std::uniform_int_distribution<> lengths_udist(0, 100000);
|
||||
std::uniform_int_distribution<> node_udist(0, NUM_NODES - 1);
|
||||
for (unsigned i = 0; i < NUM_EDGES; i++)
|
||||
{
|
||||
edges.emplace_back(
|
||||
TestEdgeArrayEntry{static_cast<unsigned>(node_udist(g)), TestData{i}});
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < NUM_NODES; i++)
|
||||
order.push_back(i);
|
||||
std::shuffle(order.begin(), order.end(), g);
|
||||
}
|
||||
|
||||
typename ShM<TestNodeArrayEntry, false>::vector nodes;
|
||||
typename ShM<TestEdgeArrayEntry, false>::vector edges;
|
||||
std::vector<unsigned> lengths;
|
||||
std::vector<unsigned> order;
|
||||
};
|
||||
|
||||
typedef RandomArrayEntryFixture<TEST_NUM_NODES, TEST_NUM_EDGES> TestRandomArrayEntryFixture;
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(array_test, TestRandomArrayEntryFixture)
|
||||
{
|
||||
auto nodes_copy = nodes;
|
||||
|
||||
TestStaticGraph graph(nodes, edges);
|
||||
|
||||
BOOST_CHECK_EQUAL(graph.GetNumberOfEdges(), TEST_NUM_EDGES);
|
||||
BOOST_CHECK_EQUAL(graph.GetNumberOfNodes(), TEST_NUM_NODES);
|
||||
|
||||
for (auto idx : order)
|
||||
{
|
||||
BOOST_CHECK_EQUAL(graph.BeginEdges((NodeID)idx), nodes_copy[idx].first_edge);
|
||||
BOOST_CHECK_EQUAL(graph.EndEdges((NodeID)idx), nodes_copy[idx + 1].first_edge);
|
||||
BOOST_CHECK_EQUAL(graph.GetOutDegree((NodeID)idx), lengths[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(find_test)
|
||||
{
|
||||
/*
|
||||
* (0) -1-> (1)
|
||||
* ^ ^
|
||||
* 2 5
|
||||
* | |
|
||||
* (3) -3-> (4)
|
||||
* <-4-
|
||||
*/
|
||||
std::vector<TestInputEdge> input_edges = {
|
||||
TestInputEdge{0, 1, TestData{1}},
|
||||
TestInputEdge{3, 0, TestData{2}},
|
||||
TestInputEdge{3, 0, TestData{5}},
|
||||
TestInputEdge{3, 4, TestData{3}},
|
||||
TestInputEdge{4, 3, TestData{4}}
|
||||
};
|
||||
TestStaticGraph simple_graph(5, input_edges);
|
||||
|
||||
auto eit = simple_graph.FindEdge(0, 1);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1);
|
||||
|
||||
eit = simple_graph.FindEdge(1, 0);
|
||||
BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID);
|
||||
|
||||
eit = simple_graph.FindEdgeInEitherDirection(1, 0);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1);
|
||||
|
||||
bool reverse = false;
|
||||
eit = simple_graph.FindEdgeIndicateIfReverse(1, 0, reverse);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1);
|
||||
BOOST_CHECK(reverse);
|
||||
|
||||
eit = simple_graph.FindEdge(3, 1);
|
||||
BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID);
|
||||
eit = simple_graph.FindEdge(0, 4);
|
||||
BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID);
|
||||
|
||||
eit = simple_graph.FindEdge(3, 4);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3);
|
||||
eit = simple_graph.FindEdgeInEitherDirection(3, 4);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3);
|
||||
|
||||
eit = simple_graph.FindEdge(3, 0);
|
||||
BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2015, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../algorithms/coordinate_calculation.hpp"
|
||||
#include "../../algorithms/geospatial_query.hpp"
|
||||
#include "../../data_structures/static_rtree.hpp"
|
||||
#include "../../data_structures/query_node.hpp"
|
||||
#include "../../data_structures/edge_based_node.hpp"
|
||||
#include "../../util/floating_point.hpp"
|
||||
#include "../../typedefs.h"
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
|
||||
#include <osrm/coordinate.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(static_rtree)
|
||||
|
||||
constexpr uint32_t TEST_BRANCHING_FACTOR = 8;
|
||||
constexpr uint32_t TEST_LEAF_NODE_SIZE = 64;
|
||||
|
||||
typedef EdgeBasedNode TestData;
|
||||
using TestStaticRTree = StaticRTree<TestData,
|
||||
std::vector<FixedPointCoordinate>,
|
||||
false,
|
||||
TEST_BRANCHING_FACTOR,
|
||||
TEST_LEAF_NODE_SIZE>;
|
||||
using MiniStaticRTree = StaticRTree<TestData, std::vector<FixedPointCoordinate>, false, 2, 3>;
|
||||
|
||||
// Choosen by a fair W20 dice roll (this value is completely arbitrary)
|
||||
constexpr unsigned RANDOM_SEED = 42;
|
||||
static const int32_t WORLD_MIN_LAT = -90 * COORDINATE_PRECISION;
|
||||
static const int32_t WORLD_MAX_LAT = 90 * COORDINATE_PRECISION;
|
||||
static const int32_t WORLD_MIN_LON = -180 * COORDINATE_PRECISION;
|
||||
static const int32_t WORLD_MAX_LON = 180 * COORDINATE_PRECISION;
|
||||
|
||||
template <typename DataT> class LinearSearchNN
|
||||
{
|
||||
public:
|
||||
LinearSearchNN(const std::shared_ptr<std::vector<FixedPointCoordinate>> &coords,
|
||||
const std::vector<DataT> &edges)
|
||||
: coords(coords), edges(edges)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<DataT> Nearest(const FixedPointCoordinate &input_coordinate,
|
||||
const unsigned num_results)
|
||||
{
|
||||
std::vector<DataT> local_edges(edges);
|
||||
|
||||
std::nth_element(
|
||||
local_edges.begin(), local_edges.begin() + num_results, local_edges.end(),
|
||||
[this, &input_coordinate](const DataT &lhs, const DataT &rhs)
|
||||
{
|
||||
float current_ratio = 0.;
|
||||
FixedPointCoordinate nearest;
|
||||
const float lhs_dist = coordinate_calculation::perpendicular_distance(
|
||||
coords->at(lhs.u), coords->at(lhs.v), input_coordinate, nearest, current_ratio);
|
||||
const float rhs_dist = coordinate_calculation::perpendicular_distance(
|
||||
coords->at(rhs.u), coords->at(rhs.v), input_coordinate, nearest, current_ratio);
|
||||
return lhs_dist < rhs_dist;
|
||||
});
|
||||
local_edges.resize(num_results);
|
||||
|
||||
return local_edges;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::shared_ptr<std::vector<FixedPointCoordinate>> &coords;
|
||||
const std::vector<TestData> &edges;
|
||||
};
|
||||
|
||||
template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomGraphFixture
|
||||
{
|
||||
struct TupleHash
|
||||
{
|
||||
typedef std::pair<unsigned, unsigned> argument_type;
|
||||
typedef std::size_t result_type;
|
||||
|
||||
result_type operator()(const argument_type &t) const
|
||||
{
|
||||
std::size_t val{0};
|
||||
boost::hash_combine(val, t.first);
|
||||
boost::hash_combine(val, t.second);
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
RandomGraphFixture() : coords(std::make_shared<std::vector<FixedPointCoordinate>>())
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Constructing " << NUM_NODES << " nodes and " << NUM_EDGES << " edges.");
|
||||
|
||||
std::mt19937 g(RANDOM_SEED);
|
||||
|
||||
std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
|
||||
std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
|
||||
|
||||
for (unsigned i = 0; i < NUM_NODES; i++)
|
||||
{
|
||||
int lat = lat_udist(g);
|
||||
int lon = lon_udist(g);
|
||||
nodes.emplace_back(QueryNode(lat, lon, OSMNodeID(i)));
|
||||
coords->emplace_back(FixedPointCoordinate(lat, lon));
|
||||
}
|
||||
|
||||
std::uniform_int_distribution<> edge_udist(0, nodes.size() - 1);
|
||||
|
||||
std::unordered_set<std::pair<unsigned, unsigned>, TupleHash> used_edges;
|
||||
|
||||
while (edges.size() < NUM_EDGES)
|
||||
{
|
||||
TestData data;
|
||||
data.u = edge_udist(g);
|
||||
data.v = edge_udist(g);
|
||||
if (used_edges.find(std::pair<unsigned, unsigned>(
|
||||
std::min(data.u, data.v), std::max(data.u, data.v))) == used_edges.end())
|
||||
{
|
||||
data.component.id = 0;
|
||||
edges.emplace_back(data);
|
||||
used_edges.emplace(std::min(data.u, data.v), std::max(data.u, data.v));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<QueryNode> nodes;
|
||||
std::shared_ptr<std::vector<FixedPointCoordinate>> coords;
|
||||
std::vector<TestData> edges;
|
||||
};
|
||||
|
||||
struct GraphFixture
|
||||
{
|
||||
GraphFixture(const std::vector<std::pair<float, float>> &input_coords,
|
||||
const std::vector<std::pair<unsigned, unsigned>> &input_edges)
|
||||
: coords(std::make_shared<std::vector<FixedPointCoordinate>>())
|
||||
{
|
||||
|
||||
for (unsigned i = 0; i < input_coords.size(); i++)
|
||||
{
|
||||
FixedPointCoordinate c(input_coords[i].first * COORDINATE_PRECISION,
|
||||
input_coords[i].second * COORDINATE_PRECISION);
|
||||
coords->emplace_back(c);
|
||||
nodes.emplace_back(QueryNode(c.lat, c.lon, OSMNodeID(i)));
|
||||
}
|
||||
|
||||
for (const auto &pair : input_edges)
|
||||
{
|
||||
TestData d;
|
||||
d.u = pair.first;
|
||||
d.v = pair.second;
|
||||
// We set the forward nodes to the target node-based-node IDs, just
|
||||
// so we have something to test against. Because this isn't a real
|
||||
// graph, the actual values aren't important, we just need something
|
||||
// to examine during tests.
|
||||
d.forward_edge_based_node_id = pair.second;
|
||||
d.reverse_edge_based_node_id = pair.first;
|
||||
edges.emplace_back(d);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<QueryNode> nodes;
|
||||
std::shared_ptr<std::vector<FixedPointCoordinate>> coords;
|
||||
std::vector<TestData> edges;
|
||||
};
|
||||
|
||||
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 3, TEST_LEAF_NODE_SIZE / 2>
|
||||
TestRandomGraphFixture_LeafHalfFull;
|
||||
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 5, TEST_LEAF_NODE_SIZE>
|
||||
TestRandomGraphFixture_LeafFull;
|
||||
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * 10, TEST_LEAF_NODE_SIZE * 2>
|
||||
TestRandomGraphFixture_TwoLeaves;
|
||||
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 3,
|
||||
TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR>
|
||||
TestRandomGraphFixture_Branch;
|
||||
typedef RandomGraphFixture<TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 3,
|
||||
TEST_LEAF_NODE_SIZE * TEST_BRANCHING_FACTOR * 2>
|
||||
TestRandomGraphFixture_MultipleLevels;
|
||||
|
||||
template <typename RTreeT>
|
||||
void simple_verify_rtree(RTreeT &rtree,
|
||||
const std::shared_ptr<std::vector<FixedPointCoordinate>> &coords,
|
||||
const std::vector<TestData> &edges)
|
||||
{
|
||||
BOOST_TEST_MESSAGE("Verify end points");
|
||||
for (const auto &e : edges)
|
||||
{
|
||||
const FixedPointCoordinate &pu = coords->at(e.u);
|
||||
const FixedPointCoordinate &pv = coords->at(e.v);
|
||||
auto result_u = rtree.Nearest(pu, 1);
|
||||
auto result_v = rtree.Nearest(pv, 1);
|
||||
BOOST_CHECK(result_u.size() == 1 && result_v.size() == 1);
|
||||
BOOST_CHECK(result_u.front().u == e.u || result_u.front().v == e.u);
|
||||
BOOST_CHECK(result_v.front().u == e.v || result_v.front().v == e.v);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename RTreeT>
|
||||
void sampling_verify_rtree(RTreeT &rtree, LinearSearchNN<TestData> &lsnn, const std::vector<FixedPointCoordinate>& coords, unsigned num_samples)
|
||||
{
|
||||
std::mt19937 g(RANDOM_SEED);
|
||||
std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT);
|
||||
std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON);
|
||||
std::vector<FixedPointCoordinate> queries;
|
||||
for (unsigned i = 0; i < num_samples; i++)
|
||||
{
|
||||
queries.emplace_back(FixedPointCoordinate(lat_udist(g), lon_udist(g)));
|
||||
}
|
||||
|
||||
BOOST_TEST_MESSAGE("Sampling queries");
|
||||
for (const auto &q : queries)
|
||||
{
|
||||
auto result_rtree = rtree.Nearest(q, 1);
|
||||
auto result_lsnn = lsnn.Nearest(q, 1);
|
||||
BOOST_CHECK(result_rtree.size() == 1);
|
||||
BOOST_CHECK(result_lsnn.size() == 1);
|
||||
auto rtree_u = result_rtree.back().u;
|
||||
auto rtree_v = result_rtree.back().v;
|
||||
auto lsnn_u = result_lsnn.back().u;
|
||||
auto lsnn_v = result_lsnn.back().v;
|
||||
|
||||
float current_ratio = 0.;
|
||||
FixedPointCoordinate nearest;
|
||||
const float rtree_dist = coordinate_calculation::perpendicular_distance(
|
||||
coords[rtree_u], coords[rtree_v], q, nearest, current_ratio);
|
||||
const float lsnn_dist = coordinate_calculation::perpendicular_distance(
|
||||
coords[lsnn_u], coords[lsnn_v], q, nearest, current_ratio);
|
||||
BOOST_CHECK_LE(std::abs(rtree_dist - lsnn_dist), std::numeric_limits<float>::epsilon());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FixtureT, typename RTreeT = TestStaticRTree>
|
||||
void build_rtree(const std::string &prefix,
|
||||
FixtureT *fixture,
|
||||
std::string &leaves_path,
|
||||
std::string &nodes_path)
|
||||
{
|
||||
nodes_path = prefix + ".ramIndex";
|
||||
leaves_path = prefix + ".fileIndex";
|
||||
const std::string coords_path = prefix + ".nodes";
|
||||
|
||||
boost::filesystem::ofstream node_stream(coords_path, std::ios::binary);
|
||||
const auto num_nodes = static_cast<unsigned>(fixture->nodes.size());
|
||||
node_stream.write((char *)&num_nodes, sizeof(unsigned));
|
||||
node_stream.write((char *)&(fixture->nodes[0]), num_nodes * sizeof(QueryNode));
|
||||
node_stream.close();
|
||||
|
||||
RTreeT r(fixture->edges, nodes_path, leaves_path, fixture->nodes);
|
||||
}
|
||||
|
||||
template <typename FixtureT, typename RTreeT = TestStaticRTree>
|
||||
void construction_test(const std::string &prefix, FixtureT *fixture)
|
||||
{
|
||||
std::string leaves_path;
|
||||
std::string nodes_path;
|
||||
build_rtree<FixtureT, RTreeT>(prefix, fixture, leaves_path, nodes_path);
|
||||
RTreeT rtree(nodes_path, leaves_path, fixture->coords);
|
||||
LinearSearchNN<TestData> lsnn(fixture->coords, fixture->edges);
|
||||
|
||||
simple_verify_rtree(rtree, fixture->coords, fixture->edges);
|
||||
sampling_verify_rtree(rtree, lsnn, *fixture->coords, 100);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(construct_half_leaf_test, TestRandomGraphFixture_LeafHalfFull)
|
||||
{
|
||||
construction_test("test_1", this);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(construct_full_leaf_test, TestRandomGraphFixture_LeafFull)
|
||||
{
|
||||
construction_test("test_2", this);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(construct_two_leaves_test, TestRandomGraphFixture_TwoLeaves)
|
||||
{
|
||||
construction_test("test_3", this);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(construct_branch_test, TestRandomGraphFixture_Branch)
|
||||
{
|
||||
construction_test("test_4", this);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(construct_multiple_levels_test, TestRandomGraphFixture_MultipleLevels)
|
||||
{
|
||||
construction_test("test_5", this);
|
||||
}
|
||||
|
||||
// Bug: If you querry a point that lies between two BBs that have a gap,
|
||||
// one BB will be pruned, even if it could contain a nearer match.
|
||||
BOOST_AUTO_TEST_CASE(regression_test)
|
||||
{
|
||||
using Coord = std::pair<float, float>;
|
||||
using Edge = std::pair<unsigned, unsigned>;
|
||||
GraphFixture fixture(
|
||||
{
|
||||
Coord(40.0, 0.0), Coord(35.0, 5.0),
|
||||
|
||||
Coord(5.0, 5.0), Coord(0.0, 10.0),
|
||||
|
||||
Coord(20.0, 10.0), Coord(20.0, 5.0),
|
||||
|
||||
Coord(40.0, 100.0), Coord(35.0, 105.0),
|
||||
|
||||
Coord(5.0, 105.0), Coord(0.0, 110.0),
|
||||
},
|
||||
{Edge(0, 1), Edge(2, 3), Edge(4, 5), Edge(6, 7), Edge(8, 9)});
|
||||
|
||||
std::string leaves_path;
|
||||
std::string nodes_path;
|
||||
build_rtree<GraphFixture, MiniStaticRTree>("test_regression", &fixture, leaves_path,
|
||||
nodes_path);
|
||||
MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords);
|
||||
LinearSearchNN<TestData> lsnn(fixture.coords, fixture.edges);
|
||||
|
||||
// query a node just right of the center of the gap
|
||||
FixedPointCoordinate input(20.0 * COORDINATE_PRECISION, 55.1 * COORDINATE_PRECISION);
|
||||
auto result_rtree = rtree.Nearest(input, 1);
|
||||
auto result_ls = lsnn.Nearest(input, 1);
|
||||
|
||||
BOOST_CHECK(result_rtree.size() == 1);
|
||||
BOOST_CHECK(result_ls.size() == 1);
|
||||
|
||||
BOOST_CHECK_EQUAL(result_ls.front().u, result_rtree.front().u);
|
||||
BOOST_CHECK_EQUAL(result_ls.front().v, result_rtree.front().v);
|
||||
}
|
||||
|
||||
void TestRectangle(double width, double height, double center_lat, double center_lon)
|
||||
{
|
||||
FixedPointCoordinate center(center_lat * COORDINATE_PRECISION,
|
||||
center_lon * COORDINATE_PRECISION);
|
||||
|
||||
TestStaticRTree::Rectangle rect;
|
||||
rect.min_lat = center.lat - height / 2.0 * COORDINATE_PRECISION;
|
||||
rect.max_lat = center.lat + height / 2.0 * COORDINATE_PRECISION;
|
||||
rect.min_lon = center.lon - width / 2.0 * COORDINATE_PRECISION;
|
||||
rect.max_lon = center.lon + width / 2.0 * COORDINATE_PRECISION;
|
||||
|
||||
unsigned offset = 5 * COORDINATE_PRECISION;
|
||||
FixedPointCoordinate north(rect.max_lat + offset, center.lon);
|
||||
FixedPointCoordinate south(rect.min_lat - offset, center.lon);
|
||||
FixedPointCoordinate west(center.lat, rect.min_lon - offset);
|
||||
FixedPointCoordinate east(center.lat, rect.max_lon + offset);
|
||||
FixedPointCoordinate north_east(rect.max_lat + offset, rect.max_lon + offset);
|
||||
FixedPointCoordinate north_west(rect.max_lat + offset, rect.min_lon - offset);
|
||||
FixedPointCoordinate south_east(rect.min_lat - offset, rect.max_lon + offset);
|
||||
FixedPointCoordinate south_west(rect.min_lat - offset, rect.min_lon - offset);
|
||||
|
||||
/* Distance to line segments of rectangle */
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(north),
|
||||
coordinate_calculation::great_circle_distance(
|
||||
north, FixedPointCoordinate(rect.max_lat, north.lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(south),
|
||||
coordinate_calculation::great_circle_distance(
|
||||
south, FixedPointCoordinate(rect.min_lat, south.lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(west),
|
||||
coordinate_calculation::great_circle_distance(
|
||||
west, FixedPointCoordinate(west.lat, rect.min_lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(east),
|
||||
coordinate_calculation::great_circle_distance(
|
||||
east, FixedPointCoordinate(east.lat, rect.max_lon)));
|
||||
|
||||
/* Distance to corner points */
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(north_east),
|
||||
coordinate_calculation::great_circle_distance(
|
||||
north_east, FixedPointCoordinate(rect.max_lat, rect.max_lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(north_west),
|
||||
coordinate_calculation::great_circle_distance(
|
||||
north_west, FixedPointCoordinate(rect.max_lat, rect.min_lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(south_east),
|
||||
coordinate_calculation::great_circle_distance(
|
||||
south_east, FixedPointCoordinate(rect.min_lat, rect.max_lon)));
|
||||
BOOST_CHECK_EQUAL(rect.GetMinDist(south_west),
|
||||
coordinate_calculation::great_circle_distance(
|
||||
south_west, FixedPointCoordinate(rect.min_lat, rect.min_lon)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rectangle_test)
|
||||
{
|
||||
TestRectangle(10, 10, 5, 5);
|
||||
TestRectangle(10, 10, -5, 5);
|
||||
TestRectangle(10, 10, 5, -5);
|
||||
TestRectangle(10, 10, -5, -5);
|
||||
TestRectangle(10, 10, 0, 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(bearing_tests)
|
||||
{
|
||||
using Coord = std::pair<float, float>;
|
||||
using Edge = std::pair<unsigned, unsigned>;
|
||||
GraphFixture fixture(
|
||||
{
|
||||
Coord(0.0, 0.0), Coord(10.0, 10.0),
|
||||
},
|
||||
{Edge(0, 1), Edge(1, 0)});
|
||||
|
||||
std::string leaves_path;
|
||||
std::string nodes_path;
|
||||
build_rtree<GraphFixture, MiniStaticRTree>("test_bearing", &fixture, leaves_path, nodes_path);
|
||||
MiniStaticRTree rtree(nodes_path, leaves_path, fixture.coords);
|
||||
GeospatialQuery<MiniStaticRTree> query(rtree, fixture.coords);
|
||||
|
||||
FixedPointCoordinate input(5.0 * COORDINATE_PRECISION, 5.1 * COORDINATE_PRECISION);
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodes(input, 5);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
BOOST_CHECK_EQUAL(results.back().phantom_node.forward_node_id, 0);
|
||||
BOOST_CHECK_EQUAL(results.back().phantom_node.reverse_node_id, 1);
|
||||
}
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodes(input, 5, 270, 10);
|
||||
BOOST_CHECK_EQUAL(results.size(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodes(input, 5, 45, 10);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
BOOST_CHECK_EQUAL(results[0].phantom_node.forward_node_id, 1);
|
||||
BOOST_CHECK_EQUAL(results[0].phantom_node.reverse_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(results[1].phantom_node.forward_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(results[1].phantom_node.reverse_node_id, 1);
|
||||
}
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodesInRange(input, 11000);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
}
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodesInRange(input, 11000, 270, 10);
|
||||
BOOST_CHECK_EQUAL(results.size(), 0);
|
||||
}
|
||||
|
||||
{
|
||||
auto results = query.NearestPhantomNodesInRange(input, 11000, 45, 10);
|
||||
BOOST_CHECK_EQUAL(results.size(), 2);
|
||||
BOOST_CHECK_EQUAL(results[0].phantom_node.forward_node_id, 1);
|
||||
BOOST_CHECK_EQUAL(results[0].phantom_node.reverse_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(results[1].phantom_node.forward_node_id, SPECIAL_NODEID);
|
||||
BOOST_CHECK_EQUAL(results[1].phantom_node.reverse_node_id, 1);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "../../util/string_util.hpp"
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/test_case_template.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(string_util)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(json_escaping)
|
||||
{
|
||||
std::string input{"\b\\"};
|
||||
std::string output{escape_JSON(input)};
|
||||
|
||||
BOOST_CHECK_EQUAL(output, "\\b\\\\");
|
||||
|
||||
input = "Aleja \"Solidarnosci\"";
|
||||
output = escape_JSON(input);
|
||||
BOOST_CHECK_EQUAL(output, "Aleja \\\"Solidarnosci\\\"");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(print_int)
|
||||
{
|
||||
const std::string input{"\b\\"};
|
||||
char buffer[12];
|
||||
buffer[11] = 0; // zero termination
|
||||
std::string output = printInt<11, 8>(buffer, 314158976);
|
||||
BOOST_CHECK_EQUAL(output, "3.14158976");
|
||||
|
||||
buffer[11] = 0;
|
||||
output = printInt<11, 8>(buffer, 0);
|
||||
BOOST_CHECK_EQUAL(output, "0.00000000");
|
||||
|
||||
output = printInt<11, 8>(buffer, -314158976);
|
||||
BOOST_CHECK_EQUAL(output, "-3.14158976");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
Reference in New Issue
Block a user