Fix running multiple configs of test_utf8_codecvt in parallel.

When running multiple different configurations of test_utf8_codecvt, e.g.
debug/release or different C++ versions, the test used to spuriously fail
because the test processes would conflict through the files the test creates.

To work around this, the test now creates the files in the same directory
where the test executable is located. With Boost.Build, that means the files
will be created in different directories for different configs.

This should fix spurious test failures in CI.
This commit is contained in:
Andrey Semashev
2021-09-16 01:26:08 +03:00
parent 399a7a65b8
commit 2ca25f118d

View File

@ -19,6 +19,10 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/core/no_exceptions_support.hpp> #include <boost/core/no_exceptions_support.hpp>
#if !defined(BOOST_NO_EXCEPTIONS)
#include <exception>
#endif
#define BOOST_UTF8_BEGIN_NAMESPACE namespace boost { namespace detail { #define BOOST_UTF8_BEGIN_NAMESPACE namespace boost { namespace detail {
#define BOOST_UTF8_END_NAMESPACE } } #define BOOST_UTF8_END_NAMESPACE } }
#include <boost/detail/utf8_codecvt_facet.hpp> #include <boost/detail/utf8_codecvt_facet.hpp>
@ -47,6 +51,9 @@ namespace std{
#include <boost/core/lightweight_test.hpp> #include <boost/core/lightweight_test.hpp>
// Directory of the test executable
std::string executable_dir;
template<std::size_t s> template<std::size_t s>
struct test_data struct test_data
{ {
@ -134,7 +141,7 @@ test_main(int /* argc */, char * /* argv */[]) {
// Send our test UTF-8 data to file // Send our test UTF-8 data to file
{ {
std::ofstream ofs; std::ofstream ofs;
ofs.open("test.dat"); ofs.open((executable_dir + "test.dat").c_str());
std::copy( std::copy(
td::utf8_encoding, td::utf8_encoding,
td::utf8_encoding + sizeof(td::utf8_encoding) / sizeof(unsigned char), td::utf8_encoding + sizeof(td::utf8_encoding) / sizeof(unsigned char),
@ -147,7 +154,7 @@ test_main(int /* argc */, char * /* argv */[]) {
{ {
std::wifstream ifs; std::wifstream ifs;
ifs.imbue(utf8_locale); ifs.imbue(utf8_locale);
ifs.open("test.dat"); ifs.open((executable_dir + "test.dat").c_str());
std::wint_t item = 0; std::wint_t item = 0;
// note can't use normal vector from iterator constructor because // note can't use normal vector from iterator constructor because
@ -169,7 +176,7 @@ test_main(int /* argc */, char * /* argv */[]) {
{ {
std::wofstream ofs; std::wofstream ofs;
ofs.imbue(utf8_locale); ofs.imbue(utf8_locale);
ofs.open("test2.dat"); ofs.open((executable_dir + "test2.dat").c_str());
std::copy( std::copy(
from_file.begin(), from_file.begin(),
from_file.end(), from_file.end(),
@ -182,12 +189,12 @@ test_main(int /* argc */, char * /* argv */[]) {
typedef std::istream_iterator<utf8_t> is_iter; typedef std::istream_iterator<utf8_t> is_iter;
is_iter end_iter; is_iter end_iter;
std::ifstream ifs1("test.dat"); std::ifstream ifs1((executable_dir + "test.dat").c_str());
is_iter it1(ifs1); is_iter it1(ifs1);
std::vector<utf8_t> data1; std::vector<utf8_t> data1;
std::copy(it1, end_iter, std::back_inserter(data1)); std::copy(it1, end_iter, std::back_inserter(data1));
std::ifstream ifs2("test2.dat"); std::ifstream ifs2((executable_dir + "test2.dat").c_str());
is_iter it2(ifs2); is_iter it2(ifs2);
std::vector<utf8_t> data2; std::vector<utf8_t> data2;
std::copy(it2, end_iter, std::back_inserter(data2)); std::copy(it2, end_iter, std::back_inserter(data2));
@ -230,7 +237,7 @@ test_main(int /* argc */, char * /* argv */[]) {
{ {
std::wofstream ofs; std::wofstream ofs;
ofs.imbue(utf8_locale); ofs.imbue(utf8_locale);
ofs.open("test3.dat"); ofs.open((executable_dir + "test3.dat").c_str());
std::copy( std::copy(
test3_data, test3_data,
test3_data + l, test3_data + l,
@ -242,7 +249,7 @@ test_main(int /* argc */, char * /* argv */[]) {
{ {
std::wifstream ifs; std::wifstream ifs;
ifs.imbue(utf8_locale); ifs.imbue(utf8_locale);
ifs.open("test3.dat"); ifs.open((executable_dir + "test3.dat").c_str());
ifs >> std::noskipws; ifs >> std::noskipws;
BOOST_TEST( BOOST_TEST(
std::equal( std::equal(
@ -278,24 +285,32 @@ test_main(int /* argc */, char * /* argv */[]) {
} }
int int
main(int argc, char * argv[]){ main(int argc, char * argv[]) {
if (argc > 0) {
// We need to save the path to executable to create test files in the same directory.
// This allows running different configurations of the test (release/debug, different C++ versions, etc.) in parallel.
std::string exec_name = argv[0];
std::string::size_type last_dir_sep_pos = exec_name.find_last_of("/\\");
if (last_dir_sep_pos != std::string::npos)
executable_dir = exec_name.substr(0, last_dir_sep_pos + 1); // include the trailing directory separator
}
int retval = 1; int retval = 1;
BOOST_TRY{ BOOST_TRY{
retval = test_main(argc, argv); retval = test_main(argc, argv);
} }
#ifndef BOOST_NO_EXCEPTION_STD_NAMESPACE #ifndef BOOST_NO_EXCEPTION_STD_NAMESPACE
BOOST_CATCH(const std::exception & e){ BOOST_CATCH(const std::exception & e){
BOOST_ERROR(e.what()); BOOST_ERROR(e.what());
} }
#endif #endif
BOOST_CATCH(...){ BOOST_CATCH(...){
BOOST_ERROR("failed with uncaught exception:"); BOOST_ERROR("failed with uncaught exception:");
} }
BOOST_CATCH_END BOOST_CATCH_END
int error_count = boost::report_errors(); int error_count = boost::report_errors();
if(error_count > 0) if (error_count > 0)
retval = error_count; retval = error_count;
return retval; return retval;
} }