Update in-tree libosmium dependency to 2.5.4

The latest releases have some critical fixes, see the changelog:
https://github.com/osmcode/libosmium/blob/v2.5.4/CHANGELOG.md

Merge commit 'afdf8e7b21fbaf597e91d9d8a7542635e60ee9a1' into use_libosmium_2_5_4
This commit is contained in:
Daniel J. Hofmann
2016-01-05 12:00:40 +01:00
171 changed files with 7150 additions and 3988 deletions
+8 -2
View File
@@ -106,6 +106,7 @@ add_unit_test(basic test_timestamp)
add_unit_test(basic test_types_from_string)
add_unit_test(basic test_way)
add_unit_test(buffer test_buffer_basics)
add_unit_test(buffer test_buffer_node)
add_unit_test(buffer test_buffer_purge)
@@ -133,9 +134,15 @@ add_unit_test(index test_id_to_location ENABLE_IF ${SPARSEHASH_FOUND})
add_unit_test(io test_bzip2 ENABLE_IF ${BZIP2_FOUND} LIBS ${BZIP2_LIBRARIES})
add_unit_test(io test_file_formats)
add_unit_test(io test_reader LIBS "${OSMIUM_XML_LIBRARIES}")
add_unit_test(io test_reader LIBS "${OSMIUM_XML_LIBRARIES};${OSMIUM_PBF_LIBRARIES}")
add_unit_test(io test_reader_with_mock_decompression ENABLE_IF ${Threads_FOUND} LIBS ${OSMIUM_XML_LIBRARIES})
add_unit_test(io test_reader_with_mock_parser ENABLE_IF ${Threads_FOUND} LIBS ${CMAKE_THREAD_LIBS_INIT})
add_unit_test(io test_output_utils)
add_unit_test(io test_output_iterator ENABLE_IF ${Threads_FOUND} LIBS ${CMAKE_THREAD_LIBS_INIT})
add_unit_test(io test_string_table)
add_unit_test(io test_writer ENABLE_IF ${Threads_FOUND} LIBS ${OSMIUM_XML_LIBRARIES})
add_unit_test(io test_writer_with_mock_compression ENABLE_IF ${Threads_FOUND} LIBS ${OSMIUM_XML_LIBRARIES})
add_unit_test(io test_writer_with_mock_encoder ENABLE_IF ${Threads_FOUND} LIBS ${OSMIUM_XML_LIBRARIES})
add_unit_test(tags test_filter)
add_unit_test(tags test_operators)
@@ -144,7 +151,6 @@ add_unit_test(tags test_tag_list)
add_unit_test(thread test_pool ENABLE_IF ${Threads_FOUND} LIBS ${CMAKE_THREAD_LIBS_INIT})
add_unit_test(util test_cast_with_assert)
add_unit_test(util test_data_file)
add_unit_test(util test_delta)
add_unit_test(util test_double)
add_unit_test(util test_file)
+3 -3
View File
@@ -88,11 +88,11 @@ set_tests_properties(testdata-overview PROPERTIES
#
#-----------------------------------------------------------------------------
find_package(Ruby 1.9)
find_program(RUBY ruby)
find_package(Gem COMPONENTS json)
find_program(SPATIALITE spatialite)
if(RUBY_FOUND AND GEM_json_FOUND AND SPATIALITE)
if(RUBY AND GEM_json_FOUND AND SPATIALITE)
add_executable(testdata-multipolygon testdata-multipolygon.cpp)
target_link_libraries(testdata-multipolygon
${OSMIUM_XML_LIBRARIES}
@@ -102,7 +102,7 @@ if(RUBY_FOUND AND GEM_json_FOUND AND SPATIALITE)
add_test(NAME testdata-multipolygon
COMMAND ${CMAKE_COMMAND}
-D OSM_TESTDATA=${OSM_TESTDATA}
-D RUBY=${RUBY_EXECUTABLE}
-D RUBY=${RUBY}
-P ${CMAKE_CURRENT_SOURCE_DIR}/run-testdata-multipolygon.cmake)
set_tests_properties(testdata-multipolygon PROPERTIES LABELS "data;slow")
@@ -3,6 +3,8 @@
#include <fstream>
#include <map>
#include <gdalcpp.hpp>
#include <osmium/index/map/sparse_mem_array.hpp>
#include <osmium/area/assembler.hpp>
@@ -41,10 +43,9 @@ inline tagmap_type create_map(const osmium::TagList& taglist) {
class TestHandler : public osmium::handler::Handler {
OGRDataSource* m_data_source;
OGRLayer* m_layer_point;
OGRLayer* m_layer_linestring;
OGRLayer* m_layer_polygon;
gdalcpp::Layer m_layer_point;
gdalcpp::Layer m_layer_lines;
gdalcpp::Layer m_layer_mpoly;
osmium::geom::OGRFactory<> m_ogr_factory;
osmium::geom::WKTFactory<> m_wkt_factory;
@@ -55,84 +56,20 @@ class TestHandler : public osmium::handler::Handler {
public:
TestHandler(OGRDataSource* data_source) :
m_data_source(data_source),
explicit TestHandler(gdalcpp::Dataset& dataset) :
m_layer_point(dataset, "points", wkbPoint),
m_layer_lines(dataset, "lines", wkbLineString),
m_layer_mpoly(dataset, "multipolygons", wkbMultiPolygon),
m_out("multipolygon-tests.json") {
OGRSpatialReference sparef;
sparef.SetWellKnownGeogCS("WGS84");
m_layer_point.add_field("id", OFTReal, 10);
m_layer_point.add_field("type", OFTString, 30);
/**************/
m_layer_lines.add_field("id", OFTReal, 10);
m_layer_lines.add_field("type", OFTString, 30);
m_layer_point = m_data_source->CreateLayer("points", &sparef, wkbPoint, nullptr);
if (!m_layer_point) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_point_field_id("id", OFTReal);
layer_point_field_id.SetWidth(10);
if (m_layer_point->CreateField(&layer_point_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_point_field_type("type", OFTString);
layer_point_field_type.SetWidth(30);
if (m_layer_point->CreateField(&layer_point_field_type) != OGRERR_NONE) {
std::cerr << "Creating type field failed.\n";
exit(1);
}
/**************/
m_layer_linestring = m_data_source->CreateLayer("lines", &sparef, wkbLineString, nullptr);
if (!m_layer_linestring) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_linestring_field_id("id", OFTReal);
layer_linestring_field_id.SetWidth(10);
if (m_layer_linestring->CreateField(&layer_linestring_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_linestring_field_type("type", OFTString);
layer_linestring_field_type.SetWidth(30);
if (m_layer_linestring->CreateField(&layer_linestring_field_type) != OGRERR_NONE) {
std::cerr << "Creating type field failed.\n";
exit(1);
}
/**************/
m_layer_polygon = m_data_source->CreateLayer("multipolygons", &sparef, wkbMultiPolygon, nullptr);
if (!m_layer_polygon) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_polygon_field_id("id", OFTInteger);
layer_polygon_field_id.SetWidth(10);
if (m_layer_polygon->CreateField(&layer_polygon_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_polygon_field_from_type("from_type", OFTString);
layer_polygon_field_from_type.SetWidth(1);
if (m_layer_polygon->CreateField(&layer_polygon_field_from_type) != OGRERR_NONE) {
std::cerr << "Creating from_type field failed.\n";
exit(1);
}
m_layer_mpoly.add_field("id", OFTReal, 10);
m_layer_mpoly.add_field("from_type", OFTString, 1);
}
~TestHandler() {
@@ -140,34 +77,18 @@ public:
}
void node(const osmium::Node& node) {
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_point->GetLayerDefn());
std::unique_ptr<OGRPoint> ogr_point = m_ogr_factory.create_point(node);
feature->SetGeometry(ogr_point.get());
feature->SetField("id", static_cast<double>(node.id()));
feature->SetField("type", node.tags().get_value_by_key("type"));
if (m_layer_point->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
gdalcpp::Feature feature(m_layer_point, m_ogr_factory.create_point(node));
feature.set_field("id", static_cast<double>(node.id()));
feature.set_field("type", node.tags().get_value_by_key("type"));
feature.add_to_layer();
}
void way(const osmium::Way& way) {
try {
std::unique_ptr<OGRLineString> ogr_linestring = m_ogr_factory.create_linestring(way);
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_linestring->GetLayerDefn());
feature->SetGeometry(ogr_linestring.get());
feature->SetField("id", static_cast<double>(way.id()));
feature->SetField("type", way.tags().get_value_by_key("type"));
if (m_layer_linestring->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
gdalcpp::Feature feature(m_layer_lines, m_ogr_factory.create_linestring(way));
feature.set_field("id", static_cast<double>(way.id()));
feature.set_field("type", way.tags().get_value_by_key("type"));
feature.add_to_layer();
} catch (osmium::geometry_error&) {
std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n";
}
@@ -200,10 +121,8 @@ public:
m_out << "INVALID\"\n}";
}
try {
std::unique_ptr<OGRMultiPolygon> ogr_polygon = m_ogr_factory.create_multipolygon(area);
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_polygon->GetLayerDefn());
feature->SetGeometry(ogr_polygon.get());
feature->SetField("id", static_cast<int>(area.orig_id()));
gdalcpp::Feature feature(m_layer_mpoly, m_ogr_factory.create_multipolygon(area));
feature.set_field("id", static_cast<double>(area.orig_id()));
std::string from_type;
if (area.from_way()) {
@@ -211,14 +130,8 @@ public:
} else {
from_type = "r";
}
feature->SetField("from_type", from_type.c_str());
if (m_layer_polygon->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
feature.set_field("from_type", from_type.c_str());
feature.add_to_layer();
} catch (osmium::geometry_error&) {
std::cerr << "Ignoring illegal geometry for area " << area.id() << " created from " << (area.from_way() ? "way" : "relation") << " with id=" << area.orig_id() << ".\n";
}
@@ -228,26 +141,6 @@ public:
/* ================================================== */
OGRDataSource* initialize_database(const std::string& output_format, const std::string& output_filename) {
OGRRegisterAll();
OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(output_format.c_str());
if (!driver) {
std::cerr << output_format << " driver not available.\n";
exit(1);
}
CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE");
const char* options[] = { "SPATIALITE=TRUE", nullptr };
OGRDataSource* data_source = driver->CreateDataSource(output_filename.c_str(), const_cast<char**>(options));
if (!data_source) {
std::cerr << "Creation of output file failed.\n";
exit(1);
}
return data_source;
}
int main(int argc, char* argv[]) {
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " INFILE\n";
@@ -258,9 +151,10 @@ int main(int argc, char* argv[]) {
std::string input_filename(argv[1]);
std::string output_filename("multipolygon.db");
OGRDataSource* data_source = initialize_database(output_format, output_filename);
CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE");
gdalcpp::Dataset dataset{output_format, output_filename, gdalcpp::SRS{}, { "SPATIALITE=TRUE" }};
osmium::area::ProblemReporterOGR problem_reporter(data_source);
osmium::area::ProblemReporterOGR problem_reporter(dataset);
osmium::area::Assembler::config_type assembler_config(&problem_reporter);
assembler_config.enable_debug_output();
osmium::area::MultipolygonCollector<osmium::area::Assembler> collector(assembler_config);
@@ -275,7 +169,7 @@ int main(int argc, char* argv[]) {
location_handler_type location_handler(index);
location_handler.ignore_errors();
TestHandler test_handler(data_source);
TestHandler test_handler(dataset);
std::cerr << "Pass 2...\n";
osmium::io::Reader reader2(input_filename);
@@ -284,8 +178,5 @@ int main(int argc, char* argv[]) {
}));
reader2.close();
std::cerr << "Pass 2 done\n";
OGRDataSource::DestroyDataSource(data_source);
OGRCleanupAll();
}
+29 -125
View File
@@ -2,6 +2,8 @@
#include <iostream>
#include <gdalcpp.hpp>
#include <osmium/index/map/sparse_mem_array.hpp>
#include <osmium/geom/ogr.hpp>
@@ -15,154 +17,53 @@ typedef osmium::handler::NodeLocationsForWays<index_type> location_handler_type;
class TestOverviewHandler : public osmium::handler::Handler {
OGRDataSource* m_data_source;
OGRLayer* m_layer_nodes;
OGRLayer* m_layer_labels;
OGRLayer* m_layer_ways;
gdalcpp::Layer m_layer_nodes;
gdalcpp::Layer m_layer_labels;
gdalcpp::Layer m_layer_ways;
osmium::geom::OGRFactory<> m_factory;
public:
TestOverviewHandler(const std::string& driver_name, const std::string& filename) {
explicit TestOverviewHandler(gdalcpp::Dataset& dataset) :
m_layer_nodes(dataset, "nodes", wkbPoint),
m_layer_labels(dataset, "labels", wkbPoint),
m_layer_ways(dataset, "ways", wkbLineString) {
OGRRegisterAll();
m_layer_nodes.add_field("id", OFTReal, 10);
OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name.c_str());
if (!driver) {
std::cerr << driver_name << " driver not available.\n";
exit(1);
}
m_layer_labels.add_field("id", OFTReal, 10);
m_layer_labels.add_field("label", OFTString, 30);
CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE");
const char* options[] = { "SPATIALITE=TRUE", nullptr };
m_data_source = driver->CreateDataSource(filename.c_str(), const_cast<char**>(options));
if (!m_data_source) {
std::cerr << "Creation of output file failed.\n";
exit(1);
}
OGRSpatialReference sparef;
sparef.SetWellKnownGeogCS("WGS84");
// nodes layer
m_layer_nodes = m_data_source->CreateLayer("nodes", &sparef, wkbPoint, nullptr);
if (!m_layer_nodes) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_nodes_field_id("id", OFTReal);
layer_nodes_field_id.SetWidth(10);
if (m_layer_nodes->CreateField(&layer_nodes_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
// labels layer
m_layer_labels = m_data_source->CreateLayer("labels", &sparef, wkbPoint, nullptr);
if (!m_layer_labels) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_labels_field_id("id", OFTReal);
layer_labels_field_id.SetWidth(10);
if (m_layer_labels->CreateField(&layer_labels_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_labels_field_label("label", OFTString);
layer_labels_field_label.SetWidth(30);
if (m_layer_labels->CreateField(&layer_labels_field_label) != OGRERR_NONE) {
std::cerr << "Creating label field failed.\n";
exit(1);
}
// ways layer
m_layer_ways = m_data_source->CreateLayer("ways", &sparef, wkbLineString, nullptr);
if (!m_layer_ways) {
std::cerr << "Layer creation failed.\n";
exit(1);
}
OGRFieldDefn layer_way_field_id("id", OFTReal);
layer_way_field_id.SetWidth(10);
if (m_layer_ways->CreateField(&layer_way_field_id) != OGRERR_NONE) {
std::cerr << "Creating id field failed.\n";
exit(1);
}
OGRFieldDefn layer_way_field_test("test", OFTInteger);
layer_way_field_test.SetWidth(3);
if (m_layer_ways->CreateField(&layer_way_field_test) != OGRERR_NONE) {
std::cerr << "Creating test field failed.\n";
exit(1);
}
}
~TestOverviewHandler() {
OGRDataSource::DestroyDataSource(m_data_source);
OGRCleanupAll();
m_layer_ways.add_field("id", OFTReal, 10);
m_layer_ways.add_field("test", OFTInteger, 3);
}
void node(const osmium::Node& node) {
const char* label = node.tags().get_value_by_key("label");
if (label) {
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_labels->GetLayerDefn());
std::unique_ptr<OGRPoint> ogr_point = m_factory.create_point(node);
feature->SetGeometry(ogr_point.get());
feature->SetField("id", static_cast<double>(node.id()));
feature->SetField("label", label);
if (m_layer_labels->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
gdalcpp::Feature feature(m_layer_labels, m_factory.create_point(node));
feature.set_field("id", static_cast<double>(node.id()));
feature.set_field("label", label);
feature.add_to_layer();
} else {
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_nodes->GetLayerDefn());
std::unique_ptr<OGRPoint> ogr_point = m_factory.create_point(node);
feature->SetGeometry(ogr_point.get());
feature->SetField("id", static_cast<double>(node.id()));
if (m_layer_nodes->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
gdalcpp::Feature feature(m_layer_nodes, m_factory.create_point(node));
feature.set_field("id", static_cast<double>(node.id()));
feature.add_to_layer();
}
}
void way(const osmium::Way& way) {
try {
std::unique_ptr<OGRLineString> ogr_linestring = m_factory.create_linestring(way);
OGRFeature* feature = OGRFeature::CreateFeature(m_layer_ways->GetLayerDefn());
feature->SetGeometry(ogr_linestring.get());
feature->SetField("id", static_cast<double>(way.id()));
gdalcpp::Feature feature(m_layer_ways, m_factory.create_linestring(way));
feature.set_field("id", static_cast<double>(way.id()));
const char* test = way.tags().get_value_by_key("test");
if (test) {
feature->SetField("test", test);
feature.set_field("test", test);
}
if (m_layer_ways->CreateFeature(feature) != OGRERR_NONE) {
std::cerr << "Failed to create feature.\n";
exit(1);
}
OGRFeature::DestroyFeature(feature);
feature.add_to_layer();
} catch (osmium::geometry_error&) {
std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n";
}
@@ -183,13 +84,16 @@ int main(int argc, char* argv[]) {
std::string output_filename("testdata-overview.db");
::unlink(output_filename.c_str());
CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE");
gdalcpp::Dataset dataset(output_format, output_filename, gdalcpp::SRS{}, { "SPATIALITE=TRUE" });
osmium::io::Reader reader(input_filename);
index_type index;
location_handler_type location_handler(index);
location_handler.ignore_errors();
TestOverviewHandler handler(output_format, output_filename);
TestOverviewHandler handler(dataset);
osmium::apply(reader, location_handler, handler);
reader.close();
+20 -15
View File
@@ -8,6 +8,7 @@
#include <iostream>
#include <string>
#include <osmium/io/detail/queue_util.hpp>
#include <osmium/io/xml_input.hpp>
#include <osmium/io/gzip_compression.hpp>
#include <osmium/visitor.hpp>
@@ -72,24 +73,27 @@ std::string read_gz_file(const char* test_id, const char* suffix) {
header_buffer_type parse_xml(std::string input) {
osmium::thread::Queue<std::string> input_queue;
osmium::thread::Queue<osmium::memory::Buffer> output_queue;
osmium::io::detail::future_string_queue_type input_queue;
osmium::io::detail::future_buffer_queue_type output_queue;
std::promise<osmium::io::Header> header_promise;
std::atomic<bool> done {false};
input_queue.push(input);
input_queue.push(std::string()); // EOF marker
std::future<osmium::io::Header> header_future = header_promise.get_future();
osmium::io::detail::XMLParser parser(input_queue, output_queue, header_promise, osmium::osm_entity_bits::all, done);
parser();
osmium::io::detail::add_to_queue(input_queue, std::move(input));
osmium::io::detail::add_to_queue(input_queue, std::string{});
osmium::io::detail::XMLParser parser(input_queue, output_queue, header_promise, osmium::osm_entity_bits::all);
parser.parse();
header_buffer_type result;
result.header = header_promise.get_future().get();
output_queue.wait_and_pop(result.buffer);
result.header = header_future.get();
std::future<osmium::memory::Buffer> future_buffer;
output_queue.wait_and_pop(future_buffer);
result.buffer = future_buffer.get();
if (result.buffer) {
osmium::memory::Buffer buffer;
output_queue.wait_and_pop(buffer);
assert(!buffer);
std::future<osmium::memory::Buffer> future_buffer2;
output_queue.wait_and_pop(future_buffer2);
assert(!future_buffer2.get());
}
return result;
@@ -534,9 +538,10 @@ TEST_CASE("Reading OSM XML 200") {
osmium::io::Header header = reader.header();
REQUIRE(header.get("generator") == "testdata");
osmium::memory::Buffer buffer = reader.read();
REQUIRE(0 == buffer.committed());
REQUIRE(! buffer);
REQUIRE_THROWS({
reader.read();
});
reader.close();
}
@@ -52,6 +52,20 @@ TEST_CASE("NodeRefSegmentClass") {
REQUIRE(calculate_intersection(s1, s7) == osmium::Location());
}
SECTION("intersection of very long segments") {
NodeRefSegment s1({ 1, {90.0, 90.0}}, { 2, {-90.0, -90.0}}, nullptr, nullptr);
NodeRefSegment s2({ 1, {-90.0, 90.0}}, { 2, {90.0, -90.0}}, nullptr, nullptr);
REQUIRE(calculate_intersection(s1, s2) == osmium::Location(0.0, 0.0));
NodeRefSegment s3({ 1, {-90.0, -90.0}}, { 2, {90.0, 90.0}}, nullptr, nullptr);
NodeRefSegment s4({ 1, {-90.0, 90.0}}, { 2, {90.0, -90.0}}, nullptr, nullptr);
REQUIRE(calculate_intersection(s3, s4) == osmium::Location(0.0, 0.0));
NodeRefSegment s5({ 1, {-90.0000001, -90.0}}, { 2, {90.0, 90.0}}, nullptr, nullptr);
NodeRefSegment s6({ 1, {-90.0, 90.0}}, { 2, {90.0, -90.0}}, nullptr, nullptr);
REQUIRE(calculate_intersection(s5, s6) == osmium::Location(0.0, 0.0));
}
SECTION("to_left_of") {
osmium::Location loc { 2.0, 2.0 };
+61 -1
View File
@@ -21,11 +21,13 @@ TEST_CASE("Basic Changeset") {
.set_created_at(100)
.set_closed_at(200)
.set_num_changes(7)
.set_num_comments(3)
.set_uid(9);
REQUIRE(42 == cs1.id());
REQUIRE(9 == cs1.uid());
REQUIRE(7 == cs1.num_changes());
REQUIRE(3 == cs1.num_comments());
REQUIRE(true == cs1.closed());
REQUIRE(osmium::Timestamp(100) == cs1.created_at());
REQUIRE(osmium::Timestamp(200) == cs1.closed_at());
@@ -33,7 +35,7 @@ TEST_CASE("Basic Changeset") {
REQUIRE(std::string("user") == cs1.user());
crc32.update(cs1);
REQUIRE(crc32().checksum() == 0xf44aff25);
REQUIRE(crc32().checksum() == 0x502e8c0e);
osmium::Changeset& cs2 = buffer_add_changeset(buffer,
"user",
@@ -42,11 +44,13 @@ TEST_CASE("Basic Changeset") {
cs2.set_id(43)
.set_created_at(120)
.set_num_changes(21)
.set_num_comments(osmium::num_comments_type(0))
.set_uid(9);
REQUIRE(43 == cs2.id());
REQUIRE(9 == cs2.uid());
REQUIRE(21 == cs2.num_changes());
REQUIRE(0 == cs2.num_comments());
REQUIRE(false == cs2.closed());
REQUIRE(osmium::Timestamp(120) == cs2.created_at());
REQUIRE(osmium::Timestamp() == cs2.closed_at());
@@ -61,3 +65,59 @@ TEST_CASE("Basic Changeset") {
REQUIRE(false == (cs1 >= cs2));
}
TEST_CASE("Create changeset without helper") {
osmium::memory::Buffer buffer(10 * 1000);
osmium::builder::ChangesetBuilder builder(buffer);
osmium::Changeset& cs1 = builder.object();
cs1.set_id(42)
.set_created_at(100)
.set_closed_at(200)
.set_num_changes(7)
.set_num_comments(2)
.set_uid(9);
builder.add_user("user");
add_tags(buffer, builder, {
{"key1", "val1"},
{"key2", "val2"}
});
{
osmium::builder::ChangesetDiscussionBuilder disc_builder(buffer, &builder);
disc_builder.add_comment(osmium::Timestamp(300), 10, "user2");
disc_builder.add_comment_text("foo");
disc_builder.add_comment(osmium::Timestamp(400), 9, "user");
disc_builder.add_comment_text("bar");
}
buffer.commit();
REQUIRE(42 == cs1.id());
REQUIRE(9 == cs1.uid());
REQUIRE(7 == cs1.num_changes());
REQUIRE(2 == cs1.num_comments());
REQUIRE(true == cs1.closed());
REQUIRE(osmium::Timestamp(100) == cs1.created_at());
REQUIRE(osmium::Timestamp(200) == cs1.closed_at());
REQUIRE(2 == cs1.tags().size());
REQUIRE(std::string("user") == cs1.user());
auto cit = cs1.discussion().begin();
REQUIRE(cit != cs1.discussion().end());
REQUIRE(cit->date() == osmium::Timestamp(300));
REQUIRE(cit->uid() == 10);
REQUIRE(std::string("user2") == cit->user());
REQUIRE(std::string("foo") == cit->text());
REQUIRE(++cit != cs1.discussion().end());
REQUIRE(cit->date() == osmium::Timestamp(400));
REQUIRE(cit->uid() == 9);
REQUIRE(std::string("user") == cit->user());
REQUIRE(std::string("bar") == cit->text());
REQUIRE(++cit == cs1.discussion().end());
}
+21
View File
@@ -24,6 +24,27 @@ TEST_CASE("CRC of basic datatypes") {
REQUIRE(crc32().checksum() == 0x8fe62899);
}
SECTION("Int16") {
crc32.update_int16(0x0123U);
crc32.update_int16(0x1234U);
REQUIRE(crc32().checksum() == 0xda923744);
}
SECTION("Int32") {
crc32.update_int32(0x01234567UL);
crc32.update_int32(0x12345678UL);
REQUIRE(crc32().checksum() == 0x9b4e2af3);
}
SECTION("Int64") {
crc32.update_int64(0x0123456789abcdefULL);
crc32.update_int64(0x123456789abcdef0ULL);
REQUIRE(crc32().checksum() == 0x6d8b7267);
}
SECTION("String") {
const char* str = "foobar";
crc32.update_string(str);
+3 -3
View File
@@ -37,12 +37,12 @@ SECTION("node_builder") {
REQUIRE(333 == node.changeset());
REQUIRE(21 == node.uid());
REQUIRE(std::string("foo") == node.user());
REQUIRE(123 == node.timestamp());
REQUIRE(123 == uint32_t(node.timestamp()));
REQUIRE(osmium::Location(3.5, 4.7) == node.location());
REQUIRE(2 == node.tags().size());
crc32.update(node);
REQUIRE(crc32().checksum() == 0xc696802f);
REQUIRE(crc32().checksum() == 0x7dc553f9);
node.set_visible(false);
REQUIRE(false == node.visible());
@@ -61,7 +61,7 @@ SECTION("node_default_attributes") {
REQUIRE(0 == node.changeset());
REQUIRE(0 == node.uid());
REQUIRE(std::string("") == node.user());
REQUIRE(0 == node.timestamp());
REQUIRE(0 == uint32_t(node.timestamp()));
REQUIRE(osmium::Location() == node.location());
REQUIRE(0 == node.tags().size());
}
@@ -31,20 +31,20 @@ TEST_CASE("Object_Comparisons") {
node1.set_version(1);
node2.set_id(15);
node2.set_version(2);
REQUIRE(true == (node1 < node2));
REQUIRE(false == (node1 > node2));
REQUIRE(node1 < node2);
REQUIRE_FALSE(node1 > node2);
node1.set_id(20);
node1.set_version(1);
node2.set_id(20);
node2.set_version(2);
REQUIRE(true == (node1 < node2));
REQUIRE(false == (node1 > node2));
REQUIRE(node1 < node2);
REQUIRE_FALSE(node1 > node2);
node1.set_id(-10);
node1.set_version(2);
node2.set_id(-15);
node2.set_version(1);
REQUIRE(true == (node1 < node2));
REQUIRE(false == (node1 > node2));
REQUIRE(node1 < node2);
REQUIRE_FALSE(node1 > node2);
}
SECTION("order_types") {
@@ -122,26 +122,26 @@ TEST_CASE("Object_Comparisons") {
const osmium::Way& way = static_cast<const osmium::Way&>(*(++it));
const osmium::Relation& relation = static_cast<const osmium::Relation&>(*(++it));
REQUIRE(true == (node1 < node2));
REQUIRE(true == (node2 < way));
REQUIRE(false == (node2 > way));
REQUIRE(true == (way < relation));
REQUIRE(true == (node1 < relation));
REQUIRE(node1 < node2);
REQUIRE(node2 < way);
REQUIRE_FALSE(node2 > way);
REQUIRE(way < relation);
REQUIRE(node1 < relation);
REQUIRE(true == osmium::object_order_type_id_version()(node1, node2));
REQUIRE(true == osmium::object_order_type_id_reverse_version()(node2, node1));
REQUIRE(true == osmium::object_order_type_id_version()(node1, way));
REQUIRE(true == osmium::object_order_type_id_reverse_version()(node1, way));
REQUIRE(osmium::object_order_type_id_version()(node1, node2));
REQUIRE(osmium::object_order_type_id_reverse_version()(node2, node1));
REQUIRE(osmium::object_order_type_id_version()(node1, way));
REQUIRE(osmium::object_order_type_id_reverse_version()(node1, way));
REQUIRE(false == osmium::object_equal_type_id_version()(node1, node2));
REQUIRE(true == osmium::object_equal_type_id_version()(node2, node3));
REQUIRE_FALSE(osmium::object_equal_type_id_version()(node1, node2));
REQUIRE(osmium::object_equal_type_id_version()(node2, node3));
REQUIRE(true == osmium::object_equal_type_id()(node1, node2));
REQUIRE(true == osmium::object_equal_type_id()(node2, node3));
REQUIRE(osmium::object_equal_type_id()(node1, node2));
REQUIRE(osmium::object_equal_type_id()(node2, node3));
REQUIRE(false == osmium::object_equal_type_id_version()(node1, way));
REQUIRE(false == osmium::object_equal_type_id_version()(node1, relation));
REQUIRE(false == osmium::object_equal_type_id()(node1, relation));
REQUIRE_FALSE(osmium::object_equal_type_id_version()(node1, way));
REQUIRE_FALSE(osmium::object_equal_type_id_version()(node1, relation));
REQUIRE_FALSE(osmium::object_equal_type_id()(node1, relation));
}
}
+13 -2
View File
@@ -36,7 +36,7 @@ TEST_CASE("Build relation") {
REQUIRE(333 == relation.changeset());
REQUIRE(21 == relation.uid());
REQUIRE(std::string("foo") == relation.user());
REQUIRE(123 == relation.timestamp());
REQUIRE(123 == uint32_t(relation.timestamp()));
REQUIRE(2 == relation.tags().size());
REQUIRE(3 == relation.members().size());
@@ -61,5 +61,16 @@ TEST_CASE("Build relation") {
}
crc32.update(relation);
REQUIRE(crc32().checksum() == 0xebcd836d);
REQUIRE(crc32().checksum() == 0x2c2352e);
}
TEST_CASE("Member role too long") {
osmium::memory::Buffer buffer(10000);
osmium::builder::RelationMemberListBuilder builder(buffer);
const char role[2000] = "";
builder.add_member(osmium::item_type::node, 1, role, 1024);
REQUIRE_THROWS(builder.add_member(osmium::item_type::node, 1, role, 1025));
}
+21 -6
View File
@@ -8,34 +8,45 @@ TEST_CASE("Timestamp") {
SECTION("can be default initialized to invalid value") {
osmium::Timestamp t;
REQUIRE(0 == t);
REQUIRE(0 == uint32_t(t));
REQUIRE("" == t.to_iso());
REQUIRE_FALSE(t.valid());
}
SECTION("invalid value is zero") {
osmium::Timestamp t(static_cast<time_t>(0));
REQUIRE(0 == t);
REQUIRE(0 == uint32_t(t));
REQUIRE("" == t.to_iso());
REQUIRE_FALSE(t.valid());
}
SECTION("can be initialized from time_t") {
osmium::Timestamp t(static_cast<time_t>(1));
REQUIRE(1 == t);
REQUIRE(1 == uint32_t(t));
REQUIRE("1970-01-01T00:00:01Z" == t.to_iso());
REQUIRE(t.valid());
}
SECTION("can be initialized from const char*") {
osmium::Timestamp t("2000-01-01T00:00:00Z");
REQUIRE("2000-01-01T00:00:00Z" == t.to_iso());
REQUIRE(t.valid());
}
SECTION("can be initialized from string") {
osmium::Timestamp t("2000-01-01T00:00:00Z");
std::string s = "2000-01-01T00:00:00Z";
osmium::Timestamp t(s);
REQUIRE("2000-01-01T00:00:00Z" == t.to_iso());
REQUIRE(t.valid());
}
SECTION("throws if initialized from bad string") {
REQUIRE_THROWS_AS(osmium::Timestamp("x"), std::invalid_argument);
}
SECTION("can be implicitly cast to time_t") {
SECTION("can be explicitly cast to time_t") {
osmium::Timestamp t(4242);
time_t x = t;
time_t x = t.seconds_since_epoch();
REQUIRE(x == 4242);
}
@@ -50,6 +61,10 @@ TEST_CASE("Timestamp") {
osmium::Timestamp t1(10);
osmium::Timestamp t2(50);
REQUIRE(t1 < t2);
REQUIRE(t1 > osmium::start_of_time());
REQUIRE(t2 > osmium::start_of_time());
REQUIRE(t1 < osmium::end_of_time());
REQUIRE(t2 < osmium::end_of_time());
}
SECTION("can be written to stream") {
+2 -2
View File
@@ -36,7 +36,7 @@ SECTION("way_builder") {
REQUIRE(333 == way.changeset());
REQUIRE(21 == way.uid());
REQUIRE(std::string("foo") == way.user());
REQUIRE(123 == way.timestamp());
REQUIRE(123 == uint32_t(way.timestamp()));
REQUIRE(2 == way.tags().size());
REQUIRE(3 == way.nodes().size());
REQUIRE(1 == way.nodes()[0].ref());
@@ -45,7 +45,7 @@ SECTION("way_builder") {
REQUIRE(! way.is_closed());
crc32.update(way);
REQUIRE(crc32().checksum() == 0x20fe7a30);
REQUIRE(crc32().checksum() == 0x7676d0c2);
}
SECTION("closed_way") {
@@ -0,0 +1,34 @@
#include "catch.hpp"
#include <osmium/memory/buffer.hpp>
TEST_CASE("Buffer basics") {
osmium::memory::Buffer invalid_buffer1;
osmium::memory::Buffer invalid_buffer2;
osmium::memory::Buffer empty_buffer1(1024);
osmium::memory::Buffer empty_buffer2(2048);
REQUIRE(!invalid_buffer1);
REQUIRE(!invalid_buffer2);
REQUIRE(empty_buffer1);
REQUIRE(empty_buffer2);
REQUIRE(invalid_buffer1 == invalid_buffer2);
REQUIRE(invalid_buffer1 != empty_buffer1);
REQUIRE(empty_buffer1 != empty_buffer2);
REQUIRE(invalid_buffer1.capacity() == 0);
REQUIRE(invalid_buffer1.written() == 0);
REQUIRE(invalid_buffer1.committed() == 0);
REQUIRE(empty_buffer1.capacity() == 1024);
REQUIRE(empty_buffer1.written() == 0);
REQUIRE(empty_buffer1.committed() == 0);
REQUIRE(empty_buffer2.capacity() == 2048);
REQUIRE(empty_buffer2.written() == 0);
REQUIRE(empty_buffer2.committed() == 0);
}
+71 -7
View File
@@ -9,7 +9,7 @@ void check_node_1(osmium::Node& node) {
REQUIRE(true == node.visible());
REQUIRE(333 == node.changeset());
REQUIRE(21 == node.uid());
REQUIRE(123 == node.timestamp());
REQUIRE(123 == uint32_t(node.timestamp()));
REQUIRE(osmium::Location(3.5, 4.7) == node.location());
REQUIRE(std::string("testuser") == node.user());
@@ -28,7 +28,7 @@ void check_node_2(osmium::Node& node) {
REQUIRE(true == node.visible());
REQUIRE(333 == node.changeset());
REQUIRE(21 == node.uid());
REQUIRE(123 == node.timestamp());
REQUIRE(123 == uint32_t(node.timestamp()));
REQUIRE(osmium::Location(3.5, 4.7) == node.location());
REQUIRE(std::string("testuser") == node.user());
@@ -56,13 +56,14 @@ void check_node_2(osmium::Node& node) {
REQUIRE(2 == n);
}
TEST_CASE("Buffer_Node") {
TEST_CASE("Node in Buffer") {
SECTION("buffer_node") {
constexpr size_t buffer_size = 10000;
unsigned char data[buffer_size];
constexpr size_t buffer_size = 10000;
unsigned char data[buffer_size];
osmium::memory::Buffer buffer(data, buffer_size, 0);
osmium::memory::Buffer buffer(data, buffer_size, 0);
SECTION("Add node to buffer") {
{
// add node 1
@@ -132,4 +133,67 @@ TEST_CASE("Buffer_Node") {
}
SECTION("Add buffer to another one") {
{
// add node 1
osmium::builder::NodeBuilder node_builder(buffer);
osmium::Node& node = node_builder.object();
REQUIRE(osmium::item_type::node == node.type());
node.set_id(1);
node.set_version(3);
node.set_visible(true);
node.set_changeset(333);
node.set_uid(21);
node.set_timestamp(123);
node.set_location(osmium::Location(3.5, 4.7));
node_builder.add_user("testuser");
buffer.commit();
}
osmium::memory::Buffer buffer2(buffer_size, osmium::memory::Buffer::auto_grow::yes);
buffer2.add_buffer(buffer);
buffer2.commit();
REQUIRE(buffer.committed() == buffer2.committed());
const osmium::Node& node = buffer2.get<osmium::Node>(0);
REQUIRE(node.id() == 1);
REQUIRE(123 == uint32_t(node.timestamp()));
}
SECTION("Use back_inserter on buffer") {
{
// add node 1
osmium::builder::NodeBuilder node_builder(buffer);
osmium::Node& node = node_builder.object();
REQUIRE(osmium::item_type::node == node.type());
node.set_id(1);
node.set_version(3);
node.set_visible(true);
node.set_changeset(333);
node.set_uid(21);
node.set_timestamp(123);
node.set_location(osmium::Location(3.5, 4.7));
node_builder.add_user("testuser");
buffer.commit();
}
osmium::memory::Buffer buffer2(buffer_size, osmium::memory::Buffer::auto_grow::yes);
std::copy(buffer.begin(), buffer.end(), std::back_inserter(buffer2));
REQUIRE(buffer.committed() == buffer2.committed());
const osmium::Node& node = buffer2.get<osmium::Node>(0);
REQUIRE(node.id() == 1);
REQUIRE(123 == uint32_t(node.timestamp()));
}
}
+3 -1
View File
@@ -1,5 +1,7 @@
std::string s = R"(127.4864358 16.8380041 223904 118630 18
#include <string>
static std::string s = R"(127.4864358 16.8380041 223904 118630 18
163.1103174 39.4760232 121 48 7
-4.1372725 -22.5105386 31 36 6
98.7193066 -36.2312406 1 1 1
+5
View File
@@ -0,0 +1,5 @@
<?xml version='1.0' encoding='UTF-8'?>
<osm version="0.6" generator="osmium/1.2.1">
<node id="1" version="1" timestamp="2015-09-17T11:52:00Z" uid="1" user="user_1" changeset="1" visible="false"/>
<node id="2" version="1" timestamp="2015-09-17T11:52:00Z" uid="1" user="user_1" changeset="1" visible="true" lat="1" lon="1"/>
</osm>
Binary file not shown.
+153
View File
@@ -0,0 +1,153 @@
#include "catch.hpp"
#include <locale>
#include <osmium/io/detail/string_util.hpp>
TEST_CASE("output formatted") {
std::string out;
SECTION("small results") {
osmium::io::detail::append_printf_formatted_string(out, "%d", 17);
REQUIRE(out == "17");
}
SECTION("several parameters") {
osmium::io::detail::append_printf_formatted_string(out, "%d %s", 17, "foo");
REQUIRE(out == "17 foo");
}
SECTION("string already containing something") {
out += "foo";
osmium::io::detail::append_printf_formatted_string(out, " %d", 23);
REQUIRE(out == "foo 23");
}
SECTION("large results") {
const char* str =
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
osmium::io::detail::append_printf_formatted_string(out, "%s", str);
REQUIRE(out == str);
}
}
TEST_CASE("UTF8 encoding") {
std::string out;
SECTION("append to string") {
out += "1234";
osmium::io::detail::append_utf8_encoded_string(out, "abc");
REQUIRE(out == "1234abc");
}
SECTION("don't encode alphabetic characters") {
const char* s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
osmium::io::detail::append_utf8_encoded_string(out, s);
REQUIRE(out == s);
}
SECTION("don't encode numeric characters") {
const char* s = "0123456789";
osmium::io::detail::append_utf8_encoded_string(out, s);
REQUIRE(out == s);
}
SECTION("don't encode lots of often used characters characters") {
const char* s = ".-;:_#+";
osmium::io::detail::append_utf8_encoded_string(out, s);
REQUIRE(out == s);
}
SECTION("encode characters that are special in OPL") {
osmium::io::detail::append_utf8_encoded_string(out, " \n,=@");
REQUIRE(out == "%20%%0a%%2c%%3d%%40%");
}
// workaround for missing support for u8 string literals on Windows
#if !defined(_MSC_VER)
SECTION("encode multibyte character") {
osmium::io::detail::append_utf8_encoded_string(out, u8"\u30dc_\U0001d11e_\U0001f6eb");
REQUIRE(out == "%30dc%_%1d11e%_%1f6eb%");
}
#endif
}
TEST_CASE("html encoding") {
std::string out;
SECTION("do not encode normal characters") {
const char* s = "abc123,.-";
osmium::io::detail::append_xml_encoded_string(out, s);
REQUIRE(out == s);
}
SECTION("encode special XML characters") {
const char* s = "& \" \' < > \n \r \t";
osmium::io::detail::append_xml_encoded_string(out, s);
REQUIRE(out == "&amp; &quot; &apos; &lt; &gt; &#xA; &#xD; &#x9;");
}
}
TEST_CASE("debug encoding") {
std::string out;
SECTION("do not encode normal characters") {
const char* s = "abc123,.-";
osmium::io::detail::append_debug_encoded_string(out, s, "[", "]");
REQUIRE(out == s);
}
SECTION("encode some unicode characters") {
const char* s = u8"\n_\u30dc_\U0001d11e_\U0001f6eb";
osmium::io::detail::append_debug_encoded_string(out, s, "[", "]");
REQUIRE(out == "[<U+000A>]_[<U+30DC>]_[<U+1D11E>]_[<U+1F6EB>]");
}
}
TEST_CASE("encoding of non-printable characters in the first 127 characters") {
std::locale cloc("C");
char s[] = "a\0";
for (char c = 1; c < 0x7f; ++c) {
std::string out;
s[0] = c;
SECTION("utf8 encode") {
osmium::io::detail::append_utf8_encoded_string(out, s);
if (!std::isprint(c, cloc)) {
REQUIRE(out[0] == '%');
}
}
SECTION("debug encode") {
osmium::io::detail::append_debug_encoded_string(out, s, "", "");
if (!std::isprint(c, cloc)) {
REQUIRE(out[0] == '<');
}
}
}
}
+100 -5
View File
@@ -4,6 +4,7 @@
#include <osmium/handler.hpp>
#include <osmium/io/any_compression.hpp>
#include <osmium/io/xml_input.hpp>
#include <osmium/io/pbf_input.hpp>
#include <osmium/visitor.hpp>
#include <osmium/memory/buffer.hpp>
@@ -17,6 +18,27 @@ struct CountHandler : public osmium::handler::Handler {
}; // class CountHandler
struct ZeroPositionNodeCountHandler : public osmium::handler::Handler {
// number of nodes seen at zero position, or visible with undefined
// location.
int count = 0;
int total_count = 0; // total number of nodes seen
const osmium::Location zero = osmium::Location(int32_t(0), int32_t(0));
void node(osmium::Node &n) {
// no nodes in the history file have a zero location, and
// no visible nodes should have an undefined location.
if ((n.location() == zero) ||
(n.visible() && !n.location())) {
++count;
}
++total_count;
}
}; // class ZeroPositionNodeCountHandler
TEST_CASE("Reader") {
SECTION("reader can be initialized with file") {
@@ -34,7 +56,7 @@ TEST_CASE("Reader") {
osmium::apply(reader, handler);
}
SECTION("should return invalid buffer after eof") {
SECTION("should throw after eof") {
osmium::io::File file(with_data_dir("t/io/data.osm"));
osmium::io::Reader reader(file);
@@ -45,9 +67,9 @@ TEST_CASE("Reader") {
REQUIRE(reader.eof());
// extra read always returns invalid buffer
osmium::memory::Buffer buffer = reader.read();
REQUIRE(!buffer);
REQUIRE_THROWS_AS({
reader.read();
}, osmium::io_error);
}
SECTION("should not hang when apply() is called twice on reader") {
@@ -56,7 +78,9 @@ TEST_CASE("Reader") {
osmium::handler::Handler handler;
osmium::apply(reader, handler);
osmium::apply(reader, handler);
REQUIRE_THROWS_AS({
osmium::apply(reader, handler);
}, osmium::io_error);
}
SECTION("should work with a buffer with uncompressed data") {
@@ -113,5 +137,76 @@ TEST_CASE("Reader") {
REQUIRE(handler.count == 1);
}
SECTION("should decode zero node positions in history (XML)") {
osmium::io::Reader reader(with_data_dir("t/io/deleted_nodes.osh"),
osmium::osm_entity_bits::node);
ZeroPositionNodeCountHandler handler;
REQUIRE(handler.count == 0);
REQUIRE(handler.total_count == 0);
osmium::apply(reader, handler);
REQUIRE(handler.count == 0);
REQUIRE(handler.total_count == 2);
}
SECTION("should decode zero node positions in history (PBF)") {
osmium::io::Reader reader(with_data_dir("t/io/deleted_nodes.osh.pbf"),
osmium::osm_entity_bits::node);
ZeroPositionNodeCountHandler handler;
REQUIRE(handler.count == 0);
REQUIRE(handler.total_count == 0);
osmium::apply(reader, handler);
REQUIRE(handler.count == 0);
REQUIRE(handler.total_count == 2);
}
}
TEST_CASE("Reader failure modes") {
SECTION("should fail with nonexistent file") {
REQUIRE_THROWS({
osmium::io::Reader reader(with_data_dir("t/io/nonexistent-file.osm"));
});
}
SECTION("should fail with nonexistent file (gz)") {
REQUIRE_THROWS({
osmium::io::Reader reader(with_data_dir("t/io/nonexistent-file.osm.gz"));
});
}
SECTION("should fail with nonexistent file (pbf)") {
REQUIRE_THROWS({
osmium::io::Reader reader(with_data_dir("t/io/nonexistent-file.osm.pbf"));
});
}
SECTION("should work when there is an exception in main thread before getting header") {
try {
osmium::io::Reader reader(with_data_dir("t/io/data.osm"));
REQUIRE(!reader.eof());
throw std::runtime_error("foo");
} catch (...) {
}
}
SECTION("should work when there is an exception in main thread while reading") {
try {
osmium::io::Reader reader(with_data_dir("t/io/data.osm"));
REQUIRE(!reader.eof());
auto header = reader.header();
throw std::runtime_error("foo");
} catch (...) {
}
}
}
@@ -0,0 +1,145 @@
#include "catch.hpp"
#include "utils.hpp"
#include <string>
#include <osmium/io/compression.hpp>
#include <osmium/io/xml_input.hpp>
// The MockDecompressor behaves like other Decompressor classes, but "invents"
// OSM data in XML format that can be read. Through a parameter to the
// constructor it can be instructed to throw an exception in specific parts
// of its code. This is then used to test the internals of the Reader.
class MockDecompressor : public osmium::io::Decompressor {
std::string m_fail_in;
int m_read_count = 0;
public:
MockDecompressor(const std::string& fail_in) :
Decompressor(),
m_fail_in(fail_in) {
if (m_fail_in == "constructor") {
throw std::runtime_error("error constructor");
}
}
~MockDecompressor() noexcept final = default;
void add_node(std::string& s, int i) {
s += "<node id='";
s += std::to_string(i);
s += "' version='1' timestamp='2014-01-01T00:00:00Z' uid='1' user='test' changeset='1' lon='1.02' lat='1.02'/>\n";
}
std::string read() final {
std::string buffer;
++m_read_count;
if (m_read_count == 1) {
if (m_fail_in == "first read") {
throw std::runtime_error("error first read");
} else {
buffer += "<?xml version='1.0' encoding='UTF-8'?>\n<osm version='0.6' generator='testdata'>\n";
for (int i = 0; i < 1000; ++i) {
add_node(buffer, i);
}
}
} else if (m_read_count == 2) {
if (m_fail_in == "second read") {
throw std::runtime_error("error second read");
} else {
for (int i = 1000; i < 2000; ++i) {
add_node(buffer, i);
}
}
} else if (m_read_count == 3) {
buffer += "</osm>";
}
return buffer;
}
void close() final {
if (m_fail_in == "close") {
throw std::runtime_error("error close");
}
}
}; // class MockDecompressor
TEST_CASE("Test Reader using MockDecompressor") {
std::string fail_in;
osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::gzip,
[](int, osmium::io::fsync) { return nullptr; },
[&](int) { return new MockDecompressor(fail_in); },
[](const char*, size_t) { return nullptr; }
);
SECTION("fail in constructor") {
fail_in = "constructor";
try {
osmium::io::Reader reader(with_data_dir("t/io/data.osm.gz"));
REQUIRE(false);
} catch (std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error constructor");
}
}
SECTION("fail in first read") {
fail_in = "first read";
try {
osmium::io::Reader reader(with_data_dir("t/io/data.osm.gz"));
reader.read();
REQUIRE(false);
} catch (std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error first read");
}
}
SECTION("fail in second read") {
fail_in = "second read";
try {
osmium::io::Reader reader(with_data_dir("t/io/data.osm.gz"));
reader.read();
reader.read();
REQUIRE(false);
} catch (std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error second read");
}
}
SECTION("fail in close") {
fail_in = "close";
try {
osmium::io::Reader reader(with_data_dir("t/io/data.osm.gz"));
reader.read();
reader.read();
reader.read();
reader.close();
REQUIRE(false);
} catch (std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error close");
}
}
SECTION("not failing") {
fail_in = "not";
osmium::io::Reader reader(with_data_dir("t/io/data.osm.gz"));
reader.read();
reader.close();
REQUIRE(true);
}
}
@@ -0,0 +1,123 @@
#include "catch.hpp"
#include "utils.hpp"
#include <string>
#include <osmium/builder/osm_object_builder.hpp>
#include <osmium/io/compression.hpp>
#include <osmium/io/detail/input_format.hpp>
#include <osmium/io/detail/queue_util.hpp>
#include <osmium/io/file_format.hpp>
#include <osmium/io/header.hpp>
#include <osmium/io/reader.hpp>
#include <osmium/thread/queue.hpp>
#include <osmium/thread/util.hpp>
class MockParser : public osmium::io::detail::Parser {
std::string m_fail_in;
public:
MockParser(osmium::io::detail::future_string_queue_type& input_queue,
osmium::io::detail::future_buffer_queue_type& output_queue,
std::promise<osmium::io::Header>& header_promise,
osmium::osm_entity_bits::type read_types,
const std::string& fail_in) :
Parser(input_queue, output_queue, header_promise, read_types),
m_fail_in(fail_in) {
}
osmium::memory::Buffer create_testdata() {
osmium::memory::Buffer buffer(1000);
{
osmium::builder::NodeBuilder nb(buffer);
nb.add_user("foo");
}
buffer.commit();
return buffer;
}
void run() final {
osmium::thread::set_thread_name("_osmium_mock_in");
if (m_fail_in == "header") {
throw std::runtime_error("error in header");
}
set_header_value(osmium::io::Header{});
send_to_output_queue(create_testdata());
if (m_fail_in == "read") {
throw std::runtime_error("error in read");
}
}
}; // class MockParser
TEST_CASE("Test Reader using MockParser") {
std::string fail_in;
osmium::io::detail::ParserFactory::instance().register_parser(
osmium::io::file_format::xml,
[&](osmium::io::detail::future_string_queue_type& input_queue,
osmium::io::detail::future_buffer_queue_type& output_queue,
std::promise<osmium::io::Header>& header_promise,
osmium::osm_entity_bits::type read_which_entities) {
return std::unique_ptr<osmium::io::detail::Parser>(new MockParser(input_queue, output_queue, header_promise, read_which_entities, fail_in));
});
SECTION("no failure") {
fail_in = "";
osmium::io::Reader reader(with_data_dir("t/io/data.osm"));
auto header = reader.header();
REQUIRE(reader.read());
REQUIRE(!reader.read());
REQUIRE(reader.eof());
reader.close();
}
SECTION("throw in header") {
fail_in = "header";
try {
osmium::io::Reader reader(with_data_dir("t/io/data.osm"));
reader.header();
} catch (std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error in header");
}
}
SECTION("throw in read") {
fail_in = "read";
osmium::io::Reader reader(with_data_dir("t/io/data.osm"));
reader.header();
try {
reader.read();
} catch (std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error in read");
}
reader.close();
}
SECTION("throw in user code") {
fail_in = "";
osmium::io::Reader reader(with_data_dir("t/io/data.osm"));
reader.header();
try {
throw std::runtime_error("error in user code");
} catch (std::runtime_error& e) {
REQUIRE(std::string{e.what()} == "error in user code");
}
REQUIRE(reader.read());
REQUIRE(!reader.read());
REQUIRE(reader.eof());
reader.close();
}
}
+3 -3
View File
@@ -33,9 +33,9 @@ TEST_CASE("String store") {
}
SECTION("add zero-length string and longer strings") {
const char* s1 = ss.add("");
const char* s2 = ss.add("xxx");
const char* s3 = ss.add("yyyyy");
ss.add("");
ss.add("xxx");
ss.add("yyyyy");
auto it = ss.begin();
REQUIRE(std::string(*it++) == "");
+117
View File
@@ -0,0 +1,117 @@
#include "catch.hpp"
#include "utils.hpp"
#include <algorithm>
#include <osmium/io/any_compression.hpp>
#include <osmium/io/xml_input.hpp>
#include <osmium/io/xml_output.hpp>
#include <osmium/io/output_iterator.hpp>
#include <osmium/memory/buffer.hpp>
TEST_CASE("Writer") {
osmium::io::Header header;
header.set("generator", "test_writer.cpp");
osmium::io::Reader reader(with_data_dir("t/io/data.osm"));
osmium::memory::Buffer buffer = reader.read();
REQUIRE(buffer);
REQUIRE(buffer.committed() > 0);
auto num = std::distance(buffer.cbegin<osmium::OSMObject>(), buffer.cend<osmium::OSMObject>());
REQUIRE(num > 0);
REQUIRE(buffer.cbegin<osmium::OSMObject>()->id() == 1);
std::string filename;
SECTION("Empty writes") {
SECTION("Empty buffer") {
filename = "test-writer-out-empty-buffer.osm";
osmium::io::Writer writer(filename, header, osmium::io::overwrite::allow);
osmium::memory::Buffer empty_buffer(1024);
writer(std::move(empty_buffer));
writer.close();
}
SECTION("Invalid buffer") {
filename = "test-writer-out-invalid-buffer.osm";
osmium::io::Writer writer(filename, header, osmium::io::overwrite::allow);
osmium::memory::Buffer invalid_buffer;
writer(std::move(invalid_buffer));
writer.close();
}
osmium::io::Reader reader_check(filename);
osmium::memory::Buffer buffer_check = reader_check.read();
REQUIRE(!buffer_check);
}
SECTION("Successfull writes") {
SECTION("Writer buffer") {
filename = "test-writer-out-buffer.osm";
osmium::io::Writer writer(filename, header, osmium::io::overwrite::allow);
writer(std::move(buffer));
writer.close();
REQUIRE_THROWS_AS({
writer(osmium::memory::Buffer{});
}, osmium::io_error);
}
SECTION("Writer item") {
filename = "test-writer-out-item.osm";
osmium::io::Writer writer(filename, header, osmium::io::overwrite::allow);
for (const auto& item : buffer) {
writer(item);
}
writer.close();
}
SECTION("Writer output iterator") {
filename = "test-writer-out-iterator.osm";
osmium::io::Writer writer(filename, header, osmium::io::overwrite::allow);
auto it = osmium::io::make_output_iterator(writer);
std::copy(buffer.cbegin(), buffer.cend(), it);
writer.close();
}
osmium::io::Reader reader_check(filename);
osmium::memory::Buffer buffer_check = reader_check.read();
REQUIRE(buffer_check);
REQUIRE(buffer_check.committed() > 0);
REQUIRE(std::distance(buffer_check.cbegin<osmium::OSMObject>(), buffer_check.cend<osmium::OSMObject>()) == num);
REQUIRE(buffer_check.cbegin<osmium::OSMObject>()->id() == 1);
}
SECTION("Interrupted write") {
int error = 0;
try {
SECTION("fail after open") {
filename = "test-writer-out-fail1.osm";
osmium::io::Writer writer(filename, header, osmium::io::overwrite::allow);
throw 1;
}
SECTION("fail after write") {
filename = "test-writer-out-fail2.osm";
osmium::io::Writer writer(filename, header, osmium::io::overwrite::allow);
writer(std::move(buffer));
throw 2;
}
} catch (int e) {
error = e;
}
REQUIRE(error > 0);
}
}
@@ -0,0 +1,99 @@
#include "catch.hpp"
#include "utils.hpp"
#include <stdexcept>
#include <string>
#include <osmium/io/compression.hpp>
#include <osmium/io/xml_input.hpp>
#include <osmium/io/xml_output.hpp>
class MockCompressor : public osmium::io::Compressor {
std::string m_fail_in;
public:
MockCompressor(const std::string& fail_in) :
Compressor(osmium::io::fsync::no),
m_fail_in(fail_in) {
if (m_fail_in == "constructor") {
throw std::logic_error("constructor");
}
}
~MockCompressor() noexcept final = default;
void write(const std::string&) final {
if (m_fail_in == "write") {
throw std::logic_error("write");
}
}
void close() final {
if (m_fail_in == "close") {
throw std::logic_error("close");
}
}
}; // class MockCompressor
TEST_CASE("Write with mock compressor") {
std::string fail_in;
osmium::io::CompressionFactory::instance().register_compression(osmium::io::file_compression::gzip,
[&](int, osmium::io::fsync) { return new MockCompressor(fail_in); },
[](int) { return nullptr; },
[](const char*, size_t) { return nullptr; }
);
osmium::io::Header header;
header.set("generator", "test_writer_with_mock_compression.cpp");
osmium::io::Reader reader(with_data_dir("t/io/data.osm"));
osmium::memory::Buffer buffer = reader.read();
REQUIRE(buffer);
REQUIRE(buffer.committed() > 0);
auto num = std::distance(buffer.cbegin<osmium::OSMObject>(), buffer.cend<osmium::OSMObject>());
REQUIRE(num > 0);
SECTION("fail on construction") {
fail_in = "constructor";
REQUIRE_THROWS_AS({
osmium::io::Writer writer("test-writer-mock-fail-on-construction.osm.gz", header, osmium::io::overwrite::allow);
writer(std::move(buffer));
writer.close();
}, std::logic_error);
}
SECTION("fail on write") {
fail_in = "write";
REQUIRE_THROWS_AS({
osmium::io::Writer writer("test-writer-mock-fail-on-write.osm.gz", header, osmium::io::overwrite::allow);
writer(std::move(buffer));
writer.close();
}, std::logic_error);
}
SECTION("fail on close") {
fail_in = "close";
REQUIRE_THROWS_AS({
osmium::io::Writer writer("test-writer-mock-fail-on-close.osm.gz", header, osmium::io::overwrite::allow);
writer(std::move(buffer));
writer.close();
}, std::logic_error);
}
}
@@ -0,0 +1,105 @@
#include "catch.hpp"
#include "utils.hpp"
#include <stdexcept>
#include <string>
#include <osmium/io/compression.hpp>
#include <osmium/io/detail/output_format.hpp>
#include <osmium/io/detail/queue_util.hpp>
#include <osmium/io/xml_input.hpp>
#include <osmium/io/writer.hpp>
class MockOutputFormat : public osmium::io::detail::OutputFormat {
std::string m_fail_in;
public:
MockOutputFormat(const osmium::io::File&, osmium::io::detail::future_string_queue_type& output_queue, const std::string& fail_in) :
OutputFormat(output_queue),
m_fail_in(fail_in) {
}
void write_header(const osmium::io::Header&) final {
if (m_fail_in == "header") {
throw std::logic_error("header");
}
send_to_output_queue(std::string{"header"});
}
void write_buffer(osmium::memory::Buffer&&) final {
if (m_fail_in == "write") {
throw std::logic_error("write");
}
send_to_output_queue(std::string{"write"});
}
void write_end() final {
if (m_fail_in == "write_end") {
throw std::logic_error("write_end");
}
send_to_output_queue(std::string{"end"});
}
}; // class MockOutputFormat
TEST_CASE("Test Writer with MockOutputFormat") {
std::string fail_in;
osmium::io::detail::OutputFormatFactory::instance().register_output_format(
osmium::io::file_format::xml,
[&](const osmium::io::File& file, osmium::io::detail::future_string_queue_type& output_queue) {
return new MockOutputFormat(file, output_queue, fail_in);
});
osmium::io::Header header;
header.set("generator", "test_writer_with_mock_encoder.cpp");
osmium::io::Reader reader(with_data_dir("t/io/data.osm"));
osmium::memory::Buffer buffer = reader.read();
REQUIRE(buffer);
REQUIRE(buffer.committed() > 0);
auto num = std::distance(buffer.cbegin<osmium::OSMObject>(), buffer.cend<osmium::OSMObject>());
REQUIRE(num > 0);
SECTION("error in header") {
fail_in = "header";
REQUIRE_THROWS_AS({
osmium::io::Writer writer("test-writer-mock-fail-on-construction.osm", header, osmium::io::overwrite::allow);
writer(std::move(buffer));
writer.close();
}, std::logic_error);
}
SECTION("error in write") {
fail_in = "write";
REQUIRE_THROWS_AS({
osmium::io::Writer writer("test-writer-mock-fail-on-construction.osm", header, osmium::io::overwrite::allow);
writer(std::move(buffer));
writer.close();
}, std::logic_error);
}
SECTION("error in write_end") {
fail_in = "write_end";
REQUIRE_THROWS_AS({
osmium::io::Writer writer("test-writer-mock-fail-on-construction.osm", header, osmium::io::overwrite::allow);
writer(std::move(buffer));
writer.close();
}, std::logic_error);
}
}
+11
View File
@@ -100,3 +100,14 @@ TEST_CASE("empty keys and values are okay") {
REQUIRE(std::string("") == tl.get_value_by_key("empty value"));
REQUIRE(std::string("empty key") == tl.get_value_by_key(""));
}
TEST_CASE("tag key or value is too long") {
osmium::memory::Buffer buffer(10240);
osmium::builder::TagListBuilder builder(buffer);
const char kv[2000] = "";
builder.add_tag(kv, 1, kv, 1000);
REQUIRE_THROWS(builder.add_tag(kv, 1500, kv, 1));
REQUIRE_THROWS(builder.add_tag(kv, 1, kv, 1500));
}
+33 -29
View File
@@ -5,14 +5,7 @@
#include <thread>
#include <osmium/thread/pool.hpp>
static std::atomic<int> result;
struct test_job_ok {
void operator()() const {
result = 1;
}
};
#include <osmium/util/compatibility.hpp>
struct test_job_with_result {
int operator()() const {
@@ -21,44 +14,55 @@ struct test_job_with_result {
};
struct test_job_throw {
void operator()() const {
OSMIUM_NORETURN void operator()() const {
throw std::runtime_error("exception in pool thread");
}
};
TEST_CASE("number of threads in pool") {
// hardcoded setting
REQUIRE(osmium::thread::detail::get_pool_size( 1, 0, 2) == 1);
REQUIRE(osmium::thread::detail::get_pool_size( 4, 0, 2) == 4);
REQUIRE(osmium::thread::detail::get_pool_size( 4, 0, 4) == 4);
REQUIRE(osmium::thread::detail::get_pool_size(16, 0, 4) == 16);
REQUIRE(osmium::thread::detail::get_pool_size(16, 0, 16) == 16);
REQUIRE(osmium::thread::detail::get_pool_size( 8, 4, 2) == 8);
REQUIRE(osmium::thread::detail::get_pool_size( 8, 16, 2) == 8);
REQUIRE(osmium::thread::detail::get_pool_size(-2, 16, 2) == 1);
REQUIRE(osmium::thread::detail::get_pool_size(-2, 16, 8) == 6);
// user decides through OSMIUM_POOL_THREADS env variable
REQUIRE(osmium::thread::detail::get_pool_size( 0, 0, 2) == 1);
REQUIRE(osmium::thread::detail::get_pool_size( 0, -2, 4) == 2);
REQUIRE(osmium::thread::detail::get_pool_size( 0, -1, 8) == 7);
REQUIRE(osmium::thread::detail::get_pool_size( 0, 0, 16) == 14);
REQUIRE(osmium::thread::detail::get_pool_size( 0, 1, 16) == 1);
REQUIRE(osmium::thread::detail::get_pool_size( 0, 2, 16) == 2);
REQUIRE(osmium::thread::detail::get_pool_size( 0, 4, 16) == 4);
REQUIRE(osmium::thread::detail::get_pool_size( 0, 8, 16) == 8);
// outliers
REQUIRE(osmium::thread::detail::get_pool_size(-100, 0, 16) == 1);
REQUIRE(osmium::thread::detail::get_pool_size(1000, 0, 16) == 256);
}
TEST_CASE("thread") {
auto& pool = osmium::thread::Pool::instance();
SECTION("can get access to thread pool") {
auto& pool = osmium::thread::Pool::instance();
REQUIRE(pool.queue_empty());
}
SECTION("can send job to thread pool") {
auto& pool = osmium::thread::Pool::instance();
result = 0;
auto future = pool.submit(test_job_ok {});
// wait a bit for the other thread to get a chance to run
std::this_thread::sleep_for(std::chrono::milliseconds(1));
REQUIRE(result == 1);
future.get();
REQUIRE(true);
}
SECTION("can send job to thread pool") {
auto& pool = osmium::thread::Pool::instance();
auto future = pool.submit(test_job_with_result {});
REQUIRE(future.get() == 42);
}
SECTION("can throw from job in thread pool") {
auto& pool = osmium::thread::Pool::instance();
result = 0;
auto future = pool.submit(test_job_throw {});
REQUIRE_THROWS_AS(future.get(), std::runtime_error);
-81
View File
@@ -1,81 +0,0 @@
#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);
}
}
+30 -4
View File
@@ -4,24 +4,50 @@
#include <osmium/util/delta.hpp>
TEST_CASE("delta encode") {
TEST_CASE("delta encode int") {
osmium::util::DeltaEncode<int> x;
SECTION("int") {
REQUIRE(x.update(17) == 17);
REQUIRE(x.update(10) == -7);
REQUIRE(x.update(-10) == -20);
}
}
TEST_CASE("delta decode") {
TEST_CASE("delta decode int") {
osmium::util::DeltaDecode<int> x;
SECTION("int") {
REQUIRE(x.update(17) == 17);
REQUIRE(x.update(10) == 27);
REQUIRE(x.update(-40) == -13);
}
}
TEST_CASE("delta encode unsigned int") {
osmium::util::DeltaEncode<unsigned int> x;
SECTION("int") {
REQUIRE(x.update(17) == 17);
REQUIRE(x.update(10) == -7);
REQUIRE(x.update(0) == -10);
}
}
TEST_CASE("delta decode unsigned int") {
osmium::util::DeltaDecode<unsigned int> x;
SECTION("int") {
REQUIRE(x.update(17) == 17);
REQUIRE(x.update(10) == 27);
REQUIRE(x.update(-15) == 12);
}
}
@@ -30,13 +56,13 @@ TEST_CASE("delta encode and decode") {
std::vector<int> a = { 5, -9, 22, 13, 0, 23 };
osmium::util::DeltaEncode<int> de;
osmium::util::DeltaEncode<int, int> de;
std::vector<int> b;
for (int x : a) {
b.push_back(de.update(x));
}
osmium::util::DeltaDecode<int> dd;
osmium::util::DeltaDecode<int, int> dd;
std::vector<int> c;
for (int x : b) {
c.push_back(dd.update(x));
+2
View File
@@ -3,6 +3,7 @@
#include <osmium/util/file.hpp>
#ifdef _WIN32
#include <crtdbg.h>
// https://msdn.microsoft.com/en-us/library/ksazx244.aspx
// https://msdn.microsoft.com/en-us/library/a9yf33zb.aspx
class DoNothingInvalidParameterHandler {
@@ -23,6 +24,7 @@ public:
DoNothingInvalidParameterHandler() :
old_handler(_set_invalid_parameter_handler(invalid_parameter_handler)) {
_CrtSetReportMode(_CRT_ASSERT, 0);
}
~DoNothingInvalidParameterHandler() {
+41 -8
View File
@@ -6,43 +6,76 @@
TEST_CASE("Options") {
SECTION("set_simple") {
osmium::util::Options o;
osmium::util::Options o;
SECTION("set a single value from string") {
o.set("foo", "bar");
REQUIRE("bar" == o.get("foo"));
REQUIRE("" == o.get("empty"));
REQUIRE("default" == o.get("empty", "default"));
REQUIRE(!o.is_true("foo"));
REQUIRE(!o.is_true("empty"));
REQUIRE(o.is_not_false("foo"));
REQUIRE(o.is_not_false("empty"));
REQUIRE(1 == o.size());
}
SECTION("set_from_bool") {
osmium::util::Options o;
SECTION("set values from booleans") {
o.set("t", true);
o.set("f", false);
REQUIRE("true" == o.get("t"));
REQUIRE("false" == o.get("f"));
REQUIRE("" == o.get("empty"));
REQUIRE(o.is_true("t"));
REQUIRE(!o.is_true("f"));
REQUIRE(o.is_not_false("t"));
REQUIRE(!o.is_not_false("f"));
REQUIRE(2 == o.size());
}
SECTION("set_from_single_string_with_equals") {
osmium::util::Options o;
SECTION("set value from string with equal sign") {
o.set("foo=bar");
REQUIRE("bar" == o.get("foo"));
REQUIRE(1 == o.size());
}
SECTION("set_from_single_string_without_equals") {
osmium::util::Options o;
SECTION("set value from string without equal sign") {
o.set("foo");
REQUIRE("true" == o.get("foo"));
REQUIRE(o.is_true("foo"));
REQUIRE(o.is_not_false("foo"));
REQUIRE(1 == o.size());
}
}
TEST_CASE("Options with initializer list") {
osmium::util::Options o{ { "foo", "true" }, { "bar", "17" } };
REQUIRE(o.get("foo") == "true");
REQUIRE(o.get("bar") == "17");
REQUIRE(o.is_true("foo"));
REQUIRE_FALSE(o.is_true("bar"));
REQUIRE(o.size() == 2);
SECTION("Change existing value") {
o.set("foo", "false");
REQUIRE_FALSE(o.is_true("foo"));
}
SECTION("Add new value") {
o.set("new", "something");
REQUIRE_FALSE(o.is_true("new"));
REQUIRE(o.get("new") == "something");
}
}