* print tracebacks and line numbers for Lua runtime errors * revert format changes * update changelog with lua traceback, #6564 * revert using protected_function for old GetStringListFromFunction and source_function #6564 * add unit test for line numbers in tracebacks, #6564 * apply clang-format (#6564) * remove unused test helper function, #6564 * suppress leaksanitizer warnings in extract-tests, #6564 When the extractor encounters a lua runtime error, some osmium objects are not freed. In production this doesn't matter because these errors bring down OSRM. In the tests we catch them to ensure they occur, and the leaksanitizer flags them.
162 lines
6.1 KiB
C++
162 lines
6.1 KiB
C++
#include <boost/test/unit_test.hpp>
|
|
|
|
#include "osrm/exception.hpp"
|
|
#include "osrm/extractor.hpp"
|
|
#include "osrm/extractor_config.hpp"
|
|
|
|
#include <boost/algorithm/string.hpp>
|
|
#include <thread>
|
|
|
|
// utility class to redirect stderr so we can test it
|
|
// inspired by https://stackoverflow.com/questions/5405016
|
|
class redirect_stderr
|
|
{
|
|
// constructor: accept a pointer to a buffer where stderr will be redirected
|
|
public:
|
|
redirect_stderr(std::streambuf *buf)
|
|
// store the original buffer for later (original buffer returned by rdbuf)
|
|
: old(std::cerr.rdbuf(buf))
|
|
{
|
|
}
|
|
|
|
// destructor: restore the original cerr, regardless of how this class gets destroyed
|
|
~redirect_stderr() { std::cerr.rdbuf(old); }
|
|
|
|
// place to store the buffer
|
|
private:
|
|
std::streambuf *old;
|
|
};
|
|
|
|
BOOST_AUTO_TEST_SUITE(library_extract)
|
|
|
|
BOOST_AUTO_TEST_CASE(test_extract_with_invalid_config)
|
|
{
|
|
osrm::ExtractorConfig config;
|
|
config.requested_num_threads = std::thread::hardware_concurrency();
|
|
BOOST_CHECK_THROW(osrm::extract(config),
|
|
std::exception); // including osrm::util::exception, osmium::io_error, etc.
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_extract_with_valid_config)
|
|
{
|
|
osrm::ExtractorConfig config;
|
|
config.input_path = OSRM_TEST_DATA_DIR "/monaco.osm.pbf";
|
|
config.UseDefaultOutputNames(OSRM_TEST_DATA_DIR "/monaco.osm.pbf");
|
|
config.profile_path = OSRM_TEST_DATA_DIR "/../../profiles/car.lua";
|
|
config.small_component_size = 1000;
|
|
config.requested_num_threads = std::thread::hardware_concurrency();
|
|
BOOST_CHECK_NO_THROW(osrm::extract(config));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_setup_runtime_error)
|
|
{
|
|
osrm::ExtractorConfig config;
|
|
config.input_path = OSRM_TEST_DATA_DIR "/monaco.osm.pbf";
|
|
config.UseDefaultOutputNames(OSRM_TEST_DATA_DIR "/monaco.osm.pbf");
|
|
config.profile_path = OSRM_TEST_DATA_DIR "/profiles/bad_setup.lua";
|
|
config.small_component_size = 1000;
|
|
config.requested_num_threads = std::thread::hardware_concurrency();
|
|
|
|
std::stringstream output;
|
|
|
|
{
|
|
redirect_stderr redir(output.rdbuf());
|
|
BOOST_CHECK_THROW(osrm::extract(config), osrm::util::exception);
|
|
}
|
|
|
|
// We just look for the line number, file name, and error message. This avoids portability
|
|
// issues since the output contains the full path to the file, which may change between systems
|
|
BOOST_CHECK(boost::algorithm::contains(output.str(),
|
|
"bad_setup.lua:6: attempt to compare number with nil"));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_way_runtime_error)
|
|
{
|
|
osrm::ExtractorConfig config;
|
|
config.input_path = OSRM_TEST_DATA_DIR "/monaco.osm.pbf";
|
|
config.UseDefaultOutputNames(OSRM_TEST_DATA_DIR "/monaco.osm.pbf");
|
|
config.profile_path = OSRM_TEST_DATA_DIR "/profiles/bad_way.lua";
|
|
config.small_component_size = 1000;
|
|
config.requested_num_threads = std::thread::hardware_concurrency();
|
|
|
|
std::stringstream output;
|
|
|
|
{
|
|
redirect_stderr redir(output.rdbuf());
|
|
BOOST_CHECK_THROW(osrm::extract(config), osrm::util::exception);
|
|
}
|
|
|
|
// We just look for the line number, file name, and error message. This avoids portability
|
|
// issues since the output contains the full path to the file, which may change between systems
|
|
BOOST_CHECK(boost::algorithm::contains(output.str(),
|
|
"bad_way.lua:41: attempt to compare number with nil"));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_node_runtime_error)
|
|
{
|
|
osrm::ExtractorConfig config;
|
|
config.input_path = OSRM_TEST_DATA_DIR "/monaco.osm.pbf";
|
|
config.UseDefaultOutputNames(OSRM_TEST_DATA_DIR "/monaco.osm.pbf");
|
|
config.profile_path = OSRM_TEST_DATA_DIR "/profiles/bad_node.lua";
|
|
config.small_component_size = 1000;
|
|
config.requested_num_threads = std::thread::hardware_concurrency();
|
|
|
|
std::stringstream output;
|
|
|
|
{
|
|
redirect_stderr redir(output.rdbuf());
|
|
BOOST_CHECK_THROW(osrm::extract(config), osrm::util::exception);
|
|
}
|
|
|
|
// We just look for the line number, file name, and error message. This avoids portability
|
|
// issues since the output contains the full path to the file, which may change between systems
|
|
BOOST_CHECK(boost::algorithm::contains(output.str(),
|
|
"bad_node.lua:36: attempt to compare number with nil"));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_segment_runtime_error)
|
|
{
|
|
osrm::ExtractorConfig config;
|
|
config.input_path = OSRM_TEST_DATA_DIR "/monaco.osm.pbf";
|
|
config.UseDefaultOutputNames(OSRM_TEST_DATA_DIR "/monaco.osm.pbf");
|
|
config.profile_path = OSRM_TEST_DATA_DIR "/profiles/bad_segment.lua";
|
|
config.small_component_size = 1000;
|
|
config.requested_num_threads = std::thread::hardware_concurrency();
|
|
|
|
std::stringstream output;
|
|
|
|
{
|
|
redirect_stderr redir(output.rdbuf());
|
|
BOOST_CHECK_THROW(osrm::extract(config), osrm::util::exception);
|
|
}
|
|
|
|
// We just look for the line number, file name, and error message. This avoids portability
|
|
// issues since the output contains the full path to the file, which may change between systems
|
|
BOOST_CHECK(boost::algorithm::contains(
|
|
output.str(), "bad_segment.lua:132: attempt to compare number with nil"));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(test_turn_runtime_error)
|
|
{
|
|
osrm::ExtractorConfig config;
|
|
config.input_path = OSRM_TEST_DATA_DIR "/monaco.osm.pbf";
|
|
config.UseDefaultOutputNames(OSRM_TEST_DATA_DIR "/monaco.osm.pbf");
|
|
config.profile_path = OSRM_TEST_DATA_DIR "/profiles/bad_turn.lua";
|
|
config.small_component_size = 1000;
|
|
config.requested_num_threads = std::thread::hardware_concurrency();
|
|
|
|
std::stringstream output;
|
|
|
|
{
|
|
redirect_stderr redir(output.rdbuf());
|
|
BOOST_CHECK_THROW(osrm::extract(config), osrm::util::exception);
|
|
}
|
|
|
|
// We just look for the line number, file name, and error message. This avoids portability
|
|
// issues since the output contains the full path to the file, which may change between systems
|
|
BOOST_CHECK(boost::algorithm::contains(output.str(),
|
|
"bad_turn.lua:122: attempt to compare number with nil"));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|