1
0
Fork 0
mirror of https://github.com/systemed/tilemaker synced 2025-02-21 13:24:09 +01:00
tilemaker/test/sorted_way_store.test.cpp
Colin Dellow b77340c870 remove PossiblyKnownTagValue
When I replaced #604 with #626, I botched extracting this part of the
code. I had the trait, which taught kaguya how to serialize
`PossiblyKnownTagValue`, but I missed updating the parameter type
of `Attribute` to actually use it, so it was a no-op.

This PR restores the behaviour of avoiding string copies, but now that
we have protozero's data_view class, we can use that rather than
our own weirdo struct.
2024-01-11 23:29:50 -05:00

233 lines
5.4 KiB
C++

#include <iostream>
#include "external/minunit.h"
#include "sorted_way_store.h"
#include "node_store.h"
class TestNodeStore : public NodeStore {
void clear() override {}
void reopen() override {}
void batchStart() override {}
void finalize(size_t threadNum) override {}
size_t size() const override { return 1; }
LatpLon at(NodeID id) const override {
return { (int32_t)id, -(int32_t)id };
}
void insert(const std::vector<std::pair<NodeID, LatpLon>>& elements) override {}
bool contains(size_t shard, NodeID id) const override { return true; }
NodeStore& shard(size_t shard) override { return *this; }
const NodeStore& shard(size_t shard) const override { return *this; }
size_t shards() const override { return 1; }
};
void roundtripWay(const std::vector<NodeID>& way) {
bool compress = false;
for (int i = 0; i < 2; i++) {
std::vector<uint8_t> output;
uint16_t flags = SortedWayStore::encodeWay(way, output, compress);
if (false) {
std::cout << "input=";
for (const auto& node : way) {
std::cout << node << " ";
}
std::cout << std::endl;
std::cout << "flags=" << flags << ", output.size()=" << output.size() << ", ";
for (const uint8_t byte : output)
std::cout << " " << std::to_string(byte);
std::cout << std::endl;
}
const std::vector<NodeID> roundtrip = SortedWayStore::decodeWay(flags, &output[0]);
mu_check(roundtrip.size() == way.size());
for (int i = 0; i < way.size(); i++) {
//std::cout << "roundtrip[" << i << "]=" << roundtrip[i] << ", way[" << i << "]=" << way[i] << std::endl;
mu_check(roundtrip[i] == way[i]);
}
compress = !compress;
}
}
MU_TEST(test_encode_way) {
roundtripWay({ 1 });
roundtripWay({ 1, 2 });
roundtripWay({ 1, 2, 1 });
roundtripWay({ 1, 2, 3, 4 });
roundtripWay({ 4294967295, 4294967297, 8589934592, 4, 5 });
// 11386679771 uses the full lower 32-bits, so is a good test case that
// zigzag encoding hasn't broken anything.
roundtripWay({ 5056880431, 538663248, 538663257, 538663260, 538663263, 11386679771, 538663266 });
// When the high bytes are all the same, it should take
// less space to encode.
{
std::vector<uint8_t> output;
SortedWayStore::encodeWay({ 1, 2, 3, 4 }, output, false);
const uint16_t l1 = output.size();
SortedWayStore::encodeWay({ 1, 8589934592, 3, 4 }, output, false);
const uint16_t l2 = output.size();
mu_check(l1 < l2);
}
}
MU_TEST(test_multiple_stores) {
bool compressed = false;
for (int i = 0; i < 2; i++) {
compressed = !compressed;
TestNodeStore ns;
SortedWayStore s1(compressed, ns), s2(compressed, ns);
s1.batchStart();
s2.batchStart();
s1.insertNodes({{ 1, { 1 } }});
// We store small ways differently than large ways, so
// store both kinds for testing.
std::vector<NodeID> longWay;
for (int i = 200; i < 2048; i++)
longWay.push_back(i + 3 * (i % 37));
s1.insertNodes({{ 42, longWay }});
s2.insertNodes({{ 2, { 2 } }});
s1.finalize(1);
s2.finalize(1);
mu_check(s1.size() == 2);
mu_check(s2.size() == 1);
mu_check(s1.contains(0, 1));
mu_check(s1.contains(0, 42));
mu_check(!s1.contains(0, 2));
}
}
MU_TEST(test_way_store) {
TestNodeStore ns;
SortedWayStore sws(true, ns);
sws.batchStart();
std::vector<std::pair<WayID, std::vector<NodeID>>> ways;
std::vector<NodeID> shortWay;
shortWay.push_back(123);
ways.push_back(std::make_pair(1, shortWay));
ways.push_back(std::make_pair(2, shortWay));
ways.push_back(std::make_pair(513, shortWay));
std::vector<NodeID> longWay;
for(int i = 200; i < 300; i++)
longWay.push_back(i);
ways.push_back(std::make_pair(65536, longWay));
ways.push_back(std::make_pair(131072, longWay));
sws.insertNodes(ways);
sws.finalize(1);
mu_check(sws.size() == 5);
{
const auto& rv = sws.at(1);
mu_check(rv.size() == 1);
mu_check(rv[0].latp == 123);
}
{
const auto& rv = sws.at(2);
mu_check(rv.size() == 1);
mu_check(rv[0].latp == 123);
}
{
const auto& rv = sws.at(513);
mu_check(rv.size() == 1);
mu_check(rv[0].latp == 123);
}
{
const auto& rv = sws.at(65536);
mu_check(rv.size() == 100);
mu_check(rv[0].latp == 200);
mu_check(rv[99].latp == 299);
}
{
const auto& rv = sws.at(131072);
mu_check(rv.size() == 100);
mu_check(rv[0].latp == 200);
mu_check(rv[99].latp == 299);
}
// missing things should throw std::out_of_range
bool threw = false;
try {
sws.at(123123123);
} catch (std::out_of_range &e) {
threw = true;
} catch (...) {}
mu_check(threw == true);
threw = false;
try {
sws.at(3);
} catch (std::out_of_range &e) {
threw = true;
} catch (...) {}
mu_check(threw == true);
}
MU_TEST(test_populate_mask) {
uint8_t mask[32];
std::vector<uint8_t> ids;
{
// No ids: all 0s
populateMask(mask, ids);
for(int i = 0; i < 32; i++)
mu_check(mask[i] == 0);
}
{
// Every id: all 1s
for(int i = 0; i < 256; i++)
ids.push_back(i);
populateMask(mask, ids);
for(int i = 0; i < 32; i++)
mu_check(mask[i] == 255);
}
{
// Every other ID
ids.clear();
for (int i = 0; i < 256; i += 2)
ids.push_back(i);
populateMask(mask, ids);
for(int i = 0; i < 32; i++)
mu_check(mask[i] == 0b01010101);
}
}
MU_TEST_SUITE(test_suite_sorted_way_store) {
MU_RUN_TEST(test_encode_way);
MU_RUN_TEST(test_multiple_stores);
MU_RUN_TEST(test_way_store);
}
MU_TEST_SUITE(test_suite_bitmask) {
MU_RUN_TEST(test_populate_mask);
}
int main() {
MU_RUN_SUITE(test_suite_sorted_way_store);
MU_RUN_SUITE(test_suite_bitmask);
MU_REPORT();
return MU_EXIT_CODE;
}