Merge commit '788bc67faa7738cf7c6b2a192ecf3e3567d1c20e' into develop

This commit is contained in:
Patrick Niklaus
2015-08-28 12:42:03 +02:00
150 changed files with 12325 additions and 4321 deletions
+81
View File
@@ -0,0 +1,81 @@
#include "catch.hpp"
#include <cstring>
#include <osmium/util/data_file.hpp>
TEST_CASE("temporary file") {
SECTION("create/open") {
osmium::util::DataFile file;
REQUIRE(!!file);
int fd = file.fd();
REQUIRE(fd > 0);
const char buf[] = "foobar";
REQUIRE(::write(fd, buf, sizeof(buf)) == sizeof(buf));
file.close();
REQUIRE(!file);
}
}
TEST_CASE("named file") {
SECTION("create/open") {
{
osmium::util::DataFile file("test.data", true);
REQUIRE(!!file);
int fd = file.fd();
REQUIRE(fd > 0);
REQUIRE(file.size() == 0);
const char buf[] = "foobar";
REQUIRE(::write(fd, buf, sizeof(buf) - 1) == sizeof(buf) - 1);
file.close();
REQUIRE(!file);
}
{
osmium::util::DataFile file("test.data", false);
REQUIRE(!!file);
int fd = file.fd();
REQUIRE(fd > 0);
REQUIRE(file.size() == 6);
char buf[10];
int len = ::read(fd, buf, sizeof(buf));
REQUIRE(len == 6);
REQUIRE(!strncmp(buf, "foobar", 6));
file.close();
REQUIRE(!file);
REQUIRE(unlink("test.data") == 0);
}
}
SECTION("grow file") {
osmium::util::DataFile file("test.data", true);
REQUIRE(!!file);
REQUIRE(file.size() == 0);
file.grow(10);
REQUIRE(file.size() == 10);
}
}
+68
View File
@@ -0,0 +1,68 @@
#include "catch.hpp"
#include <vector>
#include <osmium/util/delta.hpp>
TEST_CASE("delta encode") {
osmium::util::DeltaEncode<int> x;
SECTION("int") {
REQUIRE(x.update(17) == 17);
REQUIRE(x.update(10) == -7);
}
}
TEST_CASE("delta decode") {
osmium::util::DeltaDecode<int> x;
SECTION("int") {
REQUIRE(x.update(17) == 17);
REQUIRE(x.update(10) == 27);
}
}
TEST_CASE("delta encode and decode") {
std::vector<int> a = { 5, -9, 22, 13, 0, 23 };
osmium::util::DeltaEncode<int> de;
std::vector<int> b;
for (int x : a) {
b.push_back(de.update(x));
}
osmium::util::DeltaDecode<int> dd;
std::vector<int> c;
for (int x : b) {
c.push_back(dd.update(x));
}
}
TEST_CASE("delta encode iterator") {
std::vector<int> data = { 4, 5, 13, 22, 12 };
auto l = [](std::vector<int>::const_iterator it) -> int {
return *it;
};
typedef osmium::util::DeltaEncodeIterator<std::vector<int>::const_iterator, decltype(l), int> it_type;
it_type it(data.begin(), data.end(), l);
it_type end(data.end(), data.end(), l);
REQUIRE(*it == 4);
++it;
REQUIRE(*it++ == 1);
REQUIRE(*it == 8);
++it;
REQUIRE(*it++ == 9);
REQUIRE(*it == -10);
++it;
REQUIRE(it == end);
}
+69
View File
@@ -0,0 +1,69 @@
#include "catch.hpp"
#include <osmium/util/file.hpp>
#ifdef _WIN32
// https://msdn.microsoft.com/en-us/library/ksazx244.aspx
// https://msdn.microsoft.com/en-us/library/a9yf33zb.aspx
class DoNothingInvalidParameterHandler {
static void invalid_parameter_handler(
const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved
) {
// do nothing
}
_invalid_parameter_handler old_handler;
public:
DoNothingInvalidParameterHandler() :
old_handler(_set_invalid_parameter_handler(invalid_parameter_handler)) {
}
~DoNothingInvalidParameterHandler() {
_set_invalid_parameter_handler(old_handler);
}
}; // class InvalidParameterHandler
#endif
TEST_CASE("file_size") {
#ifdef _WIN32
DoNothingInvalidParameterHandler handler;
#endif
SECTION("illegal fd should throw") {
REQUIRE_THROWS_AS(osmium::util::file_size(-1), std::system_error);
}
SECTION("unused fd should throw") {
// its unlikely that fd 1000 is open...
REQUIRE_THROWS_AS(osmium::util::file_size(1000), std::system_error);
}
}
TEST_CASE("resize_file") {
#ifdef _WIN32
DoNothingInvalidParameterHandler handler;
#endif
SECTION("illegal fd should throw") {
REQUIRE_THROWS_AS(osmium::util::resize_file(-1, 10), std::system_error);
}
SECTION("unused fd should throw") {
// its unlikely that fd 1000 is open...
REQUIRE_THROWS_AS(osmium::util::resize_file(1000, 10), std::system_error);
}
}
@@ -0,0 +1,419 @@
#include "catch.hpp"
#include <sys/types.h>
#include <limits>
#include <osmium/util/file.hpp>
#include <osmium/util/memory_mapping.hpp>
#if defined(_MSC_VER) || (defined(__GNUC__) && defined(_WIN32))
#include "win_mkstemp.hpp"
#endif
static const size_t huge = std::numeric_limits<size_t>::max();
TEST_CASE("anonymous mapping") {
SECTION("simple memory mapping should work") {
osmium::util::MemoryMapping mapping(1000, osmium::util::MemoryMapping::mapping_mode::write_private);
REQUIRE(mapping.get_addr() != nullptr);
REQUIRE(mapping.size() >= 1000);
volatile int* addr = mapping.get_addr<int>();
REQUIRE(mapping.writable());
*addr = 42;
REQUIRE(*addr == 42);
REQUIRE(!!mapping);
mapping.unmap();
REQUIRE(!mapping);
mapping.unmap(); // second unmap is okay
}
SECTION("memory mapping of zero length should work") {
osmium::util::MemoryMapping mapping(0, osmium::util::MemoryMapping::mapping_mode::write_private);
REQUIRE(mapping.get_addr() != nullptr);
REQUIRE(mapping.size() == osmium::util::get_pagesize());
REQUIRE(!!mapping);
mapping.unmap();
REQUIRE(!mapping);
}
SECTION("moving a memory mapping should work") {
osmium::util::MemoryMapping mapping1(1000, osmium::util::MemoryMapping::mapping_mode::write_private);
int* addr1 = mapping1.get_addr<int>();
*addr1 = 42;
REQUIRE(!!mapping1);
osmium::util::MemoryMapping mapping2(std::move(mapping1));
REQUIRE(!!mapping2);
REQUIRE(!mapping1);
mapping1.unmap();
int* addr2 = mapping2.get_addr<int>();
REQUIRE(*addr2 == 42);
mapping2.unmap();
REQUIRE(!mapping2);
}
SECTION("move assignment should work") {
osmium::util::MemoryMapping mapping1(1000, osmium::util::MemoryMapping::mapping_mode::write_private);
osmium::util::MemoryMapping mapping2(1000, osmium::util::MemoryMapping::mapping_mode::write_private);
REQUIRE(!!mapping1);
REQUIRE(!!mapping2);
int* addr1 = mapping1.get_addr<int>();
*addr1 = 42;
mapping2 = std::move(mapping1);
REQUIRE(!!mapping2);
REQUIRE(!mapping1);
int* addr2 = mapping2.get_addr<int>();
REQUIRE(*addr2 == 42);
mapping2.unmap();
REQUIRE(!mapping2);
}
#ifdef __linux__
SECTION("remapping to larger size should work") {
osmium::util::MemoryMapping mapping(1000, osmium::util::MemoryMapping::mapping_mode::write_private);
REQUIRE(mapping.size() >= 1000);
size_t size1 = mapping.size();
int* addr1 = mapping.get_addr<int>();
*addr1 = 42;
mapping.resize(8000);
REQUIRE(mapping.size() > size1);
int* addr2 = mapping.get_addr<int>();
REQUIRE(*addr2 == 42);
}
SECTION("remapping to smaller size should work") {
osmium::util::MemoryMapping mapping(8000, osmium::util::MemoryMapping::mapping_mode::write_private);
REQUIRE(mapping.size() >= 1000);
size_t size1 = mapping.size();
int* addr1 = mapping.get_addr<int>();
*addr1 = 42;
mapping.resize(500);
REQUIRE(mapping.size() < size1);
int* addr2 = mapping.get_addr<int>();
REQUIRE(*addr2 == 42);
}
#endif
}
TEST_CASE("file-based mapping") {
SECTION("writing to a mapped file should work") {
char filename[] = "test_mmap_write_XXXXXX";
const int fd = mkstemp(filename);
REQUIRE(fd > 0);
osmium::util::resize_file(fd, 100);
{
osmium::util::MemoryMapping mapping(100, osmium::util::MemoryMapping::mapping_mode::write_shared, fd);
REQUIRE(mapping.writable());
REQUIRE(!!mapping);
REQUIRE(mapping.size() >= 100);
*mapping.get_addr<int>() = 1234;
mapping.unmap();
}
REQUIRE(osmium::util::file_size(fd) == 100);
{
osmium::util::MemoryMapping mapping(100, osmium::util::MemoryMapping::mapping_mode::readonly, fd);
REQUIRE(!mapping.writable());
REQUIRE(!!mapping);
REQUIRE(mapping.size() >= 100);
REQUIRE(*mapping.get_addr<int>() == 1234);
mapping.unmap();
}
REQUIRE(0 == close(fd));
REQUIRE(0 == unlink(filename));
}
SECTION("writing to a privately mapped file should work") {
char filename[] = "test_mmap_write_XXXXXX";
const int fd = mkstemp(filename);
REQUIRE(fd > 0);
osmium::util::resize_file(fd, 100);
{
osmium::util::MemoryMapping mapping(100, osmium::util::MemoryMapping::mapping_mode::write_private, fd);
REQUIRE(mapping.writable());
REQUIRE(!!mapping);
REQUIRE(mapping.size() >= 100);
*mapping.get_addr<int>() = 1234;
mapping.unmap();
}
REQUIRE(osmium::util::file_size(fd) == 100);
{
osmium::util::MemoryMapping mapping(100, osmium::util::MemoryMapping::mapping_mode::readonly, fd);
REQUIRE(!mapping.writable());
REQUIRE(!!mapping);
REQUIRE(mapping.size() >= 100);
REQUIRE(*mapping.get_addr<int>() == 0); // should not see the value set above
mapping.unmap();
}
REQUIRE(0 == close(fd));
REQUIRE(0 == unlink(filename));
}
SECTION("remapping to larger size should work") {
char filename[] = "test_mmap_grow_XXXXXX";
const int fd = mkstemp(filename);
REQUIRE(fd > 0);
osmium::util::MemoryMapping mapping(100, osmium::util::MemoryMapping::mapping_mode::write_shared, fd);
REQUIRE(mapping.size() >= 100);
size_t size1 = mapping.size();
int* addr1 = mapping.get_addr<int>();
*addr1 = 42;
mapping.resize(8000);
REQUIRE(mapping.size() >= 8000);
REQUIRE(mapping.size() > size1);
int* addr2 = mapping.get_addr<int>();
REQUIRE(*addr2 == 42);
mapping.unmap();
REQUIRE(0 == close(fd));
REQUIRE(0 == unlink(filename));
}
SECTION("remapping to smaller size should work") {
char filename[] = "test_mmap_shrink_XXXXXX";
const int fd = mkstemp(filename);
REQUIRE(fd > 0);
{
osmium::util::MemoryMapping mapping(8000, osmium::util::MemoryMapping::mapping_mode::write_shared, fd);
REQUIRE(mapping.size() >= 8000);
size_t size1 = mapping.size();
int* addr1 = mapping.get_addr<int>();
*addr1 = 42;
mapping.resize(50);
REQUIRE(mapping.size() >= 50);
REQUIRE(mapping.size() < size1);
int* addr2 = mapping.get_addr<int>();
REQUIRE(*addr2 == 42);
}
REQUIRE(0 == close(fd));
REQUIRE(0 == unlink(filename));
}
}
TEST_CASE("typed anonymous mapping") {
SECTION("simple memory mapping should work") {
osmium::util::TypedMemoryMapping<uint32_t> mapping(1000);
volatile uint32_t* addr = mapping.begin();
REQUIRE(mapping.writable());
*addr = 42;
REQUIRE(*addr == 42);
REQUIRE(!!mapping);
mapping.unmap();
REQUIRE(!mapping);
mapping.unmap(); // second unmap is okay
}
SECTION("moving a memory mapping should work") {
osmium::util::TypedMemoryMapping<uint32_t> mapping1(1000);
uint32_t* addr1 = mapping1.begin();
*addr1 = 42;
REQUIRE(!!mapping1);
osmium::util::TypedMemoryMapping<uint32_t> mapping2(std::move(mapping1));
REQUIRE(!!mapping2);
REQUIRE(!mapping1);
mapping1.unmap();
auto addr2 = mapping2.begin();
REQUIRE(*addr2 == 42);
mapping2.unmap();
REQUIRE(!mapping2);
}
SECTION("move assignment should work") {
osmium::util::TypedMemoryMapping<uint32_t> mapping1(1000);
osmium::util::TypedMemoryMapping<uint32_t> mapping2(1000);
REQUIRE(!!mapping1);
REQUIRE(!!mapping2);
auto addr1 = mapping1.begin();
*addr1 = 42;
mapping2 = std::move(mapping1);
REQUIRE(!!mapping2);
REQUIRE(!mapping1);
auto addr2 = mapping2.begin();
REQUIRE(*addr2 == 42);
mapping2.unmap();
REQUIRE(!mapping2);
}
#ifdef __linux__
SECTION("remapping to larger size should work") {
osmium::util::TypedMemoryMapping<uint32_t> mapping(1000);
REQUIRE(mapping.size() >= 1000);
auto addr1 = mapping.begin();
*addr1 = 42;
mapping.resize(8000);
auto addr2 = mapping.begin();
REQUIRE(*addr2 == 42);
}
SECTION("remapping to smaller size should work") {
osmium::util::TypedMemoryMapping<uint32_t> mapping(8000);
REQUIRE(mapping.size() >= 8000);
auto addr1 = mapping.begin();
*addr1 = 42;
mapping.resize(500);
auto addr2 = mapping.begin();
REQUIRE(*addr2 == 42);
}
#endif
}
TEST_CASE("typed file-based mapping") {
SECTION("writing to a mapped file should work") {
char filename[] = "test_mmap_file_size_XXXXXX";
const int fd = mkstemp(filename);
REQUIRE(fd > 0);
osmium::util::resize_file(fd, 100);
{
osmium::util::TypedMemoryMapping<uint32_t> mapping(100, osmium::util::MemoryMapping::mapping_mode::write_shared, fd);
REQUIRE(mapping.writable());
REQUIRE(!!mapping);
REQUIRE(mapping.size() >= 100);
*mapping.begin() = 1234;
mapping.unmap();
}
{
osmium::util::TypedMemoryMapping<uint32_t> mapping(100, osmium::util::MemoryMapping::mapping_mode::readonly, fd);
REQUIRE(!mapping.writable());
REQUIRE(!!mapping);
REQUIRE(mapping.size() >= 100);
REQUIRE(*mapping.begin() == 1234);
mapping.unmap();
}
REQUIRE(0 == close(fd));
REQUIRE(0 == unlink(filename));
}
}
TEST_CASE("anonymous memory mapping class") {
SECTION("simple memory mapping should work") {
osmium::util::AnonymousMemoryMapping mapping(1000);
REQUIRE(mapping.get_addr() != nullptr);
volatile int* addr = mapping.get_addr<int>();
REQUIRE(mapping.writable());
*addr = 42;
REQUIRE(*addr == 42);
REQUIRE(!!mapping);
mapping.unmap();
REQUIRE(!mapping);
mapping.unmap(); // second unmap is okay
}
#ifdef __linux__
SECTION("remapping to larger size should work") {
osmium::util::AnonymousMemoryMapping mapping(1000);
REQUIRE(mapping.size() >= 1000);
int* addr1 = mapping.get_addr<int>();
*addr1 = 42;
mapping.resize(2000);
int* addr2 = mapping.get_addr<int>();
REQUIRE(*addr2 == 42);
}
SECTION("remapping to smaller size should work") {
osmium::util::AnonymousMemoryMapping mapping(2000);
REQUIRE(mapping.size() >= 2000);
int* addr1 = mapping.get_addr<int>();
*addr1 = 42;
mapping.resize(500);
int* addr2 = mapping.get_addr<int>();
REQUIRE(*addr2 == 42);
}
#endif
}
+68
View File
@@ -0,0 +1,68 @@
#include "catch.hpp"
#include <osmium/util/minmax.hpp>
#include <osmium/osm/timestamp.hpp>
TEST_CASE("minmax numeric") {
SECTION("min") {
osmium::min_op<int> x;
REQUIRE(x() == std::numeric_limits<int>::max());
x.update(17);
REQUIRE(x() == 17);
x.update(10);
REQUIRE(x() == 10);
x.update(22);
REQUIRE(x() == 10);
}
SECTION("max") {
osmium::max_op<uint32_t> x;
REQUIRE(x() == 0);
x.update(17);
REQUIRE(x() == 17);
x.update(10);
REQUIRE(x() == 17);
x.update(22);
REQUIRE(x() == 22);
}
}
TEST_CASE("minmax timestamp") {
SECTION("min") {
osmium::min_op<osmium::Timestamp> x;
x.update(osmium::Timestamp("2010-01-01T00:00:00Z"));
REQUIRE(x().to_iso() == "2010-01-01T00:00:00Z");
x.update(osmium::Timestamp("2015-01-01T00:00:00Z"));
REQUIRE(x().to_iso() == "2010-01-01T00:00:00Z");
x.update(osmium::Timestamp("2000-01-01T00:00:00Z"));
REQUIRE(x().to_iso() == "2000-01-01T00:00:00Z");
}
SECTION("max") {
osmium::max_op<osmium::Timestamp> x;
x.update(osmium::Timestamp("2010-01-01T00:00:00Z"));
REQUIRE(x().to_iso() == "2010-01-01T00:00:00Z");
x.update(osmium::Timestamp("2015-01-01T00:00:00Z"));
REQUIRE(x().to_iso() == "2015-01-01T00:00:00Z");
x.update(osmium::Timestamp("2000-01-01T00:00:00Z"));
REQUIRE(x().to_iso() == "2015-01-01T00:00:00Z");
}
}
+11
View File
@@ -9,6 +9,7 @@ TEST_CASE("split_string") {
std::vector<std::string> result = {"foo", "baramba", "baz"};
REQUIRE(result == osmium::split_string(str, ','));
REQUIRE(result == osmium::split_string(str, ',', true));
}
SECTION("split_string string without sep") {
@@ -16,34 +17,43 @@ TEST_CASE("split_string") {
std::vector<std::string> result = {"foo"};
REQUIRE(result == osmium::split_string(str, ','));
REQUIRE(result == osmium::split_string(str, ',', true));
}
SECTION("split_string string with empty at end") {
std::string str { "foo,bar," };
std::vector<std::string> result = {"foo", "bar", ""};
std::vector<std::string> resultc = {"foo", "bar"};
REQUIRE(result == osmium::split_string(str, ','));
REQUIRE(resultc == osmium::split_string(str, ',', true));
}
SECTION("split_string string with empty in middle") {
std::string str { "foo,,bar" };
std::vector<std::string> result = {"foo", "", "bar"};
std::vector<std::string> resultc = {"foo", "bar"};
REQUIRE(result == osmium::split_string(str, ','));
REQUIRE(resultc == osmium::split_string(str, ',', true));
}
SECTION("split_string string with empty at start") {
std::string str { ",bar,baz" };
std::vector<std::string> result = {"", "bar", "baz"};
std::vector<std::string> resultc = {"bar", "baz"};
REQUIRE(result == osmium::split_string(str, ','));
REQUIRE(resultc == osmium::split_string(str, ',', true));
}
SECTION("split_string sep") {
std::string str { "," };
std::vector<std::string> result = {"", ""};
std::vector<std::string> resultc;
REQUIRE(result == osmium::split_string(str, ','));
REQUIRE(resultc == osmium::split_string(str, ',', true));
}
SECTION("split_string empty string") {
@@ -51,6 +61,7 @@ TEST_CASE("split_string") {
std::vector<std::string> result;
REQUIRE(result == osmium::split_string(str, ','));
REQUIRE(result == osmium::split_string(str, ',', true));
}
}