test: update test codes to v4

This commit is contained in:
ToruNiina
2024-06-15 19:14:06 +09:00
parent 7c123ab378
commit c47ff10a64
69 changed files with 6792 additions and 8535 deletions

View File

@@ -1,299 +0,0 @@
include(ExternalProject)
set(TOML11_LANGSPEC_GIT_REPOSITORY "https://github.com/toml-lang/toml" CACHE STRING
"URL of the TOML language specification repository")
set(TOML11_LANGSPEC_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/toml" CACHE FILEPATH
"directory for the TOML language specification tree")
if(NOT EXISTS "${TOML11_LANGSPEC_SOURCE_DIR}/toml.abnf")
ExternalProject_Add(toml
SOURCE_DIR "${TOML11_LANGSPEC_SOURCE_DIR}"
GIT_REPOSITORY "${TOML11_LANGSPEC_GIT_REPOSITORY}"
GIT_TAG "v0.5.0"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND "")
endif()
set(TEST_NAMES
test_datetime
test_string
test_utility
test_result
test_traits
test_value
test_lex_boolean
test_lex_integer
test_lex_floating
test_lex_datetime
test_lex_string
test_lex_key_comment
test_parse_boolean
test_parse_integer
test_parse_floating
test_parse_string
test_parse_datetime
test_parse_array
test_parse_table
test_parse_inline_table
test_parse_key
test_parse_table_key
test_literals
test_comments
test_get
test_get_or
test_find
test_find_or
test_find_or_recursive
test_expect
test_parse_file
test_serialize_file
test_parse_unicode
test_error_detection
test_format_error
test_extended_conversions
)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-Wall" COMPILER_SUPPORTS_WALL)
CHECK_CXX_COMPILER_FLAG("-Wextra" COMPILER_SUPPORTS_WEXTRA)
CHECK_CXX_COMPILER_FLAG("-Wpedantic" COMPILER_SUPPORTS_WPEDANTIC)
CHECK_CXX_COMPILER_FLAG("-Werror" COMPILER_SUPPORTS_WERROR)
CHECK_CXX_COMPILER_FLAG("-Wsign-conversion" COMPILER_SUPPORTS_WSIGN_CONVERSION)
CHECK_CXX_COMPILER_FLAG("-Wconversion" COMPILER_SUPPORTS_WCONVERSION)
CHECK_CXX_COMPILER_FLAG("-Wduplicated-cond" COMPILER_SUPPORTS_WDUPLICATED_COND)
CHECK_CXX_COMPILER_FLAG("-Wduplicated-branches" COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
CHECK_CXX_COMPILER_FLAG("-Wlogical-op" COMPILER_SUPPORTS_WLOGICAL_OP)
CHECK_CXX_COMPILER_FLAG("-Wuseless-cast" COMPILER_SUPPORTS_WUSELESS_CAST)
CHECK_CXX_COMPILER_FLAG("-Wdouble-promotion" COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
CHECK_CXX_COMPILER_FLAG("-Wrange-loop-analysis" COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS)
CHECK_CXX_COMPILER_FLAG("-Wundef" COMPILER_SUPPORTS_WUNDEF)
CHECK_CXX_COMPILER_FLAG("-Wshadow" COMPILER_SUPPORTS_WSHADOW)
include(CheckCXXSourceCompiles)
# check which standard library implementation is used. If libstdc++ is used,
# it will fail to compile. It compiles if libc++ is used.
check_cxx_source_compiles("
#include <cstddef>
#ifdef __GLIBCXX__
static_assert(false);
#endif
int main() {
return 0;
}" TOML11_WITH_LIBCXX_LIBRARY)
# LLVM 8 requires -lc++fs if compiled with libc++ to use <filesystem>.
# LLVM 9+ does not require any special library.
# GCC 8 requires -lstdc++fs. GCC 9+ does not require it.
#
# Yes, we can check the version of the compiler used in the current build
# directly in CMake. But, in most cases, clang build uses libstdc++ as the
# standard library implementation and it makes the condition complicated.
# In many environment, the default installed C++ compiler is GCC and libstdc++
# is installed along with it. In most build on such an environment, even if we
# chose clang as the C++ compiler, still libstdc++ is used. Checking default
# gcc version makes the condition complicated.
# The purpose of this file is to compile tests. We know the environment on which
# the tests run. We can set this option and, I think, it is easier and better.
option(TOML11_REQUIRE_FILESYSTEM_LIBRARY "need to link -lstdc++fs or -lc++fs" OFF)
find_package(Boost COMPONENTS unit_test_framework REQUIRED)
set(PREVIOUSLY_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES}")
set(PREVIOUSLY_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
set(PREVIOUSLY_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
list(APPEND CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIRS})
list(APPEND CMAKE_REQUIRED_LIBRARIES ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
if(APPLE)
list(APPEND CMAKE_REQUIRED_FLAGS "-std=c++11")
endif()
check_cxx_source_compiles("
#define BOOST_TEST_MODULE \"dummy\"
#undef BOOST_TEST_DYN_LINK
#define BOOST_TEST_NO_LIB
#include <boost/test/included/unit_test.hpp>
BOOST_AUTO_TEST_CASE(proforma) { BOOST_TEST(true); }
" TOML11_WITH_BOOST_TEST_HEADER)
check_cxx_source_compiles("
#define BOOST_TEST_MODULE \"dummy\"
#undef BOOST_TEST_DYN_LINK
#undef BOOST_TEST_NO_LIB
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(proforma) { BOOST_TEST(true); }
" TOML11_WITH_BOOST_TEST_STATIC)
check_cxx_source_compiles("
#define BOOST_TEST_MODULE \"dummy\"
#define BOOST_TEST_DYN_LINK
#undef BOOST_TEST_NO_LIB
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(proforma) { BOOST_TEST(true); }
" TOML11_WITH_BOOST_TEST_DYNAMIC)
set(CMAKE_REQUIRED_INCLUDES "${PREVIOUSLY_REQUIRED_INCLUDES}")
set(CMAKE_REQUIRED_LIBRARIES "${PREVIOUSLY_REQUIRED_LIBRARIES}")
set(CMAKE_REQUIRED_FLAGS "${PREVIOUSLY_REQUIRED_FLAGS}")
unset(PREVIOUSLY_REQUIRED_INCLUDES)
unset(PREVIOUSLY_REQUIRED_LIBRARIES)
unset(PREVIOUSLY_REQUIRED_FLAGS)
if(TOML11_WITH_BOOST_TEST_DYNAMIC)
add_definitions(-DUNITTEST_FRAMEWORK_LIBRARY_EXIST -DBOOST_TEST_DYN_LINK)
elseif(TOML11_WITH_BOOST_TEST_STATIC)
add_definitions(-DUNITTEST_FRAMEWORK_LIBRARY_EXIST)
elseif(TOML11_WITH_BOOST_TEST_HEADER)
add_definitions(-DBOOST_TEST_NO_LIB)
else()
message(FATAL_ERROR "Neither the Boost.Test static or shared library nor the header-only version seem to be usable.")
endif()
if(COMPILER_SUPPORTS_WALL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
endif()
if(COMPILER_SUPPORTS_WEXTRA)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
endif()
if(COMPILER_SUPPORTS_WPEDANTIC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
endif()
if(COMPILER_SUPPORTS_WERROR)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif()
if(COMPILER_SUPPORTS_WSHADOW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow")
endif()
if(COMPILER_SUPPORTS_WSIGN_CONVERSION)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-conversion")
endif()
if(COMPILER_SUPPORTS_WCONVERSION)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wconversion")
endif()
if(COMPILER_SUPPORTS_WDUPLICATED_COND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-cond")
endif()
if(COMPILER_SUPPORTS_WDUPLICATED_BRANCHES)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wduplicated-branches")
endif()
if(COMPILER_SUPPORTS_WLOGICAL_OP)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wlogical-op")
endif()
if(COMPILER_SUPPORTS_WUSELESS_CAST)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wuseless-cast")
endif()
if(COMPILER_SUPPORTS_WDOUBLE_PROMOTION)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdouble-promotion")
endif()
if(COMPILER_SUPPORTS_WRANGE_LOOP_ANALYSIS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wrange-loop-analysis")
endif()
if(COMPILER_SUPPORTS_WUNDEF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wundef")
endif()
if(TOML11_USE_UNRELEASED_TOML_FEATURES)
message(STATUS "adding TOML11_USE_UNRELEASED_TOML_FEATURES flag")
add_definitions("-DTOML11_USE_UNRELEASED_TOML_FEATURES")
endif()
# Disable some MSVC warnings
if(MSVC)
# conversion from 'double' to 'unsigned int', possible loss of data
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244")
# conversion from 'int' to 'unsigned int', signed/unsigned mismatch
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4365")
# layout of class may have changed from a previous version of the compiler
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4371")
# enumerator in switch of enum is not explicitly handled by a case label
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4061")
# unreferenced inline function has been removed
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4514")
# constructor is not implicitly called
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4582")
# destructor is not implicitly called
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4583")
# pragma warning: there is no warning number <x>
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4619")
# default constructor was implicitly defined as deleted
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4623")
# copy constructor was implicitly defined as deleted
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4625")
# assignment operator was implicitly defined as deleted
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4626")
# move assignment operator was implicitly defined as deleted
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4627")
# <X> is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4668")
# function not inlined
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4710")
# function selected for automatic inlining
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4711")
# <x> bytes padding added after data member
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4820")
# pragma warning(pop): likely mismatch, popping warning state pushed in different file
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd5031")
# pragma warning(pop): spectre warnings in tests
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd5045")
# pragma warning(pop): spectre warnings in tests
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4265")
endif()
set(TEST_ENVIRON "TOMLDIR=${TOML11_LANGSPEC_SOURCE_DIR}")
if(WIN32)
# Set the PATH to be able to find Boost DLL
STRING(REPLACE ";" "\\;" PATH_STRING "$ENV{PATH}")
list(APPEND TEST_ENVIRON "PATH=${PATH_STRING}\;${Boost_LIBRARY_DIRS}")
endif()
foreach(TEST_NAME ${TEST_NAMES})
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
target_link_libraries(${TEST_NAME} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} toml11::toml11)
target_include_directories(${TEST_NAME} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS})
target_compile_definitions(${TEST_NAME} PRIVATE "BOOST_TEST_MODULE=\"${TEST_NAME}\"")
# to compile tests with <filesystem>...
if(TOML11_REQUIRE_FILESYSTEM_LIBRARY)
if(TOML11_WITH_LIBCXX_LIBRARY)
target_link_libraries(${TEST_NAME} "c++fs")
else()
target_link_libraries(${TEST_NAME} "stdc++fs")
endif()
endif()
target_include_directories(${TEST_NAME} PRIVATE ${Boost_INCLUDE_DIRS})
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
if(toml11_TEST_WITH_ASAN)
set_target_properties(${TEST_NAME} PROPERTIES
COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer"
LINK_FLAGS "-fsanitize=address -fno-omit-frame-pointer")
elseif(toml11_TEST_WITH_UBSAN)
set_target_properties(${TEST_NAME} PROPERTIES
COMPILE_FLAGS "-fsanitize=undefined"
LINK_FLAGS "-fsanitize=undefined")
endif()
endif()
add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set_tests_properties(${TEST_NAME} PROPERTIES ENVIRONMENT "${TEST_ENVIRON}")
endforeach(TEST_NAME)
# this test is to check it compiles. it will not run
add_executable(test_multiple_translation_unit
test_multiple_translation_unit_1.cpp
test_multiple_translation_unit_2.cpp)
target_link_libraries(test_multiple_translation_unit toml11::toml11)
if(WIN32)
add_executable(test_windows test_windows.cpp)
target_link_libraries(test_windows toml11::toml11)
endif()

View File

@@ -1,42 +0,0 @@
#include <toml.hpp>
#include <iostream>
#include <iomanip>
int main(int argc, char **argv)
{
if(argc != 3)
{
std::cerr << "usage: ./check [filename] [valid|invalid]" << std::endl;
return 1;
}
const std::string file_kind(argv[2]);
try
{
const auto data = toml::parse(argv[1]);
std::cout << std::setprecision(16) << std::setw(80) << data;
if(file_kind == "valid")
{
return 0;
}
else
{
return 1;
}
}
catch(const toml::syntax_error& err)
{
std::cout << "what(): " << err.what() << std::endl;
if(file_kind == "invalid")
{
return 0;
}
else
{
return 1;
}
}
return 127;
}

View File

@@ -1,114 +0,0 @@
#include <toml.hpp>
#include <iomanip>
#include <iostream>
int main(int argc, char **argv)
{
if(argc != 2)
{
std::cerr << "usage: ./check [filename]" << std::endl;
return 1;
}
const std::string filename(argv[1]);
{
const auto data = toml::parse(filename);
{
std::ofstream ofs("tmp.toml");
ofs << std::setprecision(16) << std::setw(80) << data;
}
const auto serialized = toml::parse("tmp.toml");
if(data != serialized)
{
// this is really a ditry hack, but is the easiest way...
// TODO: cleanup by adding comparison function to check if a value is NaN or not
if(filename.substr(filename.size() - 22, 22) == "float-inf-and-nan.toml" &&
std::isnan (toml::find<double>(serialized, "nan")) &&
!std::signbit (toml::find<double>(serialized, "nan")) &&
std::isnan (toml::find<double>(serialized, "nan_plus")) &&
!std::signbit (toml::find<double>(serialized, "nan_plus")) &&
std::isnan (toml::find<double>(serialized, "nan_neg")) &&
std::signbit (toml::find<double>(serialized, "nan_neg")) &&
!std::isnan (toml::find<double>(serialized, "infinity")) &&
!std::isfinite(toml::find<double>(serialized, "infinity")) &&
!std::signbit (toml::find<double>(serialized, "infinity")) &&
!std::isnan (toml::find<double>(serialized, "infinity_plus")) &&
!std::isfinite(toml::find<double>(serialized, "infinity_plus")) &&
!std::signbit (toml::find<double>(serialized, "infinity_plus")) &&
!std::isnan (toml::find<double>(serialized, "infinity_neg")) &&
!std::isfinite(toml::find<double>(serialized, "infinity_neg")) &&
std::signbit (toml::find<double>(serialized, "infinity_neg")))
{
// then it is correctly serialized.
// Note that, the result of (nan == nan) is false. so `data == serialized` is false.
}
else
{
std::cerr << "============================================================\n";
std::cerr << "result (w/o comment) different: " << filename << std::endl;
std::cerr << "------------------------------------------------------------\n";
std::cerr << "# serialized\n";
std::cerr << serialized;
std::cerr << "------------------------------------------------------------\n";
std::cerr << "# data\n";
std::cerr << data;
return 1;
}
}
}
{
const auto data = toml::parse<toml::preserve_comments>(filename);
{
std::ofstream ofs("tmp.toml");
ofs << std::setprecision(16) << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments>("tmp.toml");
if(data != serialized)
{
// this is really a ditry hack, but is the easiest way...
// TODO: cleanup by adding comparison function to check if a value is NaN or not
if(filename.substr(filename.size() - 22, 22) == "float-inf-and-nan.toml" &&
std::isnan (toml::find<double>(serialized, "nan")) &&
!std::signbit (toml::find<double>(serialized, "nan")) &&
std::isnan (toml::find<double>(serialized, "nan_plus")) &&
!std::signbit (toml::find<double>(serialized, "nan_plus")) &&
std::isnan (toml::find<double>(serialized, "nan_neg")) &&
std::signbit (toml::find<double>(serialized, "nan_neg")) &&
!std::isnan (toml::find<double>(serialized, "infinity")) &&
!std::isfinite(toml::find<double>(serialized, "infinity")) &&
!std::signbit (toml::find<double>(serialized, "infinity")) &&
!std::isnan (toml::find<double>(serialized, "infinity_plus")) &&
!std::isfinite(toml::find<double>(serialized, "infinity_plus")) &&
!std::signbit (toml::find<double>(serialized, "infinity_plus")) &&
!std::isnan (toml::find<double>(serialized, "infinity_neg")) &&
!std::isfinite(toml::find<double>(serialized, "infinity_neg")) &&
std::signbit (toml::find<double>(serialized, "infinity_neg")) &&
toml::find(data, "nan").comments() == toml::find(serialized, "nan").comments() &&
toml::find(data, "nan_plus").comments() == toml::find(serialized, "nan_plus").comments() &&
toml::find(data, "nan_neg").comments() == toml::find(serialized, "nan_neg").comments() &&
toml::find(data, "infinity").comments() == toml::find(serialized, "infinity").comments() &&
toml::find(data, "infinity_plus").comments() == toml::find(serialized, "infinity_plus").comments() &&
toml::find(data, "infinity_neg").comments() == toml::find(serialized, "infinity_neg").comments() )
{
// then it is correctly serialized.
// Note that, the result of (nan == nan) is false. so `data == serialized` is false.
}
else
{
std::cerr << "============================================================\n";
std::cerr << "result (w/ comment) different: " << filename << std::endl;
std::cerr << "------------------------------------------------------------\n";
std::cerr << "# serialized\n";
std::cerr << serialized;
std::cerr << "------------------------------------------------------------\n";
std::cerr << "# data\n";
std::cerr << data;
return 1;
}
}
}
return 0;
}

View File

@@ -1,139 +0,0 @@
#include <toml.hpp>
#include <iomanip>
#include <iostream>
struct json_serializer
{
void operator()(toml::boolean v)
{
std::cout << "{\"type\":\"bool\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(toml::integer v)
{
std::cout << "{\"type\":\"integer\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(toml::floating v)
{
if(std::isnan(v) && std::signbit(v))
{
// toml-test does not allow negative NaN represented in "-nan" because
// there are languages that does not distinguish nan and -nan.
// But toml11 keeps sign from input. To resolve this difference,
// we convert -nan to nan here.
v = std::numeric_limits<toml::floating>::quiet_NaN();
}
std::cout << "{\"type\":\"float\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(const toml::string& v)
{
// since toml11 automatically convert string to multiline string that is
// valid only in TOML, we need to format the string to make it valid in
// JSON.
toml::serializer<toml::value> ser(std::numeric_limits<std::size_t>::max());
std::cout << "{\"type\":\"string\",\"value\":"
<< ser(v.str) << "}";
return ;
}
void operator()(const toml::local_time& v)
{
std::cout << "{\"type\":\"time-local\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(const toml::local_date& v)
{
std::cout << "{\"type\":\"date-local\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(const toml::local_datetime& v)
{
std::cout << "{\"type\":\"datetime-local\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(const toml::offset_datetime& v)
{
std::cout << "{\"type\":\"datetime\",\"value\":\"" << toml::value(v) << "\"}";
return ;
}
void operator()(const toml::array& v)
{
if(!v.empty() && v.front().is_table())
{
std::cout << '[';
bool is_first = true;
for(const auto& elem : v)
{
if(!is_first) {std::cout << ", ";}
is_first = false;
toml::visit(*this, elem);
}
std::cout << ']';
}
else
{
// std::cout << "{\"type\":\"array\",\"value\":[";
std::cout << "[";
bool is_first = true;
for(const auto& elem : v)
{
if(!is_first) {std::cout << ", ";}
is_first = false;
toml::visit(*this, elem);
}
std::cout << "]";
}
return ;
}
void operator()(const toml::table& v)
{
std::cout << '{';
bool is_first = true;
for(const auto& elem : v)
{
if(!is_first) {std::cout << ", ";}
is_first = false;
const auto k = toml::format_key(elem.first);
if(k.at(0) == '"')
{
std::cout << k << ":";
}
else // bare key
{
std::cout << '\"' << k << "\":";
}
toml::visit(*this, elem.second);
}
std::cout << '}';
return ;
}
};
int main()
{
try
{
std::vector<char> buf;
std::cin.peek();
while(!std::cin.eof())
{
buf.push_back(std::cin.get());
std::cin.peek();
}
std::string bufstr(buf.begin(), buf.end());
std::istringstream ss(bufstr);
const auto data = toml::parse(ss);
std::cout << std::setprecision(std::numeric_limits<double>::max_digits10);
toml::visit(json_serializer(), data);
return 0;
}
catch(const toml::syntax_error& err)
{
std::cout << "what(): " << err.what() << std::endl;
return 1;
}
}

View File

@@ -1,545 +1,21 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <toml.hpp> #include <toml.hpp>
#include "unit_test.hpp" TEST_CASE("testing comments on simple value")
BOOST_AUTO_TEST_CASE(test_comment_before)
{ {
{ const toml::value root = toml::parse_str(R"(
const std::string file = R"( # comment 1
# comment for a. # comment 2
a = 42 a = "foo" # comment 3
# comment for b.
b = "baz"
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto a = toml::find(v, "a"); # comment 4
const auto b = toml::find(v, "b"); )");
BOOST_TEST(a.comments().size() == 1u);
BOOST_TEST(a.comments().front() == " comment for a.");
BOOST_TEST(b.comments().size() == 1u);
BOOST_TEST(b.comments().front() == " comment for b.");
}
{
const std::string file = R"(
# comment for a.
# another comment for a.
a = 42
# comment for b.
# also comment for b.
b = "baz"
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto a = toml::find(v, "a");
const auto b = toml::find(v, "b");
BOOST_TEST(a.comments().size() == 2u);
BOOST_TEST(a.comments().front() == " comment for a.");
BOOST_TEST(a.comments().back() == " another comment for a.");
BOOST_TEST(b.comments().size() == 2u);
BOOST_TEST(b.comments().front() == " comment for b.");
BOOST_TEST(b.comments().back() == " also comment for b.");
}
}
BOOST_AUTO_TEST_CASE(test_comment_inline)
{
{
const std::string file = R"(
a = 42 # comment for a.
b = "baz" # comment for b.
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto a = toml::find(v, "a");
const auto b = toml::find(v, "b");
BOOST_TEST(a.comments().size() == 1u);
BOOST_TEST(a.comments().front() == " comment for a.");
BOOST_TEST(b.comments().size() == 1u);
BOOST_TEST(b.comments().front() == " comment for b.");
}
{
const std::string file = R"(
a = [
42,
] # comment for a.
b = [
"bar", # this is not a comment for b, but "bar"
] # this is a comment for b.
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto a = toml::find(v, "a");
const auto b = toml::find(v, "b");
const auto b0 = b.as_array().at(0);
BOOST_TEST(a.comments().size() == 1u);
BOOST_TEST(a.comments().front() == " comment for a.");
BOOST_TEST(b.comments().size() == 1u);
BOOST_TEST(b.comments().front() == " this is a comment for b.");
BOOST_TEST(b0.comments().size() == 1u);
BOOST_TEST(b0.comments().front() == " this is not a comment for b, but \"bar\"");
}
}
BOOST_AUTO_TEST_CASE(test_comment_both)
{
{
const std::string file = R"(
# comment for a.
a = 42 # inline comment for a.
# comment for b.
b = "baz" # inline comment for b.
# comment for c.
c = [ # this comment will be ignored
# comment for the first element.
10 # this also.
] # another comment for c.
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto a = toml::find(v, "a");
const auto b = toml::find(v, "b");
const auto c = toml::find(v, "c");
const auto c0 = c.as_array().at(0);
BOOST_TEST(a.comments().size() == 2u);
BOOST_TEST(a.comments().front() == " comment for a.");
BOOST_TEST(a.comments().back() == " inline comment for a.");
BOOST_TEST(b.comments().size() == 2u);
BOOST_TEST(b.comments().front() == " comment for b.");
BOOST_TEST(b.comments().back() == " inline comment for b.");
BOOST_TEST(c.comments().size() == 2u);
BOOST_TEST(c.comments().front() == " comment for c.");
BOOST_TEST(c.comments().back() == " another comment for c.");
BOOST_TEST(c0.comments().size() == 2u);
BOOST_TEST(c0.comments().front() == " comment for the first element.");
BOOST_TEST(c0.comments().back() == " this also.");
}
}
BOOST_AUTO_TEST_CASE(test_comments_on_implicit_values)
{
{
const std::string file = R"(
# comment for the first element of array-of-tables.
[[array-of-tables]]
foo = "bar"
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto aot = toml::find(v, "array-of-tables");
const auto elm = aot.at(0);
BOOST_TEST(aot.comments().empty());
BOOST_TEST(elm.comments().size() == 1);
BOOST_TEST(elm.comments().front() == " comment for the first element of array-of-tables.");
}
{
const std::string file = R"(
# comment for the array itself
array-of-tables = [
# comment for the first element of array-of-tables.
{foo = "bar"}
]
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::preserve_comments>(iss);
const auto aot = toml::find(v, "array-of-tables");
const auto elm = aot.at(0);
BOOST_TEST(aot.comments().size() == 1);
BOOST_TEST(aot.comments().front() == " comment for the array itself");
BOOST_TEST(elm.comments().size() == 1);
BOOST_TEST(elm.comments().front() == " comment for the first element of array-of-tables.");
}
}
BOOST_AUTO_TEST_CASE(test_discard_comment)
{
const std::string file = R"(
# comment for a.
a = 42 # inline comment for a.
# comment for b.
b = "baz" # inline comment for b.
# comment for c.
c = [ # this comment will be ignored
# comment for the first element.
10 # this also.
] # another comment for c.
)";
std::istringstream iss(file);
const auto v = toml::parse<toml::discard_comments>(iss);
const auto a = toml::find(v, "a");
const auto b = toml::find(v, "b");
const auto c = toml::find(v, "c");
const auto c0 = c.as_array().at(0);
BOOST_TEST(a.comments().empty());
BOOST_TEST(b.comments().empty());
BOOST_TEST(c.comments().empty());
BOOST_TEST(c0.comments().empty());
}
BOOST_AUTO_TEST_CASE(test_construct_value_with_comments)
{
using value_type = toml::basic_value<toml::preserve_comments>;
{
const value_type v(true, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_boolean());
BOOST_TEST(v.as_boolean() == true);
}
{
const value_type v(42, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_integer());
BOOST_TEST(v.as_integer() == 42);
}
{
const value_type v(3.14, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_floating());
BOOST_TEST(v.as_floating() == 3.14);
}
{
const value_type v(toml::string("str"), {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
{
const value_type v(std::string("str"), {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
{
const value_type v(std::string("str"), toml::string_t::literal,
{"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
{
const value_type v("str", {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
{
const value_type v("str", toml::string_t::literal,
{"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
{
using namespace std::literals::string_view_literals;
const value_type v("str"sv, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
{
using namespace std::literals::string_view_literals;
const value_type v("str"sv, toml::string_t::literal,
{"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_string());
BOOST_TEST(v.as_string() == "str");
}
#endif
const toml::local_date ld{2019, toml::month_t::Apr, 1};
const toml::local_time lt{12, 30, 45};
const toml::local_datetime ldt{ld, lt};
const toml::offset_datetime odt{ld, lt, toml::time_offset{9, 0}};
{
const value_type v(ld, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_local_date());
BOOST_TEST(v.as_local_date() == ld);
}
{
const value_type v(lt, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_local_time());
BOOST_TEST(v.as_local_time() == lt);
}
{
const toml::local_time three_hours{3,0,0};
const value_type v(std::chrono::hours(3), {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_local_time());
BOOST_TEST(v.as_local_time() == three_hours);
}
{
const value_type v(ldt, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_local_datetime());
BOOST_TEST(v.as_local_datetime() == ldt);
}
{
const value_type v(odt, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_offset_datetime());
BOOST_TEST(v.as_offset_datetime() == odt);
}
{
const auto systp = static_cast<std::chrono::system_clock::time_point>(odt);
const value_type v(systp, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_offset_datetime());
// While the conversion, the information about time offset may change.
const auto systp2 = static_cast<std::chrono::system_clock::time_point>(
v.as_offset_datetime());
const bool result = systp == systp2; // because there is no operator<<
BOOST_TEST(result);
}
{
const typename value_type::array_type a{1,2,3,4,5};
const value_type v(a, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_array());
BOOST_TEST(v.as_array().at(0).is_integer());
BOOST_TEST(v.as_array().at(1).is_integer());
BOOST_TEST(v.as_array().at(2).is_integer());
BOOST_TEST(v.as_array().at(3).is_integer());
BOOST_TEST(v.as_array().at(4).is_integer());
BOOST_TEST(v.as_array().at(0).as_integer() == 1);
BOOST_TEST(v.as_array().at(1).as_integer() == 2);
BOOST_TEST(v.as_array().at(2).as_integer() == 3);
BOOST_TEST(v.as_array().at(3).as_integer() == 4);
BOOST_TEST(v.as_array().at(4).as_integer() == 5);
}
{
const std::initializer_list<int> a = {1,2,3,4,5};
const value_type v(a, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_array());
BOOST_TEST(v.as_array().at(0).is_integer());
BOOST_TEST(v.as_array().at(1).is_integer());
BOOST_TEST(v.as_array().at(2).is_integer());
BOOST_TEST(v.as_array().at(3).is_integer());
BOOST_TEST(v.as_array().at(4).is_integer());
BOOST_TEST(v.as_array().at(0).as_integer() == 1);
BOOST_TEST(v.as_array().at(1).as_integer() == 2);
BOOST_TEST(v.as_array().at(2).as_integer() == 3);
BOOST_TEST(v.as_array().at(3).as_integer() == 4);
BOOST_TEST(v.as_array().at(4).as_integer() == 5);
}
{
const std::vector<int> a = {1,2,3,4,5};
const value_type v(a, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_array());
BOOST_TEST(v.as_array().at(0).is_integer());
BOOST_TEST(v.as_array().at(1).is_integer());
BOOST_TEST(v.as_array().at(2).is_integer());
BOOST_TEST(v.as_array().at(3).is_integer());
BOOST_TEST(v.as_array().at(4).is_integer());
BOOST_TEST(v.as_array().at(0).as_integer() == 1);
BOOST_TEST(v.as_array().at(1).as_integer() == 2);
BOOST_TEST(v.as_array().at(2).as_integer() == 3);
BOOST_TEST(v.as_array().at(3).as_integer() == 4);
BOOST_TEST(v.as_array().at(4).as_integer() == 5);
}
{
const typename value_type::table_type t{
{"key1", 42}, {"key2", "foobar"}
};
const value_type v(t, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_table());
BOOST_TEST(v.as_table().at("key1").is_integer());
BOOST_TEST(v.as_table().at("key1").as_integer() == 42);
BOOST_TEST(v.as_table().at("key2").is_string());
BOOST_TEST(v.as_table().at("key2").as_string() == "foobar");
}
{
const std::initializer_list<std::pair<std::string, value_type>> t{
{"key1", 42}, {"key2", "foobar"}
};
const value_type v(t, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_table());
BOOST_TEST(v.as_table().at("key1").is_integer());
BOOST_TEST(v.as_table().at("key1").as_integer() == 42);
BOOST_TEST(v.as_table().at("key2").is_string());
BOOST_TEST(v.as_table().at("key2").as_string() == "foobar");
}
{
const std::map<std::string, value_type> t{
{"key1", 42}, {"key2", "foobar"}
};
const value_type v(t, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_table());
BOOST_TEST(v.as_table().at("key1").is_integer());
BOOST_TEST(v.as_table().at("key1").as_integer() == 42);
BOOST_TEST(v.as_table().at("key2").is_string());
BOOST_TEST(v.as_table().at("key2").as_string() == "foobar");
}
}
BOOST_AUTO_TEST_CASE(test_overwrite_comments)
{
using value_type = toml::basic_value<toml::preserve_comments>;
{
const value_type v(42, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_integer());
BOOST_TEST(v.as_integer() == 42);
const value_type u(v, {"comment3", "comment4"});
BOOST_TEST(u.comments().size() == 2u);
BOOST_TEST(u.comments().at(0) == "comment3");
BOOST_TEST(u.comments().at(1) == "comment4");
BOOST_TEST(u.is_integer());
BOOST_TEST(u.as_integer() == 42);
}
{
const value_type v(42, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_integer());
BOOST_TEST(v.as_integer() == 42);
const value_type u(v);
BOOST_TEST(u.comments().size() == 2u);
BOOST_TEST(u.comments().at(0) == "comment1");
BOOST_TEST(u.comments().at(1) == "comment2");
BOOST_TEST(u.is_integer());
BOOST_TEST(u.as_integer() == 42);
}
{
const value_type v(42, {"comment1", "comment2"});
BOOST_TEST(v.comments().size() == 2u);
BOOST_TEST(v.comments().at(0) == "comment1");
BOOST_TEST(v.comments().at(1) == "comment2");
BOOST_TEST(v.is_integer());
BOOST_TEST(v.as_integer() == 42);
const value_type u(v, {});
BOOST_TEST(u.comments().size() == 0u);
BOOST_TEST(u.is_integer());
BOOST_TEST(u.as_integer() == 42);
}
}
BOOST_AUTO_TEST_CASE(test_output_comments)
{
using value_type = toml::basic_value<toml::preserve_comments>;
{
const value_type v(42, {"comment1", "comment2"});
std::ostringstream oss;
oss << v.comments();
std::ostringstream ref;
ref << "#comment1\n";
ref << "#comment2\n";
BOOST_TEST(oss.str() == ref.str());
}
{
const value_type v(42, {"comment1", "comment2"});
std::ostringstream oss;
// If v is not a table, toml11 assumes that user is writing something
// like the following.
oss << "answer = " << v;
BOOST_TEST(oss.str() == "answer = 42 #comment1comment2");
}
{
const value_type v(42, {"comment1", "comment2"});
std::ostringstream oss;
// If v is not a table, toml11 assumes that user is writing something
// like the following.
oss << toml::nocomment << "answer = " << v;
BOOST_TEST(oss.str() == "answer = 42");
}
{
const value_type v(42, {"comment1", "comment2"});
std::ostringstream oss;
// If v is not a table, toml11 assumes that user is writing something
// like the following.
oss << toml::nocomment << toml::showcomment << "answer = " << v;
BOOST_TEST(oss.str() == "answer = 42 #comment1comment2");
}
const auto& a = root.at("a");
CHECK_EQ(a.comments().size(), 3);
CHECK_EQ(a.comments().at(0), "# comment 1");
CHECK_EQ(a.comments().at(1), "# comment 2");
CHECK_EQ(a.comments().at(2), "# comment 3");
} }

View File

@@ -1,109 +1,110 @@
#include <toml/datetime.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include <toml11/datetime.hpp>
BOOST_AUTO_TEST_CASE(test_local_date) TEST_CASE("testing local date")
{ {
const toml::local_date date(2018, toml::month_t::Jan, 1); const toml::local_date date(2018, toml::month_t::Jan, 1);
const toml::local_date date1(date); const toml::local_date date1(date);
BOOST_TEST(date == date1); CHECK(date == date1);
const std::chrono::system_clock::time_point tp(date); const std::chrono::system_clock::time_point tp(date);
const toml::local_date date2(tp); const toml::local_date date2(tp);
BOOST_TEST(date == date2); CHECK(date == date2);
const toml::local_date date3(2017, toml::month_t::Dec, 31); const toml::local_date date3(2017, toml::month_t::Dec, 31);
BOOST_TEST(date > date3); CHECK(date > date3);
std::ostringstream oss; std::ostringstream oss;
oss << date; oss << date;
BOOST_TEST(oss.str() == std::string("2018-01-01")); CHECK(oss.str() == std::string("2018-01-01"));
} }
BOOST_AUTO_TEST_CASE(test_local_time) TEST_CASE("testing local time")
{ {
const toml::local_time time(12, 30, 45); const toml::local_time time(12, 30, 45);
const toml::local_time time1(time); const toml::local_time time1(time);
BOOST_TEST(time == time1); CHECK(time == time1);
const std::chrono::nanoseconds dur(time); const std::chrono::nanoseconds dur(time);
std::chrono::nanoseconds ns(0); std::chrono::nanoseconds ns(0);
ns += std::chrono::hours (12); ns += std::chrono::hours (12);
ns += std::chrono::minutes(30); ns += std::chrono::minutes(30);
ns += std::chrono::seconds(45); ns += std::chrono::seconds(45);
BOOST_TEST(dur.count() == ns.count()); CHECK(dur.count() == ns.count());
const toml::local_time time3(12, 15, 45); const toml::local_time time3(12, 15, 45);
BOOST_TEST(time > time3); CHECK(time > time3);
{ {
std::ostringstream oss; std::ostringstream oss;
oss << time; oss << time;
BOOST_TEST(oss.str() == std::string("12:30:45")); CHECK(oss.str() == std::string("12:30:45"));
} }
{ {
const toml::local_time time4(12, 30, 45, 123, 456); const toml::local_time time4(12, 30, 45, 123, 456);
std::ostringstream oss; std::ostringstream oss;
oss << time4; oss << time4;
BOOST_TEST(oss.str() == std::string("12:30:45.123456")); CHECK(oss.str() == std::string("12:30:45.123456"));
} }
} }
BOOST_AUTO_TEST_CASE(test_time_offset) TEST_CASE("testing time offset")
{ {
const toml::time_offset time(9, 30); const toml::time_offset time(9, 30);
const toml::time_offset time1(time); const toml::time_offset time1(time);
BOOST_TEST(time == time1); CHECK(time == time1);
const std::chrono::minutes dur(time); const std::chrono::minutes dur(time);
std::chrono::minutes m(0); std::chrono::minutes m(0);
m += std::chrono::hours (9); m += std::chrono::hours (9);
m += std::chrono::minutes(30); m += std::chrono::minutes(30);
BOOST_TEST(dur.count() == m.count()); CHECK(dur.count() == m.count());
const toml::time_offset time2(9, 0); const toml::time_offset time2(9, 0);
BOOST_TEST(time2 < time); CHECK(time2 < time);
std::ostringstream oss; std::ostringstream oss;
oss << time; oss << time;
BOOST_TEST(oss.str() == std::string("+09:30")); CHECK(oss.str() == std::string("+09:30"));
} }
BOOST_AUTO_TEST_CASE(test_local_datetime) TEST_CASE("testing local datetime")
{ {
const toml::local_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1), const toml::local_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1),
toml::local_time(12, 30, 45)); toml::local_time(12, 30, 45));
const toml::local_datetime dt1(dt); const toml::local_datetime dt1(dt);
BOOST_TEST(dt == dt1); CHECK(dt == dt1);
const std::chrono::system_clock::time_point tp(dt); const std::chrono::system_clock::time_point tp(dt);
const toml::local_datetime dt2(tp); const toml::local_datetime dt2(tp);
BOOST_TEST(dt == dt2); CHECK(dt == dt2);
std::ostringstream oss; std::ostringstream oss;
oss << dt; oss << dt;
BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45")); CHECK(oss.str() == std::string("2018-01-01T12:30:45"));
} }
BOOST_AUTO_TEST_CASE(test_offset_datetime) TEST_CASE("testing offset datetime")
{ {
const toml::offset_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1), const toml::offset_datetime dt(toml::local_date(2018, toml::month_t::Jan, 1),
toml::local_time(12, 30, 45), toml::local_time(12, 30, 45),
toml::time_offset(9, 30)); toml::time_offset(9, 30));
const toml::offset_datetime dt1(dt); const toml::offset_datetime dt1(dt);
BOOST_TEST(dt == dt1); CHECK(dt == dt1);
const std::chrono::system_clock::time_point tp1(dt); const std::chrono::system_clock::time_point tp1(dt);
const toml::offset_datetime dt2(tp1); const toml::offset_datetime dt2(tp1);
const std::chrono::system_clock::time_point tp2(dt2); const std::chrono::system_clock::time_point tp2(dt2);
const bool tp_same = (tp1 == tp2); const bool tp_same = (tp1 == tp2);
BOOST_TEST(tp_same); CHECK(tp_same);
{ {
std::ostringstream oss; std::ostringstream oss;
oss << dt; oss << dt;
BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45+09:30")); CHECK(oss.str() == std::string("2018-01-01T12:30:45+09:30"));
} }
{ {
const toml::offset_datetime dt3( const toml::offset_datetime dt3(
@@ -112,6 +113,6 @@ BOOST_AUTO_TEST_CASE(test_offset_datetime)
toml::time_offset(0, 0)); toml::time_offset(0, 0));
std::ostringstream oss; std::ostringstream oss;
oss << dt3; oss << dt3;
BOOST_TEST(oss.str() == std::string("2018-01-01T12:30:45Z")); CHECK(oss.str() == std::string("2018-01-01T12:30:45Z"));
} }
} }

View File

@@ -1,97 +0,0 @@
#include <toml.hpp>
#include "unit_test.hpp"
#include <fstream>
#include <iostream>
BOOST_AUTO_TEST_CASE(test_detect_empty_key)
{
std::istringstream stream(std::string("= \"value\""));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_missing_value)
{
std::istringstream stream(std::string("a ="));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_too_many_value)
{
std::istringstream stream(std::string("a = 1 = \"value\""));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_duplicate_table)
{
std::istringstream stream(std::string(
"[table]\n"
"a = 42\n"
"[table]\n"
"b = 42\n"
));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_conflict_array_table)
{
std::istringstream stream(std::string(
"[[table]]\n"
"a = 42\n"
"[table]\n"
"b = 42\n"
));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_conflict_table_array)
{
std::istringstream stream(std::string(
"[table]\n"
"a = 42\n"
"[[table]]\n"
"b = 42\n"
));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_duplicate_value)
{
std::istringstream stream(std::string(
"a = 1\n"
"a = 2\n"
));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_conflicting_value)
{
std::istringstream stream(std::string(
"a.b = 1\n"
"a.b.c = 2\n"
));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_detect_inhomogeneous_array)
{
#ifdef TOML11_DISALLOW_HETEROGENEOUS_ARRAYS
std::istringstream stream(std::string(
"a = [1, 1.0]\n"
));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
#else
BOOST_TEST_MESSAGE("After v1.0.0-rc.1, heterogeneous arrays are allowed");
#endif
}
BOOST_AUTO_TEST_CASE(test_detect_appending_array_of_table)
{
std::istringstream stream(std::string(
"a = [{b = 1}]\n"
"[[a]]\n"
"b = 2\n"
));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error);
}

View File

@@ -1,26 +0,0 @@
#include <toml.hpp>
#include "unit_test.hpp"
#include <array>
#include <deque>
#include <list>
#include <map>
#include <unordered_map>
BOOST_AUTO_TEST_CASE(test_expect)
{
{
toml::value v1(42);
toml::value v2(3.14);
const auto v1_or_0 = toml::expect<int>(v1).unwrap_or(0);
const auto v2_or_0 = toml::expect<int>(v2).unwrap_or(0);
BOOST_TEST(42 == v1_or_0);
BOOST_TEST( 0 == v2_or_0);
const auto v1_or_none = toml::expect<int>(v1).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none"));
const auto v2_or_none = toml::expect<int>(v2).map([](int i){return std::to_string(i);}).unwrap_or(std::string("none"));
BOOST_TEST("42" == v1_or_none);
BOOST_TEST("none" == v2_or_none);
}
}

View File

@@ -1,627 +0,0 @@
#include <toml.hpp>
#include "unit_test.hpp"
#include <deque>
#include <map>
namespace extlib
{
struct foo
{
int a;
std::string b;
};
struct bar
{
int a;
std::string b;
void from_toml(const toml::value& v)
{
this->a = toml::find<int>(v, "a");
this->b = toml::find<std::string>(v, "b");
return ;
}
toml::table into_toml() const
{
return toml::table{{"a", this->a}, {"b", this->b}};
}
};
struct baz
{
int a;
std::string b;
};
struct qux
{
int a;
std::string b;
};
struct foobar
{
// via constructor
explicit foobar(const toml::value& v)
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
{}
int a;
std::string b;
};
} // extlib
namespace toml
{
template<>
struct from<extlib::foo>
{
static extlib::foo from_toml(const toml::value& v)
{
return extlib::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib::foo>
{
static toml::value into_toml(const extlib::foo& f)
{
return toml::value{{"a", f.a}, {"b", f.b}};
}
};
template<>
struct from<extlib::baz>
{
static extlib::baz from_toml(const toml::value& v)
{
return extlib::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib::qux>
{
static toml::table into_toml(const extlib::qux& f)
{
return toml::table{{"a", f.a}, {"b", f.b}};
}
};
} // toml
// ---------------------------------------------------------------------------
namespace extlib2
{
struct foo
{
int a;
std::string b;
};
struct bar
{
int a;
std::string b;
template<typename C, template<typename ...> class M, template<typename ...> class A>
void from_toml(const toml::basic_value<C, M, A>& v)
{
this->a = toml::find<int>(v, "a");
this->b = toml::find<std::string>(v, "b");
return ;
}
toml::table into_toml() const
{
return toml::table{{"a", this->a}, {"b", this->b}};
}
};
struct baz
{
int a;
std::string b;
};
struct qux
{
int a;
std::string b;
};
struct foobar
{
template<typename C, template<typename ...> class M, template<typename ...> class A>
explicit foobar(const toml::basic_value<C, M, A>& v)
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
{}
int a;
std::string b;
};
} // extlib2
namespace toml
{
template<>
struct from<extlib2::foo>
{
template<typename C, template<typename ...> class M, template<typename ...> class A>
static extlib2::foo from_toml(const toml::basic_value<C, M, A>& v)
{
return extlib2::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib2::foo>
{
static toml::table into_toml(const extlib2::foo& f)
{
return toml::table{{"a", f.a}, {"b", f.b}};
}
};
template<>
struct from<extlib2::baz>
{
template<typename C, template<typename ...> class M, template<typename ...> class A>
static extlib2::baz from_toml(const toml::basic_value<C, M, A>& v)
{
return extlib2::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib2::qux>
{
static toml::basic_value<toml::preserve_comments, std::map>
into_toml(const extlib2::qux& f)
{
return toml::basic_value<toml::preserve_comments, std::map>{
{"a", f.a}, {"b", f.b}
};
}
};
} // toml
// ---------------------------------------------------------------------------
BOOST_AUTO_TEST_CASE(test_conversion_by_member_methods)
{
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib::foo>(v);
BOOST_TEST(foo.a == 42);
BOOST_TEST(foo.b == "baz");
const toml::value v2(foo);
BOOST_TEST(v == v2);
}
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib2::foo>(v);
BOOST_TEST(foo.a == 42);
BOOST_TEST(foo.b == "baz");
const toml::value v2(foo);
BOOST_TEST(v == v2);
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib2::foo>(v);
BOOST_TEST(foo.a == 42);
BOOST_TEST(foo.b == "baz");
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v2(foo);
BOOST_TEST(v == v2);
}
}
BOOST_AUTO_TEST_CASE(test_conversion_by_specialization)
{
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto bar = toml::get<extlib::bar>(v);
BOOST_TEST(bar.a == 42);
BOOST_TEST(bar.b == "baz");
const toml::value v2(bar);
BOOST_TEST(v == v2);
}
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto bar = toml::get<extlib2::bar>(v);
BOOST_TEST(bar.a == 42);
BOOST_TEST(bar.b == "baz");
const toml::value v2(bar);
BOOST_TEST(v == v2);
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v{{"a", 42}, {"b", "baz"}};
const auto bar = toml::get<extlib2::bar>(v);
BOOST_TEST(bar.a == 42);
BOOST_TEST(bar.b == "baz");
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v2(bar);
BOOST_TEST(v == v2);
}
}
BOOST_AUTO_TEST_CASE(test_conversion_one_way)
{
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto baz = toml::get<extlib::baz>(v);
BOOST_TEST(baz.a == 42);
BOOST_TEST(baz.b == "baz");
}
{
const extlib::qux q{42, "qux"};
const toml::value v(q);
BOOST_TEST(toml::find<int>(v, "a") == 42);
BOOST_TEST(toml::find<std::string>(v, "b") == "qux");
}
{
const toml::basic_value<toml::discard_comments, std::map> v{
{"a", 42}, {"b", "baz"}
};
const auto baz = toml::get<extlib2::baz>(v);
BOOST_TEST(baz.a == 42);
BOOST_TEST(baz.b == "baz");
}
{
const extlib::qux q{42, "qux"};
const toml::basic_value<toml::preserve_comments, std::map> v(q);
BOOST_TEST(toml::find<int>(v, "a") == 42);
BOOST_TEST(toml::find<std::string>(v, "b") == "qux");
}
}
BOOST_AUTO_TEST_CASE(test_conversion_via_constructor)
{
{
const toml::value v{{"a", 42}, {"b", "foobar"}};
const auto foobar = toml::get<extlib::foobar>(v);
BOOST_TEST(foobar.a == 42);
BOOST_TEST(foobar.b == "foobar");
}
{
const toml::basic_value<toml::discard_comments, std::map> v{
{"a", 42}, {"b", "foobar"}
};
const auto foobar = toml::get<extlib2::foobar>(v);
BOOST_TEST(foobar.a == 42);
BOOST_TEST(foobar.b == "foobar");
}
}
BOOST_AUTO_TEST_CASE(test_recursive_conversion)
{
{
const toml::value v{
toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 44}, {"b", "quux"}},
toml::table{{"a", 45}, {"b", "foobar"}},
};
const auto foos = toml::get<std::vector<extlib::foo>>(v);
BOOST_TEST(foos.size() == 4ul);
BOOST_TEST(foos.at(0).a == 42);
BOOST_TEST(foos.at(1).a == 43);
BOOST_TEST(foos.at(2).a == 44);
BOOST_TEST(foos.at(3).a == 45);
BOOST_TEST(foos.at(0).b == "baz");
BOOST_TEST(foos.at(1).b == "qux");
BOOST_TEST(foos.at(2).b == "quux");
BOOST_TEST(foos.at(3).b == "foobar");
const auto bars = toml::get<std::vector<extlib::bar>>(v);
BOOST_TEST(bars.size() == 4ul);
BOOST_TEST(bars.at(0).a == 42);
BOOST_TEST(bars.at(1).a == 43);
BOOST_TEST(bars.at(2).a == 44);
BOOST_TEST(bars.at(3).a == 45);
BOOST_TEST(bars.at(0).b == "baz");
BOOST_TEST(bars.at(1).b == "qux");
BOOST_TEST(bars.at(2).b == "quux");
BOOST_TEST(bars.at(3).b == "foobar");
}
{
const toml::value v{
toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 44}, {"b", "quux"}},
toml::table{{"a", 45}, {"b", "foobar"}},
};
const auto foos = toml::get<std::vector<extlib2::foo>>(v);
BOOST_TEST(foos.size() == 4ul);
BOOST_TEST(foos.at(0).a == 42);
BOOST_TEST(foos.at(1).a == 43);
BOOST_TEST(foos.at(2).a == 44);
BOOST_TEST(foos.at(3).a == 45);
BOOST_TEST(foos.at(0).b == "baz");
BOOST_TEST(foos.at(1).b == "qux");
BOOST_TEST(foos.at(2).b == "quux");
BOOST_TEST(foos.at(3).b == "foobar");
const auto bars = toml::get<std::vector<extlib2::bar>>(v);
BOOST_TEST(bars.size() == 4ul);
BOOST_TEST(bars.at(0).a == 42);
BOOST_TEST(bars.at(1).a == 43);
BOOST_TEST(bars.at(2).a == 44);
BOOST_TEST(bars.at(3).a == 45);
BOOST_TEST(bars.at(0).b == "baz");
BOOST_TEST(bars.at(1).b == "qux");
BOOST_TEST(bars.at(2).b == "quux");
BOOST_TEST(bars.at(3).b == "foobar");
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v{
toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 44}, {"b", "quux"}},
toml::table{{"a", 45}, {"b", "foobar"}}
};
const auto foos = toml::get<std::vector<extlib2::foo>>(v);
BOOST_TEST(foos.size() == 4ul);
BOOST_TEST(foos.at(0).a == 42);
BOOST_TEST(foos.at(1).a == 43);
BOOST_TEST(foos.at(2).a == 44);
BOOST_TEST(foos.at(3).a == 45);
BOOST_TEST(foos.at(0).b == "baz");
BOOST_TEST(foos.at(1).b == "qux");
BOOST_TEST(foos.at(2).b == "quux");
BOOST_TEST(foos.at(3).b == "foobar");
const auto bars = toml::get<std::vector<extlib2::bar>>(v);
BOOST_TEST(bars.size() == 4ul);
BOOST_TEST(bars.at(0).a == 42);
BOOST_TEST(bars.at(1).a == 43);
BOOST_TEST(bars.at(2).a == 44);
BOOST_TEST(bars.at(3).a == 45);
BOOST_TEST(bars.at(0).b == "baz");
BOOST_TEST(bars.at(1).b == "qux");
BOOST_TEST(bars.at(2).b == "quux");
BOOST_TEST(bars.at(3).b == "foobar");
}
// via constructor
{
const toml::value v{
toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 44}, {"b", "quux"}},
toml::table{{"a", 45}, {"b", "foobar"}}
};
{
const auto foobars = toml::get<std::vector<extlib::foobar>>(v);
BOOST_TEST(foobars.size() == 4ul);
BOOST_TEST(foobars.at(0).a == 42);
BOOST_TEST(foobars.at(1).a == 43);
BOOST_TEST(foobars.at(2).a == 44);
BOOST_TEST(foobars.at(3).a == 45);
BOOST_TEST(foobars.at(0).b == "baz");
BOOST_TEST(foobars.at(1).b == "qux");
BOOST_TEST(foobars.at(2).b == "quux");
BOOST_TEST(foobars.at(3).b == "foobar");
}
{
const auto foobars = toml::get<std::vector<extlib2::foobar>>(v);
BOOST_TEST(foobars.size() == 4ul);
BOOST_TEST(foobars.at(0).a == 42);
BOOST_TEST(foobars.at(1).a == 43);
BOOST_TEST(foobars.at(2).a == 44);
BOOST_TEST(foobars.at(3).a == 45);
BOOST_TEST(foobars.at(0).b == "baz");
BOOST_TEST(foobars.at(1).b == "qux");
BOOST_TEST(foobars.at(2).b == "quux");
BOOST_TEST(foobars.at(3).b == "foobar");
}
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v{
toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 44}, {"b", "quux"}},
toml::table{{"a", 45}, {"b", "foobar"}}
};
const auto foobars = toml::get<std::vector<extlib2::foobar>>(v);
BOOST_TEST(foobars.size() == 4ul);
BOOST_TEST(foobars.at(0).a == 42);
BOOST_TEST(foobars.at(1).a == 43);
BOOST_TEST(foobars.at(2).a == 44);
BOOST_TEST(foobars.at(3).a == 45);
BOOST_TEST(foobars.at(0).b == "baz");
BOOST_TEST(foobars.at(1).b == "qux");
BOOST_TEST(foobars.at(2).b == "quux");
BOOST_TEST(foobars.at(3).b == "foobar");
}
// via constructor
{
const toml::value v{
{"0", toml::table{{"a", 42}, {"b", "baz"}}},
{"1", toml::table{{"a", 43}, {"b", "qux"}}},
{"2", toml::table{{"a", 44}, {"b", "quux"}}},
{"3", toml::table{{"a", 45}, {"b", "foobar"}}}
};
{
const auto foobars = toml::get<std::map<std::string, extlib::foobar>>(v);
BOOST_TEST(foobars.size() == 4ul);
BOOST_TEST(foobars.at("0").a == 42);
BOOST_TEST(foobars.at("1").a == 43);
BOOST_TEST(foobars.at("2").a == 44);
BOOST_TEST(foobars.at("3").a == 45);
BOOST_TEST(foobars.at("0").b == "baz");
BOOST_TEST(foobars.at("1").b == "qux");
BOOST_TEST(foobars.at("2").b == "quux");
BOOST_TEST(foobars.at("3").b == "foobar");
}
{
const auto foobars = toml::get<std::map<std::string, extlib2::foobar>>(v);
BOOST_TEST(foobars.size() == 4ul);
BOOST_TEST(foobars.at("0").a == 42);
BOOST_TEST(foobars.at("1").a == 43);
BOOST_TEST(foobars.at("2").a == 44);
BOOST_TEST(foobars.at("3").a == 45);
BOOST_TEST(foobars.at("0").b == "baz");
BOOST_TEST(foobars.at("1").b == "qux");
BOOST_TEST(foobars.at("2").b == "quux");
BOOST_TEST(foobars.at("3").b == "foobar");
}
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque>
v{
{"0", toml::table{{"a", 42}, {"b", "baz"}}},
{"1", toml::table{{"a", 43}, {"b", "qux"}}},
{"2", toml::table{{"a", 44}, {"b", "quux"}}},
{"3", toml::table{{"a", 45}, {"b", "foobar"}}}
};
const auto foobars = toml::get<std::map<std::string, extlib::foobar>>(v);
BOOST_TEST(foobars.size() == 4ul);
BOOST_TEST(foobars.at("0").a == 42);
BOOST_TEST(foobars.at("1").a == 43);
BOOST_TEST(foobars.at("2").a == 44);
BOOST_TEST(foobars.at("3").a == 45);
BOOST_TEST(foobars.at("0").b == "baz");
BOOST_TEST(foobars.at("1").b == "qux");
BOOST_TEST(foobars.at("2").b == "quux");
BOOST_TEST(foobars.at("3").b == "foobar");
}
}
// ===========================================================================
#ifndef TOML11_WITHOUT_DEFINE_NON_INTRUSIVE
namespace extlib3
{
struct foo
{
int a;
std::string b;
};
struct bar
{
int a;
std::string b;
foo f;
};
} // extlib3
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib3::foo, a, b)
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib3::bar, a, b, f)
BOOST_AUTO_TEST_CASE(test_conversion_via_macro)
{
{
const toml::value v{{"a", 42}, {"b", "baz"}};
const auto foo = toml::get<extlib3::foo>(v);
BOOST_TEST(foo.a == 42);
BOOST_TEST(foo.b == "baz");
const toml::value v2(foo);
BOOST_TEST(v2 == v);
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque> v{
{"a", 42}, {"b", "baz"}
};
const auto foo = toml::get<extlib3::foo>(v);
BOOST_TEST(foo.a == 42);
BOOST_TEST(foo.b == "baz");
const toml::basic_value<toml::discard_comments, std::map, std::deque> v2(foo);
BOOST_TEST(v2 == v);
}
// -----------------------------------------------------------------------
{
const toml::value v{
{"a", 42},
{"b", "bar.b"},
{"f", toml::table{{"a", 42}, {"b", "foo.b"}}}
};
const auto bar = toml::get<extlib3::bar>(v);
BOOST_TEST(bar.a == 42);
BOOST_TEST(bar.b == "bar.b");
BOOST_TEST(bar.f.a == 42);
BOOST_TEST(bar.f.b == "foo.b");
const toml::value v2(bar);
BOOST_TEST(v2 == v);
}
{
const toml::basic_value<toml::discard_comments, std::map, std::deque> v{
{"a", 42},
{"b", "bar.b"},
{"f", toml::table{{"a", 42}, {"b", "foo.b"}}}
};
const auto bar = toml::get<extlib3::bar>(v);
BOOST_TEST(bar.a == 42);
BOOST_TEST(bar.b == "bar.b");
BOOST_TEST(bar.f.a == 42);
BOOST_TEST(bar.f.b == "foo.b");
const toml::basic_value<toml::discard_comments, std::map, std::deque> v2(bar);
BOOST_TEST(v2 == v);
}
}
#endif // TOML11_WITHOUT_DEFINE_NON_INTRUSIVE

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,10 @@
#include <toml.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include "utility.hpp"
#include <toml11/value.hpp>
#include <toml11/find.hpp>
#include <array> #include <array>
#include <deque> #include <deque>
@@ -13,235 +17,179 @@
#include <string_view> #include <string_view>
#endif #endif
using test_value_types = std::tuple< #define TOML11_TEST_FIND_OR_EXACT(ty, init_expr, opt_expr)\
toml::basic_value<toml::discard_comments>, { \
toml::basic_value<toml::preserve_comments>, const ty init init_expr ; \
toml::basic_value<toml::discard_comments, std::map, std::deque>, const ty opt opt_expr ; \
toml::basic_value<toml::preserve_comments, std::map, std::deque> const value_type v = toml::table{{"key", init}}; \
>; CHECK_NE(init, opt); \
CHECK_EQ(init, toml::find_or(v, "key", opt)); \
}
namespace test TEST_CASE("testing toml::find_or with toml types")
{ {
template<typename charT, typename traits, typename T, typename Alloc> using value_type = toml::value;
std::basic_ostream<charT, traits>& using boolean_type = typename value_type::boolean_type ;
operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v) using integer_type = typename value_type::integer_type ;
{ using floating_type = typename value_type::floating_type ;
os << "[ "; using string_type = typename value_type::string_type ;
for(const auto& i : v) {os << i << ' ';} using local_time_type = typename value_type::local_time_type ;
os << ']'; using local_date_type = typename value_type::local_date_type ;
return os; using local_datetime_type = typename value_type::local_datetime_type ;
} using offset_datetime_type = typename value_type::offset_datetime_type;
template<typename charT, typename traits, typename T, typename Alloc> using array_type = typename value_type::array_type ;
std::basic_ostream<charT, traits>& using table_type = typename value_type::table_type ;
operator<<(std::basic_ostream<charT, traits>& os, const std::deque<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::list<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Comp, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::map<Key, Value, Comp, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Hash, typename Eq, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::unordered_map<Key, Value, Hash, Eq, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
} // test
#define TOML11_TEST_FIND_OR_EXACT(toml_type, init_expr, opt_expr)\ TOML11_TEST_FIND_OR_EXACT(boolean_type, ( true), (false))
{ \ TOML11_TEST_FIND_OR_EXACT(integer_type, ( 42), ( 54))
using namespace test; \ TOML11_TEST_FIND_OR_EXACT(floating_type, ( 3.14), ( 2.71))
const toml::toml_type init init_expr ; \ TOML11_TEST_FIND_OR_EXACT(string_type, ("foo"), ("bar"))
const toml::toml_type opt opt_expr ; \ TOML11_TEST_FIND_OR_EXACT(local_time_type, (12, 30, 45), (6, 0, 30))
const value_type v{{"key", init}}; \ TOML11_TEST_FIND_OR_EXACT(local_date_type, (2019, toml::month_t::Apr, 1),
BOOST_TEST(init != opt); \ (1999, toml::month_t::Jan, 2))
BOOST_TEST(init == toml::find_or(v, "key", opt)); \ TOML11_TEST_FIND_OR_EXACT(local_datetime_type,
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_exact, value_type, test_value_types)
{
TOML11_TEST_FIND_OR_EXACT(boolean, ( true), (false))
TOML11_TEST_FIND_OR_EXACT(integer, ( 42), ( 54))
TOML11_TEST_FIND_OR_EXACT(floating, ( 3.14), ( 2.71))
TOML11_TEST_FIND_OR_EXACT(string, ("foo"), ("bar"))
TOML11_TEST_FIND_OR_EXACT(local_time, (12, 30, 45), (6, 0, 30))
TOML11_TEST_FIND_OR_EXACT(local_date, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_FIND_OR_EXACT(local_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
) )
TOML11_TEST_FIND_OR_EXACT(offset_datetime, TOML11_TEST_FIND_OR_EXACT(offset_datetime_type,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
) )
{ TOML11_TEST_FIND_OR_EXACT(array_type, ({1,2,3,4,5}), ({6,7,8,9,10}));
const typename value_type::array_type init{1,2,3,4,5}; TOML11_TEST_FIND_OR_EXACT(table_type, ({{"key1", 42}, {"key2", "foo"}}),
const typename value_type::array_type opt {6,7,8,9,10}; ({{"key1", 54}, {"key2", "bar"}}));
const value_type v{{"key", init}};
BOOST_TEST(init != opt);
BOOST_TEST(init == toml::find_or(v, "key", opt));
}
{
const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
const value_type v{{"key", init}};
BOOST_TEST(init != opt);
BOOST_TEST(init == toml::find_or(v, "key", opt));
}
} }
#undef TOML11_TEST_FIND_OR_EXACT #undef TOML11_TEST_FIND_OR_EXACT
#define TOML11_TEST_FIND_OR_MOVE(toml_type, init_expr, opt_expr) \ #define TOML11_TEST_FIND_OR_MOVE(ty, init_expr, opt_expr) \
{ \ { \
using namespace test; \ const ty init init_expr ; \
const toml::toml_type init init_expr ; \ ty opt opt_expr ; \
toml::toml_type opt opt_expr ; \ value_type v = toml::table{{"key", init}}; \
value_type v{{"key", init}}; \ CHECK_NE(init, opt); \
BOOST_TEST(init != opt); \
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));\ const auto moved = toml::find_or(std::move(v), "key", std::move(opt));\
BOOST_TEST(init == moved); \ CHECK_EQ(init, moved); \
} \ }
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move, value_type, test_value_types) TEST_CASE("testing toml::find_or with moved argument")
{ {
TOML11_TEST_FIND_OR_MOVE(boolean, ( true), (false)) using value_type = toml::value;
TOML11_TEST_FIND_OR_MOVE(integer, ( 42), ( 54)) using boolean_type = typename value_type::boolean_type ;
TOML11_TEST_FIND_OR_MOVE(floating, ( 3.14), ( 2.71)) using integer_type = typename value_type::integer_type ;
TOML11_TEST_FIND_OR_MOVE(string, ("foo"), ("bar")) using floating_type = typename value_type::floating_type ;
TOML11_TEST_FIND_OR_MOVE(local_time, (12, 30, 45), (6, 0, 30)) using string_type = typename value_type::string_type ;
TOML11_TEST_FIND_OR_MOVE(local_date, (2019, toml::month_t::Apr, 1), using local_time_type = typename value_type::local_time_type ;
using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
TOML11_TEST_FIND_OR_MOVE(boolean_type, ( true), (false))
TOML11_TEST_FIND_OR_MOVE(integer_type, ( 42), ( 54))
TOML11_TEST_FIND_OR_MOVE(floating_type, ( 3.14), ( 2.71))
TOML11_TEST_FIND_OR_MOVE(string_type, ("foo"), ("bar"))
TOML11_TEST_FIND_OR_MOVE(local_time_type, (12, 30, 45), (6, 0, 30))
TOML11_TEST_FIND_OR_MOVE(local_date_type, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2)) (1999, toml::month_t::Jan, 2))
TOML11_TEST_FIND_OR_MOVE(local_datetime, TOML11_TEST_FIND_OR_MOVE(local_datetime_type,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
) )
TOML11_TEST_FIND_OR_MOVE(offset_datetime, TOML11_TEST_FIND_OR_MOVE(offset_datetime_type,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
) )
{ TOML11_TEST_FIND_OR_MOVE(array_type, ({1,2,3,4,5}), ({6,7,8,9,10}));
typename value_type::array_type init{1,2,3,4,5}; TOML11_TEST_FIND_OR_MOVE(table_type, ({{"key1", 42}, {"key2", "foo"}}),
typename value_type::array_type opt {6,7,8,9,10}; ({{"key1", 54}, {"key2", "bar"}}));
value_type v{{"key", init}};
BOOST_TEST(init != opt);
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
BOOST_TEST(init == moved);
}
{
typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
value_type v{{"key", init}};
BOOST_TEST(init != opt);
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
BOOST_TEST(init == moved);
}
} }
#undef TOML11_TEST_FIND_OR_MOVE #undef TOML11_TEST_FIND_OR_MOVE
#define TOML11_TEST_FIND_OR_MODIFY(toml_type, init_expr, opt_expr)\ #define TOML11_TEST_FIND_OR_MODIFY(ty, init_expr, opt_expr)\
{ \ { \
using namespace test; \ const ty init init_expr ; \
const toml::toml_type init init_expr ; \ ty opt1 opt_expr ; \
toml::toml_type opt1 opt_expr ; \ ty opt2 opt_expr ; \
toml::toml_type opt2 opt_expr ; \ value_type v = toml::table{{"key", init}}; \
value_type v{{"key", init}}; \ CHECK_NE(init, opt1); \
BOOST_TEST(init != opt1); \ toml::find_or(v, "key", opt2) = opt1; \
toml::find_or(v, "key", opt2) = opt1; \ CHECK_EQ(opt1, toml::find<ty>(v, "key")); \
BOOST_TEST(opt1 == toml::find<toml::toml_type>(v, "key"));\ }
} \
/**/ TEST_CASE("testing find_or with modification")
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_modify, value_type, test_value_types)
{ {
TOML11_TEST_FIND_OR_MODIFY(boolean, ( true), (false)) using value_type = toml::value;
TOML11_TEST_FIND_OR_MODIFY(integer, ( 42), ( 54)) using boolean_type = typename value_type::boolean_type ;
TOML11_TEST_FIND_OR_MODIFY(floating, ( 3.14), ( 2.71)) using integer_type = typename value_type::integer_type ;
TOML11_TEST_FIND_OR_MODIFY(string, ("foo"), ("bar")) using floating_type = typename value_type::floating_type ;
TOML11_TEST_FIND_OR_MODIFY(local_time, (12, 30, 45), (6, 0, 30)) using string_type = typename value_type::string_type ;
TOML11_TEST_FIND_OR_MODIFY(local_date, (2019, toml::month_t::Apr, 1), using local_time_type = typename value_type::local_time_type ;
using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
TOML11_TEST_FIND_OR_MODIFY(boolean_type, ( true), (false))
TOML11_TEST_FIND_OR_MODIFY(integer_type, ( 42), ( 54))
TOML11_TEST_FIND_OR_MODIFY(floating_type, ( 3.14), ( 2.71))
TOML11_TEST_FIND_OR_MODIFY(string_type, ("foo"), ("bar"))
TOML11_TEST_FIND_OR_MODIFY(local_time_type, (12, 30, 45), (6, 0, 30))
TOML11_TEST_FIND_OR_MODIFY(local_date_type, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2)) (1999, toml::month_t::Jan, 2))
TOML11_TEST_FIND_OR_MODIFY(local_datetime, TOML11_TEST_FIND_OR_MODIFY(local_datetime_type,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
) )
TOML11_TEST_FIND_OR_MODIFY(offset_datetime, TOML11_TEST_FIND_OR_MODIFY(offset_datetime_type,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
) )
{
typename value_type::array_type init{1,2,3,4,5}; TOML11_TEST_FIND_OR_MODIFY(array_type, ({1,2,3,4,5}), ({6,7,8,9,10}));
typename value_type::array_type opt1{6,7,8,9,10}; TOML11_TEST_FIND_OR_MODIFY(table_type, ({{"key1", 42}, {"key2", "foo"}}),
typename value_type::array_type opt2{6,7,8,9,10}; ({{"key1", 54}, {"key2", "bar"}}));
BOOST_TEST(init != opt1);
value_type v{{"key", init}};
toml::find_or(v, "key", opt2) = opt1;
BOOST_TEST(opt1 == toml::find<typename value_type::array_type>(v, "key"));
}
{
typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}};
typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}};
value_type v{{"key", init}};
BOOST_TEST(init != opt1);
toml::find_or(v, "key", opt2) = opt1;
BOOST_TEST(opt1 == toml::find<typename value_type::table_type>(v, "key"));
}
} }
#undef TOML11_TEST_FIND_OR_MODIFY #undef TOML11_TEST_FIND_OR_MODIFY
#define TOML11_TEST_FIND_OR_FALLBACK(init_type, opt_type) \ #define TOML11_TEST_FIND_OR_FALLBACK(init_type, opt_type) \
{ \ { \
using namespace test; \ value_type v1(init_type); \
value_type v(init_type); \ CHECK_EQ(opt_type, toml::find_or(v1, "key", opt_type)); \
BOOST_TEST(opt_type == toml::find_or(v, "key", opt_type));\ value_type v2 = toml::table{{"different_key", init_type}}; \
} \ CHECK_EQ(opt_type, toml::find_or(v2, "key", opt_type)); \
/**/ }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_fallback, value_type, test_value_types) TEST_CASE("testing toml::find_or returns fallback if failed")
{ {
const toml::boolean boolean (true); using value_type = toml::value;
const toml::integer integer (42); using boolean_type = typename value_type::boolean_type ;
const toml::floating floating (3.14); using integer_type = typename value_type::integer_type ;
const toml::string string ("foo"); using floating_type = typename value_type::floating_type ;
const toml::local_time local_time (12, 30, 45); using string_type = typename value_type::string_type ;
const toml::local_date local_date (2019, toml::month_t::Apr, 1); using local_time_type = typename value_type::local_time_type ;
const toml::local_datetime local_datetime ( using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
const boolean_type boolean (true);
const integer_type integer (42);
const floating_type floating (3.14);
const string_type string ("foo");
const local_time_type local_time (12, 30, 45);
const local_date_type local_date (2019, toml::month_t::Apr, 1);
const local_datetime_type local_datetime (
toml::local_date(2019, toml::month_t::Apr, 1), toml::local_date(2019, toml::month_t::Apr, 1),
toml::local_time(12, 30, 45)); toml::local_time(12, 30, 45));
const toml::offset_datetime offset_datetime( const offset_datetime_type offset_datetime(
toml::local_date(2019, toml::month_t::Apr, 1), toml::local_date(2019, toml::month_t::Apr, 1),
toml::local_time(12, 30, 45), toml::time_offset( 9, 0)); toml::local_time(12, 30, 45), toml::time_offset( 9, 0));
using array_type = typename value_type::array_type;
using table_type = typename value_type::table_type;
const array_type array{1, 2, 3, 4, 5}; const array_type array{1, 2, 3, 4, 5};
const table_type table{{"key1", 42}, {"key2", "foo"}}; const table_type table{{"key1", 42}, {"key2", "foo"}};
@@ -347,46 +295,46 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_fallback, value_type, test_value_type
} }
#undef TOML11_TEST_FIND_OR_FALLBACK #undef TOML11_TEST_FIND_OR_FALLBACK
BOOST_AUTO_TEST_CASE(test_find_or_integer) TEST_CASE("testing find_or; converting to an integer")
{ {
{ {
toml::value v{{"num", 42}}; toml::value v = toml::table{{"num", 42}};
BOOST_TEST(42u == toml::find_or(v, "num", 0u)); CHECK_EQ(42u, toml::find_or(v, "num", 0u));
BOOST_TEST(0u == toml::find_or(v, "foo", 0u)); CHECK_EQ(0u , toml::find_or(v, "foo", 0u));
} }
{ {
toml::value v{{"num", 42}}; toml::value v = toml::table{{"num", 42}};
const auto moved = toml::find_or(std::move(v), "num", 0u); const auto moved = toml::find_or(std::move(v), "num", 0u);
BOOST_TEST(42u == moved); CHECK_EQ(42u, moved);
} }
{ {
toml::value v{{"num", 42}}; toml::value v = toml::table{{"num", 42}};
const auto moved = toml::find_or(std::move(v), "foo", 0u); const auto moved = toml::find_or(std::move(v), "foo", 0u);
BOOST_TEST(0u == moved); CHECK_EQ(0u, moved);
} }
} }
BOOST_AUTO_TEST_CASE(test_find_or_floating) TEST_CASE("testing find_or; converting to a floating")
{ {
{ {
toml::value v1{{"key", 42}}; toml::value v1 = toml::table{{"key", 42}};
toml::value v2{{"key", 3.14}}; toml::value v2 = toml::table{{"key", 3.14}};
BOOST_TEST(2.71f == toml::find_or(v1, "key", 2.71f)); CHECK_EQ(2.71f, toml::find_or(v1, "key", 2.71f));
const double ref(3.14); const double ref(3.14);
BOOST_TEST(static_cast<float>(ref) == toml::find_or(v2, "key", 2.71f)); CHECK_EQ(static_cast<float>(ref), toml::find_or(v2, "key", 2.71f));
} }
{ {
toml::value v1{{"key", 42}}; toml::value v1 = toml::table{{"key", 42}};
toml::value v2{{"key", 3.14}}; toml::value v2 = toml::table{{"key", 3.14}};
const auto moved1 = toml::find_or(std::move(v1), "key", 2.71f); const auto moved1 = toml::find_or(std::move(v1), "key", 2.71f);
const auto moved2 = toml::find_or(std::move(v2), "key", 2.71f); const auto moved2 = toml::find_or(std::move(v2), "key", 2.71f);
BOOST_TEST(2.71f == moved1); CHECK_EQ(2.71f, moved1);
const double ref(3.14); const double ref(3.14);
BOOST_TEST(static_cast<float>(ref) == moved2); CHECK_EQ(static_cast<float>(ref), moved2);
} }
} }
BOOST_AUTO_TEST_CASE(test_find_or_string) TEST_CASE("testing find_or; converting to a string")
{ {
{ {
toml::value v1 = toml::table{{"key", "foobar"}}; toml::value v1 = toml::table{{"key", "foobar"}};
@@ -395,21 +343,21 @@ BOOST_AUTO_TEST_CASE(test_find_or_string)
std::string s1("bazqux"); std::string s1("bazqux");
const std::string s2("bazqux"); const std::string s2("bazqux");
BOOST_TEST("foobar" == toml::find_or(v1, "key", s1)); CHECK_EQ("foobar", toml::find_or(v1, "key", s1));
BOOST_TEST("bazqux" == toml::find_or(v2, "key", s1)); CHECK_EQ("bazqux", toml::find_or(v2, "key", s1));
std::string& v1r = toml::find_or(v1, "key", s1); std::string& v1r = toml::find_or(v1, "key", s1);
std::string& s1r = toml::find_or(v2, "key", s1); std::string& s1r = toml::find_or(v2, "key", s1);
BOOST_TEST("foobar" == v1r); CHECK_EQ("foobar", v1r);
BOOST_TEST("bazqux" == s1r); CHECK_EQ("bazqux", s1r);
BOOST_TEST("foobar" == toml::find_or(v1, "key", s2)); CHECK_EQ("foobar", toml::find_or(v1, "key", s2));
BOOST_TEST("bazqux" == toml::find_or(v2, "key", s2)); CHECK_EQ("bazqux", toml::find_or(v2, "key", s2));
BOOST_TEST("foobar" == toml::find_or(std::move(v1), "key", std::move(s1))); CHECK_EQ("foobar", toml::find_or(std::move(v1), "key", std::move(s1)));
s1 = "bazqux"; // restoring moved value s1 = "bazqux"; // restoring moved value
BOOST_TEST("bazqux" == toml::find_or(std::move(v2), "key", std::move(s1))); CHECK_EQ("bazqux", toml::find_or(std::move(v2), "key", std::move(s1)));
} }
{ {
toml::value v1 = toml::table{{"key", "foobar"}}; toml::value v1 = toml::table{{"key", "foobar"}};
@@ -420,8 +368,8 @@ BOOST_AUTO_TEST_CASE(test_find_or_string)
const auto moved1 = toml::find_or(std::move(v1), "key", s1); const auto moved1 = toml::find_or(std::move(v1), "key", s1);
const auto moved2 = toml::find_or(std::move(v2), "key", s1); const auto moved2 = toml::find_or(std::move(v2), "key", s1);
BOOST_TEST("foobar" == moved1); CHECK_EQ("foobar", moved1);
BOOST_TEST("bazqux" == moved2); CHECK_EQ("bazqux", moved2);
} }
{ {
toml::value v1 = toml::table{{"key", "foobar"}}; toml::value v1 = toml::table{{"key", "foobar"}};
@@ -433,8 +381,8 @@ BOOST_AUTO_TEST_CASE(test_find_or_string)
const auto moved1 = toml::find_or(std::move(v1), "key", std::move(s1)); const auto moved1 = toml::find_or(std::move(v1), "key", std::move(s1));
const auto moved2 = toml::find_or(std::move(v2), "key", std::move(s2)); const auto moved2 = toml::find_or(std::move(v2), "key", std::move(s2));
BOOST_TEST("foobar" == moved1); CHECK_EQ("foobar", moved1);
BOOST_TEST("bazqux" == moved2); CHECK_EQ("bazqux", moved2);
} }
// string literal // string literal
@@ -442,12 +390,12 @@ BOOST_AUTO_TEST_CASE(test_find_or_string)
toml::value v1 = toml::table{{"key", "foobar"}}; toml::value v1 = toml::table{{"key", "foobar"}};
toml::value v2 = toml::table{{"key",42}}; toml::value v2 = toml::table{{"key",42}};
BOOST_TEST("foobar" == toml::find_or(v1, "key", "bazqux")); CHECK_EQ("foobar", toml::find_or(v1, "key", "bazqux"));
BOOST_TEST("bazqux" == toml::find_or(v2, "key", "bazqux")); CHECK_EQ("bazqux", toml::find_or(v2, "key", "bazqux"));
const char* lit = "bazqux"; const auto lit = "bazqux";
BOOST_TEST("foobar" == toml::find_or(v1, "key", lit)); CHECK_EQ("foobar", toml::find_or(v1, "key", lit));
BOOST_TEST("bazqux" == toml::find_or(v2, "key", lit)); CHECK_EQ("bazqux", toml::find_or(v2, "key", lit));
} }
{ {
toml::value v1 = toml::table{{"key", "foobar"}}; toml::value v1 = toml::table{{"key", "foobar"}};
@@ -456,8 +404,8 @@ BOOST_AUTO_TEST_CASE(test_find_or_string)
const auto moved1 = toml::find_or(std::move(v1), "key", "bazqux"); const auto moved1 = toml::find_or(std::move(v1), "key", "bazqux");
const auto moved2 = toml::find_or(std::move(v2), "key", "bazqux"); const auto moved2 = toml::find_or(std::move(v2), "key", "bazqux");
BOOST_TEST("foobar" == moved1); CHECK_EQ("foobar", moved1);
BOOST_TEST("bazqux" == moved2); CHECK_EQ("bazqux", moved2);
} }
{ {
toml::value v1 = toml::table{{"key", "foobar"}}; toml::value v1 = toml::table{{"key", "foobar"}};
@@ -467,72 +415,155 @@ BOOST_AUTO_TEST_CASE(test_find_or_string)
const auto moved1 = toml::find_or(std::move(v1), "key", lit); const auto moved1 = toml::find_or(std::move(v1), "key", lit);
const auto moved2 = toml::find_or(std::move(v2), "key", lit); const auto moved2 = toml::find_or(std::move(v2), "key", lit);
BOOST_TEST("foobar" == moved1); CHECK_EQ("foobar", moved1);
BOOST_TEST("bazqux" == moved2); CHECK_EQ("bazqux", moved2);
} }
} }
BOOST_AUTO_TEST_CASE(test_find_or_map) TEST_CASE("testing find_or; converting to a map")
{ {
using map_type = std::map<std::string, std::string>; using map_type = std::map<std::string, std::string>;
{ {
const toml::value v1{ const toml::value v1 = toml::table{
{"key", {{"key", "value"}}} {"key", toml::table{{"key", "value"}}}
}; };
const auto key = toml::find_or(v1, "key", map_type{}); const auto key = toml::find_or(v1, "key", map_type{});
const auto key2 = toml::find_or(v1, "key2", map_type{}); const auto key2 = toml::find_or(v1, "key2", map_type{});
BOOST_TEST(!key.empty()); CHECK_UNARY(!key.empty());
BOOST_TEST(key2.empty()); CHECK_UNARY(key2.empty());
BOOST_TEST(key.size() == 1u); CHECK_EQ(key.size() , 1u);
BOOST_TEST(key.at("key") == "value"); CHECK_EQ(key.at("key"), "value");
} }
{ {
toml::value v1{ toml::value v1 = toml::table{
{"key", {{"key", "value"}}} {"key", toml::table{{"key", "value"}}}
}; };
const auto key = toml::find_or<map_type>(v1, "key", map_type{}); const auto key = toml::find_or<map_type>(v1, "key", map_type{});
const auto key2 = toml::find_or<map_type>(v1, "key2", map_type{}); const auto key2 = toml::find_or<map_type>(v1, "key2", map_type{});
BOOST_TEST(!key.empty()); CHECK_UNARY(!key.empty());
BOOST_TEST(key2.empty()); CHECK_UNARY(key2.empty());
BOOST_TEST(key.size() == 1u); CHECK_EQ(key.size() , 1u);
BOOST_TEST(key.at("key") == "value"); CHECK_EQ(key.at("key"), "value");
} }
{ {
toml::value v1{ toml::value v1 = toml::table{
{"key", {{"key", "value"}}} {"key", toml::table{{"key", "value"}}}
}; };
toml::value v2(v1); toml::value v2(v1);
const auto key = toml::find_or(std::move(v1), "key", map_type{}); const auto key = toml::find_or(std::move(v1), "key", map_type{});
const auto key2 = toml::find_or(std::move(v2), "key2", map_type{}); const auto key2 = toml::find_or(std::move(v2), "key2", map_type{});
BOOST_TEST(!key.empty()); CHECK_UNARY(!key.empty());
BOOST_TEST(key2.empty()); CHECK_UNARY(key2.empty());
BOOST_TEST(key.size() == 1u); CHECK_EQ(key.size() , 1u);
BOOST_TEST(key.at("key") == "value"); CHECK_EQ(key.at("key"), "value");
} }
{ {
toml::value v1{ toml::value v1 = toml::table{
{"key", {{"key", "value"}}} {"key", toml::table{{"key", "value"}}}
}; };
toml::value v2(v1); toml::value v2(v1);
const auto key = toml::find_or<map_type>(std::move(v1), "key", map_type{}); const auto key = toml::find_or<map_type>(std::move(v1), "key", map_type{});
const auto key2 = toml::find_or<map_type>(std::move(v2), "key2", map_type{}); const auto key2 = toml::find_or<map_type>(std::move(v2), "key2", map_type{});
BOOST_TEST(!key.empty()); CHECK_UNARY(!key.empty());
BOOST_TEST(key2.empty()); CHECK_UNARY(key2.empty());
BOOST_TEST(key.size() == 1u); CHECK_EQ(key.size() , 1u);
BOOST_TEST(key.at("key") == "value"); CHECK_EQ(key.at("key"), "value");
}
}
TEST_CASE("testing find_or(val, keys..., opt)")
{
// &, using type deduction
{
toml::value v(
toml::table{ {"foo",
toml::table{ {"bar",
toml::table{ {"baz",
"qux"
} }
} }
} }
);
std::string opt("hoge");
auto& v1 = toml::find_or(v, "foo", "bar", "baz", opt);
auto& v2 = toml::find_or(v, "foo", "bar", "qux", opt);
CHECK_EQ(v1, "qux");
CHECK_EQ(v2, "hoge");
v1 = "hoge";
v2 = "fuga";
CHECK_EQ(v1, "hoge");
CHECK_EQ(v2, "fuga");
}
// const&, type deduction
{
const toml::value v(
toml::table{ {"foo",
toml::table{ {"bar",
toml::table{ {"baz",
"qux"
} }
} }
} }
);
std::string opt("hoge");
const auto& v1 = toml::find_or(v, "foo", "bar", "baz", opt);
const auto& v2 = toml::find_or(v, "foo", "bar", "qux", opt);
CHECK_EQ(v1, "qux");
CHECK_EQ(v2, "hoge");
}
// explicitly specify type, doing type conversion
{
const toml::value v(
toml::table{ {"foo",
toml::table{ {"bar",
toml::table{ {"baz",
42
} }
} }
} }
);
int opt = 6 * 9;
auto v1 = toml::find_or<int>(v, "foo", "bar", "baz", opt);
auto v2 = toml::find_or<int>(v, "foo", "bar", "qux", opt);
CHECK_EQ(v1, 42);
CHECK_EQ(v2, 6*9);
}
{
const toml::value v(
toml::table{ {"foo",
toml::table{ {"bar",
toml::table{ {"baz",
42
} }
} }
} }
);
auto v1 = toml::find_or<std::string>(v, "foo", "bar", "baz", "hoge");
CHECK_EQ(v1, "hoge");
} }
} }

View File

@@ -1,393 +0,0 @@
#include <toml.hpp>
#include "unit_test.hpp"
#include <array>
#include <deque>
#include <list>
#include <map>
#include <tuple>
#include <unordered_map>
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
#include <string_view>
#endif
using test_value_types = std::tuple<
toml::basic_value<toml::discard_comments>,
toml::basic_value<toml::preserve_comments>,
toml::basic_value<toml::discard_comments, std::map, std::deque>,
toml::basic_value<toml::preserve_comments, std::map, std::deque>
>;
namespace test
{
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::deque<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::list<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Comp, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::map<Key, Value, Comp, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Hash, typename Eq, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::unordered_map<Key, Value, Hash, Eq, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
} // test
#define TOML11_TEST_FIND_OR_EXACT(toml_type, init_expr, opt_expr) \
{ \
using namespace test; \
const toml::toml_type init init_expr ; \
const toml::toml_type opt opt_expr ; \
const value_type v{{"key1", value_type{{"key2", init}} }};\
BOOST_TEST(init != opt); \
BOOST_TEST(init == toml::find_or(v, "key1", "key2", opt));\
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_exact, value_type, test_value_types)
{
TOML11_TEST_FIND_OR_EXACT(boolean, ( true), (false))
TOML11_TEST_FIND_OR_EXACT(integer, ( 42), ( 54))
TOML11_TEST_FIND_OR_EXACT(floating, ( 3.14), ( 2.71))
TOML11_TEST_FIND_OR_EXACT(string, ("foo"), ("bar"))
TOML11_TEST_FIND_OR_EXACT(local_time, (12, 30, 45), (6, 0, 30))
TOML11_TEST_FIND_OR_EXACT(local_date, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_FIND_OR_EXACT(local_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
)
TOML11_TEST_FIND_OR_EXACT(offset_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
)
{
const typename value_type::array_type init{1,2,3,4,5};
const typename value_type::array_type opt {6,7,8,9,10};
const value_type v{{"key", init}};
BOOST_TEST(init != opt);
BOOST_TEST(init == toml::find_or(v, "key", opt));
}
{
const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
const value_type v{{"key", init}};
BOOST_TEST(init != opt);
BOOST_TEST(init == toml::find_or(v, "key", opt));
}
}
#undef TOML11_TEST_FIND_OR_EXACT
#define TOML11_TEST_FIND_OR_MOVE(toml_type, init_expr, opt_expr) \
{ \
using namespace test; \
const toml::toml_type init init_expr ; \
toml::toml_type opt opt_expr ; \
value_type v{{"key1", value_type{{"key2", init}} }}; \
BOOST_TEST(init != opt); \
const auto moved = toml::find_or(std::move(v), "key1", "key2", std::move(opt));\
BOOST_TEST(init == moved); \
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move, value_type, test_value_types)
{
TOML11_TEST_FIND_OR_MOVE(boolean, ( true), (false))
TOML11_TEST_FIND_OR_MOVE(integer, ( 42), ( 54))
TOML11_TEST_FIND_OR_MOVE(floating, ( 3.14), ( 2.71))
TOML11_TEST_FIND_OR_MOVE(string, ("foo"), ("bar"))
TOML11_TEST_FIND_OR_MOVE(local_time, (12, 30, 45), (6, 0, 30))
TOML11_TEST_FIND_OR_MOVE(local_date, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_FIND_OR_MOVE(local_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
)
TOML11_TEST_FIND_OR_MOVE(offset_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
)
{
typename value_type::array_type init{1,2,3,4,5};
typename value_type::array_type opt {6,7,8,9,10};
value_type v{{"key", init}};
BOOST_TEST(init != opt);
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
BOOST_TEST(init == moved);
}
{
typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
value_type v{{"key", init}};
BOOST_TEST(init != opt);
const auto moved = toml::find_or(std::move(v), "key", std::move(opt));
BOOST_TEST(init == moved);
}
}
#undef TOML11_TEST_FIND_OR_MOVE
#define TOML11_TEST_FIND_OR_MODIFY(toml_type, init_expr, opt_expr)\
{ \
using namespace test; \
const toml::toml_type init init_expr ; \
toml::toml_type opt1 opt_expr ; \
toml::toml_type opt2 opt_expr ; \
value_type v{{"key1", value_type{{"key2", init}} }}; \
BOOST_TEST(init != opt1); \
toml::find_or(v, "key1", "key2", opt2) = opt1; \
BOOST_TEST(opt1 == toml::find<toml::toml_type>(v, "key1", "key2"));\
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_modify, value_type, test_value_types)
{
TOML11_TEST_FIND_OR_MODIFY(boolean, ( true), (false))
TOML11_TEST_FIND_OR_MODIFY(integer, ( 42), ( 54))
TOML11_TEST_FIND_OR_MODIFY(floating, ( 3.14), ( 2.71))
TOML11_TEST_FIND_OR_MODIFY(string, ("foo"), ("bar"))
TOML11_TEST_FIND_OR_MODIFY(local_time, (12, 30, 45), (6, 0, 30))
TOML11_TEST_FIND_OR_MODIFY(local_date, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_FIND_OR_MODIFY(local_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
)
TOML11_TEST_FIND_OR_MODIFY(offset_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
)
{
typename value_type::array_type init{1,2,3,4,5};
typename value_type::array_type opt1{6,7,8,9,10};
typename value_type::array_type opt2{6,7,8,9,10};
BOOST_TEST(init != opt1);
value_type v{{"key", init}};
toml::find_or(v, "key", opt2) = opt1;
BOOST_TEST(opt1 == toml::find<typename value_type::array_type>(v, "key"));
}
{
typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}};
typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}};
value_type v{{"key", init}};
BOOST_TEST(init != opt1);
toml::find_or(v, "key", opt2) = opt1;
BOOST_TEST(opt1 == toml::find<typename value_type::table_type>(v, "key"));
}
}
#undef TOML11_TEST_FIND_OR_MODIFY
#define TOML11_TEST_FIND_OR_FALLBACK(init_type, opt_type) \
{ \
using namespace test; \
value_type v1{{"key1", value_type{{"key3", "foo"}}}}; \
BOOST_TEST(opt_type == toml::find_or(v1, "key1", "key2", opt_type));\
value_type v2{{"key1", "foo"}}; \
BOOST_TEST(opt_type == toml::find_or(v2, "key1", "key3", opt_type));\
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_fallback, value_type, test_value_types)
{
const toml::boolean boolean (true);
const toml::integer integer (42);
const toml::floating floating (3.14);
const toml::string string ("foo");
const toml::local_time local_time (12, 30, 45);
const toml::local_date local_date (2019, toml::month_t::Apr, 1);
const toml::local_datetime local_datetime (
toml::local_date(2019, toml::month_t::Apr, 1),
toml::local_time(12, 30, 45));
const toml::offset_datetime offset_datetime(
toml::local_date(2019, toml::month_t::Apr, 1),
toml::local_time(12, 30, 45), toml::time_offset( 9, 0));
using array_type = typename value_type::array_type;
using table_type = typename value_type::table_type;
const array_type array{1, 2, 3, 4, 5};
const table_type table{{"key1", 42}, {"key2", "foo"}};
TOML11_TEST_FIND_OR_FALLBACK(boolean, integer );
TOML11_TEST_FIND_OR_FALLBACK(boolean, floating );
TOML11_TEST_FIND_OR_FALLBACK(boolean, string );
TOML11_TEST_FIND_OR_FALLBACK(boolean, local_time );
TOML11_TEST_FIND_OR_FALLBACK(boolean, local_date );
TOML11_TEST_FIND_OR_FALLBACK(boolean, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(boolean, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(boolean, array );
TOML11_TEST_FIND_OR_FALLBACK(boolean, table );
TOML11_TEST_FIND_OR_FALLBACK(integer, boolean );
TOML11_TEST_FIND_OR_FALLBACK(integer, floating );
TOML11_TEST_FIND_OR_FALLBACK(integer, string );
TOML11_TEST_FIND_OR_FALLBACK(integer, local_time );
TOML11_TEST_FIND_OR_FALLBACK(integer, local_date );
TOML11_TEST_FIND_OR_FALLBACK(integer, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(integer, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(integer, array );
TOML11_TEST_FIND_OR_FALLBACK(integer, table );
TOML11_TEST_FIND_OR_FALLBACK(floating, boolean );
TOML11_TEST_FIND_OR_FALLBACK(floating, integer );
TOML11_TEST_FIND_OR_FALLBACK(floating, string );
TOML11_TEST_FIND_OR_FALLBACK(floating, local_time );
TOML11_TEST_FIND_OR_FALLBACK(floating, local_date );
TOML11_TEST_FIND_OR_FALLBACK(floating, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(floating, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(floating, array );
TOML11_TEST_FIND_OR_FALLBACK(floating, table );
TOML11_TEST_FIND_OR_FALLBACK(string, boolean );
TOML11_TEST_FIND_OR_FALLBACK(string, integer );
TOML11_TEST_FIND_OR_FALLBACK(string, floating );
TOML11_TEST_FIND_OR_FALLBACK(string, local_time );
TOML11_TEST_FIND_OR_FALLBACK(string, local_date );
TOML11_TEST_FIND_OR_FALLBACK(string, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(string, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(string, array );
TOML11_TEST_FIND_OR_FALLBACK(string, table );
TOML11_TEST_FIND_OR_FALLBACK(local_time, boolean );
TOML11_TEST_FIND_OR_FALLBACK(local_time, integer );
TOML11_TEST_FIND_OR_FALLBACK(local_time, floating );
TOML11_TEST_FIND_OR_FALLBACK(local_time, string );
TOML11_TEST_FIND_OR_FALLBACK(local_time, local_date );
TOML11_TEST_FIND_OR_FALLBACK(local_time, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(local_time, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(local_time, array );
TOML11_TEST_FIND_OR_FALLBACK(local_time, table );
TOML11_TEST_FIND_OR_FALLBACK(local_date, boolean );
TOML11_TEST_FIND_OR_FALLBACK(local_date, integer );
TOML11_TEST_FIND_OR_FALLBACK(local_date, floating );
TOML11_TEST_FIND_OR_FALLBACK(local_date, string );
TOML11_TEST_FIND_OR_FALLBACK(local_date, local_time );
TOML11_TEST_FIND_OR_FALLBACK(local_date, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(local_date, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(local_date, array );
TOML11_TEST_FIND_OR_FALLBACK(local_date, table );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, boolean );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, integer );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, floating );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, string );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_time );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, local_date );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, array );
TOML11_TEST_FIND_OR_FALLBACK(local_datetime, table );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, boolean );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, integer );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, floating );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, string );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_time );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_date );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, array );
TOML11_TEST_FIND_OR_FALLBACK(offset_datetime, table );
TOML11_TEST_FIND_OR_FALLBACK(array, boolean );
TOML11_TEST_FIND_OR_FALLBACK(array, integer );
TOML11_TEST_FIND_OR_FALLBACK(array, floating );
TOML11_TEST_FIND_OR_FALLBACK(array, string );
TOML11_TEST_FIND_OR_FALLBACK(array, local_time );
TOML11_TEST_FIND_OR_FALLBACK(array, local_date );
TOML11_TEST_FIND_OR_FALLBACK(array, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(array, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(array, table );
TOML11_TEST_FIND_OR_FALLBACK(table, boolean );
TOML11_TEST_FIND_OR_FALLBACK(table, integer );
TOML11_TEST_FIND_OR_FALLBACK(table, floating );
TOML11_TEST_FIND_OR_FALLBACK(table, string );
TOML11_TEST_FIND_OR_FALLBACK(table, local_time );
TOML11_TEST_FIND_OR_FALLBACK(table, local_date );
TOML11_TEST_FIND_OR_FALLBACK(table, local_datetime );
TOML11_TEST_FIND_OR_FALLBACK(table, offset_datetime);
TOML11_TEST_FIND_OR_FALLBACK(table, array );
}
#undef TOML11_TEST_FIND_OR_FALLBACK
struct move_only_type
{
explicit move_only_type(const std::string& n): name_(n) {}
void from_toml(const toml::value& v)
{
this->name_ = toml::find<std::string>(v, "name");
return;
}
move_only_type(): name_("default"){}
~move_only_type() = default;
move_only_type(move_only_type&&) = default;
move_only_type& operator=(move_only_type&&) = default;
move_only_type(const move_only_type&) = delete;
move_only_type& operator=(const move_only_type&) = delete;
bool operator==(const move_only_type& other) const noexcept {return this->name_ == other.name_;}
bool operator!=(const move_only_type& other) const noexcept {return this->name_ != other.name_;}
bool operator< (const move_only_type& other) const noexcept {return this->name_ < other.name_;}
bool operator<=(const move_only_type& other) const noexcept {return this->name_ <= other.name_;}
bool operator> (const move_only_type& other) const noexcept {return this->name_ > other.name_;}
bool operator>=(const move_only_type& other) const noexcept {return this->name_ >= other.name_;}
std::string name_;
};
std::ostream& operator<<(std::ostream& os, const move_only_type& mot)
{
os << mot.name_;
return os;
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_find_or_move_only, value_type, test_value_types)
{
const move_only_type ref("reference");
move_only_type opt("optional");
{
const value_type v{{"key1", value_type{{"key2", value_type{{"name", "reference"}} }} }};
BOOST_TEST(ref == toml::find_or(v, "key1", "key2", std::move(opt)));
}
}

View File

@@ -1,72 +0,0 @@
#include <toml.hpp>
#include "unit_test.hpp"
#include <iostream>
// to check it successfully compiles. it does not check the formatted string.
BOOST_AUTO_TEST_CASE(test_1_value)
{
toml::value val(42);
{
const std::string pretty_error =
toml::format_error("[error] test error", val, "this is a value");
std::cout << pretty_error << std::endl;
}
{
const std::string pretty_error =
toml::format_error("[error] test error", val, "this is a value",
{"this is a hint"});
std::cout << pretty_error << std::endl;
}
}
BOOST_AUTO_TEST_CASE(test_2_values)
{
toml::value v1(42);
toml::value v2(3.14);
{
const std::string pretty_error =
toml::format_error("[error] test error with two values",
v1, "this is the answer",
v2, "this is the pi");
std::cout << pretty_error << std::endl;
}
{
const std::string pretty_error =
toml::format_error("[error] test error with two values",
v1, "this is the answer",
v2, "this is the pi",
{"hint"});
std::cout << pretty_error << std::endl;
}
}
BOOST_AUTO_TEST_CASE(test_3_values)
{
toml::value v1(42);
toml::value v2(3.14);
toml::value v3("foo");
{
const std::string pretty_error =
toml::format_error("[error] test error with two values",
v1, "this is the answer",
v2, "this is the pi",
v3, "this is a meta-syntactic variable");
std::cout << pretty_error << std::endl;
}
{
const std::string pretty_error =
toml::format_error("[error] test error with two values",
v1, "this is the answer",
v2, "this is the pi",
v3, "this is a meta-syntactic variable",
{"hint 1", "hint 2"});
std::cout << pretty_error << std::endl;
}
}

View File

@@ -0,0 +1,143 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <toml11/parser.hpp>
#include <toml11/serializer.hpp>
#include <toml11/types.hpp>
TEST_CASE("testing fractional float")
{
auto fmt = [](std::size_t prec) {
toml::floating_format_info f;
f.fmt = toml::floating_format::fixed;
f.prec = prec;
return f;
};
auto format_as = [](const double f, int w) -> std::string {
std::ostringstream oss;
oss.imbue(std::locale::classic());
oss << std::fixed << std::setprecision(w) << f;
return oss.str();
};
CHECK_EQ(format_as( 1.0 , 1), toml::format(toml::value( 1.0 , fmt( 1))));
CHECK_EQ(format_as( 0.1 , 1), toml::format(toml::value( 0.1 , fmt( 1))));
CHECK_EQ(format_as( 0.001 , 3), toml::format(toml::value( 0.001 , fmt( 3))));
CHECK_EQ(format_as( 0.1 , 3), toml::format(toml::value( 0.1 , fmt( 3))));
CHECK_EQ(format_as( 3.14 , 2), toml::format(toml::value( 3.14 , fmt( 2))));
CHECK_EQ(format_as(-3.14 , 2), toml::format(toml::value(-3.14 , fmt( 2))));
CHECK_EQ(format_as( 3.141592653589, 12), toml::format(toml::value( 3.141592653589, fmt(12))));
CHECK_EQ(format_as(-3.141592653589, 12), toml::format(toml::value(-3.141592653589, fmt(12))));
}
TEST_CASE("testing scientific float")
{
auto fmt = [](std::size_t prec) {
toml::floating_format_info f;
f.fmt = toml::floating_format::scientific;
f.prec = prec;
return f;
};
auto format_as = [](const double f, int w) -> std::string {
std::ostringstream oss;
oss.imbue(std::locale::classic());
oss << std::scientific << std::setprecision(w) << f;
return oss.str();
};
CHECK_EQ(format_as( 1.0 , 1), toml::format(toml::value( 1.0 , fmt( 1))));
CHECK_EQ(format_as( 0.1 , 1), toml::format(toml::value( 0.1 , fmt( 1))));
CHECK_EQ(format_as( 0.001 , 3), toml::format(toml::value( 0.001 , fmt( 3))));
CHECK_EQ(format_as( 0.1 , 3), toml::format(toml::value( 0.1 , fmt( 3))));
CHECK_EQ(format_as( 3.14 , 2), toml::format(toml::value( 3.14 , fmt( 2))));
CHECK_EQ(format_as(-3.14 , 2), toml::format(toml::value(-3.14 , fmt( 2))));
CHECK_EQ(format_as( 3.141592653589, 12), toml::format(toml::value( 3.141592653589, fmt(12))));
CHECK_EQ(format_as(-3.141592653589, 12), toml::format(toml::value(-3.141592653589, fmt(12))));
}
TEST_CASE("testing hex float")
{
toml::spec s = toml::spec::v(1,0,0);
s.ext_hex_float = true;
toml::floating_format_info fmt;
fmt.fmt = toml::floating_format::hex;
auto format_as = [](const double f) -> std::string {
std::ostringstream oss;
oss.imbue(std::locale::classic());
oss << std::hexfloat << f;
return oss.str();
};
CHECK_EQ(format_as( 1.0 ), toml::format(toml::value( 1.0 , fmt), s));
CHECK_EQ(format_as( 0.1 ), toml::format(toml::value( 0.1 , fmt), s));
CHECK_EQ(format_as( 0.001 ), toml::format(toml::value( 0.001 , fmt), s));
CHECK_EQ(format_as( 0.1 ), toml::format(toml::value( 0.1 , fmt), s));
CHECK_EQ(format_as( 3.14 ), toml::format(toml::value( 3.14 , fmt), s));
CHECK_EQ(format_as(-3.14 ), toml::format(toml::value(-3.14 , fmt), s));
CHECK_EQ(format_as( 3.141592653589), toml::format(toml::value( 3.141592653589, fmt), s));
CHECK_EQ(format_as(-3.141592653589), toml::format(toml::value(-3.141592653589, fmt), s));
}
TEST_CASE("testing suffix + fractional")
{
toml::spec s = toml::spec::v(1,0,0);
s.ext_hex_float = true;
s.ext_num_suffix = true;
auto fmt = [](std::string sfx) {
toml::floating_format_info f;
f.fmt = toml::floating_format::fixed;
f.suffix = sfx;
return f;
};
auto format_as = [](const double f, std::string sfx) -> std::string {
std::ostringstream oss;
oss.imbue(std::locale::classic());
oss << std::fixed << f << "_" << sfx;
return oss.str();
};
CHECK_EQ(format_as( 1.0 , "m" ), toml::format(toml::value( 1.0 , fmt("m" )), s));
CHECK_EQ(format_as( 0.1 , "m" ), toml::format(toml::value( 0.1 , fmt("m" )), s));
CHECK_EQ(format_as( 0.001 , "mm" ), toml::format(toml::value( 0.001 , fmt("mm" )), s));
CHECK_EQ(format_as( 0.1 , "mm" ), toml::format(toml::value( 0.1 , fmt("mm" )), s));
CHECK_EQ(format_as( 3.14 , "rad"), toml::format(toml::value( 3.14 , fmt("rad")), s));
CHECK_EQ(format_as(-3.14 , "rad"), toml::format(toml::value(-3.14 , fmt("rad")), s));
CHECK_EQ(format_as( 3.141592653589, "rad"), toml::format(toml::value( 3.141592653589, fmt("rad")), s));
CHECK_EQ(format_as(-3.141592653589, "rad"), toml::format(toml::value(-3.141592653589, fmt("rad")), s));
}
TEST_CASE("testing suffix + scientific")
{
toml::spec s = toml::spec::v(1,0,0);
s.ext_hex_float = true;
s.ext_num_suffix = true;
auto fmt = [](std::string sfx) {
toml::floating_format_info f;
f.fmt = toml::floating_format::scientific;
f.suffix = sfx;
return f;
};
auto format_as = [](const double f, std::string sfx) -> std::string {
std::ostringstream oss;
oss.imbue(std::locale::classic());
oss << std::scientific << f << "_" << sfx;
return oss.str();
};
CHECK_EQ(format_as( 1.0 , "m" ), toml::format(toml::value( 1.0 , fmt("m" )), s));
CHECK_EQ(format_as( 0.1 , "m" ), toml::format(toml::value( 0.1 , fmt("m" )), s));
CHECK_EQ(format_as( 0.001 , "mm" ), toml::format(toml::value( 0.001 , fmt("mm" )), s));
CHECK_EQ(format_as( 0.1 , "mm" ), toml::format(toml::value( 0.1 , fmt("mm" )), s));
CHECK_EQ(format_as( 3.14 , "rad"), toml::format(toml::value( 3.14 , fmt("rad")), s));
CHECK_EQ(format_as(-3.14 , "rad"), toml::format(toml::value(-3.14 , fmt("rad")), s));
CHECK_EQ(format_as( 3.141592653589, "rad"), toml::format(toml::value( 3.141592653589, fmt("rad")), s));
CHECK_EQ(format_as(-3.141592653589, "rad"), toml::format(toml::value(-3.141592653589, fmt("rad")), s));
}

View File

@@ -0,0 +1,89 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <toml11/parser.hpp>
#include <toml11/serializer.hpp>
#include <toml11/types.hpp>
TEST_CASE("testing decimal")
{
const auto decimal_fmt = [](std::size_t w, std::size_t s) {
toml::integer_format_info fmt;
fmt.fmt = toml::integer_format::dec;
fmt.width = w;
fmt.spacer = s;
return fmt;
};
CHECK_EQ( "0", toml::format(toml::value( 0, decimal_fmt(1, 0))));
CHECK_EQ( "1234", toml::format(toml::value( 1234, decimal_fmt(0, 0))));
CHECK_EQ( "-1234", toml::format(toml::value( -1234, decimal_fmt(0, 0))));
CHECK_EQ( "1_2_3_4", toml::format(toml::value( 1234, decimal_fmt(4, 1))));
CHECK_EQ( "-1_2_3_4", toml::format(toml::value( -1234, decimal_fmt(5, 1))));
CHECK_EQ("123_456_789", toml::format(toml::value(123456789, decimal_fmt(9, 3))));
}
TEST_CASE("testing hex")
{
const auto hex_fmt = [](std::size_t w, std::size_t s) {
toml::integer_format_info fmt;
fmt.fmt = toml::integer_format::hex;
fmt.width = w;
fmt.spacer = s;
return fmt;
};
CHECK_EQ("0xdeadbeef", toml::format(toml::value(0xDEADBEEF, hex_fmt(8, 0))));
CHECK_EQ("0xdead_beef", toml::format(toml::value(0xDEADBEEF, hex_fmt(8, 4))));
CHECK_EQ("0xff", toml::format(toml::value(0xFF, hex_fmt(2, 0))));
CHECK_EQ("0x00ff", toml::format(toml::value(0xFF, hex_fmt(4, 0))));
CHECK_EQ("0x0000ff", toml::format(toml::value(0xFF, hex_fmt(6, 0))));
}
TEST_CASE("testing oct")
{
const auto oct_fmt = [](std::size_t w, std::size_t s) {
toml::integer_format_info fmt;
fmt.fmt = toml::integer_format::oct;
fmt.width = w;
fmt.spacer = s;
return fmt;
};
CHECK_EQ("0o644", toml::format(toml::value(64*6+8*4+4, oct_fmt(3, 0))));
CHECK_EQ("0o7_7_7", toml::format(toml::value(64*7+8*7+7, oct_fmt(3, 1))));
CHECK_EQ("0o000644", toml::format(toml::value(64*6+8*4+4, oct_fmt(6, 0))));
}
TEST_CASE("testing bin")
{
const auto bin_fmt = [](std::size_t w, std::size_t s) {
toml::integer_format_info fmt;
fmt.fmt = toml::integer_format::bin;
fmt.width = w;
fmt.spacer = s;
return fmt;
};
CHECK_EQ("0b1000", toml::format(toml::value(8, bin_fmt(4, 0))));
CHECK_EQ("0b00001000", toml::format(toml::value(8, bin_fmt(8, 0))));
CHECK_EQ("0b0000_1000", toml::format(toml::value(8, bin_fmt(8, 4))));
}
TEST_CASE("testing decimal with suffix")
{
toml::spec sp = toml::spec::v(1,0,0);
sp.ext_num_suffix = true;
const auto decimal_fmt = [](std::size_t w, std::size_t s, std::string sfx) {
toml::integer_format_info fmt;
fmt.fmt = toml::integer_format::dec;
fmt.width = w;
fmt.spacer = s;
fmt.suffix = sfx;
return fmt;
};
CHECK_EQ( "0_J", toml::format(toml::value( 0, decimal_fmt(1, 0, "J")), sp));
CHECK_EQ( "1234_kcal", toml::format(toml::value( 1234, decimal_fmt(0, 0, "kcal")), sp));
CHECK_EQ("1_2_3_4_μm", toml::format(toml::value( 1234, decimal_fmt(4, 1, "μm")), sp));
}

View File

@@ -0,0 +1,78 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <toml11/parser.hpp>
#include <toml11/serializer.hpp>
#include <toml11/types.hpp>
TEST_CASE("testing multiline table")
{
const auto table_fmt = [](toml::indent_char c, std::int32_t body, std::int32_t name) {
toml::table_format_info fmt;
fmt.fmt = toml::table_format::multiline;
fmt.indent_type = c;
fmt.body_indent = body;
fmt.name_indent = name;
fmt.closing_indent = 0;
return fmt;
};
toml::value v(toml::table{
{"a", 42},
{"b", 3.14},
{"c", "foobar"},
});
v.as_table_fmt() = table_fmt(toml::indent_char::space, 0, 0);
CHECK_EQ(v, toml::parse_str(toml::format(v)));
v.as_table_fmt() = table_fmt(toml::indent_char::space, 0, 2);
CHECK_EQ(v, toml::parse_str(toml::format(v)));
v.as_table_fmt() = table_fmt(toml::indent_char::space, 2, 0);
CHECK_EQ(v, toml::parse_str(toml::format(v)));
v.as_table_fmt() = table_fmt(toml::indent_char::space, 2, 2);
CHECK_EQ(v, toml::parse_str(toml::format(v)));
v.as_table_fmt() = table_fmt(toml::indent_char::tab, 0, 0);
CHECK_EQ(v, toml::parse_str(toml::format(v)));
v.as_table_fmt() = table_fmt(toml::indent_char::tab, 0, 2);
CHECK_EQ(v, toml::parse_str(toml::format(v)));
v.as_table_fmt() = table_fmt(toml::indent_char::tab, 2, 0);
CHECK_EQ(v, toml::parse_str(toml::format(v)));
v.as_table_fmt() = table_fmt(toml::indent_char::tab, 2, 2);
CHECK_EQ(v, toml::parse_str(toml::format(v)));
}
TEST_CASE("testing multiline table")
{
const auto table_fmt = [](toml::indent_char c, std::int32_t body, std::int32_t name) {
toml::table_format_info fmt;
fmt.fmt = toml::table_format::dotted;
fmt.indent_type = c;
fmt.body_indent = body;
fmt.name_indent = name;
fmt.closing_indent = 0;
return fmt;
};
{
toml::value v(toml::table{});
v["a"]["b"]["c"] = "foobar";
CHECK_EQ(v, toml::parse_str(toml::format(v)));
v.at("a").as_table_fmt() = table_fmt(toml::indent_char::space, 0, 0);
CHECK_EQ(v, toml::parse_str(toml::format(v)));
v.at("a").at("b").as_table_fmt() = table_fmt(toml::indent_char::space, 0, 0);
CHECK_EQ(v, toml::parse_str(toml::format(v)));
v.at("a").as_table_fmt().fmt = toml::table_format::multiline;
CHECK_EQ(v, toml::parse_str(toml::format(v)));
}
}

View File

@@ -1,6 +1,10 @@
#include <toml.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include "utility.hpp"
#include <toml11/value.hpp>
#include <toml11/get.hpp>
#include <array> #include <array>
#include <deque> #include <deque>
@@ -13,402 +17,411 @@
#include <string_view> #include <string_view>
#endif #endif
using test_value_types = std::tuple< TEST_CASE("testing toml::get with toml types")
toml::basic_value<toml::discard_comments>,
toml::basic_value<toml::preserve_comments>,
toml::basic_value<toml::discard_comments, std::map, std::deque>,
toml::basic_value<toml::preserve_comments, std::map, std::deque>
>;
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_exact, value_type, test_value_types)
{ {
using value_type = toml::value;
using boolean_type = typename value_type::boolean_type ;
using integer_type = typename value_type::integer_type ;
using floating_type = typename value_type::floating_type ;
using string_type = typename value_type::string_type ;
using local_time_type = typename value_type::local_time_type ;
using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
{ {
value_type v(true); value_type v(true);
BOOST_TEST(true == toml::get<toml::boolean>(v)); CHECK_EQ(true, toml::get<boolean_type>(v));
toml::get<toml::boolean>(v) = false; toml::get<boolean_type>(v) = false;
BOOST_TEST(false == toml::get<toml::boolean>(v)); CHECK_EQ(false, toml::get<boolean_type>(v));
toml::boolean x = toml::get<toml::boolean>(std::move(v)); boolean_type x = toml::get<boolean_type>(std::move(v));
BOOST_TEST(false == x); CHECK_EQ(false, x);
} }
{ {
value_type v(42); value_type v(42);
BOOST_TEST(toml::integer(42) == toml::get<toml::integer>(v)); CHECK_EQ(integer_type(42), toml::get<integer_type>(v));
toml::get<toml::integer>(v) = 54; toml::get<integer_type>(v) = 54;
BOOST_TEST(toml::integer(54) == toml::get<toml::integer>(v)); CHECK_EQ(integer_type(54), toml::get<integer_type>(v));
toml::integer x = toml::get<toml::integer>(std::move(v)); integer_type x = toml::get<integer_type>(std::move(v));
BOOST_TEST(toml::integer(54) == x); CHECK_EQ(integer_type(54), x);
} }
{ {
value_type v(3.14); value_type v(3.14);
BOOST_TEST(toml::floating(3.14) == toml::get<toml::floating>(v)); CHECK_EQ(floating_type(3.14), toml::get<floating_type>(v));
toml::get<toml::floating>(v) = 2.71; toml::get<floating_type>(v) = 2.71;
BOOST_TEST(toml::floating(2.71) == toml::get<toml::floating>(v)); CHECK_EQ(floating_type(2.71), toml::get<floating_type>(v));
toml::floating x = toml::get<toml::floating>(std::move(v)); floating_type x = toml::get<floating_type>(std::move(v));
BOOST_TEST(toml::floating(2.71) == x); CHECK_EQ(floating_type(2.71), x);
} }
{ {
value_type v("foo"); value_type v("foo");
BOOST_TEST(toml::string("foo", toml::string_t::basic) == CHECK_EQ("foo", toml::get<string_type>(v));
toml::get<toml::string>(v));
toml::get<toml::string>(v).str += "bar"; toml::get<string_type>(v) += "bar";
BOOST_TEST(toml::string("foobar", toml::string_t::basic) == CHECK_EQ("foobar", toml::get<string_type>(v));
toml::get<toml::string>(v));
toml::string x = toml::get<toml::string>(std::move(v)); string_type x = toml::get<string_type>(std::move(v));
BOOST_TEST(toml::string("foobar") == x); CHECK_EQ("foobar", x);
} }
{ {
value_type v("foo", toml::string_t::literal); local_date_type d(2018, toml::month_t::Apr, 22);
BOOST_TEST(toml::string("foo", toml::string_t::literal) ==
toml::get<toml::string>(v));
toml::get<toml::string>(v).str += "bar";
BOOST_TEST(toml::string("foobar", toml::string_t::literal) ==
toml::get<toml::string>(v));
toml::string x = toml::get<toml::string>(std::move(v));
BOOST_TEST(toml::string("foobar", toml::string_t::literal) == x);
}
{
toml::local_date d(2018, toml::month_t::Apr, 22);
value_type v(d); value_type v(d);
BOOST_TEST(d == toml::get<toml::local_date>(v)); CHECK_EQ(d, toml::get<local_date_type>(v));
toml::get<toml::local_date>(v).year = 2017; toml::get<local_date_type>(v).year = 2017;
d.year = 2017; d.year = 2017;
BOOST_TEST(d == toml::get<toml::local_date>(v)); CHECK_EQ(d, toml::get<local_date_type>(v));
toml::local_date x = toml::get<toml::local_date>(std::move(v)); local_date_type x = toml::get<local_date_type>(std::move(v));
BOOST_TEST(d == x); CHECK_EQ(d, x);
} }
{ {
toml::local_time t(12, 30, 45); local_time_type t(12, 30, 45);
value_type v(t); value_type v(t);
BOOST_TEST(t == toml::get<toml::local_time>(v)); CHECK_EQ(t, toml::get<local_time_type>(v));
toml::get<toml::local_time>(v).hour = 9; toml::get<local_time_type>(v).hour = 9;
t.hour = 9; t.hour = 9;
BOOST_TEST(t == toml::get<toml::local_time>(v)); CHECK_EQ(t, toml::get<local_time_type>(v));
toml::local_time x = toml::get<toml::local_time>(std::move(v)); local_time_type x = toml::get<local_time_type>(std::move(v));
BOOST_TEST(t == x); CHECK_EQ(t, x);
} }
{ {
toml::local_datetime dt(toml::local_date(2018, toml::month_t::Apr, 22), local_datetime_type dt(toml::local_date(2018, toml::month_t::Apr, 22),
toml::local_time(12, 30, 45)); toml::local_time(12, 30, 45));
value_type v(dt); value_type v(dt);
BOOST_TEST(dt == toml::get<toml::local_datetime>(v)); CHECK_EQ(dt, toml::get<local_datetime_type>(v));
toml::get<toml::local_datetime>(v).date.year = 2017; toml::get<local_datetime_type>(v).date.year = 2017;
dt.date.year = 2017; dt.date.year = 2017;
BOOST_TEST(dt == toml::get<toml::local_datetime>(v)); CHECK_EQ(dt, toml::get<local_datetime_type>(v));
toml::local_datetime x = toml::get<toml::local_datetime>(std::move(v)); toml::local_datetime x = toml::get<local_datetime_type>(std::move(v));
BOOST_TEST(dt == x); CHECK_EQ(dt, x);
} }
{ {
toml::offset_datetime dt(toml::local_datetime( offset_datetime_type dt(toml::local_datetime(
toml::local_date(2018, toml::month_t::Apr, 22), toml::local_date(2018, toml::month_t::Apr, 22),
toml::local_time(12, 30, 45)), toml::time_offset(9, 0)); toml::local_time(12, 30, 45)), toml::time_offset(9, 0));
value_type v(dt); value_type v(dt);
BOOST_TEST(dt == toml::get<toml::offset_datetime>(v)); CHECK_EQ(dt, toml::get<offset_datetime_type>(v));
toml::get<toml::offset_datetime>(v).date.year = 2017; toml::get<toml::offset_datetime>(v).date.year = 2017;
dt.date.year = 2017; dt.date.year = 2017;
BOOST_TEST(dt == toml::get<toml::offset_datetime>(v)); CHECK_EQ(dt, toml::get<offset_datetime_type>(v));
toml::offset_datetime x = toml::get<toml::offset_datetime>(std::move(v)); offset_datetime_type x = toml::get<offset_datetime_type>(std::move(v));
BOOST_TEST(dt == x); CHECK_EQ(dt, x);
} }
{ {
using array_type = typename value_type::array_type;
array_type vec; array_type vec;
vec.push_back(value_type(42)); vec.push_back(value_type(42));
vec.push_back(value_type(54)); vec.push_back(value_type(54));
value_type v(vec); value_type v(vec);
BOOST_TEST(vec == toml::get<array_type>(v)); CHECK_EQ(vec, toml::get<array_type>(v));
toml::get<array_type>(v).push_back(value_type(123)); toml::get<array_type>(v).push_back(value_type(123));
vec.push_back(value_type(123)); vec.push_back(value_type(123));
BOOST_TEST(vec == toml::get<array_type>(v)); CHECK_EQ(vec, toml::get<array_type>(v));
array_type x = toml::get<array_type>(std::move(v)); array_type x = toml::get<array_type>(std::move(v));
BOOST_TEST(vec == x); CHECK_EQ(vec, x);
} }
{ {
using table_type = typename value_type::table_type;
table_type tab; table_type tab;
tab["key1"] = value_type(42); tab["key1"] = value_type(42);
tab["key2"] = value_type(3.14); tab["key2"] = value_type(3.14);
value_type v(tab); value_type v(tab);
BOOST_TEST(tab == toml::get<table_type>(v)); CHECK_EQ(tab, toml::get<table_type>(v));
toml::get<table_type>(v)["key3"] = value_type(123); toml::get<table_type>(v)["key3"] = value_type(123);
tab["key3"] = value_type(123); tab["key3"] = value_type(123);
BOOST_TEST(tab == toml::get<table_type>(v)); CHECK_EQ(tab, toml::get<table_type>(v));
table_type x = toml::get<table_type>(std::move(v)); table_type x = toml::get<table_type>(std::move(v));
BOOST_TEST(tab == x); CHECK_EQ(tab, x);
} }
{ {
value_type v1(42); value_type v1(42);
BOOST_TEST(v1 == toml::get<value_type>(v1)); CHECK_EQ(v1, toml::get<value_type>(v1));
value_type v2(54); value_type v2(54);
toml::get<value_type>(v1) = v2; toml::get<value_type>(v1) = v2;
BOOST_TEST(v2 == toml::get<value_type>(v1)); CHECK_EQ(v2, toml::get<value_type>(v1));
value_type x = toml::get<value_type>(std::move(v1)); value_type x = toml::get<value_type>(std::move(v1));
BOOST_TEST(v2 == x); CHECK_EQ(v2, x);
} }
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_integer_type, value_type, test_value_types) TEST_CASE("testing toml::get<integer-like>")
{ {
using value_type = toml::value;
{ {
value_type v(42); value_type v(42);
BOOST_TEST(int(42) == toml::get<int >(v));
BOOST_TEST(short(42) == toml::get<short >(v));
BOOST_TEST(char(42) == toml::get<char >(v));
BOOST_TEST(unsigned(42) == toml::get<unsigned >(v));
BOOST_TEST(long(42) == toml::get<long >(v));
BOOST_TEST(std::int64_t(42) == toml::get<std::int64_t >(v));
BOOST_TEST(std::uint64_t(42) == toml::get<std::uint64_t>(v));
BOOST_TEST(std::int16_t(42) == toml::get<std::int16_t >(v));
BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(v));
BOOST_TEST(std::uint16_t(42) == toml::get<std::uint16_t>(std::move(v))); CHECK_EQ(int(42), toml::get<int >(v));
CHECK_EQ(short(42), toml::get<short >(v));
CHECK_EQ(char(42), toml::get<char >(v));
CHECK_EQ(unsigned(42), toml::get<unsigned >(v));
CHECK_EQ(long(42), toml::get<long >(v));
CHECK_EQ(std::int64_t(42), toml::get<std::int64_t >(v));
CHECK_EQ(std::uint64_t(42), toml::get<std::uint64_t>(v));
CHECK_EQ(std::int16_t(42), toml::get<std::int16_t >(v));
CHECK_EQ(std::uint16_t(42), toml::get<std::uint16_t>(v));
CHECK_EQ(int(42), toml::get<int >(as_const(v)));
CHECK_EQ(short(42), toml::get<short >(as_const(v)));
CHECK_EQ(char(42), toml::get<char >(as_const(v)));
CHECK_EQ(unsigned(42), toml::get<unsigned >(as_const(v)));
CHECK_EQ(long(42), toml::get<long >(as_const(v)));
CHECK_EQ(std::int64_t(42), toml::get<std::int64_t >(as_const(v)));
CHECK_EQ(std::uint64_t(42), toml::get<std::uint64_t>(as_const(v)));
CHECK_EQ(std::int16_t(42), toml::get<std::int16_t >(as_const(v)));
CHECK_EQ(std::uint16_t(42), toml::get<std::uint16_t>(as_const(v)));
value_type v1(v);
value_type v2(v);
value_type v3(v);
value_type v4(v);
value_type v5(v);
value_type v6(v);
value_type v7(v);
value_type v8(v);
value_type v9(v);
CHECK_EQ(int(42), toml::get<int >(v1));
CHECK_EQ(short(42), toml::get<short >(v2));
CHECK_EQ(char(42), toml::get<char >(v3));
CHECK_EQ(unsigned(42), toml::get<unsigned >(v4));
CHECK_EQ(long(42), toml::get<long >(v5));
CHECK_EQ(std::int64_t(42), toml::get<std::int64_t >(v6));
CHECK_EQ(std::uint64_t(42), toml::get<std::uint64_t>(v7));
CHECK_EQ(std::int16_t(42), toml::get<std::int16_t >(v8));
CHECK_EQ(std::uint16_t(42), toml::get<std::uint16_t>(v9));
} }
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_floating_type, value_type, test_value_types) TEST_CASE("testing toml::get<floating-like>")
{ {
using value_type = toml::value;
{ {
value_type v(3.14);
const double ref(3.14); const double ref(3.14);
BOOST_TEST(static_cast<float >(ref) == toml::get<float >(v));
BOOST_TEST( ref == toml::get<double >(v)); value_type v(ref);
BOOST_TEST(static_cast<long double>(ref) == toml::get<long double>(v)); CHECK_EQ(static_cast<float >(ref), toml::get<float >(v));
BOOST_TEST(static_cast<float >(ref) == toml::get<float>(std::move(v))); CHECK_EQ( ref , toml::get<double >(v));
CHECK_EQ(static_cast<long double>(ref), toml::get<long double>(v));
value_type v1(ref);
value_type v2(ref);
value_type v3(ref);
CHECK_EQ(static_cast<float >(ref), toml::get<float >(std::move(v1)));
CHECK_EQ( ref , toml::get<double >(std::move(v2)));
CHECK_EQ(static_cast<long double>(ref), toml::get<long double>(std::move(v3)));
} }
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_string_type, value_type, test_value_types)
{
{
value_type v("foo", toml::string_t::basic);
BOOST_TEST("foo" == toml::get<std::string>(v));
toml::get<std::string>(v) += "bar";
BOOST_TEST("foobar" == toml::get<std::string>(v));
const auto x = toml::get<std::string>(std::move(v));
BOOST_TEST("foobar" == x);
}
{
value_type v("foo", toml::string_t::literal);
BOOST_TEST("foo" == toml::get<std::string>(v));
toml::get<std::string>(v) += "bar";
BOOST_TEST("foobar" == toml::get<std::string>(v));
const auto x = toml::get<std::string>(std::move(v));
BOOST_TEST("foobar" == x);
}
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L #if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
{ TEST_CASE("testing toml::get<string-like>")
value_type v("foo", toml::string_t::basic);
BOOST_TEST("foo" == toml::get<std::string_view>(v));
}
{
value_type v("foo", toml::string_t::literal);
BOOST_TEST("foo" == toml::get<std::string_view>(v));
}
#endif
}
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array, value_type, test_value_types)
{ {
using value_type = toml::value;
{ {
const value_type v{42, 54, 69, 72}; value_type v("foo");
CHECK_EQ("foo", toml::get<std::string_view>(v));
}
}
#endif
TEST_CASE("testing toml::get<array-like>")
{
using value_type = toml::value;
{
const value_type v(toml::array{42, 54, 69, 72});
const std::vector<int> vec = toml::get<std::vector<int>>(v); const std::vector<int> vec = toml::get<std::vector<int>>(v);
const std::list<short> lst = toml::get<std::list<short>>(v); const std::list<short> lst = toml::get<std::list<short>>(v);
const std::deque<std::int64_t> deq = toml::get<std::deque<std::int64_t>>(v); const std::deque<std::int64_t> deq = toml::get<std::deque<std::int64_t>>(v);
BOOST_TEST(42 == vec.at(0)); CHECK_EQ(42, vec.at(0));
BOOST_TEST(54 == vec.at(1)); CHECK_EQ(54, vec.at(1));
BOOST_TEST(69 == vec.at(2)); CHECK_EQ(69, vec.at(2));
BOOST_TEST(72 == vec.at(3)); CHECK_EQ(72, vec.at(3));
std::list<short>::const_iterator iter = lst.begin(); std::list<short>::const_iterator iter = lst.begin();
BOOST_TEST(static_cast<short>(42) == *(iter++)); CHECK_EQ(static_cast<short>(42), *(iter++));
BOOST_TEST(static_cast<short>(54) == *(iter++)); CHECK_EQ(static_cast<short>(54), *(iter++));
BOOST_TEST(static_cast<short>(69) == *(iter++)); CHECK_EQ(static_cast<short>(69), *(iter++));
BOOST_TEST(static_cast<short>(72) == *(iter++)); CHECK_EQ(static_cast<short>(72), *(iter++));
BOOST_TEST(static_cast<std::int64_t>(42) == deq.at(0)); CHECK_EQ(static_cast<std::int64_t>(42), deq.at(0));
BOOST_TEST(static_cast<std::int64_t>(54) == deq.at(1)); CHECK_EQ(static_cast<std::int64_t>(54), deq.at(1));
BOOST_TEST(static_cast<std::int64_t>(69) == deq.at(2)); CHECK_EQ(static_cast<std::int64_t>(69), deq.at(2));
BOOST_TEST(static_cast<std::int64_t>(72) == deq.at(3)); CHECK_EQ(static_cast<std::int64_t>(72), deq.at(3));
std::array<int, 4> ary = toml::get<std::array<int, 4>>(v); std::array<int, 4> ary = toml::get<std::array<int, 4>>(v);
BOOST_TEST(42 == ary.at(0)); CHECK_EQ(42, ary.at(0));
BOOST_TEST(54 == ary.at(1)); CHECK_EQ(54, ary.at(1));
BOOST_TEST(69 == ary.at(2)); CHECK_EQ(69, ary.at(2));
BOOST_TEST(72 == ary.at(3)); CHECK_EQ(72, ary.at(3));
std::tuple<int, short, unsigned, long> tpl = std::tuple<int, short, unsigned, long> tpl =
toml::get<std::tuple<int, short, unsigned, long>>(v); toml::get<std::tuple<int, short, unsigned, long>>(v);
BOOST_TEST( 42 == std::get<0>(tpl)); CHECK_EQ( 42 , std::get<0>(tpl));
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl)); CHECK_EQ(static_cast<short >(54), std::get<1>(tpl));
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl)); CHECK_EQ(static_cast<unsigned>(69), std::get<2>(tpl));
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl)); CHECK_EQ(static_cast<long >(72), std::get<3>(tpl));
const value_type p{3.14, 2.71}; const value_type p(toml::array{3.14, 2.71});
std::pair<double, double> pr = toml::get<std::pair<double, double> >(p); std::pair<double, double> pr = toml::get<std::pair<double, double> >(p);
BOOST_TEST(3.14 == pr.first); CHECK_EQ(3.14, pr.first);
BOOST_TEST(2.71 == pr.second); CHECK_EQ(2.71, pr.second);
} }
{ {
value_type v{42, 54, 69, 72}; value_type v(toml::array{42, 54, 69, 72});
const std::vector<int> vec = toml::get<std::vector<int>>(std::move(v)); const std::vector<int> vec = toml::get<std::vector<int>>(std::move(v));
BOOST_TEST(42 == vec.at(0)); CHECK_EQ(42, vec.at(0));
BOOST_TEST(54 == vec.at(1)); CHECK_EQ(54, vec.at(1));
BOOST_TEST(69 == vec.at(2)); CHECK_EQ(69, vec.at(2));
BOOST_TEST(72 == vec.at(3)); CHECK_EQ(72, vec.at(3));
} }
{ {
value_type v{42, 54, 69, 72}; value_type v(toml::array{42, 54, 69, 72});
const std::deque<int> deq = toml::get<std::deque<int>>(std::move(v)); const std::deque<int> deq = toml::get<std::deque<int>>(std::move(v));
BOOST_TEST(42 == deq.at(0)); CHECK_EQ(42, deq.at(0));
BOOST_TEST(54 == deq.at(1)); CHECK_EQ(54, deq.at(1));
BOOST_TEST(69 == deq.at(2)); CHECK_EQ(69, deq.at(2));
BOOST_TEST(72 == deq.at(3)); CHECK_EQ(72, deq.at(3));
} }
{ {
value_type v{42, 54, 69, 72}; value_type v(toml::array{42, 54, 69, 72});
const std::list<int> lst = toml::get<std::list<int>>(std::move(v)); const std::list<int> lst = toml::get<std::list<int>>(std::move(v));
std::list<int>::const_iterator iter = lst.begin(); std::list<int>::const_iterator iter = lst.begin();
BOOST_TEST(42 == *(iter++)); CHECK_EQ(42, *(iter++));
BOOST_TEST(54 == *(iter++)); CHECK_EQ(54, *(iter++));
BOOST_TEST(69 == *(iter++)); CHECK_EQ(69, *(iter++));
BOOST_TEST(72 == *(iter++)); CHECK_EQ(72, *(iter++));
} }
{ {
value_type v{42, 54, 69, 72}; value_type v(toml::array{42, 54, 69, 72});
std::array<int, 4> ary = toml::get<std::array<int, 4>>(std::move(v)); std::array<int, 4> ary = toml::get<std::array<int, 4>>(std::move(v));
BOOST_TEST(42 == ary.at(0)); CHECK_EQ(42, ary.at(0));
BOOST_TEST(54 == ary.at(1)); CHECK_EQ(54, ary.at(1));
BOOST_TEST(69 == ary.at(2)); CHECK_EQ(69, ary.at(2));
BOOST_TEST(72 == ary.at(3)); CHECK_EQ(72, ary.at(3));
} }
{ {
value_type v{42, 54, 69, 72}; value_type v(toml::array{42, 54, 69, 72});
std::tuple<int, short, unsigned, long> tpl = std::tuple<int, short, unsigned, long> tpl =
toml::get<std::tuple<int, short, unsigned, long>>(std::move(v)); toml::get<std::tuple<int, short, unsigned, long>>(std::move(v));
BOOST_TEST( 42 == std::get<0>(tpl)); CHECK_EQ( 42 , std::get<0>(tpl));
BOOST_TEST(static_cast<short >(54) == std::get<1>(tpl)); CHECK_EQ(static_cast<short >(54), std::get<1>(tpl));
BOOST_TEST(static_cast<unsigned>(69) == std::get<2>(tpl)); CHECK_EQ(static_cast<unsigned>(69), std::get<2>(tpl));
BOOST_TEST(static_cast<long >(72) == std::get<3>(tpl)); CHECK_EQ(static_cast<long >(72), std::get<3>(tpl));
} }
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_array_of_array, value_type, test_value_types) TEST_CASE("testing toml::get<array-of-arrays>")
{ {
using value_type = toml::value;
{ {
const value_type v1{42, 54, 69, 72}; const value_type v1(toml::array{42, 54, 69, 72});
const value_type v2{"foo", "bar", "baz"}; const value_type v2(toml::array{"foo", "bar", "baz"});
const value_type v{v1, v2}; const value_type v (toml::array{v1, v2});
std::pair<std::vector<int>, std::vector<std::string>> p = std::pair<std::vector<int>, std::vector<std::string>> p =
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v); toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(v);
BOOST_TEST(p.first.size() == 4u); CHECK_EQ(p.first.size(), 4u);
BOOST_TEST(p.first.at(0) == 42); CHECK_EQ(p.first.at(0), 42);
BOOST_TEST(p.first.at(1) == 54); CHECK_EQ(p.first.at(1), 54);
BOOST_TEST(p.first.at(2) == 69); CHECK_EQ(p.first.at(2), 69);
BOOST_TEST(p.first.at(3) == 72); CHECK_EQ(p.first.at(3), 72);
BOOST_TEST(p.second.size() == 3u); CHECK_EQ(p.second.size(), 3u);
BOOST_TEST(p.second.at(0) == "foo"); CHECK_EQ(p.second.at(0), "foo");
BOOST_TEST(p.second.at(1) == "bar"); CHECK_EQ(p.second.at(1), "bar");
BOOST_TEST(p.second.at(2) == "baz"); CHECK_EQ(p.second.at(2), "baz");
std::tuple<std::vector<int>, std::vector<std::string>> t = std::tuple<std::vector<int>, std::vector<std::string>> t =
toml::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v); toml::get<std::tuple<std::vector<int>, std::vector<std::string>>>(v);
BOOST_TEST(std::get<0>(t).at(0) == 42); CHECK_EQ(std::get<0>(t).at(0), 42);
BOOST_TEST(std::get<0>(t).at(1) == 54); CHECK_EQ(std::get<0>(t).at(1), 54);
BOOST_TEST(std::get<0>(t).at(2) == 69); CHECK_EQ(std::get<0>(t).at(2), 69);
BOOST_TEST(std::get<0>(t).at(3) == 72); CHECK_EQ(std::get<0>(t).at(3), 72);
BOOST_TEST(std::get<1>(t).at(0) == "foo"); CHECK_EQ(std::get<1>(t).at(0), "foo");
BOOST_TEST(std::get<1>(t).at(1) == "bar"); CHECK_EQ(std::get<1>(t).at(1), "bar");
BOOST_TEST(std::get<1>(t).at(2) == "baz"); CHECK_EQ(std::get<1>(t).at(2), "baz");
} }
{ {
const value_type v1{42, 54, 69, 72}; const value_type v1(toml::array{42, 54, 69, 72});
const value_type v2{"foo", "bar", "baz"}; const value_type v2(toml::array{"foo", "bar", "baz"});
value_type v{v1, v2}; value_type v (toml::array{v1, v2});
std::pair<std::vector<int>, std::vector<std::string>> p = std::pair<std::vector<int>, std::vector<std::string>> p =
toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(std::move(v)); toml::get<std::pair<std::vector<int>, std::vector<std::string>>>(std::move(v));
BOOST_TEST(p.first.size() == 4u); CHECK_EQ(p.first.size(), 4u);
BOOST_TEST(p.first.at(0) == 42); CHECK_EQ(p.first.at(0), 42);
BOOST_TEST(p.first.at(1) == 54); CHECK_EQ(p.first.at(1), 54);
BOOST_TEST(p.first.at(2) == 69); CHECK_EQ(p.first.at(2), 69);
BOOST_TEST(p.first.at(3) == 72); CHECK_EQ(p.first.at(3), 72);
BOOST_TEST(p.second.size() == 3u); CHECK_EQ(p.second.size(), 3u);
BOOST_TEST(p.second.at(0) == "foo"); CHECK_EQ(p.second.at(0), "foo");
BOOST_TEST(p.second.at(1) == "bar"); CHECK_EQ(p.second.at(1), "bar");
BOOST_TEST(p.second.at(2) == "baz"); CHECK_EQ(p.second.at(2), "baz");
} }
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_table, value_type, test_value_types) TEST_CASE("testing toml::get<table-like>")
{ {
using value_type = toml::value;
{ {
const value_type v1{ const value_type v1(toml::table{
{"key1", 1}, {"key1", 1},
{"key2", 2}, {"key2", 2},
{"key3", 3}, {"key3", 3},
{"key4", 4} {"key4", 4}
}; });
const auto v = toml::get<std::map<std::string, int>>(v1); const auto v = toml::get<std::map<std::string, int>>(v1);
BOOST_TEST(v.at("key1") == 1); CHECK_EQ(v.at("key1"), 1);
BOOST_TEST(v.at("key2") == 2); CHECK_EQ(v.at("key2"), 2);
BOOST_TEST(v.at("key3") == 3); CHECK_EQ(v.at("key3"), 3);
BOOST_TEST(v.at("key4") == 4); CHECK_EQ(v.at("key4"), 4);
} }
{ {
value_type v1{ value_type v1(toml::table{
{"key1", 1}, {"key1", 1},
{"key2", 2}, {"key2", 2},
{"key3", 3}, {"key3", 3},
{"key4", 4} {"key4", 4}
}; });
const auto v = toml::get<std::map<std::string, int>>(std::move(v1)); const auto v = toml::get<std::map<std::string, int>>(std::move(v1));
BOOST_TEST(v.at("key1") == 1); CHECK_EQ(v.at("key1"), 1);
BOOST_TEST(v.at("key2") == 2); CHECK_EQ(v.at("key2"), 2);
BOOST_TEST(v.at("key3") == 3); CHECK_EQ(v.at("key3"), 3);
BOOST_TEST(v.at("key4") == 4); CHECK_EQ(v.at("key4"), 4);
} }
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_date, value_type, test_value_types) TEST_CASE("testing toml::get<time_point>(local_date)")
{ {
using value_type = toml::value;
value_type v1(toml::local_date{2018, toml::month_t::Apr, 1}); value_type v1(toml::local_date{2018, toml::month_t::Apr, 1});
const auto date = std::chrono::system_clock::to_time_t( const auto date = std::chrono::system_clock::to_time_t(
toml::get<std::chrono::system_clock::time_point>(v1)); toml::get<std::chrono::system_clock::time_point>(v1));
@@ -422,27 +435,32 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_date, value_type, test_value_t
t.tm_sec = 0; t.tm_sec = 0;
t.tm_isdst = -1; t.tm_isdst = -1;
const auto c = std::mktime(&t); const auto c = std::mktime(&t);
BOOST_TEST(c == date); CHECK_EQ(c, date);
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_time, value_type, test_value_types) TEST_CASE("testing toml::get<duration>")
{ {
using value_type = toml::value;
value_type v1(toml::local_time{12, 30, 45}); value_type v1(toml::local_time{12, 30, 45});
const auto time = toml::get<std::chrono::seconds>(v1); const auto time = toml::get<std::chrono::seconds>(v1);
const bool result = time == std::chrono::hours(12) + const bool result = time == std::chrono::hours(12) +
std::chrono::minutes(30) + std::chrono::minutes(30) +
std::chrono::seconds(45); std::chrono::seconds(45);
BOOST_TEST(result); CHECK_UNARY(result);
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_datetime, value_type, test_value_types) TEST_CASE("testing toml::get<time_point>(local_datetime)")
{ {
using value_type = toml::value;
value_type v1(toml::local_datetime( value_type v1(toml::local_datetime(
toml::local_date{2018, toml::month_t::Apr, 1}, toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 45})); toml::local_time{12, 30, 45}));
const auto date = std::chrono::system_clock::to_time_t( const auto date = std::chrono::system_clock::to_time_t(
toml::get<std::chrono::system_clock::time_point>(v1)); toml::get<std::chrono::system_clock::time_point>(v1));
std::tm t; std::tm t;
t.tm_year = 2018 - 1900; t.tm_year = 2018 - 1900;
t.tm_mon = 4 - 1; t.tm_mon = 4 - 1;
@@ -452,54 +470,55 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_local_datetime, value_type, test_val
t.tm_sec = 45; t.tm_sec = 45;
t.tm_isdst = -1; t.tm_isdst = -1;
const auto c = std::mktime(&t); const auto c = std::mktime(&t);
BOOST_TEST(c == date); CHECK_EQ(c, date);
} }
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_toml_offset_datetime, value_type, test_value_types) TEST_CASE("testing toml::get<time_point>(offset_datetime)")
{ {
using value_type = toml::value;
{ {
value_type v1(toml::offset_datetime( value_type v1(toml::offset_datetime(
toml::local_date{2018, toml::month_t::Apr, 1}, toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 0}, toml::local_time{12, 30, 0},
toml::time_offset{9, 0})); toml::time_offset{9, 0}));
// 2018-04-01T12:30:00+09:00 // 2018-04-01T12:30:00+09:00
// == 2018-04-01T03:30:00Z // == 2018-04-01T03:30:00Z
const auto date = toml::get<std::chrono::system_clock::time_point>(v1); const auto date = toml::get<std::chrono::system_clock::time_point>(v1);
const auto timet = std::chrono::system_clock::to_time_t(date); const auto timet = std::chrono::system_clock::to_time_t(date);
// get time_t as gmtime (2018-04-01T03:30:00Z) // get time_t as gmtime (2018-04-01T03:30:00Z)
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
BOOST_TEST(tmp); CHECK_UNARY(tmp);
const auto tm = *tmp; const auto tm = *tmp;
BOOST_TEST(tm.tm_year + 1900 == 2018); CHECK_EQ(tm.tm_year + 1900, 2018);
BOOST_TEST(tm.tm_mon + 1 == 4); CHECK_EQ(tm.tm_mon + 1, 4);
BOOST_TEST(tm.tm_mday == 1); CHECK_EQ(tm.tm_mday, 1);
BOOST_TEST(tm.tm_hour == 3); CHECK_EQ(tm.tm_hour, 3);
BOOST_TEST(tm.tm_min == 30); CHECK_EQ(tm.tm_min, 30);
BOOST_TEST(tm.tm_sec == 0); CHECK_EQ(tm.tm_sec, 0);
} }
{ {
value_type v1(toml::offset_datetime( value_type v1(toml::offset_datetime(
toml::local_date{2018, toml::month_t::Apr, 1}, toml::local_date{2018, toml::month_t::Apr, 1},
toml::local_time{12, 30, 0}, toml::local_time{12, 30, 0},
toml::time_offset{-8, 0})); toml::time_offset{-8, 0}));
// 2018-04-01T12:30:00-08:00 // 2018-04-01T12:30:00-08:00
// == 2018-04-01T20:30:00Z //, 2018-04-01T20:30:00Z
const auto date = toml::get<std::chrono::system_clock::time_point>(v1); const auto date = toml::get<std::chrono::system_clock::time_point>(v1);
const auto timet = std::chrono::system_clock::to_time_t(date); const auto timet = std::chrono::system_clock::to_time_t(date);
// get time_t as gmtime (2018-04-01T03:30:00Z) // get time_t as gmtime (2018-04-01T03:30:00Z)
const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe! const auto tmp = std::gmtime(std::addressof(timet)); // XXX not threadsafe!
BOOST_TEST(tmp); CHECK_UNARY(tmp);
const auto tm = *tmp; const auto tm = *tmp;
BOOST_TEST(tm.tm_year + 1900 == 2018); CHECK_EQ(tm.tm_year + 1900, 2018);
BOOST_TEST(tm.tm_mon + 1 == 4); CHECK_EQ(tm.tm_mon + 1, 4);
BOOST_TEST(tm.tm_mday == 1); CHECK_EQ(tm.tm_mday, 1);
BOOST_TEST(tm.tm_hour == 20); CHECK_EQ(tm.tm_hour, 20);
BOOST_TEST(tm.tm_min == 30); CHECK_EQ(tm.tm_min, 30);
BOOST_TEST(tm.tm_sec == 0); CHECK_EQ(tm.tm_sec, 0);
} }
} }

View File

@@ -1,6 +1,10 @@
#include <toml.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include "utility.hpp"
#include <toml11/value.hpp>
#include <toml11/get.hpp>
#include <array> #include <array>
#include <deque> #include <deque>
@@ -13,240 +17,180 @@
#include <string_view> #include <string_view>
#endif #endif
using test_value_types = std::tuple< #define TOML11_TEST_GET_OR_EXACT(ty, init_expr, opt_expr)\
toml::basic_value<toml::discard_comments>, { \
toml::basic_value<toml::preserve_comments>, const ty init init_expr ; \
toml::basic_value<toml::discard_comments, std::map, std::deque>, const ty opt opt_expr ; \
toml::basic_value<toml::preserve_comments, std::map, std::deque> const value_type v(init); \
>; CHECK_NE(init, opt); \
CHECK_EQ(init, toml::get_or(v, opt)); \
}
namespace test TEST_CASE("testing get_or with exact types")
{ {
// to compare result values in BOOST_TEST(). using value_type = toml::value;
// using boolean_type = typename value_type::boolean_type ;
// BOOST_TEST outputs the expected and actual values. Thus it includes the using integer_type = typename value_type::integer_type ;
// output stream operator inside. To compile it, we need operator<<s for using floating_type = typename value_type::floating_type ;
// containers to compare. using string_type = typename value_type::string_type ;
template<typename charT, typename traits, typename T, typename Alloc> using local_time_type = typename value_type::local_time_type ;
std::basic_ostream<charT, traits>& using local_date_type = typename value_type::local_date_type ;
operator<<(std::basic_ostream<charT, traits>& os, const std::vector<T, Alloc>& v) using local_datetime_type = typename value_type::local_datetime_type ;
{ using offset_datetime_type = typename value_type::offset_datetime_type;
os << "[ "; using array_type = typename value_type::array_type ;
for(const auto& i : v) {os << i << ' ';} using table_type = typename value_type::table_type ;
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::deque<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits, typename T, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const std::list<T, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << i << ' ';}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Comp, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::map<Key, Value, Comp, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
template<typename charT, typename traits,
typename Key, typename Value, typename Hash, typename Eq, typename Alloc>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const std::unordered_map<Key, Value, Hash, Eq, Alloc>& v)
{
os << "[ ";
for(const auto& i : v) {os << '{' << i.first << ", " << i.second << "} ";}
os << ']';
return os;
}
} // test
#define TOML11_TEST_GET_OR_EXACT(toml_type, init_expr, opt_expr)\ TOML11_TEST_GET_OR_EXACT(boolean_type, ( true), (false))
{ \ TOML11_TEST_GET_OR_EXACT(integer_type, ( 42), ( 54))
using namespace test; \ TOML11_TEST_GET_OR_EXACT(floating_type, ( 3.14), ( 2.71))
const toml::toml_type init init_expr ; \ TOML11_TEST_GET_OR_EXACT(string_type, ("foo"), ("bar"))
const toml::toml_type opt opt_expr ; \ TOML11_TEST_GET_OR_EXACT(local_time_type, (12, 30, 45), (6, 0, 30))
const value_type v(init); \ TOML11_TEST_GET_OR_EXACT(local_date_type, (2019, toml::month_t::Apr, 1),
BOOST_TEST(init != opt); \ (1999, toml::month_t::Jan, 2))
BOOST_TEST(init == toml::get_or(v, opt)); \ TOML11_TEST_GET_OR_EXACT(local_datetime_type,
} \
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_exact, value_type, test_value_types)
{
TOML11_TEST_GET_OR_EXACT(boolean, ( true), (false))
TOML11_TEST_GET_OR_EXACT(integer, ( 42), ( 54))
TOML11_TEST_GET_OR_EXACT(floating, ( 3.14), ( 2.71))
TOML11_TEST_GET_OR_EXACT(string, ("foo"), ("bar"))
TOML11_TEST_GET_OR_EXACT(local_time, (12, 30, 45), (6, 0, 30))
TOML11_TEST_GET_OR_EXACT(local_date, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_GET_OR_EXACT(local_datetime,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
) )
TOML11_TEST_GET_OR_EXACT(offset_datetime, TOML11_TEST_GET_OR_EXACT(offset_datetime_type,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
) )
{
const typename value_type::array_type init{1,2,3,4,5}; TOML11_TEST_GET_OR_EXACT(array_type, ({1,2,3,4,5}), ({6,7,8,9,10}));
const typename value_type::array_type opt {6,7,8,9,10}; TOML11_TEST_GET_OR_EXACT(table_type, ({{"key1", 42}, {"key2", "foo"}}),
const value_type v(init); ({{"key1", 54}, {"key2", "bar"}}));
BOOST_TEST(init != opt);
BOOST_TEST(init == toml::get_or(v, opt));
}
{
const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
const typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
const value_type v(init);
BOOST_TEST(init != opt);
BOOST_TEST(init == toml::get_or(v, opt));
}
} }
#undef TOML11_TEST_GET_OR_EXACT #undef TOML11_TEST_GET_OR_EXACT
#define TOML11_TEST_GET_OR_MOVE_EXACT(toml_type, init_expr, opt_expr)\ #define TOML11_TEST_GET_OR_MOVE_EXACT(ty, init_expr, opt_expr) \
{ \ { \
using namespace test; \ const ty init init_expr ; \
const toml::toml_type init init_expr ; \ ty opt opt_expr ; \
toml::toml_type opt opt_expr ; \
value_type v(init); \ value_type v(init); \
BOOST_TEST(init != opt); \ CHECK_NE(init, opt); \
const auto opt_ = toml::get_or(std::move(v), std::move(opt));\ const auto opt_ = toml::get_or(std::move(v), std::move(opt));\
BOOST_TEST(init == opt_); \ CHECK_EQ(init, opt_); \
} \ }
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_move, value_type, test_value_types) TEST_CASE("testing toml::get_or with moved argument")
{ {
TOML11_TEST_GET_OR_MOVE_EXACT(boolean, ( true), (false)) using value_type = toml::value;
TOML11_TEST_GET_OR_MOVE_EXACT(integer, ( 42), ( 54)) using boolean_type = typename value_type::boolean_type ;
TOML11_TEST_GET_OR_MOVE_EXACT(floating, ( 3.14), ( 2.71)) using integer_type = typename value_type::integer_type ;
TOML11_TEST_GET_OR_MOVE_EXACT(string, ("foo"), ("bar")) using floating_type = typename value_type::floating_type ;
TOML11_TEST_GET_OR_MOVE_EXACT(local_time, (12, 30, 45), (6, 0, 30)) using string_type = typename value_type::string_type ;
TOML11_TEST_GET_OR_MOVE_EXACT(local_date, (2019, toml::month_t::Apr, 1), using local_time_type = typename value_type::local_time_type ;
(1999, toml::month_t::Jan, 2)) using local_date_type = typename value_type::local_date_type ;
TOML11_TEST_GET_OR_MOVE_EXACT(local_datetime, using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
TOML11_TEST_GET_OR_MOVE_EXACT(boolean_type, ( true), (false))
TOML11_TEST_GET_OR_MOVE_EXACT(integer_type, ( 42), ( 54))
TOML11_TEST_GET_OR_MOVE_EXACT(floating_type, ( 3.14), ( 2.71))
TOML11_TEST_GET_OR_MOVE_EXACT(string_type, ("foo"), ("bar"))
TOML11_TEST_GET_OR_MOVE_EXACT(local_time_type, (12, 30, 45), (6, 0, 30))
TOML11_TEST_GET_OR_MOVE_EXACT(local_date_type, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_GET_OR_MOVE_EXACT(local_datetime_type,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
) )
TOML11_TEST_GET_OR_MOVE_EXACT(offset_datetime, TOML11_TEST_GET_OR_MOVE_EXACT(offset_datetime_type,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
) )
{
const typename value_type::array_type init{1,2,3,4,5}; TOML11_TEST_GET_OR_MOVE_EXACT(array_type, ({1,2,3,4,5}), ({6,7,8,9,10}));
typename value_type::array_type opt {6,7,8,9,10}; TOML11_TEST_GET_OR_MOVE_EXACT(table_type, ({{"key1", 42}, {"key2", "foo"}}),
value_type v(init); ({{"key1", 54}, {"key2", "bar"}}));
BOOST_TEST(init != opt);
const auto opt_ = toml::get_or(std::move(v), std::move(opt));
BOOST_TEST(init == opt_);
}
{
const typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
typename value_type::table_type opt {{"key1", 54}, {"key2", "bar"}};
value_type v(init);
BOOST_TEST(init != opt);
const auto opt_ = toml::get_or(std::move(v), std::move(opt));
BOOST_TEST(init == opt_);
}
} }
#undef TOML11_TEST_GET_OR_MOVE_EXACT #undef TOML11_TEST_GET_OR_MOVE_EXACT
#define TOML11_TEST_GET_OR_MODIFY(toml_type, init_expr, opt_expr)\ #define TOML11_TEST_GET_OR_MODIFY(ty, init_expr, opt_expr)\
{ \ { \
using namespace test; \ const ty init init_expr ; \
const toml::toml_type init init_expr ; \ ty opt1 opt_expr ; \
toml::toml_type opt1 opt_expr ; \ ty opt2 opt_expr ; \
toml::toml_type opt2 opt_expr ; \ value_type v(init); \
value_type v(init); \ CHECK_NE(init, opt1); \
BOOST_TEST(init != opt1); \ toml::get_or(v, opt2) = opt1; \
toml::get_or(v, opt2) = opt1; \ CHECK_EQ(opt1, toml::get<ty>(v)); \
BOOST_TEST(opt1 == toml::get<toml::toml_type>(v)); \ }
} \
/**/ TEST_CASE("testing if get_or can modify value")
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_modify, value_type, test_value_types)
{ {
TOML11_TEST_GET_OR_MODIFY(boolean, ( true), (false)) using value_type = toml::value;
TOML11_TEST_GET_OR_MODIFY(integer, ( 42), ( 54)) using boolean_type = typename value_type::boolean_type ;
TOML11_TEST_GET_OR_MODIFY(floating, ( 3.14), ( 2.71)) using integer_type = typename value_type::integer_type ;
TOML11_TEST_GET_OR_MODIFY(string, ("foo"), ("bar")) using floating_type = typename value_type::floating_type ;
TOML11_TEST_GET_OR_MODIFY(local_time, (12, 30, 45), (6, 0, 30)) using string_type = typename value_type::string_type ;
TOML11_TEST_GET_OR_MODIFY(local_date, (2019, toml::month_t::Apr, 1), using local_time_type = typename value_type::local_time_type ;
(1999, toml::month_t::Jan, 2)) using local_date_type = typename value_type::local_date_type ;
TOML11_TEST_GET_OR_MODIFY(local_datetime, using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
TOML11_TEST_GET_OR_MODIFY(boolean_type, ( true), (false))
TOML11_TEST_GET_OR_MODIFY(integer_type, ( 42), ( 54))
TOML11_TEST_GET_OR_MODIFY(floating_type, ( 3.14), ( 2.71))
TOML11_TEST_GET_OR_MODIFY(string_type, ("foo"), ("bar"))
TOML11_TEST_GET_OR_MODIFY(local_time_type, (12, 30, 45), (6, 0, 30))
TOML11_TEST_GET_OR_MODIFY(local_date_type, (2019, toml::month_t::Apr, 1),
(1999, toml::month_t::Jan, 2))
TOML11_TEST_GET_OR_MODIFY(local_datetime_type,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30))
) )
TOML11_TEST_GET_OR_MODIFY(offset_datetime, TOML11_TEST_GET_OR_MODIFY(offset_datetime_type,
(toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)), (toml::local_date(2019, toml::month_t::Apr, 1), toml::local_time(12, 30, 45), toml::time_offset( 9, 0)),
(toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0)) (toml::local_date(1999, toml::month_t::Jan, 2), toml::local_time( 6, 0, 30), toml::time_offset(-3, 0))
) )
{
typename value_type::array_type init{1,2,3,4,5}; TOML11_TEST_GET_OR_MODIFY(array_type, ({1,2,3,4,5}), ({6,7,8,9,10}));
typename value_type::array_type opt1{6,7,8,9,10}; TOML11_TEST_GET_OR_MODIFY(table_type, ({{"key1", 42}, {"key2", "foo"}}),
typename value_type::array_type opt2{6,7,8,9,10}; ({{"key1", 54}, {"key2", "bar"}}));
BOOST_TEST(init != opt1);
value_type v(init);
toml::get_or(v, opt2) = opt1;
BOOST_TEST(opt1 == toml::get<typename value_type::array_type>(v));
}
{
typename value_type::table_type init{{"key1", 42}, {"key2", "foo"}};
typename value_type::table_type opt1{{"key1", 54}, {"key2", "bar"}};
typename value_type::table_type opt2{{"key1", 54}, {"key2", "bar"}};
value_type v(init);
BOOST_TEST(init != opt1);
toml::get_or(v, opt2) = opt1;
BOOST_TEST(opt1 == toml::get<typename value_type::table_type>(v));
}
} }
#undef TOML11_TEST_GET_OR_MODIFY #undef TOML11_TEST_GET_OR_MODIFY
#define TOML11_TEST_GET_OR_FALLBACK(init_type, opt_type) \ #define TOML11_TEST_GET_OR_FALLBACK(init_type, opt_type) \
{ \ { \
using namespace test; \
value_type v(init_type); \ value_type v(init_type); \
BOOST_TEST(opt_type == toml::get_or(v, opt_type));\ CHECK_EQ(opt_type, toml::get_or(v, opt_type)); \
} \ }
/**/
BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_fallback, value_type, test_value_types) TEST_CASE("testing get_or can return optional value on failure")
{ {
const toml::boolean boolean (true); using value_type = toml::value;
const toml::integer integer (42); using boolean_type = typename value_type::boolean_type ;
const toml::floating floating (3.14); using integer_type = typename value_type::integer_type ;
const toml::string string ("foo"); using floating_type = typename value_type::floating_type ;
const toml::local_time local_time (12, 30, 45); using string_type = typename value_type::string_type ;
const toml::local_date local_date (2019, toml::month_t::Apr, 1); using local_time_type = typename value_type::local_time_type ;
const toml::local_datetime local_datetime ( using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
const boolean_type boolean (true);
const integer_type integer (42);
const floating_type floating (3.14);
const string_type string ("foo");
const local_time_type local_time (12, 30, 45);
const local_date_type local_date (2019, toml::month_t::Apr, 1);
const local_datetime_type local_datetime (
toml::local_date(2019, toml::month_t::Apr, 1), toml::local_date(2019, toml::month_t::Apr, 1),
toml::local_time(12, 30, 45)); toml::local_time(12, 30, 45)
const toml::offset_datetime offset_datetime( );
const offset_datetime_type offset_datetime(
toml::local_date(2019, toml::month_t::Apr, 1), toml::local_date(2019, toml::month_t::Apr, 1),
toml::local_time(12, 30, 45), toml::time_offset( 9, 0)); toml::local_time(12, 30, 45), toml::time_offset( 9, 0));
using array_type = typename value_type::array_type;
using table_type = typename value_type::table_type;
const array_type array{1, 2, 3, 4, 5}; const array_type array{1, 2, 3, 4, 5};
const table_type table{{"key1", 42}, {"key2", "foo"}}; const table_type table{{"key1", 42}, {"key2", "foo"}};
@@ -352,98 +296,52 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(test_get_or_fallback, value_type, test_value_types
} }
#undef TOML11_TEST_GET_OR_FALLBACK #undef TOML11_TEST_GET_OR_FALLBACK
BOOST_AUTO_TEST_CASE(test_get_or_integer) TEST_CASE("testing get_or with optional integer")
{ {
{ {
toml::value v1(42); toml::value v1(42);
toml::value v2(3.14); toml::value v2(3.14);
BOOST_TEST(42u == toml::get_or(v1, 0u)); CHECK_EQ(42u, toml::get_or(v1, 0u));
BOOST_TEST(0u == toml::get_or(v2, 0u)); CHECK_EQ(0u , toml::get_or(v2, 0u));
} }
{ {
toml::value v1(42); toml::value v1(42);
toml::value v2(3.14); toml::value v2(3.14);
BOOST_TEST(42u == toml::get_or(std::move(v1), 0u)); CHECK_EQ(42u, toml::get_or(std::move(v1), 0u));
BOOST_TEST(0u == toml::get_or(std::move(v2), 0u)); CHECK_EQ( 0u, toml::get_or(std::move(v2), 0u));
} }
} }
BOOST_AUTO_TEST_CASE(test_get_or_floating) TEST_CASE("testing get_or with optional float")
{ {
{ {
toml::value v1(42); toml::value v1(42);
toml::value v2(3.14); toml::value v2(3.14);
BOOST_TEST(2.71f == toml::get_or(v1, 2.71f)); CHECK_EQ(2.71f, toml::get_or(v1, 2.71f));
BOOST_TEST(static_cast<float>(v2.as_floating()) == toml::get_or(v2, 2.71f)); CHECK_EQ(static_cast<float>(v2.as_floating()), toml::get_or(v2, 2.71f));
} }
{ {
toml::value v1(42); toml::value v1(42);
toml::value v2(3.14); toml::value v2(3.14);
BOOST_TEST(2.71f == toml::get_or(std::move(v1), 2.71f)); CHECK_EQ(2.71f , toml::get_or(std::move(v1), 2.71f));
BOOST_TEST(static_cast<float>(3.14) == toml::get_or(std::move(v2), 2.71f)); CHECK_EQ(static_cast<float>(3.14), toml::get_or(std::move(v2), 2.71f));
} }
} }
BOOST_AUTO_TEST_CASE(test_get_or_string) TEST_CASE("testing get_or with optional string literal")
{ {
{ {
toml::value v1("foobar"); toml::value v1("foobar");
toml::value v2(42); toml::value v2(42);
std::string s1("bazqux"); CHECK_EQ("foobar", toml::get_or(v1, "bazqux"));
const std::string s2("bazqux"); CHECK_EQ("bazqux", toml::get_or(v2, "bazqux"));
BOOST_TEST("foobar" == toml::get_or(v1, s1));
BOOST_TEST("bazqux" == toml::get_or(v2, s1));
std::string& v1r = toml::get_or(v1, s1);
std::string& s1r = toml::get_or(v2, s1);
BOOST_TEST("foobar" == v1r);
BOOST_TEST("bazqux" == s1r);
BOOST_TEST("foobar" == toml::get_or(v1, s2));
BOOST_TEST("bazqux" == toml::get_or(v2, s2));
BOOST_TEST("foobar" == toml::get_or(v1, std::move(s1)));
BOOST_TEST("bazqux" == toml::get_or(v2, std::move(s1)));
} }
{ {
toml::value v1("foobar"); toml::value v1("foobar");
toml::value v2(42); toml::value v2(42);
std::string s1("bazqux"); CHECK_EQ("foobar", toml::get_or(std::move(v1), "bazqux"));
const std::string s2("bazqux"); CHECK_EQ("bazqux", toml::get_or(std::move(v2), "bazqux"));
BOOST_TEST("foobar" == toml::get_or(std::move(v1), s1));
BOOST_TEST("bazqux" == toml::get_or(std::move(v2), s1));
} }
{
toml::value v1("foobar");
toml::value v2(42);
BOOST_TEST("foobar" == toml::get_or(v1, "bazqux"));
BOOST_TEST("bazqux" == toml::get_or(v2, "bazqux"));
const char* lit = "bazqux";
BOOST_TEST("foobar" == toml::get_or(v1, lit));
BOOST_TEST("bazqux" == toml::get_or(v2, lit));
}
{
toml::value v1("foobar");
toml::value v2(42);
BOOST_TEST("foobar" == toml::get_or(std::move(v1), "bazqux"));
BOOST_TEST("bazqux" == toml::get_or(std::move(v2), "bazqux"));
}
{
toml::value v1("foobar");
toml::value v2(42);
const char* lit = "bazqux";
BOOST_TEST("foobar" == toml::get_or(v1, lit));
BOOST_TEST("bazqux" == toml::get_or(v2, lit));
}
} }

View File

@@ -1,36 +0,0 @@
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <toml/region.hpp>
#include <toml/result.hpp>
#define TOML11_TEST_LEX_ACCEPT(lxr, tkn, expct) \
do { \
const std::string token (tkn); \
const std::string expected(expct); \
toml::detail::location loc("test", token); \
const auto result = lxr::invoke(loc); \
BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \
const auto region = result.unwrap(); \
BOOST_TEST(region.str() == expected); \
BOOST_TEST(region.str().size() == expected.size()); \
BOOST_TEST(static_cast<std::size_t>(std::distance( \
loc.begin(), loc.iter())) == region.size()); \
} else { \
std::cerr << "lexer failed with input `"; \
std::cerr << token << "`. expected `" << expected << "`\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \
} while(false); \
/**/
#define TOML11_TEST_LEX_REJECT(lxr, tkn) \
do { \
const std::string token (tkn); \
toml::detail::location loc("test", token); \
const auto result = lxr::invoke(loc); \
BOOST_TEST(result.is_err()); \
const bool loc_same = (loc.begin() == loc.iter()); \
BOOST_TEST(loc_same); \
} while(false); /**/

View File

@@ -1,23 +0,0 @@
#include <toml/lexer.hpp>
#include "unit_test.hpp"
#include "test_lex_aux.hpp"
using namespace toml;
using namespace detail;
BOOST_AUTO_TEST_CASE(test_correct)
{
TOML11_TEST_LEX_ACCEPT(lex_boolean, "true", "true");
TOML11_TEST_LEX_ACCEPT(lex_boolean, "false", "false");
TOML11_TEST_LEX_ACCEPT(lex_boolean, "true # trailing", "true");
TOML11_TEST_LEX_ACCEPT(lex_boolean, "false # trailing", "false");
}
BOOST_AUTO_TEST_CASE(test_invalid)
{
TOML11_TEST_LEX_REJECT(lex_boolean, "TRUE");
TOML11_TEST_LEX_REJECT(lex_boolean, "FALSE");
TOML11_TEST_LEX_REJECT(lex_boolean, "True");
TOML11_TEST_LEX_REJECT(lex_boolean, "False");
}

View File

@@ -1,57 +0,0 @@
#include <toml/lexer.hpp>
#include "unit_test.hpp"
#include "test_lex_aux.hpp"
using namespace toml;
using namespace detail;
BOOST_AUTO_TEST_CASE(test_offset_datetime)
{
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
"1979-05-27T07:32:00Z",
"1979-05-27T07:32:00Z");
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
"1979-05-27T07:32:00-07:00",
"1979-05-27T07:32:00-07:00");
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
"1979-05-27T07:32:00.999999-07:00",
"1979-05-27T07:32:00.999999-07:00");
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
"1979-05-27 07:32:00Z",
"1979-05-27 07:32:00Z");
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
"1979-05-27 07:32:00-07:00",
"1979-05-27 07:32:00-07:00");
TOML11_TEST_LEX_ACCEPT(lex_offset_date_time,
"1979-05-27 07:32:00.999999-07:00",
"1979-05-27 07:32:00.999999-07:00");
}
BOOST_AUTO_TEST_CASE(test_local_datetime)
{
TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
"1979-05-27T07:32:00",
"1979-05-27T07:32:00");
TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
"1979-05-27T07:32:00.999999",
"1979-05-27T07:32:00.999999");
TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
"1979-05-27 07:32:00",
"1979-05-27 07:32:00");
TOML11_TEST_LEX_ACCEPT(lex_local_date_time,
"1979-05-27 07:32:00.999999",
"1979-05-27 07:32:00.999999");
}
BOOST_AUTO_TEST_CASE(test_local_date)
{
TOML11_TEST_LEX_ACCEPT(lex_local_date, "1979-05-27", "1979-05-27");
}
BOOST_AUTO_TEST_CASE(test_local_time)
{
TOML11_TEST_LEX_ACCEPT(lex_local_time, "07:32:00", "07:32:00");
TOML11_TEST_LEX_ACCEPT(lex_local_time, "07:32:00.999999", "07:32:00.999999");
}

View File

@@ -1,107 +0,0 @@
#include <toml/lexer.hpp>
#include "unit_test.hpp"
#include "test_lex_aux.hpp"
#include <limits>
using namespace toml;
using namespace detail;
BOOST_AUTO_TEST_CASE(test_fractional_valid)
{
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0", "1.0" );
TOML11_TEST_LEX_ACCEPT(lex_float, "0.1", "0.1" );
TOML11_TEST_LEX_ACCEPT(lex_float, "0.001", "0.001" );
TOML11_TEST_LEX_ACCEPT(lex_float, "0.100", "0.100" );
TOML11_TEST_LEX_ACCEPT(lex_float, "+3.14", "+3.14" );
TOML11_TEST_LEX_ACCEPT(lex_float, "-3.14", "-3.14" );
TOML11_TEST_LEX_ACCEPT(lex_float, "3.1415_9265_3589", "3.1415_9265_3589" );
TOML11_TEST_LEX_ACCEPT(lex_float, "+3.1415_9265_3589", "+3.1415_9265_3589");
TOML11_TEST_LEX_ACCEPT(lex_float, "-3.1415_9265_3589", "-3.1415_9265_3589");
TOML11_TEST_LEX_ACCEPT(lex_float, "123_456.789", "123_456.789" );
TOML11_TEST_LEX_ACCEPT(lex_float, "+123_456.789", "+123_456.789" );
TOML11_TEST_LEX_ACCEPT(lex_float, "-123_456.789", "-123_456.789" );
}
BOOST_AUTO_TEST_CASE(test_fractional_invalid)
{
TOML11_TEST_LEX_REJECT(lex_float, "0.");
TOML11_TEST_LEX_REJECT(lex_float, ".0");
TOML11_TEST_LEX_REJECT(lex_float, "01.0");
TOML11_TEST_LEX_REJECT(lex_float, "3,14");
TOML11_TEST_LEX_REJECT(lex_float, "+-1.0");
TOML11_TEST_LEX_REJECT(lex_float, "1._0");
}
BOOST_AUTO_TEST_CASE(test_exponential_valid)
{
TOML11_TEST_LEX_ACCEPT(lex_float, "1e10", "1e10");
TOML11_TEST_LEX_ACCEPT(lex_float, "1e+10", "1e+10");
TOML11_TEST_LEX_ACCEPT(lex_float, "1e-10", "1e-10");
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e10", "+1e10");
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e+10", "+1e+10");
TOML11_TEST_LEX_ACCEPT(lex_float, "+1e-10", "+1e-10");
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e10", "-1e10");
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e+10", "-1e+10");
TOML11_TEST_LEX_ACCEPT(lex_float, "-1e-10", "-1e-10");
TOML11_TEST_LEX_ACCEPT(lex_float, "123e-10", "123e-10");
TOML11_TEST_LEX_ACCEPT(lex_float, "1E10", "1E10");
TOML11_TEST_LEX_ACCEPT(lex_float, "1E+10", "1E+10");
TOML11_TEST_LEX_ACCEPT(lex_float, "1E-10", "1E-10");
TOML11_TEST_LEX_ACCEPT(lex_float, "123E-10", "123E-10");
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-10", "1_2_3E-10");
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-1_0", "1_2_3E-1_0");
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
// toml-lang/toml master permits leading 0s in exp part (unreleased)
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-01", "1_2_3E-01");
TOML11_TEST_LEX_ACCEPT(lex_float, "1_2_3E-0_1", "1_2_3E-0_1");
#endif
}
BOOST_AUTO_TEST_CASE(test_exponential_invalid)
{
// accept partially
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1E0", "1e1");
TOML11_TEST_LEX_ACCEPT(lex_float, "1E1e0", "1E1");
}
BOOST_AUTO_TEST_CASE(test_both_valid)
{
TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e23", "6.02e23");
TOML11_TEST_LEX_ACCEPT(lex_float, "6.02e+23", "6.02e+23");
TOML11_TEST_LEX_ACCEPT(lex_float, "1.112_650_06e-17", "1.112_650_06e-17");
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
// toml-lang/toml master permits leading 0s in exp part (unreleased)
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e-07", "1.0e-07");
#endif
}
BOOST_AUTO_TEST_CASE(test_both_invalid)
{
TOML11_TEST_LEX_REJECT(lex_float, "01e1.0");
// accept partially
TOML11_TEST_LEX_ACCEPT(lex_float, "1e1.0", "1e1");
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
// toml-lang/toml master permits leading 0s in exp part (unreleased)
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e_01", "1.0");
TOML11_TEST_LEX_ACCEPT(lex_float, "1.0e0__1", "1.0e0");
#endif
}
BOOST_AUTO_TEST_CASE(test_special_floating_point)
{
TOML11_TEST_LEX_ACCEPT(lex_float, "inf", "inf");
TOML11_TEST_LEX_ACCEPT(lex_float, "+inf", "+inf");
TOML11_TEST_LEX_ACCEPT(lex_float, "-inf", "-inf");
TOML11_TEST_LEX_ACCEPT(lex_float, "nan", "nan");
TOML11_TEST_LEX_ACCEPT(lex_float, "+nan", "+nan");
TOML11_TEST_LEX_ACCEPT(lex_float, "-nan", "-nan");
}

View File

@@ -1,101 +0,0 @@
#include <toml/lexer.hpp>
#include "unit_test.hpp"
#include "test_lex_aux.hpp"
using namespace toml;
using namespace detail;
BOOST_AUTO_TEST_CASE(test_decimal_correct)
{
TOML11_TEST_LEX_ACCEPT(lex_integer, "1234", "1234" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "+1234", "+1234" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "-1234", "-1234" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0", "0" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "1_2_3_4", "1_2_3_4" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "+1_2_3_4", "+1_2_3_4" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "-1_2_3_4", "-1_2_3_4" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "123_456_789", "123_456_789");
}
BOOST_AUTO_TEST_CASE(test_decimal_invalid)
{
TOML11_TEST_LEX_ACCEPT(lex_integer, "123+45", "123");
TOML11_TEST_LEX_ACCEPT(lex_integer, "123-45", "123");
TOML11_TEST_LEX_ACCEPT(lex_integer, "01234", "0");
TOML11_TEST_LEX_ACCEPT(lex_integer, "123__45", "123");
TOML11_TEST_LEX_REJECT(lex_integer, "_1234");
}
BOOST_AUTO_TEST_CASE(test_hex_correct)
{
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEADBEEF", "0xDEADBEEF" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdeadbeef", "0xdeadbeef" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEADbeef", "0xDEADbeef" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD_BEEF", "0xDEAD_BEEF");
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdead_beef", "0xdead_beef");
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xdead_BEEF", "0xdead_BEEF");
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xFF", "0xFF" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0x00FF", "0x00FF" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0x0000FF", "0x0000FF");
}
BOOST_AUTO_TEST_CASE(test_hex_invalid)
{
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xAPPLE", "0xA");
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD+BEEF", "0xDEAD");
TOML11_TEST_LEX_ACCEPT(lex_integer, "0xDEAD__BEEF", "0xDEAD");
TOML11_TEST_LEX_REJECT(lex_hex_int, "0x_DEADBEEF");
TOML11_TEST_LEX_REJECT(lex_hex_int, "0x+DEADBEEF");
TOML11_TEST_LEX_REJECT(lex_hex_int, "-0xFF" );
TOML11_TEST_LEX_REJECT(lex_hex_int, "-0x00FF" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0x_DEADBEEF", "0" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0x+DEADBEEF", "0" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "-0xFF" , "-0" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "-0x00FF" , "-0" );
}
BOOST_AUTO_TEST_CASE(test_oct_correct)
{
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o777", "0o777" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o7_7_7", "0o7_7_7");
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o007", "0o007" );
}
BOOST_AUTO_TEST_CASE(test_oct_invalid)
{
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o77+7", "0o77");
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o1__0", "0o1");
TOML11_TEST_LEX_REJECT(lex_oct_int, "0o800" );
TOML11_TEST_LEX_REJECT(lex_oct_int, "-0o777");
TOML11_TEST_LEX_REJECT(lex_oct_int, "0o+777");
TOML11_TEST_LEX_REJECT(lex_oct_int, "0o_10" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o800", "0");
TOML11_TEST_LEX_ACCEPT(lex_integer, "-0o777", "-0");
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o+777", "0");
TOML11_TEST_LEX_ACCEPT(lex_integer, "0o_10", "0");
}
BOOST_AUTO_TEST_CASE(test_bin_correct)
{
TOML11_TEST_LEX_ACCEPT(lex_integer, "0b10000", "0b10000" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0b010000", "0b010000" );
TOML11_TEST_LEX_ACCEPT(lex_integer, "0b01_00_00", "0b01_00_00");
TOML11_TEST_LEX_ACCEPT(lex_integer, "0b111111", "0b111111" );
}
BOOST_AUTO_TEST_CASE(test_bin_invalid)
{
TOML11_TEST_LEX_ACCEPT(lex_bin_int, "0b11__11", "0b11");
TOML11_TEST_LEX_ACCEPT(lex_bin_int, "0b11+11" , "0b11");
TOML11_TEST_LEX_REJECT(lex_bin_int, "-0b10000");
TOML11_TEST_LEX_REJECT(lex_bin_int, "0b_1111" );
}

View File

@@ -1,52 +0,0 @@
#include <toml/lexer.hpp>
#include "unit_test.hpp"
#include "test_lex_aux.hpp"
using namespace toml;
using namespace detail;
BOOST_AUTO_TEST_CASE(test_bare_key)
{
TOML11_TEST_LEX_ACCEPT(lex_key, "barekey", "barekey");
TOML11_TEST_LEX_ACCEPT(lex_key, "bare-key", "bare-key");
TOML11_TEST_LEX_ACCEPT(lex_key, "bare_key", "bare_key");
TOML11_TEST_LEX_ACCEPT(lex_key, "1234", "1234");
}
BOOST_AUTO_TEST_CASE(test_quoted_key)
{
TOML11_TEST_LEX_ACCEPT(lex_key, "\"127.0.0.1\"", "\"127.0.0.1\"");
TOML11_TEST_LEX_ACCEPT(lex_key, "\"character encoding\"", "\"character encoding\"");
// UTF-8 codepoint of characters that looks like "key" written upside down
TOML11_TEST_LEX_ACCEPT(lex_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"",
"\"\xCA\x8E\xC7\x9D\xCA\x9E\"");
TOML11_TEST_LEX_ACCEPT(lex_key, "'key2'", "'key2'");
TOML11_TEST_LEX_ACCEPT(lex_key, "'quoted \"value\"'", "'quoted \"value\"'");
}
BOOST_AUTO_TEST_CASE(test_dotted_key)
{
TOML11_TEST_LEX_ACCEPT(lex_key, "physical.color", "physical.color");
TOML11_TEST_LEX_ACCEPT(lex_key, "physical.shape", "physical.shape");
TOML11_TEST_LEX_ACCEPT(lex_key, "x.y", "x.y");
TOML11_TEST_LEX_ACCEPT(lex_key, "x . y", "x . y");
TOML11_TEST_LEX_ACCEPT(lex_key, "x.y.z", "x.y.z");
TOML11_TEST_LEX_ACCEPT(lex_key, "x. y .z", "x. y .z");
TOML11_TEST_LEX_ACCEPT(lex_key, "x .y. z", "x .y. z");
TOML11_TEST_LEX_ACCEPT(lex_key, "x . y . z", "x . y . z");
TOML11_TEST_LEX_ACCEPT(lex_key, "x.y.z.w", "x.y.z.w");
TOML11_TEST_LEX_ACCEPT(lex_key, "x. y .z. w", "x. y .z. w");
TOML11_TEST_LEX_ACCEPT(lex_key, "x . y . z . w", "x . y . z . w");
TOML11_TEST_LEX_ACCEPT(lex_key, "site.\"google.com\"", "site.\"google.com\"");
}
BOOST_AUTO_TEST_CASE(test_comment)
{
TOML11_TEST_LEX_ACCEPT(lex_comment, "# hoge", "# hoge");
TOML11_TEST_LEX_ACCEPT(lex_comment, "# \n", "# ");
TOML11_TEST_LEX_ACCEPT(lex_comment, "# \r\n", "# ");
TOML11_TEST_LEX_ACCEPT(lex_comment, "# # \n", "# # ");
}

122
tests/test_literal.cpp Normal file
View File

@@ -0,0 +1,122 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <iostream>
#include <toml11/value.hpp>
#include <toml11/literal.hpp>
TEST_CASE("testing toml value literal")
{
using namespace toml::literals::toml_literals;
{
const toml::value v1 = "true"_toml;
const toml::value v2 = "false"_toml;
CHECK_UNARY(v1.is_boolean());
CHECK_UNARY(v2.is_boolean());
CHECK_EQ(v1.as_boolean(), true);
CHECK_EQ(v2.as_boolean(), false);
}
{
const toml::value v1 = "123_456"_toml;
const toml::value v2 = "0b0010"_toml;
const toml::value v3 = "0xDEADBEEF"_toml;
CHECK_UNARY(v1.is_integer());
CHECK_UNARY(v2.is_integer());
CHECK_UNARY(v3.is_integer());
CHECK_EQ(v1.as_integer(), 123456);
CHECK_EQ(v2.as_integer(), 2);
CHECK_EQ(v3.as_integer(), 0xDEADBEEF);
}
{
const toml::value v1 = "3.1415"_toml;
const toml::value v2 = "6.02e+23"_toml;
CHECK_UNARY(v1.is_floating());
CHECK_UNARY(v2.is_floating());
CHECK_EQ(v1.as_floating(), doctest::Approx(3.1415 ).epsilon(0.00001));
CHECK_EQ(v2.as_floating(), doctest::Approx(6.02e23).epsilon(0.0001 ));
}
{
const toml::value v1 = R"("foo")"_toml;
const toml::value v2 = R"('foo')"_toml;
const toml::value v3 = R"("""foo""")"_toml;
const toml::value v4 = R"('''foo''')"_toml;
CHECK_UNARY(v1.is_string());
CHECK_UNARY(v2.is_string());
CHECK_UNARY(v3.is_string());
CHECK_UNARY(v4.is_string());
CHECK_EQ(v1.as_string(), "foo");
CHECK_EQ(v2.as_string(), "foo");
CHECK_EQ(v3.as_string(), "foo");
CHECK_EQ(v4.as_string(), "foo");
}
{
{
const toml::value v1 = R"([1,2,3])"_toml;
CHECK_UNARY(v1.is_array());
CHECK_EQ(v1.size(), 3);
CHECK_EQ(v1.at(0).as_integer(), 1);
CHECK_EQ(v1.at(1).as_integer(), 2);
CHECK_EQ(v1.at(2).as_integer(), 3);
}
{
const toml::value v2 = R"([1,])"_toml;
CHECK_UNARY(v2.is_array());
CHECK_EQ(v2.size(), 1);
CHECK_EQ(v2.at(0).as_integer(), 1);
}
{
const toml::value v3 = R"([[1,]])"_toml;
CHECK_UNARY(v3.is_array());
CHECK_EQ(v3.size(), 1);
CHECK_UNARY(v3.at(0).is_array());
CHECK_EQ(v3.at(0).at(0).as_integer(), 1);
}
{
const toml::value v4 = R"([[1],])"_toml;
CHECK_UNARY(v4.is_array());
CHECK_EQ(v4.size(), 1);
CHECK_UNARY(v4.at(0).is_array());
CHECK_EQ(v4.at(0).at(0).as_integer(), 1);
}
}
{
const toml::value v1 = R"({a = 42})"_toml;
CHECK_UNARY(v1.is_table());
CHECK_EQ(v1.size(), 1);
CHECK_UNARY(v1.at("a").is_integer());
CHECK_EQ(v1.at("a").as_integer(), 42);
}
{
const toml::value v1 = "1979-05-27"_toml;
CHECK_UNARY(v1.is_local_date());
CHECK_EQ(v1.as_local_date(), toml::local_date(1979, toml::month_t::May, 27));
}
{
const toml::value v1 = "12:00:00"_toml;
CHECK_UNARY(v1.is_local_time());
CHECK_EQ(v1.as_local_time(), toml::local_time(12, 0, 0));
}
{
const toml::value v1 = "1979-05-27T07:32:00"_toml;
CHECK_UNARY(v1.is_local_datetime());
CHECK_EQ(v1.as_local_datetime(), toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)));
}
{
const toml::value v1 = "1979-05-27T07:32:00Z"_toml;
CHECK_UNARY(v1.is_offset_datetime());
CHECK_EQ(v1.as_offset_datetime(), toml::offset_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0),
toml::time_offset(0, 0)));
}
}

View File

@@ -1,336 +0,0 @@
#include <toml.hpp>
#include "unit_test.hpp"
#include <map>
BOOST_AUTO_TEST_CASE(test_file_as_literal)
{
using namespace toml::literals::toml_literals;
{
const toml::value r{{"a", 42}, {"b", "baz"}};
const toml::value v = R"(
a = 42
b = "baz"
)"_toml;
BOOST_TEST(r == v);
}
{
const toml::value r{
{"c", 3.14},
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
};
const toml::value v = R"(
c = 3.14
[table]
a = 42
b = "baz"
)"_toml;
BOOST_TEST(r == v);
}
{
const toml::value r{
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
};
const toml::value v = R"(
[table]
a = 42
b = "baz"
)"_toml;
BOOST_TEST(r == v);
}
{
const toml::value r{
{"array_of_tables", toml::array{toml::table{}}}
};
const toml::value v = R"(
[[array_of_tables]]
)"_toml;
BOOST_TEST(r == v);
}
}
BOOST_AUTO_TEST_CASE(test_value_as_literal)
{
using namespace toml::literals::toml_literals;
{
const toml::value v1 = "true"_toml;
const toml::value v2 = "false"_toml;
BOOST_TEST(v1.is_boolean());
BOOST_TEST(v2.is_boolean());
BOOST_TEST(toml::get<bool>(v1));
BOOST_TEST(!toml::get<bool>(v2));
}
{
const toml::value v1 = "123_456"_toml;
const toml::value v2 = "0b0010"_toml;
const toml::value v3 = "0xDEADBEEF"_toml;
BOOST_TEST(v1.is_integer());
BOOST_TEST(v2.is_integer());
BOOST_TEST(v3.is_integer());
BOOST_TEST(toml::get<toml::integer>(v1) == 123456);
BOOST_TEST(toml::get<toml::integer>(v2) == 2);
BOOST_TEST(toml::get<toml::integer>(v3) == 0xDEADBEEF);
}
{
const toml::value v1 = "3.1415"_toml;
const toml::value v2 = "6.02e+23"_toml;
BOOST_TEST(v1.is_floating());
BOOST_TEST(v2.is_floating());
BOOST_TEST(toml::get<double>(v1) == 3.1415, boost::test_tools::tolerance(0.00001));
BOOST_TEST(toml::get<double>(v2) == 6.02e23, boost::test_tools::tolerance(0.0001));
}
{
const toml::value v1 = R"("foo")"_toml;
const toml::value v2 = R"('foo')"_toml;
const toml::value v3 = R"("""foo""")"_toml;
const toml::value v4 = R"('''foo''')"_toml;
BOOST_TEST(v1.is_string());
BOOST_TEST(v2.is_string());
BOOST_TEST(v3.is_string());
BOOST_TEST(v4.is_string());
BOOST_TEST(toml::get<std::string>(v1) == "foo");
BOOST_TEST(toml::get<std::string>(v2) == "foo");
BOOST_TEST(toml::get<std::string>(v3) == "foo");
BOOST_TEST(toml::get<std::string>(v4) == "foo");
}
{
{
const toml::value v1 = R"([1,2,3])"_toml;
BOOST_TEST(v1.is_array());
const bool result = (toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3});
BOOST_TEST(result);
}
{
const toml::value v2 = R"([1,])"_toml;
BOOST_TEST(v2.is_array());
const bool result = (toml::get<std::vector<int>>(v2) == std::vector<int>{1});
BOOST_TEST(result);
}
{
const toml::value v3 = R"([[1,]])"_toml;
BOOST_TEST(v3.is_array());
const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1});
BOOST_TEST(result);
}
{
const toml::value v4 = R"([[1],])"_toml;
BOOST_TEST(v4.is_array());
const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1});
BOOST_TEST(result);
}
}
{
const toml::value v1 = R"({a = 42})"_toml;
BOOST_TEST(v1.is_table());
const bool result = toml::get<std::map<std::string,int>>(v1) ==
std::map<std::string,int>{{"a", 42}};
BOOST_TEST(result);
}
{
const toml::value v1 = "1979-05-27"_toml;
BOOST_TEST(v1.is_local_date());
BOOST_TEST(toml::get<toml::local_date>(v1) ==
toml::local_date(1979, toml::month_t::May, 27));
}
{
const toml::value v1 = "12:00:00"_toml;
BOOST_TEST(v1.is_local_time());
const bool result = toml::get<std::chrono::hours>(v1) == std::chrono::hours(12);
BOOST_TEST(result);
}
{
const toml::value v1 = "1979-05-27T07:32:00"_toml;
BOOST_TEST(v1.is_local_datetime());
BOOST_TEST(toml::get<toml::local_datetime>(v1) ==
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)));
}
{
const toml::value v1 = "1979-05-27T07:32:00Z"_toml;
BOOST_TEST(v1.is_offset_datetime());
BOOST_TEST(toml::get<toml::offset_datetime>(v1) ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
}
}
BOOST_AUTO_TEST_CASE(test_file_as_u8_literal)
{
using namespace toml::literals::toml_literals;
{
const toml::value r{{"a", 42}, {"b", "baz"}};
const toml::value v = u8R"(
a = 42
b = "baz"
)"_toml;
BOOST_TEST(r == v);
}
{
const toml::value r{
{"c", 3.14},
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
};
const toml::value v = u8R"(
c = 3.14
[table]
a = 42
b = "baz"
)"_toml;
BOOST_TEST(r == v);
}
{
const toml::value r{
{"table", toml::table{{"a", 42}, {"b", "baz"}}}
};
const toml::value v = u8R"(
[table]
a = 42
b = "baz"
)"_toml;
BOOST_TEST(r == v);
}
{
const toml::value r{
{"array_of_tables", toml::array{toml::table{}}}
};
const toml::value v = u8R"(
[[array_of_tables]]
)"_toml;
BOOST_TEST(r == v);
}
}
BOOST_AUTO_TEST_CASE(test_value_as_u8_literal)
{
using namespace toml::literals::toml_literals;
{
const toml::value v1 = u8"true"_toml;
const toml::value v2 = u8"false"_toml;
BOOST_TEST(v1.is_boolean());
BOOST_TEST(v2.is_boolean());
BOOST_TEST(toml::get<bool>(v1));
BOOST_TEST(!toml::get<bool>(v2));
}
{
const toml::value v1 = u8"123_456"_toml;
const toml::value v2 = u8"0b0010"_toml;
const toml::value v3 = u8"0xDEADBEEF"_toml;
BOOST_TEST(v1.is_integer());
BOOST_TEST(v2.is_integer());
BOOST_TEST(v3.is_integer());
BOOST_TEST(toml::get<toml::integer>(v1) == 123456);
BOOST_TEST(toml::get<toml::integer>(v2) == 2);
BOOST_TEST(toml::get<toml::integer>(v3) == 0xDEADBEEF);
}
{
const toml::value v1 = u8"3.1415"_toml;
const toml::value v2 = u8"6.02e+23"_toml;
BOOST_TEST(v1.is_floating());
BOOST_TEST(v2.is_floating());
BOOST_TEST(toml::get<double>(v1) == 3.1415, boost::test_tools::tolerance(0.00001));
BOOST_TEST(toml::get<double>(v2) == 6.02e23, boost::test_tools::tolerance(0.0001));
}
{
const toml::value v1 = u8R"("foo")"_toml;
const toml::value v2 = u8R"('foo')"_toml;
const toml::value v3 = u8R"("""foo""")"_toml;
const toml::value v4 = u8R"('''foo''')"_toml;
const toml::value v5 = u8R"("")"_toml;
BOOST_TEST(v1.is_string());
BOOST_TEST(v2.is_string());
BOOST_TEST(v3.is_string());
BOOST_TEST(v4.is_string());
BOOST_TEST(v5.is_string());
BOOST_TEST(toml::get<std::string>(v1) == "foo");
BOOST_TEST(toml::get<std::string>(v2) == "foo");
BOOST_TEST(toml::get<std::string>(v3) == "foo");
BOOST_TEST(toml::get<std::string>(v4) == "foo");
BOOST_TEST(toml::get<std::string>(v5) == "\xE3\x81\xB2\xE3\x82\x89\xE3\x81\x8C\xE3\x81\xAA");
}
{
{
const toml::value v1 = u8R"([1,2,3])"_toml;
BOOST_TEST(v1.is_array());
const bool result = (toml::get<std::vector<int>>(v1) == std::vector<int>{1,2,3});
BOOST_TEST(result);
}
{
const toml::value v2 = u8R"([1,])"_toml;
BOOST_TEST(v2.is_array());
const bool result = (toml::get<std::vector<int>>(v2) == std::vector<int>{1});
BOOST_TEST(result);
}
{
const toml::value v3 = u8R"([[1,]])"_toml;
BOOST_TEST(v3.is_array());
const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v3).front()) == std::vector<int>{1});
BOOST_TEST(result);
}
{
const toml::value v4 = u8R"([[1],])"_toml;
BOOST_TEST(v4.is_array());
const bool result = (toml::get<std::vector<int>>(toml::get<toml::array>(v4).front()) == std::vector<int>{1});
BOOST_TEST(result);
}
}
{
const toml::value v1 = u8R"({a = 42})"_toml;
BOOST_TEST(v1.is_table());
const bool result = toml::get<std::map<std::string,int>>(v1) ==
std::map<std::string,int>{{"a", 42}};
BOOST_TEST(result);
}
{
const toml::value v1 = u8"1979-05-27"_toml;
BOOST_TEST(v1.is_local_date());
BOOST_TEST(toml::get<toml::local_date>(v1) ==
toml::local_date(1979, toml::month_t::May, 27));
}
{
const toml::value v1 = u8"12:00:00"_toml;
BOOST_TEST(v1.is_local_time());
const bool result = toml::get<std::chrono::hours>(v1) == std::chrono::hours(12);
BOOST_TEST(result);
}
{
const toml::value v1 = u8"1979-05-27T07:32:00"_toml;
BOOST_TEST(v1.is_local_datetime());
BOOST_TEST(toml::get<toml::local_datetime>(v1) ==
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)));
}
{
const toml::value v1 = u8"1979-05-27T07:32:00Z"_toml;
BOOST_TEST(v1.is_offset_datetime());
BOOST_TEST(toml::get<toml::offset_datetime>(v1) ==
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
}
}

63
tests/test_location.cpp Normal file
View File

@@ -0,0 +1,63 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <toml11/location.hpp>
TEST_CASE("testing location")
{
const auto first = toml::detail::make_temporary_location("hogefuga");
auto loc = first;
loc.advance(4);
CHECK_UNARY(loc.is_ok());
CHECK_UNARY( ! loc.eof());
CHECK_EQ(loc.current(), 'f');
CHECK_EQ(loc.line_number(), 1);
CHECK_EQ(loc.column_number(), 5);
const auto loc2 = loc;
CHECK_EQ(loc, loc2);
CHECK_UNARY(loc == loc2);
CHECK_UNARY(!(loc != loc2));
loc.advance(4);
CHECK_UNARY(loc.is_ok());
CHECK_UNARY(loc.eof());
CHECK_EQ(loc.current(), '\0');
CHECK_EQ(loc.line_number(), 1);
CHECK_EQ(loc.column_number(), 9);
CHECK_NE(loc, loc2);
CHECK_UNARY(!(loc == loc2));
CHECK_UNARY(loc != loc2);
CHECK_EQ(toml::detail::count(first, loc, 'e'), 1);
CHECK_EQ(toml::detail::count(first, loc, 'g'), 2);
}
TEST_CASE("testing multiline location")
{
const auto first = toml::detail::make_temporary_location("hoge\nfuga");
auto loc = first;
loc.advance(5);
CHECK_UNARY(loc.is_ok());
CHECK_UNARY( ! loc.eof());
CHECK_EQ(loc.current(), 'f');
CHECK_EQ(loc.line_number(), 2);
CHECK_EQ(loc.column_number(), 1);
const auto newline_r = toml::detail::rfind(first, loc, '\n');
CHECK_UNARY(newline_r.is_ok());
const auto newline = newline_r.as_ok();
CHECK_EQ(newline.current(), '\n');
loc.advance(4);
CHECK_UNARY(loc.is_ok());
CHECK_UNARY(loc.eof());
CHECK_EQ(loc.current(), '\0');
CHECK_EQ(loc.line_number(), 2);
CHECK_EQ(loc.column_number(), 5);
}

View File

@@ -1,11 +0,0 @@
#include <toml.hpp>
int read_a(const toml::table&);
int main()
{
const std::string content("a = 0");
std::istringstream iss(content);
const auto data = toml::parse(iss, "test_multiple_translation_unit.toml");
return read_a(toml::get<toml::table>(data));
}

View File

@@ -1,6 +0,0 @@
#include <toml.hpp>
int read_a(const toml::table& t)
{
return toml::get<int>(t.at("a"));
}

View File

@@ -1,288 +1,142 @@
#include <toml/parser.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "unit_test.hpp" #include <iostream>
#include "test_parse_aux.hpp" #include "utility.hpp"
#include <toml11/parser.hpp>
#include <toml11/types.hpp>
using namespace toml; #include "doctest.h"
using namespace detail;
BOOST_AUTO_TEST_CASE(test_oneline_array) TEST_CASE("testing an array")
{ {
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<toml::value>, "[]", array()); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
{ const auto make_format = [](toml::array_format ty, toml::indent_char ic, std::int32_t i, std::int32_t c) {
array a(5); toml::array_format_info fmt;
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); fmt.fmt = ty;
a[3] = toml::value(1); a[4] = toml::value(5); fmt.indent_type = ic;
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<toml::value>, "[3,1,4,1,5]", a); fmt.body_indent = i;
} fmt.closing_indent = c;
{ return fmt;
array a(3); };
a[0] = toml::value("foo"); a[1] = toml::value("bar");
a[2] = toml::value("baz"); toml11_test_parse_success<toml::value_t::array>("[]", (toml::array{}), comments(), make_format(toml::array_format::oneline, toml::indent_char::none, 4, 0), ctx);
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<toml::value>, "[\"foo\", \"bar\", \"baz\"]", a); toml11_test_parse_success<toml::value_t::array>("[1]", (toml::array{1}), comments(), make_format(toml::array_format::oneline, toml::indent_char::none, 4, 0), ctx);
} toml11_test_parse_success<toml::value_t::array>("[1, 2]", (toml::array{1, 2}), comments(), make_format(toml::array_format::oneline, toml::indent_char::none, 4, 0), ctx);
{ toml11_test_parse_success<toml::value_t::array>("[1, 2, ]", (toml::array{1, 2}), comments(), make_format(toml::array_format::oneline, toml::indent_char::none, 4, 0), ctx);
array a(5);
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); toml11_test_parse_success<toml::value_t::array>("[\n 1,\n 2,\n]", (toml::array{1, 2}), comments(), make_format(toml::array_format::multiline, toml::indent_char::space, 2, 0), ctx);
a[3] = toml::value(1); a[4] = toml::value(5); toml11_test_parse_success<toml::value_t::array>("[\n 1,\n 2,\n ]", (toml::array{1, 2}), comments(), make_format(toml::array_format::multiline, toml::indent_char::space, 2, 2), ctx);
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<toml::value>, "[3,1,4,1,5,]", a); toml11_test_parse_success<toml::value_t::array>("[\n\t1,\n\t2,\n]", (toml::array{1, 2}), comments(), make_format(toml::array_format::multiline, toml::indent_char::tab, 1, 0), ctx);
} toml11_test_parse_success<toml::value_t::array>("[\n\t1,\n\t2,\n\t]", (toml::array{1, 2}), comments(), make_format(toml::array_format::multiline, toml::indent_char::tab, 1, 1), ctx);
{
array a(3); // comment 3 is before comma, so is a comment for `2`.
a[0] = toml::value("foo"); a[1] = toml::value("bar"); toml11_test_parse_success<toml::value_t::array>(R"([
a[2] = toml::value("baz"); 1, # comment 1
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<toml::value>, "[\"foo\", \"bar\", \"baz\",]", a); 2, # comment 2
} # comment 3
# comment 4
# comment 5
])",
(toml::array{
toml::value(1, comments("# comment 1")),
toml::value(2, comments("# comment 2")),
}), comments(), make_format(toml::array_format::multiline, toml::indent_char::space, 4, 0), ctx);
// comment 3 is before comma, so is a comment for `2`.
toml11_test_parse_success<toml::value_t::array>(R"([
1, # comment 1
2, # comment 2
# comment 3
# comment 4
# comment 5
])",
(toml::array{
toml::value(1, comments("# comment 1")),
toml::value(2, comments("# comment 2")),
}), comments(), make_format(toml::array_format::multiline, toml::indent_char::space, 4, 2), ctx);
// comment 3 is before comma, so is a comment for `2`.
toml11_test_parse_success<toml::value_t::array>(R"([1 # comment 1
, 2 # comment 2
# comment 3
, # comment 4
# comment 5 (free comment)
])",
(toml::array{
toml::value(1, comments("# comment 1")),
toml::value(2, comments("# comment 2", "# comment 3", "# comment 4")),
}), comments(), make_format(toml::array_format::multiline, toml::indent_char::none, 4, 0), ctx);
toml11_test_parse_success<toml::value_t::array>(R"([1 # comment 1
, # comment 2
# comment 3
# ditto
# comment 4
2 # comment 5
# comment 6
, 3
# comment 7
])",
(toml::array{
toml::value(1, comments("# comment 1", "# comment 2")),
toml::value(2, comments("# comment 4", "# comment 5", "# comment 6")),
toml::value(3, comments("# comment 7")),
}), comments(), make_format(toml::array_format::multiline, toml::indent_char::none, 4, 0), ctx);
} }
BOOST_AUTO_TEST_CASE(test_oneline_array_value) TEST_CASE("testing invalid arrays")
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[]", toml::value(array())); using namespace toml::detail;
{ {
array a(5); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); auto loc = toml::detail::make_temporary_location("[ 1, hoge ]");
a[3] = toml::value(1); a[4] = toml::value(5); const auto res = parse_array(loc, ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,1,4,1,5]", toml::value(a)); CHECK_UNARY(res.is_err());
for(const auto& e : ctx.errors())
{
std::cerr << toml::format_error(e) << std::endl;
}
} }
{ {
array a(3); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
a[0] = toml::value("foo"); a[1] = toml::value("bar"); auto loc = toml::detail::make_temporary_location("[ 1, 2");
a[2] = toml::value("baz"); const auto res = parse_array(loc, ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", \"bar\", \"baz\"]", toml::value(a)); CHECK_UNARY(res.is_err());
ctx.report_error(res.unwrap_err());
for(const auto& e : ctx.errors())
{
std::cerr << toml::format_error(e) << std::endl;
}
} }
{ {
array a(5); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
a[0] = toml::value(3); a[1] = toml::value(1); a[2] = toml::value(4); auto loc = toml::detail::make_temporary_location("[");
a[3] = toml::value(1); a[4] = toml::value(5); const auto res = parse_array(loc, ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[3,1,4,1,5,]", toml::value(a)); CHECK_UNARY(res.is_err());
ctx.report_error(res.unwrap_err());
for(const auto& e : ctx.errors())
{
std::cerr << toml::format_error(e) << std::endl;
}
} }
{ {
array a(3); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
a[0] = toml::value("foo"); a[1] = toml::value("bar"); auto loc = toml::detail::make_temporary_location("[ 1, 2, 3\n a = b");
a[2] = toml::value("baz"); const auto res = parse_array(loc, ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", \"bar\", \"baz\",]", toml::value(a)); CHECK_UNARY(res.is_err());
ctx.report_error(res.unwrap_err());
for(const auto& e : ctx.errors())
{
std::cerr << toml::format_error(e) << std::endl;
}
} }
} }
BOOST_AUTO_TEST_CASE(test_multiline_array)
{
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value< discard_comments>>, "[\n#comment\n]", typename basic_value< discard_comments>::array_type());
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<preserve_comments>>, "[\n#comment\n]", typename basic_value<preserve_comments>::array_type());
{
typename basic_value<discard_comments>::array_type a(5);
a[0] = basic_value<discard_comments>(3);
a[1] = basic_value<discard_comments>(1);
a[2] = basic_value<discard_comments>(4);
a[3] = basic_value<discard_comments>(1);
a[4] = basic_value<discard_comments>(5);
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<discard_comments>>, "[3,\n1,\n4,\n1,\n5]", a);
}
{
typename basic_value<preserve_comments>::array_type a(5);
a[0] = basic_value<preserve_comments>(3);
a[1] = basic_value<preserve_comments>(1);
a[2] = basic_value<preserve_comments>(4);
a[3] = basic_value<preserve_comments>(1);
a[4] = basic_value<preserve_comments>(5);
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<preserve_comments>>, "[3,\n1,\n4,\n1,\n5]", a);
}
{
typename basic_value<discard_comments>::array_type a(5);
a[0] = basic_value<discard_comments>(3);
a[1] = basic_value<discard_comments>(1);
a[2] = basic_value<discard_comments>(4);
a[3] = basic_value<discard_comments>(1);
a[4] = basic_value<discard_comments>(5);
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<discard_comments>>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", a);
}
{
typename basic_value<preserve_comments>::array_type a(5);
a[0] = basic_value<preserve_comments>(3, {"comment"});
a[1] = basic_value<preserve_comments>(1, {"comment"});
a[2] = basic_value<preserve_comments>(4, {"comment"});
a[3] = basic_value<preserve_comments>(1, {"comment"});
a[4] = basic_value<preserve_comments>(5, {"comment"});
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<preserve_comments>>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", a);
}
{
typename basic_value<discard_comments>::array_type a(3);
a[0] = basic_value<discard_comments>("foo");
a[1] = basic_value<discard_comments>("bar");
a[2] = basic_value<discard_comments>("baz");
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<discard_comments>>, "[\"foo\",\n\"bar\",\n\"baz\"]", a);
}
{
typename basic_value<preserve_comments>::array_type a(3);
a[0] = basic_value<preserve_comments>("foo");
a[1] = basic_value<preserve_comments>("bar");
a[2] = basic_value<preserve_comments>("baz");
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<preserve_comments>>, "[\"foo\",\n\"bar\",\n\"baz\"]", a);
}
{
typename basic_value<discard_comments>::array_type a(3);
a[0] = basic_value<discard_comments>("foo");
a[1] = basic_value<discard_comments>("b#r");
a[2] = basic_value<discard_comments>("b#z");
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<discard_comments>>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a);
}
{
typename basic_value<preserve_comments>::array_type a(3);
a[0] = basic_value<preserve_comments>("foo", {"comment"});
a[1] = basic_value<preserve_comments>("b#r", {"comment"});
a[2] = basic_value<preserve_comments>("b#z", {"comment"});
TOML11_TEST_PARSE_EQUAL_VAT(parse_array<basic_value<preserve_comments>>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", a);
}
}
BOOST_AUTO_TEST_CASE(test_multiline_array_value)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value< discard_comments>>, "[\n#comment\n]", basic_value< discard_comments>(typename basic_value< discard_comments>::array_type()));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>, "[\n#comment\n]", basic_value<preserve_comments>(typename basic_value<preserve_comments>::array_type()));
{
typename basic_value<discard_comments>::array_type a(5);
a[0] = basic_value<discard_comments>(3);
a[1] = basic_value<discard_comments>(1);
a[2] = basic_value<discard_comments>(4);
a[3] = basic_value<discard_comments>(1);
a[4] = basic_value<discard_comments>(5);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<discard_comments>>, "[3,\n1,\n4,\n1,\n5]", basic_value<discard_comments>(a));
}
{
typename basic_value<preserve_comments>::array_type a(5);
a[0] = basic_value<preserve_comments>(3);
a[1] = basic_value<preserve_comments>(1);
a[2] = basic_value<preserve_comments>(4);
a[3] = basic_value<preserve_comments>(1);
a[4] = basic_value<preserve_comments>(5);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>, "[3,\n1,\n4,\n1,\n5]", basic_value<preserve_comments>(a));
}
{
typename basic_value<discard_comments>::array_type a(5);
a[0] = basic_value<discard_comments>(3);
a[1] = basic_value<discard_comments>(1);
a[2] = basic_value<discard_comments>(4);
a[3] = basic_value<discard_comments>(1);
a[4] = basic_value<discard_comments>(5);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<discard_comments>>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", basic_value<discard_comments>(a));
}
{
typename basic_value<preserve_comments>::array_type a(5);
a[0] = basic_value<preserve_comments>(3, {"comment"});
a[1] = basic_value<preserve_comments>(1, {"comment"});
a[2] = basic_value<preserve_comments>(4, {"comment"});
a[3] = basic_value<preserve_comments>(1, {"comment"});
a[4] = basic_value<preserve_comments>(5, {"comment"});
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>, "[3,#comment\n1,#comment\n4,#comment\n1,#comment\n5 #comment\n]", basic_value<preserve_comments>(a));
}
{
typename basic_value<discard_comments>::array_type a(3);
a[0] = basic_value<discard_comments>("foo");
a[1] = basic_value<discard_comments>("bar");
a[2] = basic_value<discard_comments>("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<discard_comments>>, "[\"foo\",\n\"bar\",\n\"baz\"]", basic_value<discard_comments>(a));
}
{
typename basic_value<preserve_comments>::array_type a(3);
a[0] = basic_value<preserve_comments>("foo");
a[1] = basic_value<preserve_comments>("bar");
a[2] = basic_value<preserve_comments>("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>, "[\"foo\",\n\"bar\",\n\"baz\"]", basic_value<preserve_comments>(a));
}
{
typename basic_value<discard_comments>::array_type a(3);
a[0] = basic_value<discard_comments>("foo");
a[1] = basic_value<discard_comments>("b#r");
a[2] = basic_value<discard_comments>("b#z");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<discard_comments>>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", basic_value<discard_comments>(a));
}
{
typename basic_value<preserve_comments>::array_type a(3);
a[0] = basic_value<preserve_comments>("foo", {"comment"});
a[1] = basic_value<preserve_comments>("b#r", {"comment"});
a[2] = basic_value<preserve_comments>("b#z", {"comment"});
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>, "[\"foo\",#comment\n\"b#r\",#comment\n\"b#z\"#comment\n]", basic_value<preserve_comments>(a));
}
}
BOOST_AUTO_TEST_CASE(test_heterogeneous_array)
{
#ifndef TOML11_USE_UNRELEASED_TOML_FEATURES
BOOST_TEST_MESSAGE("In strict TOML v0.5.0, heterogeneous arrays are not allowed.");
#else
{
array a(5);
a[0] = toml::value("foo");
a[1] = toml::value(3.14);
a[2] = toml::value(42);
a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
a[4] = toml::value{{"key", "value"}};
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\", 3.14, 42, [\"array\", \"of\", \"hetero-array\", 1], {key = \"value\"}]", toml::value(a));
}
{
array a(5);
a[0] = toml::value("foo");
a[1] = toml::value(3.14);
a[2] = toml::value(42);
a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
a[4] = toml::value{{"key", "value"}};
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",\n 3.14,\n 42,\n [\"array\", \"of\", \"hetero-array\", 1],\n {key = \"value\"},\n]", toml::value(a));
}
{
array a(5);
a[0] = toml::value("foo");
a[1] = toml::value(3.14);
a[2] = toml::value(42);
a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
a[4] = toml::value{{"key", "value"}};
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",#comment\n 3.14,#comment\n 42,#comment\n [\"array\", \"of\", \"hetero-array\", 1],#comment\n {key = \"value\"},#comment\n]#comment", toml::value(a));
}
{
array a(5);
a[0] = toml::value("foo");
a[1] = toml::value(3.14);
a[2] = toml::value(42);
a[3] = toml::value{toml::value("array"), toml::value("of"), toml::value("hetero-array"), toml::value(1)};
a[4] = toml::value{{"key", "value"}};
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "[\"foo\",\n 3.14,\n 42,\n [\"array\",\n \"of\",\n \"hetero-array\",\n 1],\n {key = \"value\"},\n]", toml::value(a));
}
#endif
}
BOOST_AUTO_TEST_CASE(test_comments_after_comma)
{
{
typename basic_value<discard_comments>::array_type a(3);
a[0] = basic_value<discard_comments>("foo");
a[1] = basic_value<discard_comments>("bar");
a[2] = basic_value<discard_comments>("baz");
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<discard_comments>>,
"[ \"foo\" # comment\n"
", \"bar\" # comment\n"
", \"baz\" # comment\n"
"]", basic_value<discard_comments>(a));
}
{
typename basic_value<preserve_comments>::array_type a(3);
a[0] = basic_value<preserve_comments>("foo", {" comment"});
a[1] = basic_value<preserve_comments>("bar", {" comment"});
a[2] = basic_value<preserve_comments>("baz", {" comment"});
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<basic_value<preserve_comments>>,
"[ \"foo\" # comment\n"
", \"bar\" # comment\n"
", \"baz\" # comment\n"
"]", basic_value<preserve_comments>(a));
}
}

View File

@@ -1,54 +0,0 @@
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <toml.hpp>
// some of the parsers returns not only a value but also a region.
#define TOML11_TEST_PARSE_EQUAL(psr, tkn, expct) \
do { \
const std::string token(tkn); \
toml::detail::location loc("test", token); \
const auto result = psr(loc); \
BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \
BOOST_TEST(result.unwrap().first == expct); \
} else { \
std::cerr << "parser " << #psr << " failed with input `"; \
std::cerr << token << "`.\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \
} while(false); \
/**/
#define TOML11_TEST_PARSE_EQUAL_VAT(psr, tkn, expct) \
do { \
const std::string token(tkn); \
toml::detail::location loc("test", token); \
const auto result = psr(loc, 0); \
BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \
BOOST_TEST(result.unwrap().first == expct); \
} else { \
std::cerr << "parser " << #psr << " failed with input `"; \
std::cerr << token << "`.\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \
} while(false); \
/**/
#define TOML11_TEST_PARSE_EQUAL_VALUE(psr, tkn, expct) \
do { \
const std::string token(tkn); \
toml::detail::location loc("test", token); \
const auto result = psr(loc, 0); \
BOOST_TEST(result.is_ok()); \
if(result.is_ok()){ \
BOOST_TEST(result.unwrap() == expct); \
} else { \
std::cerr << "parse_value failed with input `"; \
std::cerr << token << "`.\n"; \
std::cerr << "reason: " << result.unwrap_err() << '\n'; \
} \
} while(false); \
/**/

View File

@@ -1,19 +1,44 @@
#include <toml/parser.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include "utility.hpp"
#include "test_parse_aux.hpp"
using namespace toml; #include <toml11/parser.hpp>
using namespace detail; #include <toml11/types.hpp>
BOOST_AUTO_TEST_CASE(test_boolean) TEST_CASE("testing valid boolean")
{ {
TOML11_TEST_PARSE_EQUAL(parse_boolean, "true", true); const toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL(parse_boolean, "false", false); {
auto loc = toml::detail::make_temporary_location("true");
const auto res = toml::detail::parse_boolean(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = res.unwrap();
REQUIRE_UNARY(val.is_boolean());
CHECK_EQ(val.as_boolean(), true);
}
{
auto loc = toml::detail::make_temporary_location("false");
const auto res = toml::detail::parse_boolean(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = res.unwrap();
REQUIRE_UNARY(val.is_boolean());
CHECK_EQ(val.as_boolean(), false);
}
} }
BOOST_AUTO_TEST_CASE(test_boolean_value) TEST_CASE("testing invalid boolean")
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "true", toml::value( true)); using namespace toml::detail;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "false", toml::value(false));
const context<toml::type_config> ctx(toml::spec::v(1,0,0));
toml11_test_parse_failure(parse_boolean<toml::type_config>, "True", ctx);
toml11_test_parse_failure(parse_boolean<toml::type_config>, "TRUE", ctx);
toml11_test_parse_failure(parse_boolean<toml::type_config>, "False", ctx);
toml11_test_parse_failure(parse_boolean<toml::type_config>, "FALSE", ctx);
} }

View File

@@ -1,246 +1,307 @@
#include <toml/parser.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include "utility.hpp"
#include "test_parse_aux.hpp"
using namespace toml; #include <toml11/parser.hpp>
using namespace detail;
BOOST_AUTO_TEST_CASE(test_time) TEST_CASE("testing offset_datetime")
{ {
TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00", toml::local_time(7, 32, 0)); const auto fmt = [](toml::datetime_delimiter_kind d, bool has_sec, std::size_t prec) {
TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.99", toml::local_time(7, 32, 0, 990, 0)); toml::offset_datetime_format_info f;
TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.999", toml::local_time(7, 32, 0, 999, 0)); f.delimiter = d;
TOML11_TEST_PARSE_EQUAL(parse_local_time, "07:32:00.999999", toml::local_time(7, 32, 0, 999, 999)); f.has_seconds = has_sec;
f.subsecond_precision = prec;
return f;
};
{
toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27T07:32:00Z",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)
),
toml::time_offset(0, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, true, 0), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27T07:32:00-07:00",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)
),
toml::time_offset(-7, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, true, 0), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27T07:32:00.999999-07:00",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 999)
),
toml::time_offset(-7, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, true, 6), ctx);
TOML11_TEST_PARSE_EQUAL(parse_local_time, "00:00:00.000000", toml::local_time( 0, 0, 0, 0, 0));
TOML11_TEST_PARSE_EQUAL(parse_local_time, "23:59:59.999999", toml::local_time(23, 59, 59, 999, 999)); toml11_test_parse_success<toml::value_t::offset_datetime>(
TOML11_TEST_PARSE_EQUAL(parse_local_time, "23:59:60.999999", toml::local_time(23, 59, 60, 999, 999)); // leap second "1979-05-27 07:32:00Z",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)
),
toml::time_offset(0, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::space, true, 0), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27 07:32:00-07:00",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)
),
toml::time_offset(-7, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::space, true, 0), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27 07:32:00.999999-07:00",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 999)
),
toml::time_offset(-7, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::space, true, 6), ctx);
}
{
auto spec = toml::spec::v(1,0,0);
spec.v1_1_0_make_seconds_optional = true;
toml::detail::context<toml::type_config> ctx(spec);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27T07:32Z",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)
),
toml::time_offset(0, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, false, 0), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27T07:32:00Z",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)
),
toml::time_offset(0, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, true, 0), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27T07:32:00-07:00",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)
),
toml::time_offset(-7, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, true, 0), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27T07:32:00.999999-07:00",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 999)
),
toml::time_offset(-7, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, true, 6), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27 07:32Z",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)
),
toml::time_offset(0, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::space, false, 0), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27 07:32:00Z",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)
),
toml::time_offset(0, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::space, true, 0), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27 07:32:00-07:00",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)
),
toml::time_offset(-7, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::space, true, 0), ctx);
toml11_test_parse_success<toml::value_t::offset_datetime>(
"1979-05-27 07:32:00.999999-07:00",
toml::offset_datetime(
toml::local_datetime(
toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 999)
),
toml::time_offset(-7, 0)
),
comments(), fmt(toml::datetime_delimiter_kind::space, true, 6), ctx);
}
} }
BOOST_AUTO_TEST_CASE(test_time_value) TEST_CASE("testing local_datetime")
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "07:32:00", toml::value(toml::local_time(7, 32, 0))); const auto fmt = [](toml::datetime_delimiter_kind d, bool has_sec, std::size_t prec) {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "07:32:00.99", toml::value(toml::local_time(7, 32, 0, 990, 0))); toml::local_datetime_format_info f;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "07:32:00.999", toml::value(toml::local_time(7, 32, 0, 999, 0))); f.delimiter = d;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "07:32:00.999999", toml::value(toml::local_time(7, 32, 0, 999, 999))); f.has_seconds = has_sec;
f.subsecond_precision = prec;
return f;
};
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "00:00:00.000000", toml::value(toml::local_time( 0, 0, 0, 0, 0))); {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "23:59:59.999999", toml::value(toml::local_time(23, 59, 59, 999, 999))); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
std::istringstream stream1(std::string("invalid-datetime = 24:00:00")); toml11_test_parse_success<toml::value_t::local_datetime>( "1979-05-27T07:32:00",
std::istringstream stream2(std::string("invalid-datetime = 00:60:00")); toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
std::istringstream stream3(std::string("invalid-datetime = 00:00:61")); toml::local_time(7, 32, 0)),
BOOST_CHECK_THROW(toml::parse(stream1), toml::syntax_error); comments(), fmt(toml::datetime_delimiter_kind::upper_T, true, 0), ctx);
BOOST_CHECK_THROW(toml::parse(stream2), toml::syntax_error); toml11_test_parse_success<toml::value_t::local_datetime>( "1979-05-27T07:32:00.9999",
BOOST_CHECK_THROW(toml::parse(stream3), toml::syntax_error); toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 900, 0)),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, true, 4), ctx);
toml11_test_parse_success<toml::value_t::local_datetime>( "1979-05-27 07:32:00",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)),
comments(), fmt(toml::datetime_delimiter_kind::space, true, 0), ctx);
toml11_test_parse_success<toml::value_t::local_datetime>( "1979-05-27 07:32:00.9999",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 900, 0)),
comments(), fmt(toml::datetime_delimiter_kind::space, true, 4), ctx);
}
{
auto spec = toml::spec::v(1,0,0);
spec.v1_1_0_make_seconds_optional = true;
toml::detail::context<toml::type_config> ctx(spec);
toml11_test_parse_success<toml::value_t::local_datetime>( "1979-05-27T07:32",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, false, 0), ctx);
toml11_test_parse_success<toml::value_t::local_datetime>( "1979-05-27T07:32:00",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, true, 0), ctx);
toml11_test_parse_success<toml::value_t::local_datetime>( "1979-05-27T07:32:00.9999",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 900, 0)),
comments(), fmt(toml::datetime_delimiter_kind::upper_T, true, 4), ctx);
toml11_test_parse_success<toml::value_t::local_datetime>( "1979-05-27 07:32",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)),
comments(), fmt(toml::datetime_delimiter_kind::space, false, 0), ctx);
toml11_test_parse_success<toml::value_t::local_datetime>( "1979-05-27 07:32:00",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0)),
comments(), fmt(toml::datetime_delimiter_kind::space, true, 0), ctx);
toml11_test_parse_success<toml::value_t::local_datetime>( "1979-05-27 07:32:00.9999",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 900, 0)),
comments(), fmt(toml::datetime_delimiter_kind::space, true, 4), ctx);
}
} }
BOOST_AUTO_TEST_CASE(test_date) TEST_CASE("testing local_date")
{ {
TOML11_TEST_PARSE_EQUAL(parse_local_date, "1979-05-27", toml::local_date(1979, toml::month_t::May, 27)); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-01-01", toml::local_date(2000, toml::month_t::Jan, 1)); toml11_test_parse_success<toml::value_t::local_date>("1979-05-27", toml::local_date(1979, toml::month_t::May, 27), comments(), toml::local_date_format_info{}, ctx);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-01-31", toml::local_date(2000, toml::month_t::Jan, 31)); toml11_test_parse_success<toml::value_t::local_date>("0979-12-27", toml::local_date( 979, toml::month_t::Dec, 27), comments(), toml::local_date_format_info{}, ctx);
std::istringstream stream1_1(std::string("invalid-datetime = 2000-01-00"));
std::istringstream stream1_2(std::string("invalid-datetime = 2000-01-32"));
BOOST_CHECK_THROW(toml::parse(stream1_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream1_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-02-01", toml::local_date(2000, toml::month_t::Feb, 1)); toml11_test_parse_failure(toml::detail::parse_local_date<toml::type_config>, "1979-00-27", ctx);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-02-29", toml::local_date(2000, toml::month_t::Feb, 29)); toml11_test_parse_failure(toml::detail::parse_local_date<toml::type_config>, "1979-13-27", ctx);
std::istringstream stream2_1(std::string("invalid-datetime = 2000-02-00")); toml11_test_parse_failure(toml::detail::parse_local_date<toml::type_config>, "1979-05-00", ctx);
std::istringstream stream2_2(std::string("invalid-datetime = 2000-02-30")); toml11_test_parse_failure(toml::detail::parse_local_date<toml::type_config>, "1979-05-32", ctx);
BOOST_CHECK_THROW(toml::parse(stream2_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream2_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2001-02-28", toml::local_date(2001, toml::month_t::Feb, 28)); toml11_test_parse_failure(toml::detail::parse_local_date<toml::type_config>, "1979-05-2", ctx);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2004-02-29", toml::local_date(2004, toml::month_t::Feb, 29)); toml11_test_parse_failure(toml::detail::parse_local_date<toml::type_config>, "1979-5-02", ctx);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2100-02-28", toml::local_date(2100, toml::month_t::Feb, 28)); toml11_test_parse_failure(toml::detail::parse_local_date<toml::type_config>, "1979-5-2", ctx);
std::istringstream stream2_3(std::string("invalid-datetime = 2001-02-29")); toml11_test_parse_failure(toml::detail::parse_local_date<toml::type_config>, "979-5-2", ctx);
std::istringstream stream2_4(std::string("invalid-datetime = 2004-02-30")); toml11_test_parse_failure(toml::detail::parse_local_date<toml::type_config>, "12345-05-27", ctx);
std::istringstream stream2_5(std::string("invalid-datetime = 2100-02-29"));
BOOST_CHECK_THROW(toml::parse(stream2_3), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream2_4), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream2_5), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-03-01", toml::local_date(2000, toml::month_t::Mar, 1));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-03-31", toml::local_date(2000, toml::month_t::Mar, 31));
std::istringstream stream3_1(std::string("invalid-datetime = 2000-03-00"));
std::istringstream stream3_2(std::string("invalid-datetime = 2000-03-32"));
BOOST_CHECK_THROW(toml::parse(stream3_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream3_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-04-01", toml::local_date(2000, toml::month_t::Apr, 1));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-04-30", toml::local_date(2000, toml::month_t::Apr, 30));
std::istringstream stream4_1(std::string("invalid-datetime = 2000-04-00"));
std::istringstream stream4_2(std::string("invalid-datetime = 2000-04-31"));
BOOST_CHECK_THROW(toml::parse(stream4_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream4_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-05-01", toml::local_date(2000, toml::month_t::May, 1));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-05-31", toml::local_date(2000, toml::month_t::May, 31));
std::istringstream stream5_1(std::string("invalid-datetime = 2000-05-00"));
std::istringstream stream5_2(std::string("invalid-datetime = 2000-05-32"));
BOOST_CHECK_THROW(toml::parse(stream5_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream5_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-06-01", toml::local_date(2000, toml::month_t::Jun, 1));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-06-30", toml::local_date(2000, toml::month_t::Jun, 30));
std::istringstream stream6_1(std::string("invalid-datetime = 2000-06-00"));
std::istringstream stream6_2(std::string("invalid-datetime = 2000-06-31"));
BOOST_CHECK_THROW(toml::parse(stream6_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream6_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-07-01", toml::local_date(2000, toml::month_t::Jul, 1));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-07-31", toml::local_date(2000, toml::month_t::Jul, 31));
std::istringstream stream7_1(std::string("invalid-datetime = 2000-07-00"));
std::istringstream stream7_2(std::string("invalid-datetime = 2000-07-32"));
BOOST_CHECK_THROW(toml::parse(stream7_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream7_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-08-01", toml::local_date(2000, toml::month_t::Aug, 1));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-08-31", toml::local_date(2000, toml::month_t::Aug, 31));
std::istringstream stream8_1(std::string("invalid-datetime = 2000-08-00"));
std::istringstream stream8_2(std::string("invalid-datetime = 2000-08-32"));
BOOST_CHECK_THROW(toml::parse(stream8_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream8_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-09-01", toml::local_date(2000, toml::month_t::Sep, 1));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-09-30", toml::local_date(2000, toml::month_t::Sep, 30));
std::istringstream stream9_1(std::string("invalid-datetime = 2000-09-00"));
std::istringstream stream9_2(std::string("invalid-datetime = 2000-09-31"));
BOOST_CHECK_THROW(toml::parse(stream9_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream9_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-10-01", toml::local_date(2000, toml::month_t::Oct, 1));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-10-31", toml::local_date(2000, toml::month_t::Oct, 31));
std::istringstream stream10_1(std::string("invalid-datetime = 2000-10-00"));
std::istringstream stream10_2(std::string("invalid-datetime = 2000-10-32"));
BOOST_CHECK_THROW(toml::parse(stream10_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream10_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-11-01", toml::local_date(2000, toml::month_t::Nov, 1));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-11-30", toml::local_date(2000, toml::month_t::Nov, 30));
std::istringstream stream11_1(std::string("invalid-datetime = 2000-11-00"));
std::istringstream stream11_2(std::string("invalid-datetime = 2000-11-31"));
BOOST_CHECK_THROW(toml::parse(stream11_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream11_2), toml::syntax_error);
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-12-01", toml::local_date(2000, toml::month_t::Dec, 1));
TOML11_TEST_PARSE_EQUAL(parse_local_date, "2000-12-31", toml::local_date(2000, toml::month_t::Dec, 31));
std::istringstream stream12_1(std::string("invalid-datetime = 2000-12-00"));
std::istringstream stream12_2(std::string("invalid-datetime = 2000-12-32"));
BOOST_CHECK_THROW(toml::parse(stream12_1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream12_2), toml::syntax_error);
std::istringstream stream13_1(std::string("invalid-datetime = 2000-13-01"));
BOOST_CHECK_THROW(toml::parse(stream13_1), toml::syntax_error);
std::istringstream stream0_1(std::string("invalid-datetime = 2000-00-01"));
BOOST_CHECK_THROW(toml::parse(stream0_1), toml::syntax_error);
} }
BOOST_AUTO_TEST_CASE(test_date_value) TEST_CASE("testing local_time")
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27", value(toml::local_date(1979, toml::month_t::May, 27))); const auto fmt = [](const bool has_sec, const std::size_t sec_prec) {
} toml::local_time_format_info f;
f.has_seconds = has_sec;
BOOST_AUTO_TEST_CASE(test_datetime) f.subsecond_precision = sec_prec;
{ return f;
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))); };
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00.99", {
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27T07:32:00.999999",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))); toml11_test_parse_success<toml::value_t::local_time>("01:02:03", toml::local_time(1, 2, 3), comments(), fmt(true, 0), ctx);
toml11_test_parse_success<toml::value_t::local_time>("01:23:45", toml::local_time(1, 23, 45), comments(), fmt(true, 0), ctx);
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00", toml11_test_parse_success<toml::value_t::local_time>("01:23:45.1", toml::local_time(1, 23, 45, 100), comments(), fmt(true, 1), ctx);
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))); toml11_test_parse_success<toml::value_t::local_time>("01:23:45.12", toml::local_time(1, 23, 45, 120), comments(), fmt(true, 2), ctx);
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00.99", toml11_test_parse_success<toml::value_t::local_time>("01:23:45.123", toml::local_time(1, 23, 45, 123), comments(), fmt(true, 3), ctx);
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))); toml11_test_parse_success<toml::value_t::local_time>("01:23:45.1234", toml::local_time(1, 23, 45, 123, 400), comments(), fmt(true, 4), ctx);
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27t07:32:00.999999", toml11_test_parse_success<toml::value_t::local_time>("01:23:45.1234567", toml::local_time(1, 23, 45, 123, 456, 700), comments(), fmt(true, 7), ctx);
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))); toml11_test_parse_success<toml::value_t::local_time>("01:23:45.123456789", toml::local_time(1, 23, 45, 123, 456, 789), comments(), fmt(true, 9), ctx);
}
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))); {
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00.99", auto spec = toml::spec::v(1,0,0);
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))); spec.v1_1_0_make_seconds_optional = true;
TOML11_TEST_PARSE_EQUAL(parse_local_datetime, "1979-05-27 07:32:00.999999",
toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))); toml::detail::context<toml::type_config> ctx(spec);
}
toml11_test_parse_success<toml::value_t::local_time>("01:23", toml::local_time(1, 23, 0), comments(), fmt(false, 0), ctx);
BOOST_AUTO_TEST_CASE(test_datetime_value) toml11_test_parse_success<toml::value_t::local_time>("01:02", toml::local_time(1, 2, 0), comments(), fmt(false, 0), ctx);
{ toml11_test_parse_success<toml::value_t::local_time>("01:02:03", toml::local_time(1, 2, 3), comments(), fmt(true, 0), ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00", toml11_test_parse_success<toml::value_t::local_time>("01:23:45", toml::local_time(1, 23, 45), comments(), fmt(true, 0), ctx);
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0)))); toml11_test_parse_success<toml::value_t::local_time>("01:23:45.1", toml::local_time(1, 23, 45, 100), comments(), fmt(true, 1), ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.99", toml11_test_parse_success<toml::value_t::local_time>("01:23:45.12", toml::local_time(1, 23, 45, 120), comments(), fmt(true, 2), ctx);
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0)))); toml11_test_parse_success<toml::value_t::local_time>("01:23:45.123", toml::local_time(1, 23, 45, 123), comments(), fmt(true, 3), ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.999999", toml11_test_parse_success<toml::value_t::local_time>("01:23:45.1234", toml::local_time(1, 23, 45, 123, 400), comments(), fmt(true, 4), ctx);
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999)))); toml11_test_parse_success<toml::value_t::local_time>("01:23:45.1234567", toml::local_time(1, 23, 45, 123, 456, 700), comments(), fmt(true, 7), ctx);
toml11_test_parse_success<toml::value_t::local_time>("01:23:45.123456789", toml::local_time(1, 23, 45, 123, 456, 789), comments(), fmt(true, 9), ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27t07:32:00", }
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27t07:32:00.99",
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27t07:32:00.999999",
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27 07:32:00",
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27 07:32:00.99",
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 990, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27 07:32:00.999999",
toml::value(toml::local_datetime(toml::local_date(1979, toml::month_t::May, 27), toml::local_time(7, 32, 0, 999, 999))));
}
BOOST_AUTO_TEST_CASE(test_offset_datetime)
{
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00Z",
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0)));
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.99Z",
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 990, 0), toml::time_offset(0, 0)));
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.999999Z",
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 999), toml::time_offset(0, 0)));
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00+09:00",
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(9, 0)));
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.99+09:00",
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 990, 0), toml::time_offset(9, 0)));
TOML11_TEST_PARSE_EQUAL(parse_offset_datetime, "1979-05-27T07:32:00.999999+09:00",
toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0)));
std::istringstream stream1(std::string("invalid-datetime = 2000-01-01T00:00:00+24:00"));
std::istringstream stream2(std::string("invalid-datetime = 2000-01-01T00:00:00+00:60"));
BOOST_CHECK_THROW(toml::parse(stream1), toml::syntax_error);
BOOST_CHECK_THROW(toml::parse(stream2), toml::syntax_error);
}
BOOST_AUTO_TEST_CASE(test_offset_datetime_value)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00Z",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(0, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.99Z",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 990, 0), toml::time_offset(0, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.999999Z",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 999), toml::time_offset(0, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00+09:00",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0), toml::time_offset(9, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.99+09:00",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 990, 0), toml::time_offset(9, 0))));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1979-05-27T07:32:00.999999+09:00",
toml::value(toml::offset_datetime(toml::local_date(1979, toml::month_t::May, 27),
toml::local_time(7, 32, 0, 999, 999), toml::time_offset(9, 0))));
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,181 +1,167 @@
#include <toml/parser.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include "utility.hpp"
#include "test_parse_aux.hpp"
#include <cmath> #include <toml11/parser.hpp>
#include <toml11/types.hpp>
using namespace toml; TEST_CASE("testing fractional float")
using namespace detail;
BOOST_AUTO_TEST_CASE(test_fractional)
{ {
TOML11_TEST_PARSE_EQUAL(parse_floating, "1.0", 1.0); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL(parse_floating, "0.1", 0.1);
TOML11_TEST_PARSE_EQUAL(parse_floating, "0.001", 0.001); auto fmt = [](std::size_t prec) {
TOML11_TEST_PARSE_EQUAL(parse_floating, "0.100", 0.1); toml::floating_format_info f;
TOML11_TEST_PARSE_EQUAL(parse_floating, "+3.14", 3.14); f.fmt = toml::floating_format::fixed;
TOML11_TEST_PARSE_EQUAL(parse_floating, "-3.14", -3.14); f.prec = prec;
TOML11_TEST_PARSE_EQUAL(parse_floating, "3.1415_9265_3589", 3.141592653589); return f;
TOML11_TEST_PARSE_EQUAL(parse_floating, "+3.1415_9265_3589", 3.141592653589); };
TOML11_TEST_PARSE_EQUAL(parse_floating, "-3.1415_9265_3589", -3.141592653589);
TOML11_TEST_PARSE_EQUAL(parse_floating, "123_456.789", 123456.789); toml11_test_parse_success<toml::value_t::floating>("1.0", 1.0 , comments(), fmt( 1), ctx);
TOML11_TEST_PARSE_EQUAL(parse_floating, "+123_456.789", 123456.789); toml11_test_parse_success<toml::value_t::floating>("0.1", 0.1 , comments(), fmt( 1), ctx);
TOML11_TEST_PARSE_EQUAL(parse_floating, "-123_456.789", -123456.789); toml11_test_parse_success<toml::value_t::floating>("0.001", 0.001 , comments(), fmt( 3), ctx);
TOML11_TEST_PARSE_EQUAL(parse_floating, "+0.0", 0.0); toml11_test_parse_success<toml::value_t::floating>("0.100", 0.1 , comments(), fmt( 3), ctx);
TOML11_TEST_PARSE_EQUAL(parse_floating, "-0.0", -0.0); toml11_test_parse_success<toml::value_t::floating>("+3.14", 3.14 , comments(), fmt( 2), ctx);
toml11_test_parse_success<toml::value_t::floating>("-3.14", -3.14 , comments(), fmt( 2), ctx);
toml11_test_parse_success<toml::value_t::floating>("3.1415_9265_3589", 3.141592653589, comments(), fmt(12), ctx);
toml11_test_parse_success<toml::value_t::floating>("+3.1415_9265_3589", 3.141592653589, comments(), fmt(12), ctx);
toml11_test_parse_success<toml::value_t::floating>("-3.1415_9265_3589", -3.141592653589, comments(), fmt(12), ctx);
toml11_test_parse_success<toml::value_t::floating>("123_456.789", 123456.789 , comments(), fmt( 3), ctx);
toml11_test_parse_success<toml::value_t::floating>("+123_456.789", 123456.789 , comments(), fmt( 3), ctx);
toml11_test_parse_success<toml::value_t::floating>("-123_456.789", -123456.789 , comments(), fmt( 3), ctx);
toml11_test_parse_success<toml::value_t::floating>("+0.0", 0.0 , comments(), fmt( 1), ctx);
toml11_test_parse_success<toml::value_t::floating>("-0.0", -0.0 , comments(), fmt( 1), ctx);
} }
BOOST_AUTO_TEST_CASE(test_fractional_value) TEST_CASE("testing exponents")
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.0", value( 1.0)); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0.1", value( 0.1));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0.001", value( 0.001)); auto fmt = [](std::size_t prec) {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0.100", value( 0.1)); toml::floating_format_info f;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+3.14", value( 3.14)); f.fmt = toml::floating_format::scientific;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-3.14", value(-3.14)); f.prec = prec;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "3.1415_9265_3589", value( 3.141592653589)); return f;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+3.1415_9265_3589", value( 3.141592653589)); };
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-3.1415_9265_3589", value(-3.141592653589));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123_456.789", value( 123456.789)); toml11_test_parse_success<toml::value_t::floating>("1e10", 1e10 , comments(), fmt(1), ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+123_456.789", value( 123456.789)); toml11_test_parse_success<toml::value_t::floating>("1e+10", 1e10 , comments(), fmt(1), ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-123_456.789", value(-123456.789)); toml11_test_parse_success<toml::value_t::floating>("1e-10", 1e-10 , comments(), fmt(1), ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+0.0", value( 0.0)); toml11_test_parse_success<toml::value_t::floating>("+1e10", 1e10 , comments(), fmt(1), ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0.0", value(-0.0)); toml11_test_parse_success<toml::value_t::floating>("+1e+10", 1e10 , comments(), fmt(1), ctx);
toml11_test_parse_success<toml::value_t::floating>("+1e-10", 1e-10 , comments(), fmt(1), ctx);
toml11_test_parse_success<toml::value_t::floating>("-1e10", -1e10 , comments(), fmt(1), ctx);
toml11_test_parse_success<toml::value_t::floating>("-1e+10", -1e10 , comments(), fmt(1), ctx);
toml11_test_parse_success<toml::value_t::floating>("-1e-10", -1e-10 , comments(), fmt(1), ctx);
toml11_test_parse_success<toml::value_t::floating>("123e-10", 123e-10, comments(), fmt(3), ctx);
toml11_test_parse_success<toml::value_t::floating>("1E10", 1e10 , comments(), fmt(1), ctx);
toml11_test_parse_success<toml::value_t::floating>("1E+10", 1e10 , comments(), fmt(1), ctx);
toml11_test_parse_success<toml::value_t::floating>("1E-10", 1e-10 , comments(), fmt(1), ctx);
toml11_test_parse_success<toml::value_t::floating>("123E-10", 123e-10, comments(), fmt(3), ctx);
toml11_test_parse_success<toml::value_t::floating>("1_2_3E-10", 123e-10, comments(), fmt(3), ctx);
toml11_test_parse_success<toml::value_t::floating>("1_2_3E-1_0", 123e-10, comments(), fmt(3), ctx);
toml11_test_parse_success<toml::value_t::floating>("+0e0", 0.0 , comments(), fmt(1), ctx);
toml11_test_parse_success<toml::value_t::floating>("-0e0", -0.0 , comments(), fmt(1), ctx);
} }
BOOST_AUTO_TEST_CASE(test_exponential) TEST_CASE("testing fraction + exponents")
{ {
TOML11_TEST_PARSE_EQUAL(parse_floating, "1e10", 1e10); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL(parse_floating, "1e+10", 1e10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "1e-10", 1e-10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e10", 1e10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e+10", 1e10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "+1e-10", 1e-10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e10", -1e10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e+10", -1e10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "-1e-10", -1e-10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "123e-10", 123e-10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "1E10", 1e10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "1E+10", 1e10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "1E-10", 1e-10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "123E-10", 123e-10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-10", 123e-10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-1_0", 123e-10);
TOML11_TEST_PARSE_EQUAL(parse_floating, "+0e0", 0.0);
TOML11_TEST_PARSE_EQUAL(parse_floating, "-0e0", -0.0);
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES auto fmt = [](std::size_t prec) {
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part"); toml::floating_format_info f;
// toml-lang/toml master permits leading 0s in exp part (unreleased) f.fmt = toml::floating_format::scientific;
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-01", 123e-1); f.prec = prec;
TOML11_TEST_PARSE_EQUAL(parse_floating, "1_2_3E-0_1", 123e-1); return f;
#endif };
toml11_test_parse_success<toml::value_t::floating>("6.02e23", 6.02e23, comments(), fmt(3), ctx);
toml11_test_parse_success<toml::value_t::floating>("6.02e+23", 6.02e23, comments(), fmt(3), ctx);
toml11_test_parse_success<toml::value_t::floating>("1.112_650_06e-17", 1.11265006e-17, comments(), fmt(9), ctx);
} }
BOOST_AUTO_TEST_CASE(test_exponential_value) TEST_CASE("testing +/-inf")
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e10", value(1e10)); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1e-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1e-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e10", value(-1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e+10", value(-1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1e-10", value(-1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123e-10", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E+10", value(1e10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1E-10", value(1e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123E-10", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-10", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-1_0", value(123e-10));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+0e0", value( 0.0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-0e0", value(-0.0));
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
// toml-lang/toml master permits leading 0s in exp part (unreleased)
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-01", value(123e-1));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3E-0_1", value(123e-1));
#endif
}
BOOST_AUTO_TEST_CASE(test_fe)
{
TOML11_TEST_PARSE_EQUAL(parse_floating, "6.02e23", 6.02e23);
TOML11_TEST_PARSE_EQUAL(parse_floating, "6.02e+23", 6.02e23);
TOML11_TEST_PARSE_EQUAL(parse_floating, "1.112_650_06e-17", 1.11265006e-17);
}
BOOST_AUTO_TEST_CASE(test_fe_vaule)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e23", value(6.02e23));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "6.02e+23", value(6.02e23));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1.112_650_06e-17", value(1.11265006e-17));
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
BOOST_TEST_MESSAGE("testing an unreleased toml feature: leading zeroes in float exponent part");
// toml-lang/toml master permits leading 0s in exp part (unreleased)
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "3.141_5e-01", value(3.1415e-1));
#endif
}
BOOST_AUTO_TEST_CASE(test_inf)
{
{ {
const std::string token("inf"); auto loc = toml::detail::make_temporary_location("inf");
toml::detail::location loc("test", token); const auto res = toml::detail::parse_floating(loc, ctx);
const auto r = parse_floating(loc); REQUIRE_UNARY(res.is_ok());
BOOST_CHECK(r.is_ok()); const auto val = res.unwrap();
BOOST_CHECK(std::isinf(r.unwrap().first)); REQUIRE_UNARY(val.is_floating());
BOOST_CHECK(r.unwrap().first > 0.0);
CHECK_UNARY(std::isinf(val.as_floating()));
CHECK_UNARY(val.as_floating() > 0); // +
} }
{ {
const std::string token("+inf"); auto loc = toml::detail::make_temporary_location("+inf");
toml::detail::location loc("test", token); const auto res = toml::detail::parse_floating(loc, ctx);
const auto r = parse_floating(loc); REQUIRE_UNARY(res.is_ok());
BOOST_CHECK(r.is_ok()); const auto val = res.unwrap();
BOOST_CHECK(std::isinf(r.unwrap().first)); REQUIRE_UNARY(val.is_floating());
BOOST_CHECK(r.unwrap().first > 0.0);
CHECK_UNARY(std::isinf(val.as_floating()));
CHECK_UNARY(val.as_floating() > 0); // +
} }
{ {
const std::string token("-inf"); auto loc = toml::detail::make_temporary_location("-inf");
toml::detail::location loc("test", token); const auto res = toml::detail::parse_floating(loc, ctx);
const auto r = parse_floating(loc); REQUIRE_UNARY(res.is_ok());
BOOST_CHECK(r.is_ok()); const auto val = res.unwrap();
BOOST_CHECK(std::isinf(r.unwrap().first)); REQUIRE_UNARY(val.is_floating());
BOOST_CHECK(r.unwrap().first < 0.0);
CHECK_UNARY(std::isinf(val.as_floating()));
CHECK_UNARY(val.as_floating() < 0); // -
} }
} }
BOOST_AUTO_TEST_CASE(test_nan) TEST_CASE("testing +/-nan")
{ {
toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
{ {
const std::string token("nan"); auto loc = toml::detail::make_temporary_location("nan");
toml::detail::location loc("test", token); const auto res = toml::detail::parse_floating(loc, ctx);
const auto r = parse_floating(loc); REQUIRE_UNARY(res.is_ok());
BOOST_CHECK(r.is_ok()); const auto val = res.unwrap();
BOOST_CHECK(std::isnan(r.unwrap().first)); REQUIRE_UNARY(val.is_floating());
CHECK_UNARY(std::isnan(val.as_floating()));
} }
{ {
const std::string token("+nan"); auto loc = toml::detail::make_temporary_location("+nan");
toml::detail::location loc("test", token); const auto res = toml::detail::parse_floating(loc, ctx);
const auto r = parse_floating(loc); REQUIRE_UNARY(res.is_ok());
BOOST_CHECK(r.is_ok()); const auto val = res.unwrap();
BOOST_CHECK(std::isnan(r.unwrap().first)); REQUIRE_UNARY(val.is_floating());
CHECK_UNARY(std::isnan(val.as_floating()));
} }
{ {
const std::string token("-nan"); auto loc = toml::detail::make_temporary_location("-nan");
toml::detail::location loc("test", token); const auto res = toml::detail::parse_floating(loc, ctx);
const auto r = parse_floating(loc); REQUIRE_UNARY(res.is_ok());
BOOST_CHECK(r.is_ok()); const auto val = res.unwrap();
BOOST_CHECK(std::isnan(r.unwrap().first)); REQUIRE_UNARY(val.is_floating());
CHECK_UNARY(std::isnan(val.as_floating()));
} }
} }
BOOST_AUTO_TEST_CASE(test_overflow) TEST_CASE("testing hexfloat")
{ {
std::istringstream float_overflow (std::string("float-overflow = 1.0e+1024")); toml::spec s = toml::spec::v(1,0,0);
BOOST_CHECK_THROW(toml::parse(float_overflow ), toml::syntax_error); s.ext_hex_float = true;
// istringstream >> float does not set failbit in case of underflow. toml::detail::context<toml::type_config> ctx(s);
{
auto loc = toml::detail::make_temporary_location("0xABCp-3");
const auto res = toml::detail::parse_floating(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = res.unwrap();
REQUIRE_UNARY(val.is_floating());
CHECK_EQ(val.as_floating(), 343.5);
}
} }

View File

@@ -1,59 +1,142 @@
#include <toml/parser.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "unit_test.hpp" #include <iostream>
#include "test_parse_aux.hpp" #include "utility.hpp"
#include <toml11/parser.hpp>
#include <toml11/types.hpp>
using namespace toml; #include "doctest.h"
using namespace detail;
BOOST_AUTO_TEST_CASE(test_inline_table) TEST_CASE("testing an inline table v1.0")
{ {
TOML11_TEST_PARSE_EQUAL_VAT(parse_inline_table<toml::value>, "{}", table());
{ {
table t; // no multiline, no trailing comma
t["foo"] = toml::value(42); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
t["bar"] = toml::value("baz");
TOML11_TEST_PARSE_EQUAL_VAT(parse_inline_table<toml::value>, "{foo = 42, bar = \"baz\"}", t); const auto make_format = [](toml::table_format ty) {
toml::table_format_info fmt;
fmt.fmt = ty;
fmt.indent_type = toml::indent_char::none;
return fmt;
};
toml11_test_parse_success<toml::value_t::table>("{}", (toml::table{}), comments(), make_format(toml::table_format::oneline), ctx);
toml11_test_parse_success<toml::value_t::table>("{a = 1}", (toml::table{{"a", 1}}), comments(), make_format(toml::table_format::oneline), ctx);
toml11_test_parse_success<toml::value_t::table>("{a = 1, b = 2}", (toml::table{{"a", 1}, {"b", 2}}), comments(), make_format(toml::table_format::oneline), ctx);
toml11_test_parse_success<toml::value_t::table>("{a.b = 1}", (toml::table{{ "a", toml::table{{"b", 1}} }}), comments(), make_format(toml::table_format::oneline), ctx);
toml11_test_parse_success<toml::value_t::table>("{a.b = 1, a.c = 2}", (toml::table{{ "a", toml::table{{"b", 1}, {"c", 2}} }}), comments(), make_format(toml::table_format::oneline), ctx);
} }
// invalids
{ {
table t; using toml::detail::parse_inline_table;
table t_sub; toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
t_sub["name"] = toml::value("pug"); toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ 1, 2 }", ctx); // no key
t["type"] = toml::value(t_sub); toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a = 1, b = 2, }", ctx); // trailing comma
TOML11_TEST_PARSE_EQUAL_VAT(parse_inline_table<toml::value>, "{type.name = \"pug\"}", t); toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a = 1, b = 2", ctx); // no closing bracket
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{", ctx); // no closing bracket
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a = 1, b = 2\n a = b", ctx); // no closing bracket
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a.b = 1, a.b.c = 2}", ctx); // a.b is not a table
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a = 1 # comment\n}", ctx); // newline not allowed
} }
} }
BOOST_AUTO_TEST_CASE(test_inline_table_value) TEST_CASE("testing an inline table v1.0 + trailing comma")
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{}", value(table()));
{ {
table t; // no multiline, no trailing comma
t["foo"] = toml::value(42); auto spec = toml::spec::v(1,0,0);
t["bar"] = toml::value("baz"); spec.v1_1_0_allow_trailing_comma_in_inline_tables = true;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{foo = 42, bar = \"baz\"}", value(t)); toml::detail::context<toml::type_config> ctx(spec);
const auto make_format = [](toml::table_format ty) {
toml::table_format_info fmt;
fmt.fmt = ty;
fmt.indent_type = toml::indent_char::none;
return fmt;
};
toml11_test_parse_success<toml::value_t::table>("{}", (toml::table{}), comments(), make_format(toml::table_format::oneline), ctx);
toml11_test_parse_success<toml::value_t::table>("{a = 1}", (toml::table{{"a", 1}}), comments(), make_format(toml::table_format::oneline), ctx);
toml11_test_parse_success<toml::value_t::table>("{a = 1,}", (toml::table{{"a", 1}}), comments(), make_format(toml::table_format::oneline), ctx);
toml11_test_parse_success<toml::value_t::table>("{a = 1, b = 2,}", (toml::table{{"a", 1}, {"b", 2}}), comments(), make_format(toml::table_format::oneline), ctx);
toml11_test_parse_success<toml::value_t::table>("{a.b = 1}", (toml::table{{ "a", toml::table{{"b", 1}} }}), comments(), make_format(toml::table_format::oneline), ctx);
toml11_test_parse_success<toml::value_t::table>("{a.b = 1, a.c = 2}", (toml::table{{ "a", toml::table{{"b", 1}, {"c", 2}} }}), comments(), make_format(toml::table_format::oneline), ctx);
} }
// invalids
{ {
table t; using toml::detail::parse_inline_table;
table t_sub;
t_sub["name"] = toml::value("pug"); auto spec = toml::spec::v(1,0,0);
t["type"] = toml::value(t_sub); spec.v1_1_0_allow_trailing_comma_in_inline_tables = true;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "{type.name = \"pug\"}", value(t)); toml::detail::context<toml::type_config> ctx(spec);
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ 1, 2 }", ctx);
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a = 1, b = 2", ctx);
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{", ctx);
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a = 1, b = 2\n a = b", ctx);
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a.b = 1, a.b.c = 2}", ctx);
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a = 1 # comment\n}", ctx);
} }
} }
BOOST_AUTO_TEST_CASE(test_inline_table_immutability) TEST_CASE("testing an inline table v1.1")
{ {
{ {
std::istringstream stream(std::string( // w/ multiline, w/ trailing comma
"a = {b = 1}\n" toml::detail::context<toml::type_config> ctx(toml::spec::v(1,1,0));
"a.c = 2\n"));
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); const auto make_format = [](toml::table_format ty,
const toml::indent_char ic,
const std::int32_t n,
const std::int32_t b,
const std::int32_t c
) {
toml::table_format_info fmt;
fmt.fmt = ty;
fmt.indent_type = ic;
fmt.name_indent = n;
fmt.body_indent = b;
fmt.closing_indent = c;
return fmt;
};
toml11_test_parse_success<toml::value_t::table>("{}", (toml::table{}), comments(), make_format(toml::table_format::oneline, toml::indent_char::none,0,0,0), ctx);
toml11_test_parse_success<toml::value_t::table>("{a = 1}", (toml::table{{"a", 1}}), comments(), make_format(toml::table_format::oneline, toml::indent_char::none,0,0,0), ctx);
toml11_test_parse_success<toml::value_t::table>("{a = 1, b = 2}", (toml::table{{"a", 1}, {"b", 2}}), comments(), make_format(toml::table_format::oneline, toml::indent_char::none,0,0,0), ctx);
toml11_test_parse_success<toml::value_t::table>("{a.b = 1}", (toml::table{{ "a", toml::table{{"b", 1}} }}), comments(), make_format(toml::table_format::oneline, toml::indent_char::none,0,0,0), ctx);
toml11_test_parse_success<toml::value_t::table>("{a.b = 1, a.c = 2}", (toml::table{{ "a", toml::table{{"b", 1}, {"c", 2}} }}), comments(), make_format(toml::table_format::oneline, toml::indent_char::none,0,0,0), ctx);
toml11_test_parse_success<toml::value_t::table>("{\n}", (toml::table{}), comments(), make_format(toml::table_format::multiline_oneline, toml::indent_char::none,0,0,0), ctx);
toml11_test_parse_success<toml::value_t::table>("{\na = 1\n}", (toml::table{{"a", 1}}), comments(), make_format(toml::table_format::multiline_oneline, toml::indent_char::none,0,0,0), ctx);
toml11_test_parse_success<toml::value_t::table>("{\n a = 1, \n b = 2\n}", (toml::table{{"a", 1}, {"b", 2}}), comments(), make_format(toml::table_format::multiline_oneline, toml::indent_char::space, 0, 2, 0), ctx);
toml11_test_parse_success<toml::value_t::table>("{\n a.b = 1\n }", (toml::table{{ "a", toml::table{{"b", 1}} }}), comments(), make_format(toml::table_format::multiline_oneline, toml::indent_char::space, 0, 2, 2), ctx);
toml11_test_parse_success<toml::value_t::table>("{a.b = 1,\n a.c = 2}", (toml::table{{ "a", toml::table{{"b", 1}, {"c", 2}} }}), comments(), make_format(toml::table_format::multiline_oneline, toml::indent_char::space, 0, 2, 0), ctx);
toml11_test_parse_success<toml::value_t::table>("{# this table is empty.\n}", (toml::table{}), comments(), make_format(toml::table_format::multiline_oneline, toml::indent_char::none,0,0,0), ctx);
toml11_test_parse_success<toml::value_t::table>("{\na = 1 # com\n}", (toml::table{{"a", toml::value(1, {"# com"}) }}), comments(), make_format(toml::table_format::multiline_oneline, toml::indent_char::none,0,0,0), ctx);
toml11_test_parse_success<toml::value_t::table>("{\n a = 1, # com-a\n b = 2 # com-b\n}", (toml::table{{"a", toml::value(1, {"# com-a"}) }, {"b", toml::value(2, {"# com-b"})}}), comments(), make_format(toml::table_format::multiline_oneline, toml::indent_char::space, 0, 2, 0), ctx);
toml11_test_parse_success<toml::value_t::table>("{# com-a-b\n a.b = 1\n }", (toml::table{{"a", toml::table{{"b", toml::value(1, {"# com-a-b"})}} }}), comments(), make_format(toml::table_format::multiline_oneline, toml::indent_char::space, 0, 2, 2), ctx);
toml11_test_parse_success<toml::value_t::table>("{a.b = 1,\n a.c = 2 # com-a-c\n}", (toml::table{{"a", toml::table{{"b", 1}, {"c", toml::value(2, {"# com-a-c"})}} }}), comments(), make_format(toml::table_format::multiline_oneline, toml::indent_char::space, 0, 2, 0), ctx);
} }
// invalids
{ {
std::istringstream stream(std::string( using toml::detail::parse_inline_table;
"a = {b = {c = 1}}\n"
"a.b.d = 2\n")); auto spec = toml::spec::v(1,1,0);
BOOST_CHECK_THROW(toml::parse(stream), toml::syntax_error); toml::detail::context<toml::type_config> ctx(spec);
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ 1, 2 }", ctx); // no key
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a = 1, b = 2", ctx); // no closing bracket
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{", ctx); // no closing bracket
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a = 1, b = 2\n a = b", ctx); // no closing bracket
toml11_test_parse_failure(parse_inline_table<toml::type_config>, "{ a.b = 1, a.b.c = 2}", ctx); // a.b is not a table
} }
} }

View File

@@ -1,116 +1,147 @@
#include <toml/parser.hpp>
#include "unit_test.hpp" #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "test_parse_aux.hpp" #include "doctest.h"
using namespace toml; #include "utility.hpp"
using namespace detail;
BOOST_AUTO_TEST_CASE(test_decimal) #include <toml11/parser.hpp>
#include <toml11/types.hpp>
TEST_CASE("testing decimal_value")
{ {
TOML11_TEST_PARSE_EQUAL(parse_integer, "1234", 1234); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL(parse_integer, "+1234", 1234); const auto decimal_fmt = [](std::size_t w, std::size_t s) {
TOML11_TEST_PARSE_EQUAL(parse_integer, "-1234", -1234); toml::integer_format_info fmt;
TOML11_TEST_PARSE_EQUAL(parse_integer, "0", 0); fmt.fmt = toml::integer_format::dec;
TOML11_TEST_PARSE_EQUAL(parse_integer, "1_2_3_4", 1234); fmt.width = w;
TOML11_TEST_PARSE_EQUAL(parse_integer, "+1_2_3_4", +1234); fmt.spacer = s;
TOML11_TEST_PARSE_EQUAL(parse_integer, "-1_2_3_4", -1234); return fmt;
TOML11_TEST_PARSE_EQUAL(parse_integer, "123_456_789", 123456789); };
toml11_test_parse_success<toml::value_t::integer>( "0", 0, comments(), decimal_fmt(1, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>( "+0", 0, comments(), decimal_fmt(2, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>( "-0", 0, comments(), decimal_fmt(2, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>( "1234", 1234, comments(), decimal_fmt(4, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>( "+1234", 1234, comments(), decimal_fmt(5, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>( "-1234", -1234, comments(), decimal_fmt(5, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>( "0", 0, comments(), decimal_fmt(1, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>( "1_2_3_4", 1234, comments(), decimal_fmt(4, 1), ctx);
toml11_test_parse_success<toml::value_t::integer>( "+1_2_3_4", +1234, comments(), decimal_fmt(5, 1), ctx);
toml11_test_parse_success<toml::value_t::integer>( "-1_2_3_4", -1234, comments(), decimal_fmt(5, 1), ctx);
toml11_test_parse_success<toml::value_t::integer>("123_456_789", 123456789, comments(), decimal_fmt(9, 3), ctx);
} }
BOOST_AUTO_TEST_CASE(test_decimal_value) TEST_CASE("testing hex_value")
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1234", toml::value( 1234)); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1234", toml::value( 1234)); const auto hex_fmt = [](std::size_t w, std::size_t s) {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1234", toml::value( -1234)); toml::integer_format_info fmt;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0", toml::value( 0)); fmt.fmt = toml::integer_format::hex;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "1_2_3_4", toml::value( 1234)); fmt.width = w;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "+1_2_3_4", toml::value( +1234)); fmt.spacer = s;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "-1_2_3_4", toml::value( -1234)); return fmt;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "123_456_789", toml::value(123456789)); };
toml11_test_parse_success<toml::value_t::integer>("0xDEADBEEF", 0xDEADBEEF, comments(), hex_fmt(8, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>("0xdeadbeef", 0xDEADBEEF, comments(), hex_fmt(8, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>("0xDEADbeef", 0xDEADBEEF, comments(), hex_fmt(8, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>("0xDEAD_BEEF", 0xDEADBEEF, comments(), hex_fmt(8, 4), ctx);
toml11_test_parse_success<toml::value_t::integer>("0xdead_beef", 0xDEADBEEF, comments(), hex_fmt(8, 4), ctx);
toml11_test_parse_success<toml::value_t::integer>("0xdead_BEEF", 0xDEADBEEF, comments(), hex_fmt(8, 4), ctx);
toml11_test_parse_success<toml::value_t::integer>("0xFF", 0xFF, comments(), hex_fmt(2, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>("0x00FF", 0xFF, comments(), hex_fmt(4, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>("0x0000FF", 0xFF, comments(), hex_fmt(6, 0), ctx);
} }
BOOST_AUTO_TEST_CASE(test_hex) TEST_CASE("testing oct_value")
{ {
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEADBEEF", 0xDEADBEEF); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdeadbeef", 0xDEADBEEF); const auto oct_fmt = [](std::size_t w, std::size_t s) {
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEADbeef", 0xDEADBEEF); toml::integer_format_info fmt;
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xDEAD_BEEF", 0xDEADBEEF); fmt.fmt = toml::integer_format::oct;
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdead_beef", 0xDEADBEEF); fmt.width = w;
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xdead_BEEF", 0xDEADBEEF); fmt.spacer = s;
TOML11_TEST_PARSE_EQUAL(parse_integer, "0xFF", 0xFF); return fmt;
TOML11_TEST_PARSE_EQUAL(parse_integer, "0x00FF", 0xFF); };
TOML11_TEST_PARSE_EQUAL(parse_integer, "0x0000FF", 0xFF);
toml11_test_parse_success<toml::value_t::integer>("0o777", 64*7+8*7+7, comments(), oct_fmt(3, 0), ctx);
toml11_test_parse_success<toml::value_t::integer>("0o7_7_7", 64*7+8*7+7, comments(), oct_fmt(3, 1), ctx);
toml11_test_parse_success<toml::value_t::integer>("0o007", 7, comments(), oct_fmt(3, 0), ctx);
} }
BOOST_AUTO_TEST_CASE(test_hex_value) TEST_CASE("testing bin_value")
{ {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEADBEEF", value(0xDEADBEEF)); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdeadbeef", value(0xDEADBEEF)); const auto bin_fmt = [](std::size_t w, std::size_t s) {
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEADbeef", value(0xDEADBEEF)); toml::integer_format_info fmt;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xDEAD_BEEF", value(0xDEADBEEF)); fmt.fmt = toml::integer_format::bin;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdead_beef", value(0xDEADBEEF)); fmt.width = w;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xdead_BEEF", value(0xDEADBEEF)); fmt.spacer = s;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0xFF", value(0xFF)); return fmt;
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0x00FF", value(0xFF)); };
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0x0000FF", value(0xFF));
}
BOOST_AUTO_TEST_CASE(test_oct) toml11_test_parse_success<toml::value_t::integer>("0b10000", 16, comments(), bin_fmt(5, 0), ctx);
{ toml11_test_parse_success<toml::value_t::integer>("0b010000", 16, comments(), bin_fmt(6, 0), ctx);
TOML11_TEST_PARSE_EQUAL(parse_integer, "0o777", 64*7+8*7+7); toml11_test_parse_success<toml::value_t::integer>("0b01_00_00", 16, comments(), bin_fmt(6, 2), ctx);
TOML11_TEST_PARSE_EQUAL(parse_integer, "0o7_7_7", 64*7+8*7+7); toml11_test_parse_success<toml::value_t::integer>("0b111111", 63, comments(), bin_fmt(6, 0), ctx);
TOML11_TEST_PARSE_EQUAL(parse_integer, "0o007", 7);
}
BOOST_AUTO_TEST_CASE(test_oct_value) toml11_test_parse_success<toml::value_t::integer>(
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0o777", value(64*7+8*7+7));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0o7_7_7", value(64*7+8*7+7));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0o007", value(7));
}
BOOST_AUTO_TEST_CASE(test_bin)
{
TOML11_TEST_PARSE_EQUAL(parse_integer, "0b10000", 16);
TOML11_TEST_PARSE_EQUAL(parse_integer, "0b010000", 16);
TOML11_TEST_PARSE_EQUAL(parse_integer, "0b01_00_00", 16);
TOML11_TEST_PARSE_EQUAL(parse_integer, "0b111111", 63);
}
BOOST_AUTO_TEST_CASE(test_bin_value)
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b10000", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b010000", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b01_00_00", value(16));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "0b111111", value(63));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"0b1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000", "0b1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000_1000",
// 1 0 0 0 0x0888888888888888, comments(), bin_fmt(60, 4), ctx);
// 0 C 8 4 toml11_test_parse_success<toml::value_t::integer>(
value(0x0888888888888888));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"0b01111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111", "0b01111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111",
// 1 0 0 0 0x7FFFFFFFFFFFFFFF, comments(), bin_fmt(64, 8), ctx);
// 0 C 8 4 toml11_test_parse_success<toml::value_t::integer>(
value(0x7FFFFFFFFFFFFFFF));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"0b00000000_01111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111", "0b00000000_01111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111",
// 1 0 0 0 0x7FFFFFFFFFFFFFFF, comments(), bin_fmt(72, 8), ctx);
// 0 C 8 4
value(0x7FFFFFFFFFFFFFFF));
} }
BOOST_AUTO_TEST_CASE(test_integer_overflow) TEST_CASE("testing integer_overflow")
{ {
std::istringstream dec_overflow(std::string("dec-overflow = 9223372036854775808")); toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
std::istringstream hex_overflow(std::string("hex-overflow = 0x1_00000000_00000000")); {
std::istringstream oct_overflow(std::string("oct-overflow = 0o1_000_000_000_000_000_000_000")); auto loc = toml::detail::make_temporary_location("9223372036854775808");
// 64 56 48 40 32 24 16 8 const auto res = toml::detail::parse_dec_integer(loc, ctx);
std::istringstream bin_overflow(std::string("bin-overflow = 0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")); CHECK_UNARY(res.is_err());
BOOST_CHECK_THROW(toml::parse(dec_overflow), toml::syntax_error); }
BOOST_CHECK_THROW(toml::parse(hex_overflow), toml::syntax_error); {
BOOST_CHECK_THROW(toml::parse(oct_overflow), toml::syntax_error); auto loc = toml::detail::make_temporary_location("0x1_00000000_00000000");
BOOST_CHECK_THROW(toml::parse(bin_overflow), toml::syntax_error); const auto res = toml::detail::parse_hex_integer(loc, ctx);
CHECK_UNARY(res.is_err());
}
{
auto loc = toml::detail::make_temporary_location("0o1_000_000_000_000_000_000_000");
const auto res = toml::detail::parse_oct_integer(loc, ctx);
CHECK_UNARY(res.is_err());
}
{
// 64 56 48 40 32 24 16 8
auto loc = toml::detail::make_temporary_location("0b10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000");
const auto res = toml::detail::parse_oct_integer(loc, ctx);
CHECK_UNARY(res.is_err());
}
}
TEST_CASE("testing decimal_value with suffix extension")
{
auto spec = toml::spec::v(1, 0, 0);
spec.ext_num_suffix = true;
toml::detail::context<toml::type_config> ctx(spec);
const auto decimal_fmt = [](std::size_t w, std::size_t s, std::string x) {
toml::integer_format_info fmt;
fmt.fmt = toml::integer_format::dec;
fmt.width = w;
fmt.spacer = s;
fmt.suffix = std::move(x);
return fmt;
};
toml11_test_parse_success<toml::value_t::integer>( "1234_μm", 1234, comments(), decimal_fmt(4, 0, "μm"), ctx);
toml11_test_parse_success<toml::value_t::integer>( "+1234_μm", 1234, comments(), decimal_fmt(5, 0, "μm"), ctx);
toml11_test_parse_success<toml::value_t::integer>( "-1234_μm", -1234, comments(), decimal_fmt(5, 0, "μm"), ctx);
toml11_test_parse_success<toml::value_t::integer>( "0_μm", 0, comments(), decimal_fmt(1, 0, "μm"), ctx);
toml11_test_parse_success<toml::value_t::integer>( "1_2_3_4_μm", 1234, comments(), decimal_fmt(4, 1, "μm"), ctx);
toml11_test_parse_success<toml::value_t::integer>( "+1_2_3_4_μm", +1234, comments(), decimal_fmt(5, 1, "μm"), ctx);
toml11_test_parse_success<toml::value_t::integer>( "-1_2_3_4_μm", -1234, comments(), decimal_fmt(5, 1, "μm"), ctx);
toml11_test_parse_success<toml::value_t::integer>("123_456_789_μm", 123456789, comments(), decimal_fmt(9, 3, "μm"), ctx);
} }

View File

@@ -1,58 +0,0 @@
#include <toml/parser.hpp>
#include "unit_test.hpp"
#include "test_parse_aux.hpp"
using namespace toml;
using namespace detail;
BOOST_AUTO_TEST_CASE(test_bare_key)
{
TOML11_TEST_PARSE_EQUAL(parse_key, "barekey", std::vector<key>(1, "barekey"));
TOML11_TEST_PARSE_EQUAL(parse_key, "bare-key", std::vector<key>(1, "bare-key"));
TOML11_TEST_PARSE_EQUAL(parse_key, "bare_key", std::vector<key>(1, "bare_key"));
TOML11_TEST_PARSE_EQUAL(parse_key, "1234", std::vector<key>(1, "1234"));
}
BOOST_AUTO_TEST_CASE(test_quoted_key)
{
TOML11_TEST_PARSE_EQUAL(parse_key, "\"127.0.0.1\"", std::vector<key>(1, "127.0.0.1" ));
TOML11_TEST_PARSE_EQUAL(parse_key, "\"character encoding\"", std::vector<key>(1, "character encoding"));
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
TOML11_TEST_PARSE_EQUAL(parse_key, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"", std::vector<key>(1, "\xCA\x8E\xC7\x9D\xCA\x9E"));
#else
TOML11_TEST_PARSE_EQUAL(parse_key, "\"ʎǝʞ\"", std::vector<key>(1, "ʎǝʞ" ));
#endif
TOML11_TEST_PARSE_EQUAL(parse_key, "'key2'", std::vector<key>(1, "key2" ));
TOML11_TEST_PARSE_EQUAL(parse_key, "'quoted \"value\"'", std::vector<key>(1, "quoted \"value\"" ));
}
BOOST_AUTO_TEST_CASE(test_dotted_key)
{
{
std::vector<key> keys(2);
keys[0] = "physical";
keys[1] = "color";
TOML11_TEST_PARSE_EQUAL(parse_key, "physical.color", keys);
}
{
std::vector<key> keys(2);
keys[0] = "physical";
keys[1] = "shape";
TOML11_TEST_PARSE_EQUAL(parse_key, "physical.shape", keys);
}
{
std::vector<key> keys(4);
keys[0] = "x";
keys[1] = "y";
keys[2] = "z";
keys[3] = "w";
TOML11_TEST_PARSE_EQUAL(parse_key, "x.y.z.w", keys);
}
{
std::vector<key> keys(2);
keys[0] = "site";
keys[1] = "google.com";
TOML11_TEST_PARSE_EQUAL(parse_key, "site.\"google.com\"", keys);
}
}

90
tests/test_parse_null.cpp Normal file
View File

@@ -0,0 +1,90 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "utility.hpp"
#include <toml11/parser.hpp>
#include <toml11/types.hpp>
TEST_CASE("testing null value extension")
{
toml::spec spec = toml::spec::v(1,0,0);
spec.ext_null_value = true;
toml::detail::context<toml::type_config> ctx(spec);
auto loc = toml::detail::make_temporary_location("null");
const auto res = toml::detail::parse_value<toml::type_config>(loc, ctx);
if(res.is_err())
{
std::cerr << format_error(res.unwrap_err()) << std::endl;
}
REQUIRE_UNARY(res.is_ok());
const auto val = res.unwrap();
REQUIRE_UNARY(val.is_empty());
}
TEST_CASE("testing null value extension OFF")
{
toml::spec spec = toml::spec::v(1,0,0);
toml::detail::context<toml::type_config> ctx(spec);
auto loc = toml::detail::make_temporary_location("null");
const auto res = toml::detail::parse_value<toml::type_config>(loc, ctx);
CHECK_UNARY(res.is_err());
}
TEST_CASE("testing null value extension, w/ comments")
{
toml::spec spec = toml::spec::v(1,0,0);
spec.ext_null_value = true;
toml::detail::context<toml::type_config> ctx(spec);
auto loc = toml::detail::make_temporary_location(R"(a = null # comment)");
toml::value table{toml::table()};
const auto res = toml::detail::parse_table(loc, ctx, table);
if(res.is_err())
{
std::cerr << format_error(res.unwrap_err()) << std::endl;
}
REQUIRE_UNARY(res.is_ok());
CHECK_UNARY(table.contains("a"));
const auto null = table.at("a");
CHECK_UNARY(null.is_empty());
CHECK_EQ(null.comments().size(), 1);
CHECK_EQ(null.comments().at(0), "# comment");
}
TEST_CASE("testing null value extension, in an array")
{
toml::spec spec = toml::spec::v(1,0,0);
spec.ext_null_value = true;
toml::detail::context<toml::type_config> ctx(spec);
auto loc = toml::detail::make_temporary_location(R"(a = [1, null, 3, 4, 5])");
toml::value table{toml::table()};
const auto res = toml::detail::parse_table(loc, ctx, table);
if(res.is_err())
{
std::cerr << format_error(res.unwrap_err()) << std::endl;
}
REQUIRE_UNARY(res.is_ok());
CHECK_UNARY(table.contains("a"));
const auto a = table.at("a");
CHECK_UNARY(a.is_array());
CHECK_EQ(a.as_array().size(), 5);
CHECK_UNARY(a.as_array().at(0).is_integer());
CHECK_UNARY(a.as_array().at(1).is_empty());
CHECK_UNARY(a.as_array().at(2).is_integer());
CHECK_UNARY(a.as_array().at(3).is_integer());
CHECK_UNARY(a.as_array().at(4).is_integer());
}

View File

@@ -1,245 +1,272 @@
#include <toml/parser.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include "utility.hpp"
#include "test_parse_aux.hpp" #include <iostream>
using namespace toml; #include <toml11/parser.hpp>
using namespace detail; #include <toml11/types.hpp>
BOOST_AUTO_TEST_CASE(test_string) TEST_CASE("testing basic string")
{ {
TOML11_TEST_PARSE_EQUAL(parse_string, toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
"\"The quick brown fox jumps over the lazy dog\"", const auto string_fmt = []() {
string("The quick brown fox jumps over the lazy dog", string_t::basic)); // inline basic_string does not use format settings
TOML11_TEST_PARSE_EQUAL(parse_string, toml::string_format_info fmt;
"\'The quick brown fox jumps over the lazy dog\'", fmt.fmt = toml::string_format::basic;
string("The quick brown fox jumps over the lazy dog", string_t::literal)); return fmt;
TOML11_TEST_PARSE_EQUAL(parse_string, };
"\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
string("The quick brown fox jumps over the lazy dog", string_t::basic));
TOML11_TEST_PARSE_EQUAL(parse_string,
"'''The quick brown fox \njumps over the lazy dog'''",
string("The quick brown fox \njumps over the lazy dog", string_t::literal));
}
BOOST_AUTO_TEST_CASE(test_string_value) toml11_test_parse_success<toml::value_t::string>(
{
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"The quick brown fox jumps over the lazy dog\"",
toml::value("The quick brown fox jumps over the lazy dog", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\'The quick brown fox jumps over the lazy dog\'",
toml::value("The quick brown fox jumps over the lazy dog", string_t::literal));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
toml::value("The quick brown fox jumps over the lazy dog", string_t::basic));
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"'''The quick brown fox \njumps over the lazy dog'''",
toml::value("The quick brown fox \njumps over the lazy dog", string_t::literal));
}
BOOST_AUTO_TEST_CASE(test_basic_string)
{
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"", "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
string("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic)); "GitHub Cofounder & CEO\nLikes tater tots and beer.", comments(),
TOML11_TEST_PARSE_EQUAL(parse_string, string_fmt(), ctx);
toml11_test_parse_success<toml::value_t::string>(
"\"192.168.1.1\"", "\"192.168.1.1\"",
string("192.168.1.1", string_t::basic)); "192.168.1.1", comments(),
string_fmt(), ctx);
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) toml11_test_parse_success<toml::value_t::string>(
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"", "\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
string("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic)); "\xE4\xB8\xAD\xE5\x9B\xBD", comments(),
#else string_fmt(), ctx);
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"中国\"",
string("中国", string_t::basic));
#endif
TOML11_TEST_PARSE_EQUAL(parse_string, toml11_test_parse_success<toml::value_t::string>(
"\"You'll hate me after this - #\"", "\"You'll hate me after this - #\"",
string("You'll hate me after this - #", string_t::basic)); "You'll hate me after this - #", comments(),
TOML11_TEST_PARSE_EQUAL(parse_string, string_fmt(), ctx);
"\" And when \\\"'s are in the along with # \\\"\"", toml11_test_parse_success<toml::value_t::string>(
string(" And when \"'s are in the along with # \"", string_t::basic)); "\" And when \\\"'s are in the parse_ml_basic_string, along with # \\\"\"",
TOML11_TEST_PARSE_EQUAL(parse_string, " And when \"'s are in the parse_ml_basic_string, along with # \"", comments(),
"\"Here are fifteen apostrophes: '''''''''''''''\"", string_fmt(), ctx);
string("Here are fifteen apostrophes: '''''''''''''''", string_t::basic));
}
BOOST_AUTO_TEST_CASE(test_basic_string_value) // -------------------------------------------------------------------------
{ // the same test cases, but with parse_string.
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
toml11_test_parse_success<toml::value_t::string>(
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"", "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
value("GitHub Cofounder & CEO\nLikes tater tots and beer.", string_t::basic)); "GitHub Cofounder & CEO\nLikes tater tots and beer.", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(), ctx);
toml11_test_parse_success<toml::value_t::string>(
"\"192.168.1.1\"", "\"192.168.1.1\"",
value("192.168.1.1", string_t::basic)); "192.168.1.1", comments(),
#if defined(_MSC_VER) || defined(__INTEL_COMPILER) string_fmt(), ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
toml11_test_parse_success<toml::value_t::string>(
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"", "\"\xE4\xB8\xAD\xE5\x9B\xBD\"",
value("\xE4\xB8\xAD\xE5\x9B\xBD", string_t::basic)); "\xE4\xB8\xAD\xE5\x9B\xBD", comments(),
#else string_fmt(), ctx);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"中国\"", toml11_test_parse_success<toml::value_t::string>(
value("中国", string_t::basic));
#endif
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
"\"You'll hate me after this - #\"", "\"You'll hate me after this - #\"",
value("You'll hate me after this - #", string_t::basic)); "You'll hate me after this - #", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(), ctx);
"\" And when \\\"'s are in the along with # \\\"\"", toml11_test_parse_success<toml::value_t::string>(
value(" And when \"'s are in the along with # \"", string_t::basic)); "\" And when \\\"'s are in the parse_ml_basic_string, along with # \\\"\"",
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, " And when \"'s are in the parse_ml_basic_string, along with # \"", comments(),
"\"Here are fifteen apostrophes: '''''''''''''''\"", string_fmt(), ctx);
value("Here are fifteen apostrophes: '''''''''''''''", string_t::basic));
} }
BOOST_AUTO_TEST_CASE(test_ml_basic_string) TEST_CASE("testing multiline basic string")
{ {
TOML11_TEST_PARSE_EQUAL(parse_string, toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
const auto string_fmt = [](bool nl) {
toml::string_format_info fmt;
fmt.fmt = toml::string_format::multiline_basic;
fmt.start_with_newline = nl;
return fmt;
};
toml11_test_parse_success<toml::value_t::string>(
// 0 1
// 01234567890123456
"\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"", "\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"",
string("The quick brown fox jumps over the lazy dog.", string_t::basic)); "The quick brown fox jumps over the lazy dog.", comments(),
TOML11_TEST_PARSE_EQUAL(parse_string, string_fmt(true), ctx
"\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"", );
string("The quick brown fox jumps over the lazy dog.", string_t::basic));
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"",
string("Here are two quotation marks: \"\". Simple enough.", string_t::basic));
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"",
string("Here are three quotation marks: \"\"\".", string_t::basic));
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"",
string("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::basic));
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"",
string("\"This,\" she said, \"is just a pointless statement.\"", string_t::basic));
}
BOOST_AUTO_TEST_CASE(test_ml_basic_string_value) toml11_test_parse_success<toml::value_t::string>(
{ // 0 1
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, // 012345678901234567
"\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"",
"The quick brown fox jumps over the lazy dog.", comments(),
string_fmt(false), ctx
);
toml11_test_parse_success<toml::value_t::string>(
"\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"",
"Here are two quotation marks: \"\". Simple enough.", comments(),
string_fmt(false), ctx
);
toml11_test_parse_success<toml::value_t::string>(
"\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"",
"Here are three quotation marks: \"\"\".", comments(),
string_fmt(false), ctx
);
toml11_test_parse_success<toml::value_t::string>(
"\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"",
"Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", comments(),
string_fmt(false), ctx
);
toml11_test_parse_success<toml::value_t::string>(
"\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"",
"\"This,\" she said, \"is just a pointless statement.\"", comments(),
string_fmt(false), ctx
);
// -------------------------------------------------------------------------
// the same test cases, but with parse_string.
toml11_test_parse_success<toml::value_t::string>(
// 0 1
// 01234567890123456
"\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"", "\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"",
value("The quick brown fox jumps over the lazy dog.", string_t::basic)); "The quick brown fox jumps over the lazy dog.", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(true), ctx
);
toml11_test_parse_success<toml::value_t::string>(
// 0 1
// 012345678901234567
"\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"", "\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"",
value("The quick brown fox jumps over the lazy dog.", string_t::basic)); "The quick brown fox jumps over the lazy dog.", comments(),
string_fmt(false), ctx
);
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, toml11_test_parse_success<toml::value_t::string>(
"\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"", "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"",
value("Here are two quotation marks: \"\". Simple enough.", string_t::basic)); "Here are two quotation marks: \"\". Simple enough.", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(false), ctx
);
toml11_test_parse_success<toml::value_t::string>(
"\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"", "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"",
value("Here are three quotation marks: \"\"\".", string_t::basic)); "Here are three quotation marks: \"\"\".", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(false), ctx
);
toml11_test_parse_success<toml::value_t::string>(
"\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"", "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"",
value("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::basic)); "Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(false), ctx
);
toml11_test_parse_success<toml::value_t::string>(
"\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"", "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"",
value("\"This,\" she said, \"is just a pointless statement.\"", string_t::basic)); "\"This,\" she said, \"is just a pointless statement.\"", comments(),
string_fmt(false), ctx
);
} }
BOOST_AUTO_TEST_CASE(test_literal_string) TEST_CASE("testing literal_string")
{ {
TOML11_TEST_PARSE_EQUAL(parse_string, toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
const auto string_fmt = []() {
// inline basic_string does not use format settings
toml::string_format_info fmt;
fmt.fmt = toml::string_format::literal;
return fmt;
};
toml11_test_parse_success<toml::value_t::string>(
"'C:\\Users\\nodejs\\templates'", "'C:\\Users\\nodejs\\templates'",
string("C:\\Users\\nodejs\\templates", string_t::literal)); "C:\\Users\\nodejs\\templates", comments(),
TOML11_TEST_PARSE_EQUAL(parse_string, string_fmt(), ctx);
toml11_test_parse_success<toml::value_t::string>(
"'\\\\ServerX\\admin$\\system32\\'", "'\\\\ServerX\\admin$\\system32\\'",
string("\\\\ServerX\\admin$\\system32\\", string_t::literal)); "\\\\ServerX\\admin$\\system32\\", comments(),
TOML11_TEST_PARSE_EQUAL(parse_string, string_fmt(), ctx);
toml11_test_parse_success<toml::value_t::string>(
"'Tom \"Dubs\" Preston-Werner'", "'Tom \"Dubs\" Preston-Werner'",
string("Tom \"Dubs\" Preston-Werner", string_t::literal)); "Tom \"Dubs\" Preston-Werner", comments(),
TOML11_TEST_PARSE_EQUAL(parse_string, string_fmt(), ctx);
toml11_test_parse_success<toml::value_t::string>(
"'<\\i\\c*\\s*>'", "'<\\i\\c*\\s*>'",
string("<\\i\\c*\\s*>", string_t::literal)); "<\\i\\c*\\s*>", comments(),
} string_fmt(), ctx);
BOOST_AUTO_TEST_CASE(test_literal_string_value) // -------------------------------------------------------------------------
{ // the same test cases, but with parse_string.
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>,
toml11_test_parse_success<toml::value_t::string>(
"'C:\\Users\\nodejs\\templates'", "'C:\\Users\\nodejs\\templates'",
value("C:\\Users\\nodejs\\templates", string_t::literal)); "C:\\Users\\nodejs\\templates", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(), ctx);
toml11_test_parse_success<toml::value_t::string>(
"'\\\\ServerX\\admin$\\system32\\'", "'\\\\ServerX\\admin$\\system32\\'",
value("\\\\ServerX\\admin$\\system32\\", string_t::literal)); "\\\\ServerX\\admin$\\system32\\", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(), ctx);
toml11_test_parse_success<toml::value_t::string>(
"'Tom \"Dubs\" Preston-Werner'", "'Tom \"Dubs\" Preston-Werner'",
value("Tom \"Dubs\" Preston-Werner", string_t::literal)); "Tom \"Dubs\" Preston-Werner", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(), ctx);
toml11_test_parse_success<toml::value_t::string>(
"'<\\i\\c*\\s*>'", "'<\\i\\c*\\s*>'",
value("<\\i\\c*\\s*>", string_t::literal)); "<\\i\\c*\\s*>", comments(),
string_fmt(), ctx);
} }
BOOST_AUTO_TEST_CASE(test_ml_literal_string) TEST_CASE("testing ml_literal_string")
{ {
TOML11_TEST_PARSE_EQUAL(parse_string, toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
const auto string_fmt = [](bool nl) {
toml::string_format_info fmt;
fmt.fmt = toml::string_format::multiline_literal;
fmt.start_with_newline = nl;
return fmt;
};
toml11_test_parse_success<toml::value_t::string>(
"'''I [dw]on't need \\d{2} apples'''", "'''I [dw]on't need \\d{2} apples'''",
string("I [dw]on't need \\d{2} apples", string_t::literal)); "I [dw]on't need \\d{2} apples", comments(),
TOML11_TEST_PARSE_EQUAL(parse_string, string_fmt(false), ctx);
toml11_test_parse_success<toml::value_t::string>(
"'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''", "'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''",
string("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", string_t::literal)); "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", comments(),
TOML11_TEST_PARSE_EQUAL(parse_string, string_fmt(true), ctx);
"''''That's still pointless', she said.'''",
string("'That's still pointless', she said.", string_t::literal));
TOML11_TEST_PARSE_EQUAL(parse_string,
"'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''",
string("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::literal));
TOML11_TEST_PARSE_EQUAL(parse_string,
"''''This,' she said, 'is just a pointless statement.''''",
string("'This,' she said, 'is just a pointless statement.'", string_t::literal));
}
BOOST_AUTO_TEST_CASE(test_ml_literal_string_value) toml11_test_parse_success<toml::value_t::string>(
{ "''''That's still pointless', she said.'''",
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, "'That's still pointless', she said.", comments(),
string_fmt(false), ctx);
toml11_test_parse_success<toml::value_t::string>(
"'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''",
"Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", comments(),
string_fmt(false), ctx);
toml11_test_parse_success<toml::value_t::string>(
"''''This,' she said, 'is just a pointless statement.''''",
"'This,' she said, 'is just a pointless statement.'", comments(),
string_fmt(false), ctx);
// -------------------------------------------------------------------------
// the same test cases, but with parse_string.
toml11_test_parse_success<toml::value_t::string>(
"'''I [dw]on't need \\d{2} apples'''", "'''I [dw]on't need \\d{2} apples'''",
value("I [dw]on't need \\d{2} apples", string_t::literal)); "I [dw]on't need \\d{2} apples", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(false), ctx);
toml11_test_parse_success<toml::value_t::string>(
"'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''", "'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''",
value("The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", string_t::literal)); "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(true), ctx);
toml11_test_parse_success<toml::value_t::string>(
"''''That's still pointless', she said.'''", "''''That's still pointless', she said.'''",
value("'That's still pointless', she said.", string_t::literal)); "'That's still pointless', she said.", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(false), ctx);
toml11_test_parse_success<toml::value_t::string>(
"'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''", "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''",
value("Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", string_t::literal)); "Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".", comments(),
TOML11_TEST_PARSE_EQUAL_VALUE(parse_value<toml::value>, string_fmt(false), ctx);
toml11_test_parse_success<toml::value_t::string>(
"''''This,' she said, 'is just a pointless statement.''''", "''''This,' she said, 'is just a pointless statement.''''",
value("'This,' she said, 'is just a pointless statement.'", string_t::literal)); "'This,' she said, 'is just a pointless statement.'", comments(),
} string_fmt(false), ctx);
BOOST_AUTO_TEST_CASE(test_simple_excape_sequences)
{
TOML11_TEST_PARSE_EQUAL(parse_string,
R"("\"\\\b\f\n\r\t")",
string("\"\\\b\f\n\r\t", string_t::basic));
#ifdef TOML11_USE_UNRELEASED_TOML_FEATURES
TOML11_TEST_PARSE_EQUAL(parse_string,
R"("\e")",
string("\x1b", string_t::basic));
#endif
}
BOOST_AUTO_TEST_CASE(test_unicode_escape_sequence)
{
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"\\u03B1\\u03B2\\u03B3\"",
string("\xCE\xB1\xCE\xB2\xCE\xB3", string_t::basic));
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"\\U0001D7AA\"",
string("\xF0\x9D\x9E\xAA", string_t::basic));
#else
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"\\u03B1\\u03B2\\u03B3\"",
string("αβγ", string_t::basic));
TOML11_TEST_PARSE_EQUAL(parse_string,
"\"\\U0001D7AA\"",
string("𝞪", string_t::basic));
#endif
} }

View File

@@ -1,45 +1,165 @@
#include <toml/get.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <toml/parser.hpp>
#include "unit_test.hpp" #include <iostream>
#include "test_parse_aux.hpp" #include "utility.hpp"
#include <toml11/parser.hpp>
#include <toml11/types.hpp>
using namespace toml; #include "doctest.h"
using namespace detail;
BOOST_AUTO_TEST_CASE(test_normal_table) TEST_CASE("testing a table")
{ {
std::string table( auto spec = toml::spec::v(1,0,0);
"key1 = \"value\"\n" {
"key2 = 42\n" toml::detail::context<toml::type_config> ctx(spec);
"key3 = 3.14\n" auto loc = toml::detail::make_temporary_location(R"(a = "foo")");
);
location loc("test", table);
const auto result = toml::detail::parse_ml_table<toml::value>(loc); toml::value table{toml::table()};
BOOST_TEST(result.is_ok()); const auto res = toml::detail::parse_table<toml::type_config>(loc, ctx, table);
const auto data = result.unwrap(); REQUIRE_UNARY(res.is_ok());
BOOST_TEST(toml::get<std::string >(data.at("key1")) == "value"); REQUIRE_UNARY(table.is_table());
BOOST_TEST(toml::get<std::int64_t>(data.at("key2")) == 42);
BOOST_TEST(toml::get<double >(data.at("key3")) == 3.14); CHECK_UNARY(table.as_table().at("a").is_string());
} CHECK_EQ (table.as_table().at("a").as_string(), "foo");
CHECK_UNARY(table.at("a").is_string());
BOOST_AUTO_TEST_CASE(test_nested_table) CHECK_EQ (table.at("a").as_string(), "foo");
{
std::string table( CHECK_EQ(table.as_table_fmt().indent_type, toml::indent_char::none);
"a.b = \"value\"\n" CHECK_EQ(table.as_table_fmt().name_indent, 0);
"a.c.d = 42\n" CHECK_EQ(table.as_table_fmt().body_indent, 0);
); CHECK_EQ(table.as_table_fmt().closing_indent, 0);
location loc("test", table); }
const auto result = toml::detail::parse_ml_table<toml::value>(loc); {
BOOST_TEST(result.is_ok()); toml::detail::context<toml::type_config> ctx(spec);
const auto data = result.unwrap(); auto loc = toml::detail::make_temporary_location(" a = \"foo\"");
const auto a = toml::get<toml::table>(data.at("a")); toml::value table{toml::table()};
const auto c = toml::get<toml::table>(a.at("c")); const auto res = toml::detail::parse_table<toml::type_config>(loc, ctx, table);
BOOST_TEST(toml::get<std::string >(a.at("b")) == "value"); REQUIRE_UNARY(res.is_ok());
BOOST_TEST(toml::get<std::int64_t>(c.at("d")) == 42);
REQUIRE_UNARY(table.is_table());
CHECK_UNARY(table.as_table().at("a").is_string());
CHECK_EQ (table.as_table().at("a").as_string(), "foo");
CHECK_UNARY(table.at("a").is_string());
CHECK_EQ (table.at("a").as_string(), "foo");
CHECK_EQ(table.as_table_fmt().indent_type, toml::indent_char::space);
CHECK_EQ(table.as_table_fmt().name_indent, 0);
CHECK_EQ(table.as_table_fmt().body_indent, 2);
CHECK_EQ(table.as_table_fmt().closing_indent, 0);
}
{
toml::detail::context<toml::type_config> ctx(spec);
auto loc = toml::detail::make_temporary_location("\ta = \"foo\"");
toml::value table{toml::table()};
const auto res = toml::detail::parse_table<toml::type_config>(loc, ctx, table);
REQUIRE_UNARY(res.is_ok());
REQUIRE_UNARY(table.is_table());
CHECK_UNARY(table.as_table().at("a").is_string());
CHECK_EQ (table.as_table().at("a").as_string(), "foo");
CHECK_UNARY(table.at("a").is_string());
CHECK_EQ (table.at("a").as_string(), "foo");
CHECK_EQ(table.as_table_fmt().indent_type, toml::indent_char::tab);
CHECK_EQ(table.as_table_fmt().name_indent, 0);
CHECK_EQ(table.as_table_fmt().body_indent, 1);
CHECK_EQ(table.as_table_fmt().closing_indent, 0);
}
{
toml::detail::context<toml::type_config> ctx(spec);
auto loc = toml::detail::make_temporary_location(R"(a = "foo"
b = "bar"
c.c1 = "baz"
c.c2 = "qux"
)");
toml::value table{toml::table()};
const auto res = toml::detail::parse_table<toml::type_config>(loc, ctx, table);
REQUIRE_UNARY(res.is_ok());
REQUIRE_UNARY(table.is_table());
CHECK_UNARY(table.at("a").is_string());
CHECK_EQ (table.at("a").as_string(), "foo");
CHECK_UNARY(table.at("b").is_string());
CHECK_EQ (table.at("b").as_string(), "bar");
CHECK_UNARY(table.at("c").at("c1").is_string());
CHECK_EQ (table.at("c").at("c1").as_string(), "baz");
CHECK_UNARY(table.at("c").at("c2").is_string());
CHECK_EQ (table.at("c").at("c2").as_string(), "qux");
CHECK_EQ(table.as_table_fmt().indent_type, toml::indent_char::none);
CHECK_EQ(table.as_table_fmt().name_indent, 0);
CHECK_EQ(table.as_table_fmt().body_indent, 0);
CHECK_EQ(table.as_table_fmt().closing_indent, 0);
}
{
toml::detail::context<toml::type_config> ctx(spec);
auto loc = toml::detail::make_temporary_location(R"(a = "foo"
b = "bar"
c.c1 = "baz"
[next.table]
c.c2 = "qux"
)");
toml::value table{toml::table()};
const auto res = toml::detail::parse_table<toml::type_config>(loc, ctx, table);
REQUIRE_UNARY(res.is_ok());
REQUIRE_UNARY(table.is_table());
CHECK_UNARY(table.at("a").is_string());
CHECK_EQ (table.at("a").as_string(), "foo");
CHECK_UNARY(table.at("b").is_string());
CHECK_EQ (table.at("b").as_string(), "bar");
CHECK_UNARY(table.at("c").at("c1").is_string());
CHECK_EQ (table.at("c").at("c1").as_string(), "baz");
CHECK_UNARY( ! table.at("c").contains("c2"));
CHECK_EQ(table.as_table_fmt().indent_type, toml::indent_char::none);
CHECK_EQ(table.as_table_fmt().name_indent, 0);
CHECK_EQ(table.as_table_fmt().body_indent, 0);
CHECK_EQ(table.as_table_fmt().closing_indent, 0);
}
{
toml::detail::context<toml::type_config> ctx(spec);
auto loc = toml::detail::make_temporary_location(R"(
a = "foo"
b = "bar"
c.c1 = "baz"
[next.table]
c.c2 = "qux"
)");
toml::value table{toml::table()};
const auto res = toml::detail::parse_table<toml::type_config>(loc, ctx, table);
REQUIRE_UNARY(res.is_ok());
REQUIRE_UNARY(table.is_table());
CHECK_UNARY(table.at("a").is_string());
CHECK_EQ (table.at("a").as_string(), "foo");
CHECK_UNARY(table.at("b").is_string());
CHECK_EQ (table.at("b").as_string(), "bar");
CHECK_UNARY(table.at("c").at("c1").is_string());
CHECK_EQ (table.at("c").at("c1").as_string(), "baz");
CHECK_UNARY( ! table.at("c").contains("c2"));
CHECK_EQ(table.as_table_fmt().indent_type, toml::indent_char::space);
CHECK_EQ(table.as_table_fmt().name_indent, 0);
CHECK_EQ(table.as_table_fmt().body_indent, 4);
CHECK_EQ(table.as_table_fmt().closing_indent, 0);
}
} }

View File

@@ -1,112 +0,0 @@
#include <toml/parser.hpp>
#include "unit_test.hpp"
#include "test_parse_aux.hpp"
using namespace toml;
using namespace detail;
BOOST_AUTO_TEST_CASE(test_table_bare_key)
{
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[barekey]", std::vector<key>(1, "barekey"));
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[bare-key]", std::vector<key>(1, "bare-key"));
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[bare_key]", std::vector<key>(1, "bare_key"));
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[1234]", std::vector<key>(1, "1234"));
}
BOOST_AUTO_TEST_CASE(test_table_quoted_key)
{
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"127.0.0.1\"]", std::vector<key>(1, "127.0.0.1" ));
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"character encoding\"]", std::vector<key>(1, "character encoding"));
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[\"ʎǝʞ\"]", std::vector<key>(1, "ʎǝʞ" ));
TOML11_TEST_PARSE_EQUAL(parse_table_key, "['key2']", std::vector<key>(1, "key2" ));
TOML11_TEST_PARSE_EQUAL(parse_table_key, "['quoted \"value\"']", std::vector<key>(1, "quoted \"value\"" ));
}
BOOST_AUTO_TEST_CASE(test_table_dotted_key)
{
{
std::vector<key> keys(2);
keys[0] = "physical";
keys[1] = "color";
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[physical.color]", keys);
}
{
std::vector<key> keys(2);
keys[0] = "physical";
keys[1] = "shape";
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[physical.shape]", keys);
}
{
std::vector<key> keys(4);
keys[0] = "x";
keys[1] = "y";
keys[2] = "z";
keys[3] = "w";
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x.y.z.w]", keys);
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x . y . z . w]", keys);
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x. y .z. w]", keys);
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[x .y. z .w]", keys);
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[ x. y .z . w ]", keys);
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[ x . y . z . w ]", keys);
}
{
std::vector<key> keys(2);
keys[0] = "site";
keys[1] = "google.com";
TOML11_TEST_PARSE_EQUAL(parse_table_key, "[site.\"google.com\"]", keys);
}
}
BOOST_AUTO_TEST_CASE(test_array_of_table_bare_key)
{
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[barekey]]", std::vector<key>(1, "barekey"));
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[bare-key]]", std::vector<key>(1, "bare-key"));
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[bare_key]]", std::vector<key>(1, "bare_key"));
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[1234]]", std::vector<key>(1, "1234"));
}
BOOST_AUTO_TEST_CASE(test_array_of_table_quoted_key)
{
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"127.0.0.1\"]]", std::vector<key>(1, "127.0.0.1" ));
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"character encoding\"]]", std::vector<key>(1, "character encoding"));
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[\"ʎǝʞ\"]]", std::vector<key>(1, "ʎǝʞ" ));
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[['key2']]", std::vector<key>(1, "key2" ));
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[['quoted \"value\"']]", std::vector<key>(1, "quoted \"value\"" ));
}
BOOST_AUTO_TEST_CASE(test_array_of_table_dotted_key)
{
{
std::vector<key> keys(2);
keys[0] = "physical";
keys[1] = "color";
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[physical.color]]", keys);
}
{
std::vector<key> keys(2);
keys[0] = "physical";
keys[1] = "shape";
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[physical.shape]]", keys);
}
{
std::vector<key> keys(4);
keys[0] = "x";
keys[1] = "y";
keys[2] = "z";
keys[3] = "w";
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x.y.z.w]]", keys);
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x . y . z . w]]", keys);
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x. y .z. w]]", keys);
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[x .y. z .w]]", keys);
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[ x. y .z . w ]]", keys);
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[ x . y . z . w ]]", keys);
}
{
std::vector<key> keys(2);
keys[0] = "site";
keys[1] = "google.com";
TOML11_TEST_PARSE_EQUAL(parse_array_table_key, "[[site.\"google.com\"]]", keys);
}
}

View File

@@ -0,0 +1,105 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <iostream>
#include "utility.hpp"
#include <toml11/parser.hpp>
#include <toml11/types.hpp>
#include "doctest.h"
TEST_CASE("testing table keys")
{
toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
{
auto loc = toml::detail::make_temporary_location("[one-key]");
const auto res = toml::detail::parse_table_key<toml::type_config>(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = std::get<0>(res.unwrap());
REQUIRE_UNARY(val.size() == 1);
REQUIRE_UNARY(val.at(0) == "one-key");
}
{
auto loc = toml::detail::make_temporary_location("[many.keys]");
const auto res = toml::detail::parse_table_key<toml::type_config>(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = std::get<0>(res.unwrap());
REQUIRE_UNARY(val.size() == 2);
REQUIRE_UNARY(val.at(0) == "many");
REQUIRE_UNARY(val.at(1) == "keys");
}
{
auto loc = toml::detail::make_temporary_location("[ many . keys . with . spaces ]");
const auto res = toml::detail::parse_table_key<toml::type_config>(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = std::get<0>(res.unwrap());
REQUIRE_UNARY(val.size() == 4);
REQUIRE_UNARY(val.at(0) == "many");
REQUIRE_UNARY(val.at(1) == "keys");
REQUIRE_UNARY(val.at(2) == "with");
REQUIRE_UNARY(val.at(3) == "spaces");
}
{
auto loc = toml::detail::make_temporary_location("[ \"one.long.key\" ]");
const auto res = toml::detail::parse_table_key<toml::type_config>(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = std::get<0>(res.unwrap());
REQUIRE_UNARY(val.size() == 1);
REQUIRE_UNARY(val.at(0) == "one.long.key");
}
}
TEST_CASE("testing array table keys")
{
toml::detail::context<toml::type_config> ctx(toml::spec::v(1,0,0));
{
auto loc = toml::detail::make_temporary_location("[[one-key]]");
const auto res = toml::detail::parse_array_table_key<toml::type_config>(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = std::get<0>(res.unwrap());
REQUIRE_UNARY(val.size() == 1);
REQUIRE_UNARY(val.at(0) == "one-key");
}
{
auto loc = toml::detail::make_temporary_location("[[many.keys]]");
const auto res = toml::detail::parse_array_table_key<toml::type_config>(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = std::get<0>(res.unwrap());
REQUIRE_UNARY(val.size() == 2);
REQUIRE_UNARY(val.at(0) == "many");
REQUIRE_UNARY(val.at(1) == "keys");
}
{
auto loc = toml::detail::make_temporary_location("[[ many . keys . with . spaces ]]");
const auto res = toml::detail::parse_array_table_key<toml::type_config>(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = std::get<0>(res.unwrap());
REQUIRE_UNARY(val.size() == 4);
REQUIRE_UNARY(val.at(0) == "many");
REQUIRE_UNARY(val.at(1) == "keys");
REQUIRE_UNARY(val.at(2) == "with");
REQUIRE_UNARY(val.at(3) == "spaces");
}
{
auto loc = toml::detail::make_temporary_location("[[ \"one.long.key\" ]]");
const auto res = toml::detail::parse_array_table_key<toml::type_config>(loc, ctx);
REQUIRE_UNARY(res.is_ok());
const auto val = std::get<0>(res.unwrap());
REQUIRE_UNARY(val.size() == 1);
REQUIRE_UNARY(val.at(0) == "one.long.key");
}
}

View File

@@ -1,37 +0,0 @@
#include <toml.hpp>
#include "unit_test.hpp"
#include <fstream>
#include <iostream>
BOOST_AUTO_TEST_CASE(test_hard_example_unicode)
{
const auto data = toml::parse(testinput("hard_example_unicode.toml"));
const auto the = toml::find<toml::table>(data, "the");
BOOST_TEST(toml::get<std::string>(the.at("test_string")) ==
std::string("\xC3\x9D\xC3\xB4\xC3\xBA\x27\xE2\x84\x93\xE2\x84\x93\x20\xCE\xBB\xC3\xA1\xC6\xAD\xC3\xA8\x20\xE2\x82\xA5\xC3\xA8\x20\xC3\xA1\xC6\x92\xC6\xAD\xC3\xA8\xC5\x99\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC6\xA8\x20\x2D\x20\x23"));
const auto hard = toml::get<toml::table>(the.at("hard"));
const std::vector<std::string> expected_the_hard_test_array{"] ", " # "};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array")) ==
expected_the_hard_test_array);
const std::vector<std::string> expected_the_hard_test_array2{
std::string("\x54\xC3\xA8\xC6\xA8\xC6\xAD\x20\x23\x31\x31\x20\x5D\xC6\xA5\xC5\x99\xC3\xB4\xC6\xB2\xC3\xA8\xCE\xB4\x20\xC6\xAD\xCE\xBB\xC3\xA1\xC6\xAD"),
std::string("\xC3\x89\xD0\xB6\xC6\xA5\xC3\xA8\xC5\x99\xC3\xAF\xE2\x82\xA5\xC3\xA8\xC3\xB1\xC6\xAD\x20\x23\x39\x20\xCF\x89\xC3\xA1\xC6\xA8\x20\xC3\xA1\x20\xC6\xA8\xC3\xBA\xC3\xA7\xC3\xA7\xC3\xA8\xC6\xA8\xC6\xA8")
};
BOOST_CHECK(toml::get<std::vector<std::string>>(hard.at("test_array2")) ==
expected_the_hard_test_array2);
BOOST_TEST(toml::get<std::string>(hard.at("another_test_string")) ==
std::string("\xC2\xA7\xC3\xA1\xE2\x82\xA5\xC3\xA8\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC3\xB1\xCF\xB1\x2C\x20\xCE\xB2\xC3\xBA\xC6\xAD\x20\xCF\x89\xC3\xAF\xC6\xAD\xCE\xBB\x20\xC3\xA1\x20\xC6\xA8\xC6\xAD\xC5\x99\xC3\xAF\xC3\xB1\xCF\xB1\x20\x23"));
BOOST_TEST(toml::get<std::string>(hard.at("harder_test_string")) ==
std::string("\x20\xC3\x82\xC3\xB1\xCE\xB4\x20\xCF\x89\xCE\xBB\xC3\xA8\xC3\xB1\x20\x22\x27\xC6\xA8\x20\xC3\xA1\xC5\x99\xC3\xA8\x20\xC3\xAF\xC3\xB1\x20\xC6\xAD\xCE\xBB\xC3\xA8\x20\xC6\xA8\xC6\xAD\xC5\x99\xC3\xAF\xC3\xB1\xCF\xB1\x2C\x20\xC3\xA1\xE2\x84\x93\xC3\xB4\xC3\xB1\xCF\xB1\x20\xCF\x89\xC3\xAF\xC6\xAD\xCE\xBB\x20\x23\x20\x22"));
//
const auto bit = toml::get<toml::table>(hard.at(std::string("\xCE\xB2\xC3\xAF\xC6\xAD\x23")));
BOOST_TEST(toml::get<std::string>(bit.at(std::string("\xCF\x89\xCE\xBB\xC3\xA1\xC6\xAD\x3F"))) ==
std::string("\xC3\x9D\xC3\xB4\xC3\xBA\x20\xCE\xB4\xC3\xB4\xC3\xB1\x27\xC6\xAD\x20\xC6\xAD\xCE\xBB\xC3\xAF\xC3\xB1\xC6\x99\x20\xC6\xA8\xC3\xB4\xE2\x82\xA5\xC3\xA8\x20\xC3\xBA\xC6\xA8\xC3\xA8\xC5\x99\x20\xCF\x89\xC3\xB4\xC3\xB1\x27\xC6\xAD\x20\xCE\xB4\xC3\xB4\x20\xC6\xAD\xCE\xBB\xC3\xA1\xC6\xAD\x3F"));
const std::vector<std::string> expected_multi_line_array{"]"};
BOOST_CHECK(toml::get<std::vector<std::string>>(bit.at("multi_line_array")) ==
expected_multi_line_array);
}

View File

@@ -1,440 +1,148 @@
#include <toml/result.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include <toml11/result.hpp>
#include <iostream> TEST_CASE("testing constructor")
BOOST_AUTO_TEST_CASE(test_construct)
{ {
{ {
auto s = toml::ok(42); auto s = toml::ok(42);
toml::result<int, std::string> result(s); toml::result<int, std::string> result(s);
BOOST_TEST(!!result); CHECK(!!result);
BOOST_TEST(result.is_ok()); CHECK(result.is_ok());
BOOST_TEST(!result.is_err()); CHECK(!result.is_err());
BOOST_TEST(result.unwrap() == 42); CHECK(result.unwrap() == 42);
} }
{ {
const auto s = toml::ok(42); const auto s = toml::ok(42);
toml::result<int, std::string> result(s); toml::result<int, std::string> result(s);
BOOST_TEST(!!result); CHECK(!!result);
BOOST_TEST(result.is_ok()); CHECK(result.is_ok());
BOOST_TEST(!result.is_err()); CHECK(!result.is_err());
BOOST_TEST(result.unwrap() == 42); CHECK(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::ok(42)); toml::result<int, std::string> result(toml::ok(42));
BOOST_TEST(!!result); CHECK(!!result);
BOOST_TEST(result.is_ok()); CHECK(result.is_ok());
BOOST_TEST(!result.is_err()); CHECK(!result.is_err());
BOOST_TEST(result.unwrap() == 42); CHECK(result.unwrap() == 42);
} }
{ {
auto f = toml::err<std::string>("foobar"); auto f = toml::err("foobar");
toml::result<int, std::string> result(f); toml::result<int, std::string> result(f);
BOOST_TEST(!result); CHECK(!result);
BOOST_TEST(!result.is_ok()); CHECK(!result.is_ok());
BOOST_TEST(result.is_err()); CHECK(result.is_err());
BOOST_TEST(result.unwrap_err() == "foobar"); CHECK(result.unwrap_err() == "foobar");
} }
{ {
const auto f = toml::err<std::string>("foobar"); const auto f = toml::err("foobar");
toml::result<int, std::string> result(f); toml::result<int, std::string> result(f);
BOOST_TEST(!result); CHECK(!result);
BOOST_TEST(!result.is_ok()); CHECK(!result.is_ok());
BOOST_TEST(result.is_err()); CHECK(result.is_err());
BOOST_TEST(result.unwrap_err() == "foobar"); CHECK(result.unwrap_err() == "foobar");
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err("foobar"));
BOOST_TEST(!result); CHECK(!result);
BOOST_TEST(!result.is_ok()); CHECK(!result.is_ok());
BOOST_TEST(result.is_err()); CHECK(result.is_err());
BOOST_TEST(result.unwrap_err() == "foobar"); CHECK(result.unwrap_err() == "foobar");
} }
} }
BOOST_AUTO_TEST_CASE(test_assignment) TEST_CASE("testing assignment op")
{ {
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err("foobar"));
result = toml::ok(42); result = toml::ok(42);
BOOST_TEST(!!result); CHECK(!!result);
BOOST_TEST(result.is_ok()); CHECK(result.is_ok());
BOOST_TEST(!result.is_err()); CHECK(!result.is_err());
BOOST_TEST(result.unwrap() == 42); CHECK(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err("foobar"));
auto s = toml::ok(42); auto s = toml::ok(42);
result = s; result = s;
BOOST_TEST(!!result); CHECK(!!result);
BOOST_TEST(result.is_ok()); CHECK(result.is_ok());
BOOST_TEST(!result.is_err()); CHECK(!result.is_err());
BOOST_TEST(result.unwrap() == 42); CHECK(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err("foobar"));
const auto s = toml::ok(42); const auto s = toml::ok(42);
result = s; result = s;
BOOST_TEST(!!result); CHECK(!!result);
BOOST_TEST(result.is_ok()); CHECK(result.is_ok());
BOOST_TEST(!result.is_err()); CHECK(!result.is_err());
BOOST_TEST(result.unwrap() == 42); CHECK(result.unwrap() == 42);
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err("foobar"));
result = toml::err<std::string>("hoge"); result = toml::err("hoge");
BOOST_TEST(!result); CHECK(!result);
BOOST_TEST(!result.is_ok()); CHECK(!result.is_ok());
BOOST_TEST(result.is_err()); CHECK(result.is_err());
BOOST_TEST(result.unwrap_err() == "hoge"); CHECK(result.unwrap_err() == "hoge");
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err("foobar"));
auto f = toml::err<std::string>("hoge"); auto f = toml::err("hoge");
result = f; result = f;
BOOST_TEST(!result); CHECK(!result);
BOOST_TEST(!result.is_ok()); CHECK(!result.is_ok());
BOOST_TEST(result.is_err()); CHECK(result.is_err());
BOOST_TEST(result.unwrap_err() == "hoge"); CHECK(result.unwrap_err() == "hoge");
} }
{ {
toml::result<int, std::string> result(toml::err<std::string>("foobar")); toml::result<int, std::string> result(toml::err("foobar"));
const auto f = toml::err<std::string>("hoge"); const auto f = toml::err("hoge");
result = f; result = f;
BOOST_TEST(!result); CHECK(!result);
BOOST_TEST(!result.is_ok()); CHECK(!result.is_ok());
BOOST_TEST(result.is_err()); CHECK(result.is_err());
BOOST_TEST(result.unwrap_err() == "hoge"); CHECK(result.unwrap_err() == "hoge");
} }
} }
BOOST_AUTO_TEST_CASE(test_map) TEST_CASE("testing result<reference_wrapper>")
{ {
{ {
const toml::result<int, std::string> result(toml::ok(42)); int a = 42;
const auto mapped = result.map(
[](const int i) -> int {
return i * 2;
});
BOOST_TEST(!!mapped); toml::result<std::reference_wrapper<int>, std::string> result(toml::ok(std::ref(a)));
BOOST_TEST(mapped.is_ok()); CHECK_UNARY(result);
BOOST_TEST(!mapped.is_err()); CHECK_UNARY(result.is_ok());
BOOST_TEST(mapped.unwrap() == 42 * 2); CHECK_UNARY_FALSE(result.is_err());
CHECK_EQ(result.unwrap(), 42);
CHECK_EQ(a, 42);
result.unwrap() = 6 * 9;
CHECK_EQ(result.unwrap(), 6*9);
CHECK_EQ(a, 6*9);
} }
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::ok(std::unique_ptr<int>(new int(42))));
const auto mapped = std::move(result).map(
[](std::unique_ptr<int> i) -> int {
return *i;
});
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42);
}
{ {
const toml::result<int, std::string> result(toml::err<std::string>("hoge")); std::string b = "foo";
const auto mapped = result.map(
[](const int i) -> int {
return i * 2;
});
BOOST_TEST(!mapped); toml::result<int, std::reference_wrapper<std::string>> result(toml::err(std::ref(b)));
BOOST_TEST(!mapped.is_ok()); CHECK_UNARY_FALSE(result);
BOOST_TEST(mapped.is_err()); CHECK_UNARY_FALSE(result.is_ok());
BOOST_TEST(mapped.unwrap_err() == "hoge"); CHECK_UNARY(result.is_err());
}
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::err<std::string>("hoge"));
const auto mapped = std::move(result).map(
[](std::unique_ptr<int> i) -> int {
return *i;
});
BOOST_TEST(!mapped); CHECK_EQ(result.unwrap_err(), "foo");
BOOST_TEST(!mapped.is_ok()); CHECK_EQ(b, "foo");
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hoge"); result.unwrap_err() = "foobar";
}
} CHECK_EQ(result.unwrap_err(), "foobar");
CHECK_EQ(b, "foobar");
BOOST_AUTO_TEST_CASE(test_map_err)
{
{
const toml::result<int, std::string> result(toml::ok(42));
const auto mapped = result.map_err(
[](const std::string s) -> std::string {
return s + s;
});
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42);
}
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::ok(std::unique_ptr<int>(new int(42))));
const auto mapped = std::move(result).map_err(
[](const std::string s) -> std::string {
return s + s;
});
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(*(mapped.unwrap()) == 42);
}
{
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
const auto mapped = result.map_err(
[](const std::string s) -> std::string {
return s + s;
});
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hogehoge");
}
{
toml::result<int, std::unique_ptr<std::string>>
result(toml::err(std::unique_ptr<std::string>(new std::string("hoge"))));
const auto mapped = std::move(result).map_err(
[](std::unique_ptr<std::string> p) -> std::string {
return *p;
});
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hoge");
}
}
BOOST_AUTO_TEST_CASE(test_map_or_else)
{
{
const toml::result<int, std::string> result(toml::ok(42));
const auto mapped = result.map_or_else(
[](const int i) -> int {
return i * 2;
}, 54);
BOOST_TEST(mapped == 42 * 2);
}
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::ok(std::unique_ptr<int>(new int(42))));
const auto mapped = std::move(result).map_or_else(
[](std::unique_ptr<int> i) -> int {
return *i;
}, 54);
BOOST_TEST(mapped == 42);
}
{
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
const auto mapped = result.map_or_else(
[](const int i) -> int {
return i * 2;
}, 54);
BOOST_TEST(mapped == 54);
}
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::err<std::string>("hoge"));
const auto mapped = std::move(result).map_or_else(
[](std::unique_ptr<int> i) -> int {
return *i;
}, 54);
BOOST_TEST(mapped == 54);
}
}
BOOST_AUTO_TEST_CASE(test_map_err_or_else)
{
{
const toml::result<int, std::string> result(toml::ok(42));
const auto mapped = result.map_err_or_else(
[](const std::string i) -> std::string {
return i + i;
}, "foobar");
BOOST_TEST(mapped == "foobar");
}
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::ok(std::unique_ptr<int>(new int(42))));
const auto mapped = std::move(result).map_err_or_else(
[](const std::string i) -> std::string {
return i + i;
}, "foobar");
BOOST_TEST(mapped == "foobar");
}
{
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
const auto mapped = result.map_err_or_else(
[](const std::string i) -> std::string {
return i + i;
}, "foobar");
BOOST_TEST(mapped == "hogehoge");
}
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::err<std::string>("hoge"));
const auto mapped = result.map_err_or_else(
[](const std::string i) -> std::string {
return i + i;
}, "foobar");
BOOST_TEST(mapped == "hogehoge");
}
}
BOOST_AUTO_TEST_CASE(test_and_then)
{
{
const toml::result<int, std::string> result(toml::ok(42));
const auto mapped = result.and_then(
[](const int i) -> toml::result<int, std::string> {
return toml::ok(i * 2);
});
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42 * 2);
}
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::ok(std::unique_ptr<int>(new int(42))));
const auto mapped = std::move(result).and_then(
[](std::unique_ptr<int> i) -> toml::result<int, std::string> {
return toml::ok(*i);
});
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42);
}
{
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
const auto mapped = result.and_then(
[](const int i) -> toml::result<int, std::string> {
return toml::ok(i * 2);
});
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hoge");
}
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::err<std::string>("hoge"));
const auto mapped = std::move(result).and_then(
[](std::unique_ptr<int> i) -> toml::result<int, std::string> {
return toml::ok(*i);
});
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hoge");
}
}
BOOST_AUTO_TEST_CASE(test_or_else)
{
{
const toml::result<int, std::string> result(toml::ok(42));
const auto mapped = result.or_else(
[](const std::string& s) -> toml::result<int, std::string> {
return toml::err(s + s);
});
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(mapped.unwrap() == 42);
}
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::ok(std::unique_ptr<int>(new int(42))));
const auto mapped = std::move(result).or_else(
[](const std::string& s) -> toml::result<std::unique_ptr<int>, std::string> {
return toml::err(s + s);
});
BOOST_TEST(!!mapped);
BOOST_TEST(mapped.is_ok());
BOOST_TEST(!mapped.is_err());
BOOST_TEST(*mapped.unwrap() == 42);
}
{
const toml::result<int, std::string> result(toml::err<std::string>("hoge"));
const auto mapped = result.or_else(
[](const std::string& s) -> toml::result<int, std::string> {
return toml::err(s + s);
});
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hogehoge");
}
{
toml::result<std::unique_ptr<int>, std::string>
result(toml::err<std::string>("hoge"));
const auto mapped = std::move(result).or_else(
[](const std::string& s) -> toml::result<std::unique_ptr<int>, std::string> {
return toml::err(s + s);
});
BOOST_TEST(!mapped);
BOOST_TEST(!mapped.is_ok());
BOOST_TEST(mapped.is_err());
BOOST_TEST(mapped.unwrap_err() == "hogehoge");
}
}
BOOST_AUTO_TEST_CASE(test_and_or_other)
{
{
const toml::result<int, std::string> r1(toml::ok(42));
const toml::result<int, std::string> r2(toml::err<std::string>("foo"));
BOOST_TEST(r1 == r1.or_other(r2));
BOOST_TEST(r2 == r1.and_other(r2));
BOOST_TEST(42 == r1.or_other(r2).unwrap());
BOOST_TEST("foo" == r1.and_other(r2).unwrap_err());
}
{
auto r1_gen = []() -> toml::result<int, std::string> {
return toml::ok(42);
};
auto r2_gen = []() -> toml::result<int, std::string> {
return toml::err<std::string>("foo");
};
const auto r3 = r1_gen();
const auto r4 = r2_gen();
BOOST_TEST(r3 == r1_gen().or_other (r2_gen()));
BOOST_TEST(r4 == r1_gen().and_other(r2_gen()));
BOOST_TEST(42 == r1_gen().or_other (r2_gen()).unwrap());
BOOST_TEST("foo" == r1_gen().and_other(r2_gen()).unwrap_err());
} }
} }

170
tests/test_scanner.cpp Normal file
View File

@@ -0,0 +1,170 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "utility.hpp"
#include <toml11/scanner.hpp>
TEST_CASE("testing scanner: character")
{
auto loc = toml::detail::make_temporary_location("\t \tA");
toml::detail::character tab('\t');
toml::detail::character space(' ');
CHECK_UNARY( tab .scan(loc).is_ok()); // loc += 1
CHECK_UNARY(!tab .scan(loc).is_ok());
CHECK_UNARY( space.scan(loc).is_ok());
CHECK_UNARY( tab .scan(loc).is_ok());
CHECK_UNARY(!tab .scan(loc).is_ok());
CHECK_UNARY(!space.scan(loc).is_ok());
}
TEST_CASE("testing scanner: character_either")
{
auto loc = toml::detail::make_temporary_location("\t \t01\0");
toml::detail::character_either wschar{'\t', ' '};
toml::detail::character_either digit01("01");
CHECK_UNARY( wschar .scan(loc).is_ok());
CHECK_UNARY( wschar .scan(loc).is_ok());
CHECK_UNARY( wschar .scan(loc).is_ok());
CHECK_UNARY(!wschar .scan(loc).is_ok());
CHECK_UNARY( digit01.scan(loc).is_ok());
CHECK_UNARY( digit01.scan(loc).is_ok());
CHECK_UNARY(!digit01.scan(loc).is_ok());
CHECK_UNARY(!wschar .scan(loc).is_ok());
}
TEST_CASE("testing scanner: character_in_range")
{
auto loc = toml::detail::make_temporary_location("abcdz12349");
toml::detail::character_in_range alpha('a', 'z');
toml::detail::character_in_range digit('0', '9');
CHECK_UNARY( alpha.scan(loc).is_ok());
CHECK_UNARY( alpha.scan(loc).is_ok());
CHECK_UNARY( alpha.scan(loc).is_ok());
CHECK_UNARY( alpha.scan(loc).is_ok());
CHECK_UNARY( alpha.scan(loc).is_ok());
CHECK_UNARY(!alpha.scan(loc).is_ok());
CHECK_UNARY( digit.scan(loc).is_ok());
CHECK_UNARY( digit.scan(loc).is_ok());
CHECK_UNARY( digit.scan(loc).is_ok());
CHECK_UNARY( digit.scan(loc).is_ok());
CHECK_UNARY( digit.scan(loc).is_ok());
CHECK_UNARY(!digit.scan(loc).is_ok());
}
TEST_CASE("testing scanner: literal")
{
auto loc = toml::detail::make_temporary_location("abcdz12349");
toml::detail::literal abcd("abcd");
toml::detail::literal z123("z123");
CHECK_UNARY( abcd.scan(loc).is_ok());
CHECK_UNARY(!abcd.scan(loc).is_ok());
CHECK_UNARY( z123.scan(loc).is_ok());
CHECK_UNARY(!z123.scan(loc).is_ok());
CHECK_UNARY(!abcd.scan(loc).is_ok());
}
TEST_CASE("testing scanner: sequence")
{
auto loc = toml::detail::make_temporary_location("abcdz12349");
toml::detail::literal abcd("abcd");
toml::detail::literal z123("z123");
toml::detail::sequence seq(abcd, z123);
CHECK_UNARY( seq.scan(loc).is_ok());
CHECK_EQ( loc.current(), toml::detail::location::char_type('4'));
auto loc2 = toml::detail::make_temporary_location("abcde12349");
CHECK_UNARY(!seq.scan(loc2).is_ok());
}
TEST_CASE("testing scanner: either")
{
auto loc = toml::detail::make_temporary_location("abcdz123");
toml::detail::literal abcd("abcd");
toml::detail::literal z123("z123");
toml::detail::either e(abcd, z123);
CHECK_UNARY( e.scan(loc).is_ok());
CHECK_EQ( loc.current(), toml::detail::location::char_type('z'));
CHECK_UNARY( e.scan(loc).is_ok());
CHECK_UNARY( loc.eof() );
}
TEST_CASE("testing scanner: repeat_exact")
{
{
auto loc = toml::detail::make_temporary_location("foofoobar");
toml::detail::repeat_exact r(2, toml::detail::literal("foo"));
CHECK_UNARY( r.scan(loc).is_ok());
CHECK_EQ( loc.current(), toml::detail::location::char_type('b'));
}
{
auto loc = toml::detail::make_temporary_location("foofoobar");
toml::detail::repeat_exact r(3, toml::detail::literal("foo"));
CHECK_UNARY( ! r.scan(loc).is_ok());
}
}
TEST_CASE("testing scanner: repeat_at_least")
{
{
auto loc = toml::detail::make_temporary_location("foofoobar");
toml::detail::repeat_at_least r(1, toml::detail::literal("foo"));
CHECK_UNARY( r.scan(loc).is_ok());
CHECK_EQ( loc.current(), toml::detail::location::char_type('b'));
}
{
auto loc = toml::detail::make_temporary_location("foofoobar");
toml::detail::repeat_at_least r(2, toml::detail::literal("foo"));
CHECK_UNARY( r.scan(loc).is_ok());
CHECK_EQ( loc.current(), toml::detail::location::char_type('b'));
}
{
auto loc = toml::detail::make_temporary_location("foofoobar");
toml::detail::repeat_at_least r(3, toml::detail::literal("foo"));
CHECK_UNARY( ! r.scan(loc).is_ok());
}
}
TEST_CASE("testing scanner: maybe")
{
{
auto loc = toml::detail::make_temporary_location("foofoobar");
toml::detail::maybe r(toml::detail::literal("foo"));
CHECK_UNARY( r.scan(loc).is_ok());
CHECK_EQ( loc.current(), toml::detail::location::char_type('f'));
CHECK_EQ( loc.get_location(), 3);
}
{
auto loc = toml::detail::make_temporary_location("foofoobar");
toml::detail::maybe r(toml::detail::literal("bar"));
CHECK_UNARY( r.scan(loc).is_ok());
CHECK_EQ( loc.current(), toml::detail::location::char_type('f'));
CHECK_EQ( loc.get_location(), 0);
}
}

View File

@@ -1,405 +0,0 @@
#include <toml.hpp>
#include "unit_test.hpp"
#include <deque>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <clocale>
template<typename Comment,
template<typename ...> class Table,
template<typename ...> class Array>
bool has_comment_inside(const toml::basic_value<Comment, Table, Array>& v)
{
if(!v.comments().empty())
{
return false;
}
// v itself does not have a comment.
if(v.is_array())
{
for(const auto& x : v.as_array())
{
if(has_comment_inside(x))
{
return false;
}
}
}
if(v.is_table())
{
for(const auto& x : v.as_table())
{
if(has_comment_inside(x.second))
{
return false;
}
}
}
return true;
}
BOOST_AUTO_TEST_CASE(test_example)
{
const auto data = toml::parse(testinput("example.toml"));
{
std::ofstream ofs("tmp1.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse("tmp1.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_example_map_dq)
{
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
testinput("example.toml"));
{
std::ofstream ofs("tmp1_map_dq.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
"tmp1_map_dq.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_example_with_comment)
{
const auto data = toml::parse<toml::preserve_comments>(testinput("example.toml"));
{
std::ofstream ofs("tmp1_com.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::preserve_comments>("tmp1_com.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
BOOST_TEST(data == serialized);
{
std::ofstream ofs("tmp1_com1.toml");
ofs << std::setw(80) << serialized;
}
}
BOOST_AUTO_TEST_CASE(test_example_with_comment_nocomment)
{
{
const auto data = toml::parse<toml::preserve_comments>(testinput("example.toml"));
{
std::ofstream ofs("tmp1_com_nocomment.toml");
ofs << std::setw(80) << toml::nocomment << data;
}
const auto serialized = toml::parse<toml::preserve_comments>("tmp1_com_nocomment.toml");
// check no comment exist
BOOST_TEST(!has_comment_inside(serialized));
}
{
const auto data_nocomment = toml::parse<toml::discard_comments>(testinput("example.toml"));
auto serialized = toml::parse<toml::discard_comments>("tmp1_com_nocomment.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
// check collectly serialized
BOOST_TEST(data_nocomment == serialized);
}
}
BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq)
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
testinput("example.toml"));
{
std::ofstream ofs("tmp1_com_map_dq.toml");
ofs << std::setw(80) << data;
}
auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
"tmp1_com_map_dq.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
BOOST_TEST(data == serialized);
{
std::ofstream ofs("tmp1_com1_map_dq.toml");
ofs << std::setw(80) << serialized;
}
}
BOOST_AUTO_TEST_CASE(test_example_with_comment_map_dq_nocomment)
{
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(testinput("example.toml"));
{
std::ofstream ofs("tmp1_com_map_dq_nocomment.toml");
ofs << std::setw(80) << toml::nocomment << data;
}
const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>("tmp1_com_map_dq_nocomment.toml");
BOOST_TEST(!has_comment_inside(serialized));
}
{
const auto data_nocomment = toml::parse<toml::discard_comments>(testinput("example.toml"));
auto serialized = toml::parse<toml::discard_comments>("tmp1_com_map_dq_nocomment.toml");
{
auto& owner = toml::find(serialized, "owner");
auto& bio = toml::find<std::string>(owner, "bio");
const auto CR = std::find(bio.begin(), bio.end(), '\r');
if(CR != bio.end())
{
bio.erase(CR);
}
}
BOOST_TEST(data_nocomment == serialized);
}
}
BOOST_AUTO_TEST_CASE(test_fruit)
{
const auto data = toml::parse(testinput("fruit.toml"));
{
std::ofstream ofs("tmp2.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse("tmp2.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_fruit_map_dq)
{
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
testinput("fruit.toml"));
{
std::ofstream ofs("tmp2.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
"tmp2.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_fruit_with_comments)
{
const auto data = toml::parse<toml::preserve_comments>(testinput("fruit.toml"));
{
std::ofstream ofs("tmp2_com.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments>("tmp2_com.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_fruit_with_comments_map_dq)
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
testinput("fruit.toml"));
{
std::ofstream ofs("tmp2_com.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>("tmp2_com.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_hard_example)
{
const auto data = toml::parse(testinput("hard_example.toml"));
{
std::ofstream ofs("tmp3.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse("tmp3.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_hard_example_map_dq)
{
const auto data = toml::parse<toml::discard_comments, std::map, std::deque>(
testinput("hard_example.toml"));
{
std::ofstream ofs("tmp3.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::discard_comments, std::map, std::deque>(
"tmp3.toml");
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_hard_example_with_comment)
{
const auto data = toml::parse<toml::preserve_comments, std::map, std::deque>(
testinput("hard_example.toml"));
{
std::ofstream ofs("tmp3_com.toml");
ofs << std::setw(80) << data;
}
const auto serialized = toml::parse<toml::preserve_comments, std::map, std::deque>(
"tmp3_com.toml");
{
std::ofstream ofs("tmp3_com1.toml");
ofs << std::setw(80) << serialized;
}
BOOST_TEST(data == serialized);
}
BOOST_AUTO_TEST_CASE(test_format_key)
{
{
const toml::key key("normal_bare-key");
BOOST_TEST("normal_bare-key" == toml::format_key(key));
}
{
const toml::key key("key.include.dots");
BOOST_TEST("\"key.include.dots\"" == toml::format_key(key));
}
{
const toml::key key("key-include-unicode-\xE3\x81\x82");
BOOST_TEST("\"key-include-unicode-\xE3\x81\x82\"" == toml::format_key(key));
}
{
const toml::key key("special-chars-\\-\"-\b-\f-\r-\n-\t");
BOOST_TEST("\"special-chars-\\\\-\\\"-\\b-\\f-\\r-\\n-\\t\"" == toml::format_key(key));
}
}
// In toml11, an implicitly-defined value does not have any comments.
// So, in the following file,
// ```toml
// # comment
// [[array-of-tables]]
// foo = "bar"
// ```
// The array named "array-of-tables" does not have the comment, but the first
// element of the array has. That means that, the above file is equivalent to
// the following.
// ```toml
// array-of-tables = [
// # comment
// {foo = "bar"},
// ]
// ```
// If the array itself has a comment (value_has_comment_ == true), we should try
// to make it inline.
// ```toml
// # comment about array
// array-of-tables = [
// # comment about table element
// {foo = "bar"}
// ]
// ```
// If it is formatted as a multiline table, the two comments becomes
// indistinguishable.
// ```toml
// # comment about array
// # comment about table element
// [[array-of-tables]]
// foo = "bar"
// ```
// So we need to try to make it inline, and it force-inlines regardless
// of the line width limit.
// It may fail if the element of a table has comment. In that case,
// the array-of-tables will be formatted as a multiline table.
BOOST_AUTO_TEST_CASE(test_distinguish_comment)
{
const std::string str = R"(# comment about array itself
array_of_table = [
# comment about the first element (table)
{key = "value"},
])";
std::istringstream iss(str);
const auto data = toml::parse<toml::preserve_comments>(iss);
const auto serialized = toml::format(data, /*width = */ 0);
std::istringstream reparse(serialized);
const auto parsed = toml::parse<toml::preserve_comments>(reparse);
BOOST_TEST(parsed.at("array_of_table").comments().size() == 1u);
BOOST_TEST(parsed.at("array_of_table").comments().front() == " comment about array itself");
BOOST_TEST(parsed.at("array_of_table").at(0).comments().size() == 1u);
BOOST_TEST(parsed.at("array_of_table").at(0).comments().front() == " comment about the first element (table)");
}
BOOST_AUTO_TEST_CASE(test_serialize_under_locale)
{
// avoid null init (setlocale returns null when it failed)
std::string setloc(std::setlocale(LC_ALL, nullptr));
// fr_FR is a one of locales that uses `,` as a decimal separator.
if(const char* try_hyphen = std::setlocale(LC_ALL, "fr_FR.UTF-8"))
{
setloc = std::string(try_hyphen);
}
else if(const char* try_nohyphen = std::setlocale(LC_ALL, "fr_FR.utf8"))
{
setloc = std::string(try_nohyphen);
}
// In some envs, fr_FR locale has not been installed. Tests must work even in such a case.
// else
// {
// BOOST_TEST(false);
// }
BOOST_TEST_MESSAGE("current locale at the beginning of the test = " << setloc);
const std::string str = R"(
pi = 3.14159
large_int = 1234567890
)";
std::istringstream iss(str);
const auto ref = toml::parse(iss);
const auto serialized_str = toml::format(ref, /*width = */ 80);
BOOST_TEST_MESSAGE("serialized = " << serialized_str);
std::istringstream serialized_iss(serialized_str);
const auto serialized_ref = toml::parse(serialized_iss);
BOOST_TEST(serialized_ref.at("pi").as_floating() == ref.at("pi").as_floating());
BOOST_TEST(serialized_ref.at("large_int").as_integer() == ref.at("large_int").as_integer());
const std::string endloc(std::setlocale(LC_ALL, nullptr));
BOOST_TEST_MESSAGE("current locale at the end of the test = " << endloc);
// check if serializer change global locale
BOOST_TEST(setloc == endloc);
}

58
tests/test_spec.cpp Normal file
View File

@@ -0,0 +1,58 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <toml11/spec.hpp>
TEST_CASE("testing constructor of semantic_version")
{
constexpr auto v123 = toml::semantic_version(1, 2, 3);
CHECK(v123.major == 1);
CHECK(v123.minor == 2);
CHECK(v123.patch == 3);
}
TEST_CASE("testing the ordering of semantic_version")
{
constexpr auto v100 = toml::semantic_version(1, 0, 0);
constexpr auto v101 = toml::semantic_version(1, 0, 1);
constexpr auto v110 = toml::semantic_version(1, 1, 0);
constexpr auto v112 = toml::semantic_version(1, 1, 2);
constexpr auto v121 = toml::semantic_version(1, 2, 1);
CHECK(v100 == v100);
CHECK(v100 >= v100);
CHECK(v100 <= v100);
CHECK_FALSE(v100 != v100);
CHECK_FALSE(v100 > v100);
CHECK_FALSE(v100 < v100);
CHECK(v100 != v101);
CHECK(v100 <= v101);
CHECK(v100 < v101);
CHECK_FALSE(v100 == v101);
CHECK_FALSE(v100 >= v101);
CHECK_FALSE(v100 > v101);
CHECK(v101 != v110);
CHECK(v101 < v110);
CHECK(v101 <= v110);
CHECK_FALSE(v101 == v110);
CHECK_FALSE(v101 > v110);
CHECK_FALSE(v101 >= v110);
CHECK(v110 != v101);
CHECK(v110 > v101);
CHECK(v110 >= v101);
CHECK_FALSE(v110 == v101);
CHECK_FALSE(v110 < v101);
CHECK_FALSE(v110 <= v101);
CHECK(v112 != v121);
CHECK(v112 < v121);
CHECK(v112 <= v121);
CHECK(v121 != v112);
CHECK(v121 > v112);
CHECK(v121 >= v112);
}

78
tests/test_storage.cpp Normal file
View File

@@ -0,0 +1,78 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <toml11/storage.hpp>
TEST_CASE("testing storage construct")
{
toml::detail::storage<int> x(42);
REQUIRE_UNARY(x.is_ok());
CHECK_EQ(x.get(), 42);
CHECK_NE(x.get(), 6*9);
x.get() = 6 * 9;
CHECK_EQ(x.get(), 6*9);
CHECK_NE(x.get(), 42);
}
TEST_CASE("testing storage copy")
{
toml::detail::storage<int> x(42);
toml::detail::storage<int> y(x);
REQUIRE_UNARY(x.is_ok());
REQUIRE_UNARY(y.is_ok());
CHECK_EQ(x.get(), 42);
CHECK_NE(x.get(), 6*9);
CHECK_EQ(y.get(), 42);
CHECK_NE(y.get(), 6*9);
x.get() = 6 * 9;
CHECK_EQ(x.get(), 6*9);
CHECK_NE(x.get(), 42);
CHECK_EQ(y.get(), 42);
CHECK_NE(y.get(), 6*9);
x = y;
CHECK_EQ(x.get(), 42);
CHECK_NE(x.get(), 6*9);
CHECK_EQ(y.get(), 42);
CHECK_NE(y.get(), 6*9);
}
TEST_CASE("testing storage move")
{
toml::detail::storage<int> x(42);
toml::detail::storage<int> y(x);
REQUIRE_UNARY(x.is_ok());
REQUIRE_UNARY(y.is_ok());
CHECK_EQ(x.get(), 42);
CHECK_NE(x.get(), 6*9);
CHECK_EQ(y.get(), 42);
CHECK_NE(y.get(), 6*9);
x.get() = 6 * 9;
CHECK_EQ(x.get(), 6*9);
CHECK_NE(x.get(), 42);
CHECK_EQ(y.get(), 42);
CHECK_NE(y.get(), 6*9);
x = std::move(y);
CHECK_EQ(x.get(), 42);
CHECK_NE(x.get(), 6*9);
}

View File

@@ -1,153 +0,0 @@
#include <toml.hpp>
#include "unit_test.hpp"
BOOST_AUTO_TEST_CASE(test_basic_string)
{
{
const toml::string str("basic string");
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "\"basic string\"");
}
{
const std::string s1 ("basic string");
const toml::string str(s1);
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "\"basic string\"");
}
{
const toml::string str("basic string", toml::string_t::basic);
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "\"basic string\"");
}
{
const std::string s1 ("basic string");
const toml::string str(s1, toml::string_t::basic);
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "\"basic string\"");
}
}
BOOST_AUTO_TEST_CASE(test_basic_ml_string)
{
{
const toml::string str("basic\nstring");
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
BOOST_TEST(oss1.str() == oss2.str());
}
{
const std::string s1 ("basic\nstring");
const toml::string str(s1);
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
BOOST_TEST(oss1.str() == oss2.str());
}
{
const toml::string str("basic\nstring", toml::string_t::basic);
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
BOOST_TEST(oss1.str() == oss2.str());
}
{
const std::string s1 ("basic\nstring");
const toml::string str(s1, toml::string_t::basic);
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "\"\"\"\nbasic\nstring\\\n\"\"\"";
BOOST_TEST(oss1.str() == oss2.str());
}
}
BOOST_AUTO_TEST_CASE(test_literal_string)
{
{
const toml::string str("literal string", toml::string_t::literal);
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "'literal string'");
}
{
const std::string s1 ("literal string");
const toml::string str(s1, toml::string_t::literal);
std::ostringstream oss;
oss << str;
BOOST_TEST(oss.str() == "'literal string'");
}
}
BOOST_AUTO_TEST_CASE(test_literal_ml_string)
{
{
const toml::string str("literal\nstring", toml::string_t::literal);
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "'''\nliteral\nstring'''";
BOOST_TEST(oss1.str() == oss2.str());
}
{
const std::string s1 ("literal\nstring");
const toml::string str(s1, toml::string_t::literal);
std::ostringstream oss1;
oss1 << str;
std::ostringstream oss2;
oss2 << "'''\nliteral\nstring'''";
BOOST_TEST(oss1.str() == oss2.str());
}
}
BOOST_AUTO_TEST_CASE(test_string_add_assign)
{
// string literal
{
toml::string str("foo");
str += "bar";
BOOST_TEST(str.str == "foobar");
}
// std::string
{
toml::string str("foo");
std::string str2("bar");
str += str2;
BOOST_TEST(str.str == "foobar");
}
// toml::string
{
toml::string str("foo");
toml::string str2("bar");
str += str2;
BOOST_TEST(str.str == "foobar");
}
#if TOML11_CPLUSPLUS_STANDARD_VERSION >= 201703L
// std::string_view
{
toml::string str("foo");
str += std::string_view("bar");
BOOST_TEST(str == "foobar");
}
#endif
// std::string += toml::string
{
std::string str("foo");
toml::string str2("bar");
str += str2;
BOOST_TEST(str == "foobar");
}
}

View File

@@ -0,0 +1,28 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "utility.hpp"
#include <toml11/syntax.hpp>
TEST_CASE("testing boolean should success")
{
const auto scanner = toml::detail::syntax::boolean(toml::spec::v(1,0,0));
test_scan_success(scanner, "true", "true");
test_scan_success(scanner, "false", "false");
test_scan_success(scanner, "true # comment", "true");
test_scan_success(scanner, "false # comment", "false");
}
TEST_CASE("testing boolean should fail")
{
const auto scanner = toml::detail::syntax::boolean(toml::spec::v(1,0,0));
test_scan_failure(scanner, "TRUE");
test_scan_failure(scanner, "FALSE");
test_scan_failure(scanner, "True");
test_scan_failure(scanner, "False");
test_scan_failure(scanner, "T");
test_scan_failure(scanner, "F");
}

View File

@@ -0,0 +1,16 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "utility.hpp"
#include <toml11/syntax.hpp>
TEST_CASE("testing comment")
{
const auto scanner = toml::detail::syntax::comment(toml::spec::v(1,0,0));
test_scan_success(scanner, "# hoge", "# hoge");
test_scan_success(scanner, "# \n", "# ");
test_scan_success(scanner, "# \r\n", "# ");
test_scan_success(scanner, "# # \n", "# # ");
}

View File

@@ -0,0 +1,136 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "utility.hpp"
#include <toml11/syntax.hpp>
TEST_CASE("testing offset_datetime")
{
{
const auto scanner = toml::detail::syntax::offset_datetime(toml::spec::v(1,0,0));
test_scan_success(scanner,
"1979-05-27T07:32:00Z",
"1979-05-27T07:32:00Z");
test_scan_success(scanner,
"1979-05-27T07:32:00-07:00",
"1979-05-27T07:32:00-07:00");
test_scan_success(scanner,
"1979-05-27T07:32:00.999999-07:00",
"1979-05-27T07:32:00.999999-07:00");
test_scan_success(scanner,
"1979-05-27 07:32:00Z",
"1979-05-27 07:32:00Z");
test_scan_success(scanner,
"1979-05-27 07:32:00-07:00",
"1979-05-27 07:32:00-07:00");
test_scan_success(scanner,
"1979-05-27 07:32:00.999999-07:00",
"1979-05-27 07:32:00.999999-07:00");
}
{
auto spec = toml::spec::v(1,0,0);
spec.v1_1_0_make_seconds_optional = true;
const auto scanner = toml::detail::syntax::offset_datetime(spec);
test_scan_success(scanner,
"1979-05-27T07:32Z",
"1979-05-27T07:32Z");
test_scan_success(scanner,
"1979-05-27T07:32:00Z",
"1979-05-27T07:32:00Z");
test_scan_success(scanner,
"1979-05-27T07:32:00-07:00",
"1979-05-27T07:32:00-07:00");
test_scan_success(scanner,
"1979-05-27T07:32:00.999999-07:00",
"1979-05-27T07:32:00.999999-07:00");
test_scan_success(scanner,
"1979-05-27 07:32Z",
"1979-05-27 07:32Z");
test_scan_success(scanner,
"1979-05-27 07:32:00Z",
"1979-05-27 07:32:00Z");
test_scan_success(scanner,
"1979-05-27 07:32:00-07:00",
"1979-05-27 07:32:00-07:00");
test_scan_success(scanner,
"1979-05-27 07:32:00.999999-07:00",
"1979-05-27 07:32:00.999999-07:00");
}
}
TEST_CASE("testing local_datetime")
{
{
const auto scanner = toml::detail::syntax::local_datetime(toml::spec::v(1,0,0));
test_scan_success(scanner,
"1979-05-27T07:32:00",
"1979-05-27T07:32:00");
test_scan_success(scanner,
"1979-05-27T07:32:00.999999",
"1979-05-27T07:32:00.999999");
test_scan_success(scanner,
"1979-05-27 07:32:00",
"1979-05-27 07:32:00");
test_scan_success(scanner,
"1979-05-27 07:32:00.999999",
"1979-05-27 07:32:00.999999");
}
{
auto spec = toml::spec::v(1,0,0);
spec.v1_1_0_make_seconds_optional = true;
const auto scanner = toml::detail::syntax::local_datetime(spec);
test_scan_success(scanner,
"1979-05-27T07:32",
"1979-05-27T07:32");
test_scan_success(scanner,
"1979-05-27T07:32:00",
"1979-05-27T07:32:00");
test_scan_success(scanner,
"1979-05-27T07:32:00.999999",
"1979-05-27T07:32:00.999999");
test_scan_success(scanner,
"1979-05-27 07:32:00",
"1979-05-27 07:32:00");
test_scan_success(scanner,
"1979-05-27 07:32:00.999999",
"1979-05-27 07:32:00.999999");
}
}
TEST_CASE("testing local_date")
{
const auto scanner = toml::detail::syntax::local_date(toml::spec::v(1,0,0));
test_scan_success(scanner, "1979-05-27", "1979-05-27");
}
TEST_CASE("testing local_time")
{
{
const auto scanner = toml::detail::syntax::local_time(toml::spec::v(1,0,0));
test_scan_success(scanner, "07:32:00", "07:32:00");
test_scan_success(scanner, "07:32:00.999999", "07:32:00.999999");
}
{
auto spec = toml::spec::v(1,0,0);
spec.v1_1_0_make_seconds_optional = true;
const auto scanner = toml::detail::syntax::local_time(spec);
test_scan_success(scanner, "07:32", "07:32");
test_scan_success(scanner, "07:32:00", "07:32:00");
test_scan_success(scanner, "07:32:00.999999", "07:32:00.999999");
}
}

View File

@@ -0,0 +1,99 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "utility.hpp"
#include <toml11/syntax.hpp>
TEST_CASE("testing fractional_valid")
{
const auto floating = toml::detail::syntax::floating(toml::spec::v(1,0,0));
test_scan_success(floating, "1.0", "1.0" );
test_scan_success(floating, "0.1", "0.1" );
test_scan_success(floating, "0.001", "0.001" );
test_scan_success(floating, "0.100", "0.100" );
test_scan_success(floating, "+3.14", "+3.14" );
test_scan_success(floating, "-3.14", "-3.14" );
test_scan_success(floating, "3.1415_9265_3589", "3.1415_9265_3589" );
test_scan_success(floating, "+3.1415_9265_3589", "+3.1415_9265_3589");
test_scan_success(floating, "-3.1415_9265_3589", "-3.1415_9265_3589");
test_scan_success(floating, "123_456.789", "123_456.789" );
test_scan_success(floating, "+123_456.789", "+123_456.789" );
test_scan_success(floating, "-123_456.789", "-123_456.789" );
}
TEST_CASE("testing fractional_invalid")
{
const auto floating = toml::detail::syntax::floating(toml::spec::v(1,0,0));
test_scan_failure(floating, "0.");
test_scan_failure(floating, ".0");
test_scan_failure(floating, "01.0");
test_scan_failure(floating, "3,14");
test_scan_failure(floating, "+-1.0");
test_scan_failure(floating, "1._0");
}
TEST_CASE("testing exponential_valid")
{
const auto floating = toml::detail::syntax::floating(toml::spec::v(1,0,0));
test_scan_success(floating, "1e10", "1e10");
test_scan_success(floating, "1e+10", "1e+10");
test_scan_success(floating, "1e-10", "1e-10");
test_scan_success(floating, "+1e10", "+1e10");
test_scan_success(floating, "+1e+10", "+1e+10");
test_scan_success(floating, "+1e-10", "+1e-10");
test_scan_success(floating, "-1e10", "-1e10");
test_scan_success(floating, "-1e+10", "-1e+10");
test_scan_success(floating, "-1e-10", "-1e-10");
test_scan_success(floating, "123e-10", "123e-10");
test_scan_success(floating, "1E10", "1E10");
test_scan_success(floating, "1E+10", "1E+10");
test_scan_success(floating, "1E-10", "1E-10");
test_scan_success(floating, "123E-10", "123E-10");
test_scan_success(floating, "1_2_3E-10", "1_2_3E-10");
test_scan_success(floating, "1_2_3E-1_0", "1_2_3E-1_0");
test_scan_success(floating, "1_2_3E-01", "1_2_3E-01");
test_scan_success(floating, "1_2_3E-0_1", "1_2_3E-0_1");
}
TEST_CASE("testing exponential_invalid")
{
const auto floating = toml::detail::syntax::floating(toml::spec::v(1,0,0));
// accept partially
test_scan_success(floating, "1e1E0", "1e1");
test_scan_success(floating, "1E1e0", "1E1");
}
TEST_CASE("testing both_valid")
{
const auto floating = toml::detail::syntax::floating(toml::spec::v(1,0,0));
test_scan_success(floating, "6.02e23", "6.02e23");
test_scan_success(floating, "6.02e+23", "6.02e+23");
test_scan_success(floating, "1.112_650_06e-17", "1.112_650_06e-17");
test_scan_success(floating, "1.0e-07", "1.0e-07");
}
TEST_CASE("testing both_invalid")
{
const auto floating = toml::detail::syntax::floating(toml::spec::v(1,0,0));
test_scan_failure(floating, "01e1.0");
// accept partially
test_scan_success(floating, "1e1.0", "1e1");
test_scan_success(floating, "1.0e_01", "1.0");
test_scan_success(floating, "1.0e0__1", "1.0e0");
}
TEST_CASE("testing special_floating_point")
{
const auto floating = toml::detail::syntax::floating(toml::spec::v(1,0,0));
test_scan_success(floating, "inf", "inf");
test_scan_success(floating, "+inf", "+inf");
test_scan_success(floating, "-inf", "-inf");
test_scan_success(floating, "nan", "nan");
test_scan_success(floating, "+nan", "+nan");
test_scan_success(floating, "-nan", "-nan");
}

View File

@@ -0,0 +1,117 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "utility.hpp"
#include <toml11/syntax.hpp>
TEST_CASE("testing decimal_correct")
{
const auto integer = toml::detail::syntax::integer(toml::spec::v(1,0,0));
test_scan_success(integer, "1234", "1234" );
test_scan_success(integer, "+1234", "+1234" );
test_scan_success(integer, "-1234", "-1234" );
test_scan_success(integer, "0", "0" );
test_scan_success(integer, "1_2_3_4", "1_2_3_4" );
test_scan_success(integer, "+1_2_3_4", "+1_2_3_4" );
test_scan_success(integer, "-1_2_3_4", "-1_2_3_4" );
test_scan_success(integer, "123_456_789", "123_456_789");
}
TEST_CASE("testing decimal_invalid")
{
const auto integer = toml::detail::syntax::integer(toml::spec::v(1,0,0));
test_scan_success(integer, "123+45", "123");
test_scan_success(integer, "123-45", "123");
test_scan_success(integer, "01234", "0");
test_scan_success(integer, "123__45", "123");
test_scan_failure(integer, "_1234");
}
TEST_CASE("testing hex_correct")
{
const auto integer = toml::detail::syntax::integer(toml::spec::v(1,0,0));
test_scan_success(integer, "0xDEADBEEF", "0xDEADBEEF" );
test_scan_success(integer, "0xdeadbeef", "0xdeadbeef" );
test_scan_success(integer, "0xDEADbeef", "0xDEADbeef" );
test_scan_success(integer, "0xDEAD_BEEF", "0xDEAD_BEEF");
test_scan_success(integer, "0xdead_beef", "0xdead_beef");
test_scan_success(integer, "0xdead_BEEF", "0xdead_BEEF");
test_scan_success(integer, "0xFF", "0xFF" );
test_scan_success(integer, "0x00FF", "0x00FF" );
test_scan_success(integer, "0x0000FF", "0x0000FF");
}
TEST_CASE("testing hex_invalid")
{
const auto integer = toml::detail::syntax::integer(toml::spec::v(1,0,0));
const auto hex_int = toml::detail::syntax::hex_int(toml::spec::v(1,0,0));
test_scan_success(integer, "0xAPPLE", "0xA");
test_scan_success(integer, "0xDEAD+BEEF", "0xDEAD");
test_scan_success(integer, "0xDEAD__BEEF", "0xDEAD");
test_scan_failure(hex_int, "0x_DEADBEEF");
test_scan_failure(hex_int, "0x+DEADBEEF");
test_scan_failure(hex_int, "-0xFF" );
test_scan_failure(hex_int, "-0x00FF" );
test_scan_success(integer, "0x_DEADBEEF", "0" );
test_scan_success(integer, "0x+DEADBEEF", "0" );
test_scan_success(integer, "-0xFF" , "-0" );
test_scan_success(integer, "-0x00FF" , "-0" );
}
TEST_CASE("testing oct_correct")
{
const auto integer = toml::detail::syntax::integer(toml::spec::v(1,0,0));
test_scan_success(integer, "0o777", "0o777" );
test_scan_success(integer, "0o7_7_7", "0o7_7_7");
test_scan_success(integer, "0o007", "0o007" );
}
TEST_CASE("testing oct_invalid")
{
const auto integer = toml::detail::syntax::integer(toml::spec::v(1,0,0));
const auto oct_int = toml::detail::syntax::hex_int(toml::spec::v(1,0,0));
test_scan_success(integer, "0o77+7", "0o77");
test_scan_success(integer, "0o1__0", "0o1");
test_scan_failure(oct_int, "0o800" );
test_scan_failure(oct_int, "-0o777");
test_scan_failure(oct_int, "0o+777");
test_scan_failure(oct_int, "0o_10" );
test_scan_success(integer, "0o800", "0");
test_scan_success(integer, "-0o777", "-0");
test_scan_success(integer, "0o+777", "0");
test_scan_success(integer, "0o_10", "0");
}
TEST_CASE("testing bin_correct")
{
const auto integer = toml::detail::syntax::integer(toml::spec::v(1,0,0));
test_scan_success(integer, "0b10000", "0b10000" );
test_scan_success(integer, "0b010000", "0b010000" );
test_scan_success(integer, "0b01_00_00", "0b01_00_00");
test_scan_success(integer, "0b111111", "0b111111" );
}
TEST_CASE("testing bin_invalid")
{
const auto bin_int = toml::detail::syntax::bin_int(toml::spec::v(1,0,0));
test_scan_success(bin_int, "0b11__11", "0b11");
test_scan_success(bin_int, "0b11+11" , "0b11");
test_scan_failure(bin_int, "-0b10000");
test_scan_failure(bin_int, "0b_1111" );
}

49
tests/test_syntax_key.cpp Normal file
View File

@@ -0,0 +1,49 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "utility.hpp"
#include <toml11/syntax.hpp>
TEST_CASE("testing bare_key")
{
const auto scanner = toml::detail::syntax::key(toml::spec::v(1,0,0));
test_scan_success(scanner, "barekey", "barekey");
test_scan_success(scanner, "bare-key", "bare-key");
test_scan_success(scanner, "bare_key", "bare_key");
test_scan_success(scanner, "1234", "1234");
}
TEST_CASE("testing quoted_key")
{
const auto scanner = toml::detail::syntax::key(toml::spec::v(1,0,0));
test_scan_success(scanner, "\"127.0.0.1\"", "\"127.0.0.1\"");
test_scan_success(scanner, "\"character encoding\"", "\"character encoding\"");
// UTF-8 codepoint of characters that looks like "key" written upside down
test_scan_success(scanner, "\"\xCA\x8E\xC7\x9D\xCA\x9E\"",
"\"\xCA\x8E\xC7\x9D\xCA\x9E\"");
test_scan_success(scanner, "'key2'", "'key2'");
test_scan_success(scanner, "'quoted \"value\"'", "'quoted \"value\"'");
}
TEST_CASE("testing dotted_key")
{
const auto scanner = toml::detail::syntax::key(toml::spec::v(1,0,0));
test_scan_success(scanner, "physical.color", "physical.color");
test_scan_success(scanner, "physical.shape", "physical.shape");
test_scan_success(scanner, "x.y", "x.y");
test_scan_success(scanner, "x . y", "x . y");
test_scan_success(scanner, "x.y.z", "x.y.z");
test_scan_success(scanner, "x. y .z", "x. y .z");
test_scan_success(scanner, "x .y. z", "x .y. z");
test_scan_success(scanner, "x . y . z", "x . y . z");
test_scan_success(scanner, "x.y.z.w", "x.y.z.w");
test_scan_success(scanner, "x. y .z. w", "x. y .z. w");
test_scan_success(scanner, "x . y . z . w", "x . y . z . w");
test_scan_success(scanner, "site.\"google.com\"", "site.\"google.com\"");
}

View File

@@ -1,108 +1,125 @@
#include <toml/lexer.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include "utility.hpp"
#include "test_lex_aux.hpp"
using namespace toml; #include <toml11/syntax.hpp>
using namespace detail;
BOOST_AUTO_TEST_CASE(test_string) TEST_CASE("testing string")
{ {
TOML11_TEST_LEX_ACCEPT(lex_string, const auto string = toml::detail::syntax::string(toml::spec::v(1,0,0));
const auto ml_basic_string = toml::detail::syntax::ml_basic_string(toml::spec::v(1,0,0));
const auto ml_literal_string = toml::detail::syntax::ml_literal_string(toml::spec::v(1,0,0));
test_scan_success(string,
"\"The quick brown fox jumps over the lazy dog\"", "\"The quick brown fox jumps over the lazy dog\"",
"\"The quick brown fox jumps over the lazy dog\""); "\"The quick brown fox jumps over the lazy dog\"");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"\'The quick brown fox jumps over the lazy dog\'", "\'The quick brown fox jumps over the lazy dog\'",
"\'The quick brown fox jumps over the lazy dog\'"); "\'The quick brown fox jumps over the lazy dog\'");
TOML11_TEST_LEX_ACCEPT(lex_ml_basic_string, test_scan_success(ml_basic_string,
"\"\"\"The quick brown fox jumps over the lazy dog\"\"\"",
"\"\"\"The quick brown fox jumps over the lazy dog\"\"\"");
test_scan_success(ml_basic_string,
"\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"", "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"",
"\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\""); "\"\"\"The quick brown fox \\\njumps over the lazy dog\"\"\"");
TOML11_TEST_LEX_ACCEPT(lex_ml_literal_string, test_scan_success(ml_literal_string,
"'''The quick brown fox jumps over the lazy dog'''",
"'''The quick brown fox jumps over the lazy dog'''");
test_scan_success(ml_literal_string,
"'''The quick brown fox \njumps over the lazy dog'''", "'''The quick brown fox \njumps over the lazy dog'''",
"'''The quick brown fox \njumps over the lazy dog'''"); "'''The quick brown fox \njumps over the lazy dog'''");
} }
BOOST_AUTO_TEST_CASE(test_basic_string) TEST_CASE("testing basic_string")
{ {
TOML11_TEST_LEX_ACCEPT(lex_string, const auto string = toml::detail::syntax::string(toml::spec::v(1,0,0));
test_scan_success(string,
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"", "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"",
"\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\""); "\"GitHub Cofounder & CEO\\nLikes tater tots and beer.\"");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"\"192.168.1.1\"", "\"192.168.1.1\"",
"\"192.168.1.1\""); "\"192.168.1.1\"");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"\"\xE4\xB8\xAD\xE5\x9B\xBD\"", // UTF-8 string (means "China" in "\"\xE4\xB8\xAD\xE5\x9B\xBD\"", // UTF-8 string (means "China" in
"\"\xE4\xB8\xAD\xE5\x9B\xBD\""); // Chinese characters) "\"\xE4\xB8\xAD\xE5\x9B\xBD\""); // Chinese characters)
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"\"You'll hate me after this - #\"", "\"You'll hate me after this - #\"",
"\"You'll hate me after this - #\""); "\"You'll hate me after this - #\"");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"\" And when \\\"'s are in the string, along with # \\\"\"", "\" And when \\\"'s are in the string, along with # \\\"\"",
"\" And when \\\"'s are in the string, along with # \\\"\""); "\" And when \\\"'s are in the string, along with # \\\"\"");
} }
BOOST_AUTO_TEST_CASE(test_ml_basic_string) TEST_CASE("testing ml_basic_string")
{ {
TOML11_TEST_LEX_ACCEPT(lex_string, const auto string = toml::detail::syntax::string(toml::spec::v(1,0,0));
test_scan_success(string,
"\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"", "\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"",
"\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\""); "\"\"\"\nThe quick brown \\\n\n fox jumps over \\\n the lazy dog.\"\"\"");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"", "\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"",
"\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\""); "\"\"\"\\\n The quick brown \\\n\n fox jumps over \\\n the lazy dog.\\\n \"\"\"");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"", "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"",
"\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\""); "\"\"\"Here are two quotation marks: \"\". Simple enough.\"\"\"");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"", "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"",
"\"\"\"Here are three quotation marks: \"\"\\\".\"\"\""); "\"\"\"Here are three quotation marks: \"\"\\\".\"\"\"");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"", "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"",
"\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\""); "\"\"\"Here are fifteen quotation marks: \"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\"\"\"\\\".\"\"\"");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"", "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"",
"\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\""); "\"\"\"\"This,\" she said, \"is just a pointless statement.\"\"\"\"");
} }
BOOST_AUTO_TEST_CASE(test_literal_string) TEST_CASE("testing literal_string")
{ {
TOML11_TEST_LEX_ACCEPT(lex_string, const auto string = toml::detail::syntax::string(toml::spec::v(1,0,0));
test_scan_success(string,
"'C:\\Users\\nodejs\\templates'", "'C:\\Users\\nodejs\\templates'",
"'C:\\Users\\nodejs\\templates'"); "'C:\\Users\\nodejs\\templates'");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"'\\\\ServerX\\admin$\\system32\\'", "'\\\\ServerX\\admin$\\system32\\'",
"'\\\\ServerX\\admin$\\system32\\'"); "'\\\\ServerX\\admin$\\system32\\'");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"'Tom \"Dubs\" Preston-Werner'", "'Tom \"Dubs\" Preston-Werner'",
"'Tom \"Dubs\" Preston-Werner'"); "'Tom \"Dubs\" Preston-Werner'");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"'<\\i\\c*\\s*>'", "'<\\i\\c*\\s*>'",
"'<\\i\\c*\\s*>'"); "'<\\i\\c*\\s*>'");
} }
BOOST_AUTO_TEST_CASE(test_ml_literal_string) TEST_CASE("testing ml_literal_string")
{ {
TOML11_TEST_LEX_ACCEPT(lex_string, const auto string = toml::detail::syntax::string(toml::spec::v(1,0,0));
test_scan_success(string,
"'''I [dw]on't need \\d{2} apples'''", "'''I [dw]on't need \\d{2} apples'''",
"'''I [dw]on't need \\d{2} apples'''"); "'''I [dw]on't need \\d{2} apples'''");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''", "'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''",
"'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''"); "'''\nThe first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n'''");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"''''That's still pointless', she said.'''", "''''That's still pointless', she said.'''",
"''''That's still pointless', she said.'''"); "''''That's still pointless', she said.'''");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''", "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''",
"'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''"); "'''Here are fifteen quotation marks: \"\"\"\"\"\"\"\"\"\"\"\"\"\"\".'''");
TOML11_TEST_LEX_ACCEPT(lex_string, test_scan_success(string,
"''''This,' she said, 'is just a pointless statement.''''", "''''This,' she said, 'is just a pointless statement.''''",
"''''This,' she said, 'is just a pointless statement.''''"); "''''This,' she said, 'is just a pointless statement.''''");
} }

View File

@@ -1,6 +1,7 @@
#include <toml/types.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include <toml11/types.hpp>
#include <array> #include <array>
#include <deque> #include <deque>
@@ -17,63 +18,72 @@ struct dummy_type{};
template<typename T> template<typename T>
struct dummy_container struct dummy_container
{ {
typedef T value_type; typedef T value_type;
typedef value_type* pointer; typedef value_type* pointer;
typedef value_type& reference; typedef value_type& reference;
typedef value_type const* const_pointer; typedef value_type const* const_pointer;
typedef value_type const& const_reference; typedef value_type const& const_reference;
typedef pointer iterator; typedef pointer iterator;
typedef const_pointer const_iterator; typedef const_pointer const_iterator;
}; };
typedef std::array<dummy_type, 10> std_array_type; TEST_CASE("testing has_xxx traits")
typedef std::map<std::string, dummy_type> std_map_type;
typedef std::unordered_map<std::string, dummy_type> std_unordered_map_type;
BOOST_AUTO_TEST_CASE(test_has_xxx)
{ {
BOOST_TEST(toml::detail::has_iterator<std::list<dummy_type>>::value); CHECK_UNARY(toml::detail::has_iterator<std::list<dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std::forward_list<dummy_type>>::value); CHECK_UNARY(toml::detail::has_iterator<std::forward_list<dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std::deque<dummy_type>>::value); CHECK_UNARY(toml::detail::has_iterator<std::deque<dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std::vector<dummy_type>>::value); CHECK_UNARY(toml::detail::has_iterator<std::vector<dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std::set<dummy_type>>::value); CHECK_UNARY(toml::detail::has_iterator<std::set<dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std::unordered_set<std::string>>::value); CHECK_UNARY(toml::detail::has_iterator<std::unordered_set<std::string>>::value);
BOOST_TEST(toml::detail::has_iterator<std_array_type>::value); CHECK_UNARY(toml::detail::has_iterator<std::array<dummy_type, 10>>::value);
BOOST_TEST(toml::detail::has_iterator<std_map_type>::value); CHECK_UNARY(toml::detail::has_iterator<std::map<std::string, dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<std_unordered_map_type>::value); CHECK_UNARY(toml::detail::has_iterator<std::unordered_map<std::string, dummy_type>>::value);
BOOST_TEST(toml::detail::has_iterator<dummy_container<dummy_type>>::value); CHECK_UNARY(toml::detail::has_iterator<dummy_container<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std::list<dummy_type>>::value); CHECK_UNARY(toml::detail::has_value_type<std::list<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std::forward_list<dummy_type>>::value); CHECK_UNARY(toml::detail::has_value_type<std::forward_list<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std::deque<dummy_type>>::value); CHECK_UNARY(toml::detail::has_value_type<std::deque<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std::vector<dummy_type>>::value); CHECK_UNARY(toml::detail::has_value_type<std::vector<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std_array_type>::value); CHECK_UNARY(toml::detail::has_value_type<std::array<dummy_type, 10>>::value);
BOOST_TEST(toml::detail::has_value_type<std::set<dummy_type>>::value); CHECK_UNARY(toml::detail::has_value_type<std::set<dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std::unordered_set<std::string>>::value); CHECK_UNARY(toml::detail::has_value_type<std::unordered_set<std::string>>::value);
BOOST_TEST(toml::detail::has_value_type<std_map_type>::value); CHECK_UNARY(toml::detail::has_value_type<std::map<std::string, dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<std_unordered_map_type>::value); CHECK_UNARY(toml::detail::has_value_type<std::unordered_map<std::string, dummy_type>>::value);
BOOST_TEST(toml::detail::has_value_type<dummy_container<dummy_type>>::value); CHECK_UNARY(toml::detail::has_value_type<dummy_container<dummy_type>>::value);
BOOST_TEST(toml::detail::has_key_type<std_map_type>::value); CHECK_UNARY(toml::detail::has_key_type<std::map<std::string, dummy_type>>::value);
BOOST_TEST(toml::detail::has_key_type<std_unordered_map_type>::value); CHECK_UNARY(toml::detail::has_key_type<std::unordered_map<std::string, dummy_type>>::value);
BOOST_TEST(toml::detail::has_mapped_type<std_map_type>::value); CHECK_UNARY(toml::detail::has_mapped_type<std::map<std::string, dummy_type>>::value);
BOOST_TEST(toml::detail::has_mapped_type<std_unordered_map_type>::value); CHECK_UNARY(toml::detail::has_mapped_type<std::unordered_map<std::string, dummy_type>>::value);
} }
BOOST_AUTO_TEST_CASE(test_is_xxx) TEST_CASE("testing is_xxx traits")
{ {
BOOST_TEST(toml::detail::is_container<std::list<dummy_type>>::value); CHECK_UNARY(toml::detail::is_container<std::list<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std::forward_list<dummy_type>>::value); CHECK_UNARY(toml::detail::is_container<std::forward_list<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std::deque<dummy_type>>::value); CHECK_UNARY(toml::detail::is_container<std::deque<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std::vector<dummy_type>>::value); CHECK_UNARY(toml::detail::is_container<std::vector<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std_array_type>::value); CHECK_UNARY(toml::detail::is_container<std::array<dummy_type, 10>>::value);
BOOST_TEST(toml::detail::is_container<std::set<dummy_type>>::value); CHECK_UNARY(toml::detail::is_container<std::set<dummy_type>>::value);
BOOST_TEST(toml::detail::is_container<std::unordered_set<std::string>>::value); CHECK_UNARY(toml::detail::is_container<std::unordered_set<std::string>>::value);
BOOST_TEST(toml::detail::is_container<dummy_container<dummy_type>>::value); CHECK_UNARY(toml::detail::is_container<dummy_container<dummy_type>>::value);
BOOST_TEST(!toml::detail::is_container<std_map_type>::value); CHECK_UNARY_FALSE(toml::detail::is_container<std::map<std::string, dummy_type>>::value);
BOOST_TEST(!toml::detail::is_container<std_unordered_map_type>::value); CHECK_UNARY_FALSE(toml::detail::is_container<std::unordered_map<std::string, dummy_type>>::value);
BOOST_TEST(toml::detail::is_map<std_map_type>::value); CHECK_UNARY(toml::detail::is_map<std::map<std::string, dummy_type>>::value);
BOOST_TEST(toml::detail::is_map<std_unordered_map_type>::value); CHECK_UNARY(toml::detail::is_map<std::unordered_map<std::string, dummy_type>>::value);
}
TEST_CASE("testing make_index_sequence")
{
static_assert(std::is_same<toml::cxx::make_index_sequence<0>, toml::cxx::index_sequence<>>::value, "");
static_assert(std::is_same<toml::cxx::make_index_sequence<1>, toml::cxx::index_sequence<0>>::value, "");
static_assert(std::is_same<toml::cxx::make_index_sequence<2>, toml::cxx::index_sequence<0,1>>::value, "");
static_assert(std::is_same<toml::cxx::make_index_sequence<3>, toml::cxx::index_sequence<0,1,2>>::value, "");
static_assert(std::is_same<toml::cxx::make_index_sequence<4>, toml::cxx::index_sequence<0,1,2,3>>::value, "");
static_assert(std::is_same<toml::cxx::make_index_sequence<5>, toml::cxx::index_sequence<0,1,2,3,4>>::value, "");
static_assert(std::is_same<toml::cxx::make_index_sequence<6>, toml::cxx::index_sequence<0,1,2,3,4,5>>::value, "");
static_assert(std::is_same<toml::cxx::make_index_sequence<7>, toml::cxx::index_sequence<0,1,2,3,4,5,6>>::value, "");
static_assert(std::is_same<toml::cxx::make_index_sequence<8>, toml::cxx::index_sequence<0,1,2,3,4,5,6,7>>::value, "");
} }

137
tests/test_types.cpp Normal file
View File

@@ -0,0 +1,137 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <toml11/types.hpp>
TEST_CASE("testing value_t to string")
{
CHECK_EQ(toml::to_string(toml::value_t::boolean ), "boolean");
CHECK_EQ(toml::to_string(toml::value_t::integer ), "integer");
CHECK_EQ(toml::to_string(toml::value_t::floating ), "floating");
CHECK_EQ(toml::to_string(toml::value_t::string ), "string");
CHECK_EQ(toml::to_string(toml::value_t::offset_datetime), "offset_datetime");
CHECK_EQ(toml::to_string(toml::value_t::local_datetime ), "local_datetime");
CHECK_EQ(toml::to_string(toml::value_t::local_date ), "local_date");
CHECK_EQ(toml::to_string(toml::value_t::local_time ), "local_time");
CHECK_EQ(toml::to_string(toml::value_t::array ), "array");
CHECK_EQ(toml::to_string(toml::value_t::table ), "table");
{std::ostringstream oss; oss << toml::value_t::boolean ; CHECK_EQ(oss.str(), "boolean" );}
{std::ostringstream oss; oss << toml::value_t::integer ; CHECK_EQ(oss.str(), "integer" );}
{std::ostringstream oss; oss << toml::value_t::floating ; CHECK_EQ(oss.str(), "floating" );}
{std::ostringstream oss; oss << toml::value_t::string ; CHECK_EQ(oss.str(), "string" );}
{std::ostringstream oss; oss << toml::value_t::offset_datetime; CHECK_EQ(oss.str(), "offset_datetime");}
{std::ostringstream oss; oss << toml::value_t::local_datetime ; CHECK_EQ(oss.str(), "local_datetime" );}
{std::ostringstream oss; oss << toml::value_t::local_date ; CHECK_EQ(oss.str(), "local_date" );}
{std::ostringstream oss; oss << toml::value_t::local_time ; CHECK_EQ(oss.str(), "local_time" );}
{std::ostringstream oss; oss << toml::value_t::array ; CHECK_EQ(oss.str(), "array" );}
{std::ostringstream oss; oss << toml::value_t::table ; CHECK_EQ(oss.str(), "table" );}
}
#include <toml11/value.hpp>
TEST_CASE("testing type_to_enum")
{
using value_type = toml::value;
using boolean_type = typename value_type::boolean_type ;
using integer_type = typename value_type::integer_type ;
using floating_type = typename value_type::floating_type ;
using string_type = typename value_type::string_type ;
using local_time_type = typename value_type::local_time_type ;
using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
CHECK_EQ((toml::detail::type_to_enum<boolean_type , value_type>::value), toml::value_t::boolean );
CHECK_EQ((toml::detail::type_to_enum<integer_type , value_type>::value), toml::value_t::integer );
CHECK_EQ((toml::detail::type_to_enum<floating_type , value_type>::value), toml::value_t::floating );
CHECK_EQ((toml::detail::type_to_enum<string_type , value_type>::value), toml::value_t::string );
CHECK_EQ((toml::detail::type_to_enum<local_time_type , value_type>::value), toml::value_t::local_time );
CHECK_EQ((toml::detail::type_to_enum<local_date_type , value_type>::value), toml::value_t::local_date );
CHECK_EQ((toml::detail::type_to_enum<local_datetime_type , value_type>::value), toml::value_t::local_datetime );
CHECK_EQ((toml::detail::type_to_enum<offset_datetime_type, value_type>::value), toml::value_t::offset_datetime);
CHECK_EQ((toml::detail::type_to_enum<array_type , value_type>::value), toml::value_t::array );
CHECK_EQ((toml::detail::type_to_enum<table_type , value_type>::value), toml::value_t::table );
}
TEST_CASE("testing enum_to_type")
{
using value_type = toml::value;
using boolean_type = typename value_type::boolean_type ;
using integer_type = typename value_type::integer_type ;
using floating_type = typename value_type::floating_type ;
using string_type = typename value_type::string_type ;
using local_time_type = typename value_type::local_time_type ;
using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
CHECK_UNARY(std::is_same<typename toml::detail::enum_to_type<toml::value_t::boolean , value_type>::type, boolean_type >::value);
CHECK_UNARY(std::is_same<typename toml::detail::enum_to_type<toml::value_t::integer , value_type>::type, integer_type >::value);
CHECK_UNARY(std::is_same<typename toml::detail::enum_to_type<toml::value_t::floating , value_type>::type, floating_type >::value);
CHECK_UNARY(std::is_same<typename toml::detail::enum_to_type<toml::value_t::string , value_type>::type, string_type >::value);
CHECK_UNARY(std::is_same<typename toml::detail::enum_to_type<toml::value_t::local_time , value_type>::type, local_time_type >::value);
CHECK_UNARY(std::is_same<typename toml::detail::enum_to_type<toml::value_t::local_date , value_type>::type, local_date_type >::value);
CHECK_UNARY(std::is_same<typename toml::detail::enum_to_type<toml::value_t::local_datetime , value_type>::type, local_datetime_type >::value);
CHECK_UNARY(std::is_same<typename toml::detail::enum_to_type<toml::value_t::offset_datetime, value_type>::type, offset_datetime_type>::value);
CHECK_UNARY(std::is_same<typename toml::detail::enum_to_type<toml::value_t::array , value_type>::type, array_type >::value);
CHECK_UNARY(std::is_same<typename toml::detail::enum_to_type<toml::value_t::table , value_type>::type, table_type >::value);
}
TEST_CASE("testing is_exact_toml_type")
{
using value_type = toml::value;
using boolean_type = typename value_type::boolean_type ;
using integer_type = typename value_type::integer_type ;
using floating_type = typename value_type::floating_type ;
using string_type = typename value_type::string_type ;
using local_time_type = typename value_type::local_time_type ;
using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
CHECK_UNARY(toml::detail::is_exact_toml_type<boolean_type , value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<integer_type , value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<floating_type , value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<string_type , value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<local_time_type , value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<local_date_type , value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<local_datetime_type , value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<offset_datetime_type, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<array_type , value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<table_type , value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<boolean_type &, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<integer_type &, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<floating_type &, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<string_type &, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<local_time_type &, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<local_date_type &, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<local_datetime_type &, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<offset_datetime_type&, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<array_type &, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<table_type &, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<boolean_type const&, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<integer_type const&, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<floating_type const&, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<string_type const&, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<local_time_type const&, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<local_date_type const&, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<local_datetime_type const&, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<offset_datetime_type const&, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<array_type const&, value_type>::value);
CHECK_UNARY(toml::detail::is_exact_toml_type<table_type const&, value_type>::value);
CHECK_UNARY_FALSE(toml::detail::is_exact_toml_type<float, value_type>::value);
CHECK_UNARY_FALSE(toml::detail::is_exact_toml_type<std::int16_t, value_type>::value);
CHECK_UNARY_FALSE(toml::detail::is_exact_toml_type<std::vector<std::string>, value_type>::value);
}

View File

@@ -0,0 +1,623 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <toml.hpp>
#include "utility.hpp"
namespace extlib
{
struct foo
{
int a;
std::string b;
};
struct bar
{
int a;
std::string b;
void from_toml(const toml::value& v)
{
this->a = toml::find<int>(v, "a");
this->b = toml::find<std::string>(v, "b");
return ;
}
toml::table into_toml() const
{
return toml::table{{"a", this->a}, {"b", this->b}};
}
};
struct baz
{
int a;
std::string b;
};
struct qux
{
int a;
std::string b;
};
struct foobar
{
// via constructor
explicit foobar(const toml::value& v)
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
{}
int a;
std::string b;
};
} // extlib
namespace toml
{
template<>
struct from<extlib::foo>
{
static extlib::foo from_toml(const toml::value& v)
{
return extlib::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib::foo>
{
template<typename TC>
static toml::basic_value<TC> into_toml(const extlib::foo& f)
{
return toml::basic_value<TC>(typename toml::basic_value<TC>::table_type{{"a", f.a}, {"b", f.b}});
}
};
template<>
struct from<extlib::baz>
{
static extlib::baz from_toml(const toml::value& v)
{
return extlib::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib::qux>
{
template<typename TC>
static toml::basic_value<TC> into_toml(const extlib::qux& f)
{
return toml::basic_value<TC>(typename toml::basic_value<TC>::table_type{{"a", f.a}, {"b", f.b}});
}
};
} // toml
// ---------------------------------------------------------------------------
namespace extlib2
{
struct foo
{
int a;
std::string b;
};
struct bar
{
int a;
std::string b;
template<typename TC>
void from_toml(const toml::basic_value<TC>& v)
{
this->a = toml::find<int>(v, "a");
this->b = toml::find<std::string>(v, "b");
return ;
}
toml::ordered_table into_toml() const
{
return toml::ordered_table{{"a", this->a}, {"b", this->b}};
}
};
struct baz
{
int a;
std::string b;
};
struct qux
{
int a;
std::string b;
};
struct foobar
{
template<typename TC>
explicit foobar(const toml::basic_value<TC>& v)
: a(toml::find<int>(v, "a")), b(toml::find<std::string>(v, "b"))
{}
int a;
std::string b;
};
} // extlib2
namespace toml
{
template<>
struct from<extlib2::foo>
{
template<typename TC>
static extlib2::foo from_toml(const toml::basic_value<TC>& v)
{
return extlib2::foo{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib2::foo>
{
template<typename TC>
static toml::basic_value<TC> into_toml(const extlib2::foo& f)
{
return toml::basic_value<TC>(typename toml::basic_value<TC>::table_type{{"a", f.a}, {"b", f.b}});
}
};
template<>
struct from<extlib2::baz>
{
template<typename TC>
static extlib2::baz from_toml(const toml::basic_value<TC>& v)
{
return extlib2::baz{toml::find<int>(v, "a"), toml::find<std::string>(v, "b")};
}
};
template<>
struct into<extlib2::qux>
{
template<typename TC>
static toml::basic_value<TC>
into_toml(const extlib2::qux& f)
{
return toml::basic_value<TC>{
{"a", f.a}, {"b", f.b}
};
}
};
} // toml
// ---------------------------------------------------------------------------
TEST_CASE("test_conversion_by_member_methods")
{
{
const toml::value v(toml::table{{"a", 42}, {"b", "baz"}});
const auto foo = toml::get<extlib::foo>(v);
CHECK_EQ(foo.a, 42);
CHECK_EQ(foo.b, "baz");
const toml::value v2(foo);
CHECK_EQ(v, v2);
}
{
const toml::value v(toml::table{{"a", 42}, {"b", "baz"}});
const auto foo = toml::get<extlib2::foo>(v);
CHECK(foo.a == 42);
CHECK(foo.b == "baz");
const toml::value v2(foo);
CHECK(v == v2);
}
{
const toml::ordered_value v(toml::ordered_table{{"a", 42}, {"b", "baz"}});
const auto foo = toml::get<extlib2::foo>(v);
CHECK(foo.a == 42);
CHECK(foo.b == "baz");
const toml::ordered_value v2(foo);
CHECK(v == v2);
}
}
TEST_CASE("test_conversion_by_specialization")
{
{
const toml::value v(toml::table{{"a", 42}, {"b", "baz"}});
const auto bar = toml::get<extlib::bar>(v);
CHECK(bar.a == 42);
CHECK(bar.b == "baz");
const toml::value v2(bar);
CHECK(v == v2);
}
{
const toml::value v(toml::table{{"a", 42}, {"b", "baz"}});
const auto bar = toml::get<extlib2::bar>(v);
CHECK(bar.a == 42);
CHECK(bar.b == "baz");
const toml::value v2(bar);
CHECK(v == v2);
}
{
const toml::ordered_value v(toml::ordered_table{{"a", 42}, {"b", "baz"}});
const auto bar = toml::get<extlib2::bar>(v);
CHECK(bar.a == 42);
CHECK(bar.b == "baz");
const toml::ordered_value v2(bar);
CHECK(v == v2);
}
}
TEST_CASE("test_conversion_one_way")
{
{
const toml::value v(toml::table{{"a", 42}, {"b", "baz"}});
const auto baz = toml::get<extlib::baz>(v);
CHECK(baz.a == 42);
CHECK(baz.b == "baz");
}
{
const extlib::qux q{42, "qux"};
const toml::value v(q);
CHECK(toml::find<int>(v, "a") == 42);
CHECK(toml::find<std::string>(v, "b") == "qux");
}
{
const toml::ordered_value v(toml::ordered_table{
{"a", 42}, {"b", "baz"}
});
const auto baz = toml::get<extlib2::baz>(v);
CHECK(baz.a == 42);
CHECK(baz.b == "baz");
}
{
const extlib::qux q{42, "qux"};
const toml::ordered_value v(q);
CHECK(toml::find<int>(v, "a") == 42);
CHECK(toml::find<std::string>(v, "b") == "qux");
}
}
TEST_CASE("test_conversion_via_constructor")
{
{
const toml::value v(toml::table{{"a", 42}, {"b", "foobar"}});
const auto foobar = toml::get<extlib::foobar>(v);
CHECK(foobar.a == 42);
CHECK(foobar.b == "foobar");
}
{
const toml::ordered_value v(toml::ordered_table{
{"a", 42}, {"b", "foobar"}
});
const auto foobar = toml::get<extlib2::foobar>(v);
CHECK(foobar.a == 42);
CHECK(foobar.b == "foobar");
}
}
TEST_CASE("test_recursive_conversion")
{
{
const toml::value v(toml::array{
toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 44}, {"b", "quux"}},
toml::table{{"a", 45}, {"b", "foobar"}},
});
const auto foos = toml::get<std::vector<extlib::foo>>(v);
CHECK(foos.size() == 4ul);
CHECK(foos.at(0).a == 42);
CHECK(foos.at(1).a == 43);
CHECK(foos.at(2).a == 44);
CHECK(foos.at(3).a == 45);
CHECK(foos.at(0).b == "baz");
CHECK(foos.at(1).b == "qux");
CHECK(foos.at(2).b == "quux");
CHECK(foos.at(3).b == "foobar");
const auto bars = toml::get<std::vector<extlib::bar>>(v);
CHECK(bars.size() == 4ul);
CHECK(bars.at(0).a == 42);
CHECK(bars.at(1).a == 43);
CHECK(bars.at(2).a == 44);
CHECK(bars.at(3).a == 45);
CHECK(bars.at(0).b == "baz");
CHECK(bars.at(1).b == "qux");
CHECK(bars.at(2).b == "quux");
CHECK(bars.at(3).b == "foobar");
}
{
const toml::value v(toml::array{
toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 44}, {"b", "quux"}},
toml::table{{"a", 45}, {"b", "foobar"}},
});
const auto foos = toml::get<std::vector<extlib2::foo>>(v);
CHECK(foos.size() == 4ul);
CHECK(foos.at(0).a == 42);
CHECK(foos.at(1).a == 43);
CHECK(foos.at(2).a == 44);
CHECK(foos.at(3).a == 45);
CHECK(foos.at(0).b == "baz");
CHECK(foos.at(1).b == "qux");
CHECK(foos.at(2).b == "quux");
CHECK(foos.at(3).b == "foobar");
const auto bars = toml::get<std::vector<extlib2::bar>>(v);
CHECK(bars.size() == 4ul);
CHECK(bars.at(0).a == 42);
CHECK(bars.at(1).a == 43);
CHECK(bars.at(2).a == 44);
CHECK(bars.at(3).a == 45);
CHECK(bars.at(0).b == "baz");
CHECK(bars.at(1).b == "qux");
CHECK(bars.at(2).b == "quux");
CHECK(bars.at(3).b == "foobar");
}
{
const toml::ordered_value v(toml::ordered_array{
toml::ordered_table{{"a", 42}, {"b", "baz"}},
toml::ordered_table{{"a", 43}, {"b", "qux"}},
toml::ordered_table{{"a", 44}, {"b", "quux"}},
toml::ordered_table{{"a", 45}, {"b", "foobar"}}
});
const auto foos = toml::get<std::vector<extlib2::foo>>(v);
CHECK(foos.size() == 4ul);
CHECK(foos.at(0).a == 42);
CHECK(foos.at(1).a == 43);
CHECK(foos.at(2).a == 44);
CHECK(foos.at(3).a == 45);
CHECK(foos.at(0).b == "baz");
CHECK(foos.at(1).b == "qux");
CHECK(foos.at(2).b == "quux");
CHECK(foos.at(3).b == "foobar");
const auto bars = toml::get<std::vector<extlib2::bar>>(v);
CHECK(bars.size() == 4ul);
CHECK(bars.at(0).a == 42);
CHECK(bars.at(1).a == 43);
CHECK(bars.at(2).a == 44);
CHECK(bars.at(3).a == 45);
CHECK(bars.at(0).b == "baz");
CHECK(bars.at(1).b == "qux");
CHECK(bars.at(2).b == "quux");
CHECK(bars.at(3).b == "foobar");
}
// via constructor
{
const toml::value v(toml::array{
toml::table{{"a", 42}, {"b", "baz"}},
toml::table{{"a", 43}, {"b", "qux"}},
toml::table{{"a", 44}, {"b", "quux"}},
toml::table{{"a", 45}, {"b", "foobar"}}
});
{
const auto foobars = toml::get<std::vector<extlib::foobar>>(v);
CHECK(foobars.size() == 4ul);
CHECK(foobars.at(0).a == 42);
CHECK(foobars.at(1).a == 43);
CHECK(foobars.at(2).a == 44);
CHECK(foobars.at(3).a == 45);
CHECK(foobars.at(0).b == "baz");
CHECK(foobars.at(1).b == "qux");
CHECK(foobars.at(2).b == "quux");
CHECK(foobars.at(3).b == "foobar");
}
{
const auto foobars = toml::get<std::vector<extlib2::foobar>>(v);
CHECK(foobars.size() == 4ul);
CHECK(foobars.at(0).a == 42);
CHECK(foobars.at(1).a == 43);
CHECK(foobars.at(2).a == 44);
CHECK(foobars.at(3).a == 45);
CHECK(foobars.at(0).b == "baz");
CHECK(foobars.at(1).b == "qux");
CHECK(foobars.at(2).b == "quux");
CHECK(foobars.at(3).b == "foobar");
}
}
{
const toml::ordered_value v(toml::ordered_array{
toml::ordered_table{{"a", 42}, {"b", "baz"}},
toml::ordered_table{{"a", 43}, {"b", "qux"}},
toml::ordered_table{{"a", 44}, {"b", "quux"}},
toml::ordered_table{{"a", 45}, {"b", "foobar"}}
});
const auto foobars = toml::get<std::vector<extlib2::foobar>>(v);
CHECK(foobars.size() == 4ul);
CHECK(foobars.at(0).a == 42);
CHECK(foobars.at(1).a == 43);
CHECK(foobars.at(2).a == 44);
CHECK(foobars.at(3).a == 45);
CHECK(foobars.at(0).b == "baz");
CHECK(foobars.at(1).b == "qux");
CHECK(foobars.at(2).b == "quux");
CHECK(foobars.at(3).b == "foobar");
}
// via constructor
{
const toml::value v(toml::table{
{"0", toml::table{{"a", 42}, {"b", "baz"}}},
{"1", toml::table{{"a", 43}, {"b", "qux"}}},
{"2", toml::table{{"a", 44}, {"b", "quux"}}},
{"3", toml::table{{"a", 45}, {"b", "foobar"}}}
});
{
const auto foobars = toml::get<std::map<std::string, extlib::foobar>>(v);
CHECK(foobars.size() == 4ul);
CHECK(foobars.at("0").a == 42);
CHECK(foobars.at("1").a == 43);
CHECK(foobars.at("2").a == 44);
CHECK(foobars.at("3").a == 45);
CHECK(foobars.at("0").b == "baz");
CHECK(foobars.at("1").b == "qux");
CHECK(foobars.at("2").b == "quux");
CHECK(foobars.at("3").b == "foobar");
}
{
const auto foobars = toml::get<std::map<std::string, extlib2::foobar>>(v);
CHECK(foobars.size() == 4ul);
CHECK(foobars.at("0").a == 42);
CHECK(foobars.at("1").a == 43);
CHECK(foobars.at("2").a == 44);
CHECK(foobars.at("3").a == 45);
CHECK(foobars.at("0").b == "baz");
CHECK(foobars.at("1").b == "qux");
CHECK(foobars.at("2").b == "quux");
CHECK(foobars.at("3").b == "foobar");
}
}
{
const toml::ordered_value v(toml::ordered_table{
{"0", toml::ordered_table{{"a", 42}, {"b", "baz"}}},
{"1", toml::ordered_table{{"a", 43}, {"b", "qux"}}},
{"2", toml::ordered_table{{"a", 44}, {"b", "quux"}}},
{"3", toml::ordered_table{{"a", 45}, {"b", "foobar"}}}
});
const auto foobars = toml::get<std::map<std::string, extlib::foobar>>(v);
CHECK(foobars.size() == 4ul);
CHECK(foobars.at("0").a == 42);
CHECK(foobars.at("1").a == 43);
CHECK(foobars.at("2").a == 44);
CHECK(foobars.at("3").a == 45);
CHECK(foobars.at("0").b == "baz");
CHECK(foobars.at("1").b == "qux");
CHECK(foobars.at("2").b == "quux");
CHECK(foobars.at("3").b == "foobar");
}
}
// ===========================================================================
#ifndef TOML11_WITHOUT_DEFINE_NON_INTRUSIVE
namespace extlib3
{
struct foo
{
int a;
std::string b;
};
struct bar
{
int a;
std::string b;
foo f;
};
} // extlib3
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib3::foo, a, b)
TOML11_DEFINE_CONVERSION_NON_INTRUSIVE(extlib3::bar, a, b, f)
TEST_CASE("test_conversion_via_macro")
{
{
const toml::value v(toml::table{{"a", 42}, {"b", "baz"}});
const auto foo = toml::get<extlib3::foo>(v);
CHECK(foo.a == 42);
CHECK(foo.b == "baz");
const toml::value v2(foo);
CHECK(v2 == v);
}
{
const toml::ordered_value v(toml::ordered_table{
{"a", 42}, {"b", "baz"}
});
const auto foo = toml::get<extlib3::foo>(v);
CHECK(foo.a == 42);
CHECK(foo.b == "baz");
const toml::ordered_value v2(foo);
CHECK(v2 == v);
}
// -----------------------------------------------------------------------
{
const toml::value v(toml::table{
{"a", 42},
{"b", "bar.b"},
{"f", toml::table{{"a", 42}, {"b", "foo.b"}}}
});
const auto bar = toml::get<extlib3::bar>(v);
CHECK(bar.a == 42);
CHECK(bar.b == "bar.b");
CHECK(bar.f.a == 42);
CHECK(bar.f.b == "foo.b");
const toml::value v2(bar);
CHECK(v2 == v);
}
{
const toml::ordered_value v(toml::ordered_table{
{"a", 42},
{"b", "bar.b"},
{"f", toml::ordered_table{{"a", 42}, {"b", "foo.b"}}}
});
const auto bar = toml::get<extlib3::bar>(v);
CHECK(bar.a == 42);
CHECK(bar.b == "bar.b");
CHECK(bar.f.a == 42);
CHECK(bar.f.b == "foo.b");
const toml::ordered_value v2(bar);
CHECK(v2 == v);
}
}
#endif // TOML11_WITHOUT_DEFINE_NON_INTRUSIVE

View File

@@ -1,11 +1,17 @@
#include <toml/utility.hpp> #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include "unit_test.hpp" #include <toml11/utility.hpp>
#include <array> TEST_CASE("testing make_unique")
#include <vector> {
const auto v = toml::cxx::make_unique<std::vector<std::string>>(std::size_t(2), "foobar");
CHECK_EQ(v->size(), 2);
CHECK_EQ(v->at(0), "foobar");
CHECK_EQ(v->at(1), "foobar");
}
BOOST_AUTO_TEST_CASE(test_try_reserve) TEST_CASE("testing try_reserve")
{ {
{ {
// since BOOST_TEST is a macro, it cannot handle commas correctly. // since BOOST_TEST is a macro, it cannot handle commas correctly.
@@ -16,30 +22,149 @@ BOOST_AUTO_TEST_CASE(test_try_reserve)
// this problem. // this problem.
using reservable_type = std::vector<int> ; using reservable_type = std::vector<int> ;
using nonreservable_type = std::array<int, 1>; using nonreservable_type = std::array<int, 1>;
BOOST_TEST( toml::detail::has_reserve_method<reservable_type >::value); CHECK_UNARY( toml::detail::has_reserve_method<reservable_type >::value);
BOOST_TEST(!toml::detail::has_reserve_method<nonreservable_type>::value); CHECK_UNARY(!toml::detail::has_reserve_method<nonreservable_type>::value);
} }
{ {
std::vector<int> v; std::vector<int> v;
toml::try_reserve(v, 100); toml::detail::try_reserve(v, 100);
BOOST_TEST(v.capacity() == 100u); CHECK_EQ(v.capacity(), 100u);
}
{
std::array<int, 1> v;
toml::detail::try_reserve(v, 100);
CHECK_EQ(v.size(), 1);
} }
} }
BOOST_AUTO_TEST_CASE(test_concat_to_string) TEST_CASE("testing from_string")
{
const std::string cat = toml::concat_to_string("foo", "bar", 42);
BOOST_TEST(cat == "foobar42");
}
BOOST_AUTO_TEST_CASE(test_from_string)
{ {
{ {
const std::string str("123"); const std::string str("123");
BOOST_TEST(toml::from_string<int>(str, 0) == 123); REQUIRE_UNARY(toml::detail::from_string<int>(str).is_ok());
CHECK_EQ(toml::detail::from_string<int>(str).unwrap(), 123);
} }
{ {
const std::string str("01"); const std::string str("01");
BOOST_TEST(toml::from_string<int>(str, 0) == 1); REQUIRE_UNARY(toml::detail::from_string<int>(str).is_ok());
CHECK_EQ(toml::detail::from_string<int>(str).unwrap(), 1);
} }
} }
TEST_CASE("testing make_string")
{
const auto s1 = toml::detail::make_string(3, 'a');
CHECK_EQ(s1, "aaa");
const auto s2 = toml::detail::make_string(0, 'a');
CHECK_EQ(s2, "");
const std::string s("bbb");
const auto s3 = toml::detail::make_string(s.begin(), s.end());
CHECK_EQ(s3, "bbb");
const auto s4 = toml::detail::make_string(s.begin(), s.begin());
CHECK_EQ(s4, "");
}
TEST_CASE("testing make_reverse_iterator")
{
const std::vector<int> v{1, 2, 3, 4, 5};
const auto iter = toml::cxx::make_reverse_iterator(v.begin());
CHECK_EQ(iter, v.rend());
}
#if defined(TOML11_HAS_STD_SOURCE_LOCATION) || defined(TOML11_HAS_EXPERIMENTAL_SOURCE_LOCATION) || defined(TOML11_HAS_BUILTIN_FILE_LINE)
TEST_CASE("cxx::source_location")
{
const std::string file = __FILE__;
const auto line = __LINE__; const auto loc = toml::cxx::source_location::current();
CHECK_EQ(file, loc.file_name());
CHECK_EQ(line, loc.line());
}
#endif
TEST_CASE("cxx::optional")
{
{
toml::cxx::optional<int> v(42);
CHECK_UNARY(static_cast<bool>(v));
CHECK_UNARY(v.has_value());
CHECK_EQ(v.value(), 42);
CHECK_EQ(v.value_or(6 * 9), 42);
v.value() = 6 * 9;
CHECK_EQ(v.value(), 54);
}
{
toml::cxx::optional<int> v;
CHECK_UNARY_FALSE(static_cast<bool>(v));
CHECK_UNARY_FALSE(v.has_value());
CHECK_THROWS(v.value());
CHECK_EQ(v.value_or(6 * 9), 54);
v = 42;
CHECK_UNARY(static_cast<bool>(v));
CHECK_UNARY(v.has_value());
CHECK_EQ(v.value(), 42);
}
{
toml::cxx::optional<int> v(toml::cxx::make_nullopt());
CHECK_UNARY_FALSE(static_cast<bool>(v));
CHECK_UNARY_FALSE(v.has_value());
CHECK_THROWS(v.value());
CHECK_EQ(v.value_or(6 * 9), 54);
v = 42;
CHECK_UNARY(static_cast<bool>(v));
CHECK_UNARY(v.has_value());
CHECK_EQ(v.value(), 42);
}
{
toml::cxx::optional<std::vector<int>> v(std::vector<int>{42});
CHECK_UNARY(static_cast<bool>(v));
CHECK_UNARY(v.has_value());
CHECK_EQ(v.value(), std::vector<int>{42});
CHECK_EQ(v.value_or(std::vector<int>{6 * 9}), std::vector<int>{42});
v.value() = std::vector<int>{6 * 9};
CHECK_EQ(v.value(), std::vector<int>{54});
}
{
toml::cxx::optional<std::vector<int>> v;
CHECK_UNARY_FALSE(static_cast<bool>(v));
CHECK_UNARY_FALSE(v.has_value());
CHECK_THROWS(v.value());
CHECK_EQ(v.value_or(std::vector<int>{6 * 9}), std::vector<int>{54});
v = std::vector<int>{42};
CHECK_UNARY(static_cast<bool>(v));
CHECK_UNARY(v.has_value());
CHECK_EQ(v.value(), std::vector<int>{42});
}
{
toml::cxx::optional<std::vector<int>> v(toml::cxx::make_nullopt());
CHECK_UNARY_FALSE(static_cast<bool>(v));
CHECK_UNARY_FALSE(v.has_value());
CHECK_THROWS(v.value());
CHECK_EQ(v.value_or(std::vector<int>{6 * 9}), std::vector<int>{54});
v = std::vector<int>{42};
CHECK_UNARY(static_cast<bool>(v));
CHECK_UNARY(v.has_value());
CHECK_EQ(v.value(), std::vector<int>{42});
}
}

File diff suppressed because it is too large Load Diff

161
tests/test_visit.cpp Normal file
View File

@@ -0,0 +1,161 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
#include <toml11/comments.hpp>
#include <toml11/types.hpp>
#include <toml11/value.hpp>
#include <toml11/visit.hpp>
template<typename Value>
struct printer
{
using value_type = Value;
using boolean_type = typename value_type::boolean_type ;
using integer_type = typename value_type::integer_type ;
using floating_type = typename value_type::floating_type ;
using string_type = typename value_type::string_type ;
using local_time_type = typename value_type::local_time_type ;
using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
std::string operator()(const boolean_type& x) const
{
if(x) {return "true";} else {return "false";}
}
std::string operator()(const integer_type& x) const
{
return std::to_string(x);
}
std::string operator()(const floating_type& x) const
{
return std::to_string(x);
}
std::string operator()(const string_type& x) const
{
return "\"" + x + "\"";
}
std::string operator()(const local_time_type& x) const
{
std::ostringstream oss;
oss << x;
return oss.str();
}
std::string operator()(const local_date_type& x) const
{
std::ostringstream oss;
oss << x;
return oss.str();
}
std::string operator()(const local_datetime_type& x) const
{
std::ostringstream oss;
oss << x;
return oss.str();
}
std::string operator()(const offset_datetime_type& x) const
{
std::ostringstream oss;
oss << x;
return oss.str();
}
std::string operator()(const array_type& a) const
{
std::string str;
str += '[';
for(const auto& e : a)
{
str += toml::visit(*this, e);
str += ", ";
}
str += ']';
return str;
}
std::string operator()(const table_type& t) const
{
std::string str;
str += '{';
for(const auto& e : t)
{
str += e.first;
str += " = ";
str += toml::visit(*this, e.second);
str += ", ";
}
if( ! t.empty())
{
str.pop_back();
str.pop_back();
}
str += '}';
return str;
}
};
struct type_config_ordered_map
{
using comment_type = toml::preserve_comments;
using boolean_type = bool;
using integer_type = std::int64_t;
using floating_type = double;
using string_type = std::string;
template<typename T>
using array_type = std::vector<T>;
template<typename K, typename T>
using table_type = std::map<K, T>;
static toml::result<integer_type, toml::error_info>
parse_int(const std::string& str, const toml::source_location src, const std::uint8_t base)
{
assert(base == 10 || base == 16 || base == 8 || base == 2);
return toml::read_int<integer_type>(str, src, base);
}
static toml::result<floating_type, toml::error_info>
parse_float(const std::string& str, const toml::source_location src, const bool is_hex)
{
return toml::read_float<floating_type>(str, src, is_hex);
}
};
TEST_CASE("testing toml::get with toml types")
{
using value_type = toml::basic_value<type_config_ordered_map>;
using array_type = typename value_type::array_type;
using table_type = typename value_type::table_type;
const printer<value_type> p;
{
value_type v(true);
CHECK_EQ("true", toml::visit(p, v));
}
{
value_type v(false);
CHECK_EQ("false", toml::visit(p, v));
}
{
value_type v(42);
CHECK_EQ(std::to_string(42), toml::visit(p, v));
}
{
value_type v(3.14);
CHECK_EQ(std::to_string(3.14), toml::visit(p, v));
}
{
value_type v("foo");
CHECK_EQ("\"foo\"", toml::visit(p, v));
}
{
value_type v(array_type{true, 42, 3.14, "foo"});
CHECK_EQ("[true, 42, " + std::to_string(3.14) + ", \"foo\", ]", toml::visit(p, v));
}
{
value_type v(table_type{{"foo", true}, {"bar", 42}});
CHECK_EQ("{bar = 42, foo = true}", toml::visit(p, v));
}
}

View File

@@ -1,12 +0,0 @@
#include <windows.h>
#include <toml.hpp>
#include <iostream>
int main()
{
using namespace toml::literals::toml_literals;
const auto data = R"(windows = "defines min and max as a macro")"_toml;
std::cout << toml::find<std::string>(data, "windows") << std::endl;
return 0;
}

161
tests/to_json.cpp Normal file
View File

@@ -0,0 +1,161 @@
#include <iomanip>
#include <iostream>
#include <string>
#include <toml.hpp>
#include <nlohmann/json.hpp>
#include <cmath>
#ifdef TOML11_TO_JSON_USE_V1_1_0
# define TOML11_TO_JSON_SPEC toml::spec::v(1, 1, 0)
#else
# define TOML11_TO_JSON_SPEC toml::spec::v(1, 0, 0)
#endif
template<typename Value = toml::value>
struct json_converter
{
using value_type = Value;
using boolean_type = typename value_type::boolean_type ;
using integer_type = typename value_type::integer_type ;
using floating_type = typename value_type::floating_type ;
using string_type = typename value_type::string_type ;
using local_time_type = typename value_type::local_time_type ;
using local_date_type = typename value_type::local_date_type ;
using local_datetime_type = typename value_type::local_datetime_type ;
using offset_datetime_type = typename value_type::offset_datetime_type;
using array_type = typename value_type::array_type ;
using table_type = typename value_type::table_type ;
nlohmann::json operator()(boolean_type v)
{
nlohmann::json j;
j["type"] = "bool";
if(v)
{
j["value"] = "true";
}
else
{
j["value"] = "false";
}
return j;
}
nlohmann::json operator()(integer_type v)
{
nlohmann::json j;
j["type"] = "integer";
j["value"] = std::to_string(v);
return j;
}
nlohmann::json operator()(floating_type v)
{
std::ostringstream oss;
oss << std::setprecision(16);
// if we set the precision as max_digit, 1.1 will be 1.1000000000000001.
// But toml-test does not allow 1.1000000000000001.
if(std::isnan(v) && std::signbit(v))
{
// toml-test does not allow negative NaN represented in "-nan" because
// there are languages that does not distinguish nan and -nan.
// But toml11 keeps sign from input. To resolve this difference,
// we convert -nan to nan here.
v = std::numeric_limits<floating_type>::quiet_NaN();
}
oss << v;
nlohmann::json j;
j["type"] = "float";
j["value"] = oss.str();
return j;
}
nlohmann::json operator()(const string_type& v)
{
nlohmann::json j;
j["type"] = "string";
j["value"] = v;
return j;
}
nlohmann::json operator()(const toml::local_time& v)
{
nlohmann::json j;
j["type"] = "time-local";
j["value"] = toml::to_string(v);
return j;
}
nlohmann::json operator()(const toml::local_date& v)
{
nlohmann::json j;
j["type"] = "date-local";
j["value"] = toml::to_string(v);
return j;
}
nlohmann::json operator()(const toml::local_datetime& v)
{
nlohmann::json j;
j["type"] = "datetime-local";
j["value"] = toml::to_string(v);
return j;
}
nlohmann::json operator()(const toml::offset_datetime& v)
{
nlohmann::json j;
j["type"] = "datetime";
j["value"] = toml::to_string(v);
return j;
}
nlohmann::json operator()(const toml::array& v)
{
nlohmann::json j = nlohmann::json::array();
for(const auto& elem : v)
{
j.push_back(toml::visit(*this, elem));
}
return j;
}
nlohmann::json operator()(const toml::table& v)
{
nlohmann::json j = nlohmann::json::object();
for(const auto& kv : v)
{
j[kv.first] = toml::visit(*this, kv.second);
}
return j;
}
};
int main(int argc, char** argv)
{
try
{
if(argc == 2)
{
const std::string fname(argv[1]);
const auto data = toml::parse(fname, TOML11_TO_JSON_SPEC);
std::cout << toml::visit(json_converter<>(), data);
return 0;
}
else
{
std::vector<unsigned char> buf;
std::cin.peek();
while(!std::cin.eof())
{
buf.push_back(static_cast<unsigned char>(std::cin.get()));
std::cin.peek();
}
const auto data = toml::parse(buf, "cin", TOML11_TO_JSON_SPEC);
std::cout << toml::visit(json_converter<>(), data);
return 0;
}
}
catch(const std::exception& err)
{
std::cout << "what(): " << err.what() << std::endl;
return 1;
}
}

113
tests/to_toml.cpp Normal file
View File

@@ -0,0 +1,113 @@
#include <iostream>
#include <string>
#include <toml.hpp>
#include <nlohmann/json.hpp>
#include <cmath>
toml::value convert_to_toml(const nlohmann::json& j)
{
if(j.is_array())
{
toml::value a(toml::array{});
for(const auto& v : j)
{
a.push_back(convert_to_toml(v));
}
return a;
}
else if(j.size() == 2 &&
j.contains("type") && j.at("type").is_string() &&
j.contains("value") && j.at("value").is_string() )
{
const auto type = j.at("type" ).get<std::string>();
const auto value = j.at("value").get<std::string>();
if(type == "string")
{
return toml::value(value);
}
else if(type == "int")
{
toml::detail::context<toml::type_config> ctx(toml::spec::default_version());
auto loc = toml::detail::make_temporary_location(value);
return toml::detail::parse_integer(loc, ctx).unwrap();
}
else if(type == "float")
{
toml::detail::context<toml::type_config> ctx(toml::spec::default_version());
auto loc = toml::detail::make_temporary_location(value);
if(auto f_r = toml::detail::parse_floating(loc, ctx))
{
return f_r.unwrap();
}
else
{
// toml-test converts "inf" into "Inf"
if(value == "Inf" || value == "+Inf")
{
return toml::value(std::numeric_limits<double>::infinity());
}
else if(value == "-Inf")
{
return toml::value(-std::numeric_limits<double>::infinity());
}
else
{
return toml::value(toml::detail::from_string<double>(value).unwrap());
}
}
}
else
{
return toml::detail::literal_internal_impl(
toml::detail::make_temporary_location(value));
}
}
else // table.
{
toml::value t(toml::table{});
for(const auto& kv : j.items())
{
t[kv.key()] = convert_to_toml(kv.value());
}
return t;
}
}
int main(int argc, char** argv)
{
try
{
if(argc == 2)
{
const std::string fname(argv[1]);
std::ifstream ifs(fname);
const auto j = nlohmann::json::parse(ifs);
const auto t = convert_to_toml(j);
std::cout << toml::format(t) << std::endl;
return 0;
}
else
{
std::vector<char> buf;
std::cin.peek();
while(!std::cin.eof())
{
buf.push_back(static_cast<char>(std::cin.get()));
std::cin.peek();
}
std::string str(buf.begin(), buf.end());
const auto j = nlohmann::json::parse(str);
const auto t = convert_to_toml(j);
std::cout << toml::format(t) << std::endl;
return 0;
}
}
catch(const std::exception& err)
{
std::cout << "what(): " << err.what() << std::endl;
return 1;
}
}

View File

@@ -1,23 +0,0 @@
#ifndef BOOST_TEST_MODULE
# error "Please #define BOOST_TEST_MODULE before you #include <unit_test.hpp>"
#endif
#ifdef UNITTEST_FRAMEWORK_LIBRARY_EXIST
# include <boost/test/unit_test.hpp>
#else
# include <boost/test/included/unit_test.hpp>
#endif
#include <cstdlib>
#include <string>
static inline auto testinput(const std::string& basename) -> std::string
{
const auto this_or_that = [](const char *const s, const char *const t) { return s ? s : t; };
std::string directory = this_or_that(std::getenv("TOMLDIR"), "toml");
if (!directory.empty() && directory.back() != '/')
{
directory.push_back('/');
}
return directory.append("tests/").append(basename);
}

104
tests/utility.cpp Normal file
View File

@@ -0,0 +1,104 @@
#include "doctest.h"
#include "utility.hpp"
#include <ostream>
#include <string>
#include <iostream>
void test_scan_success(const toml::detail::scanner_base& s,
const std::string& in, const std::string& out)
{
auto loc = toml::detail::make_temporary_location(in);
const auto reg = s.scan(loc);
CHECK_UNARY(reg.is_ok());
CHECK_EQ(reg.as_string(), out);
}
void test_scan_failure(const toml::detail::scanner_base& s,
const std::string& in)
{
auto loc = toml::detail::make_temporary_location(in);
const auto reg = s.scan(loc);
CHECK_UNARY_FALSE(reg.is_ok());
}
namespace toml
{
std::ostream& operator<<(std::ostream& os, const integer_format_info& fmt)
{
os << "integer_format_info{";
os << "fmt = " << fmt.fmt << ", ";
os << "width = " << fmt.width << ", ";
os << "spacer = " << fmt.spacer << ", ";
os << "suffix = \"" << fmt.suffix << "\"}";
return os;
}
std::ostream& operator<<(std::ostream& os, const floating_format_info& fmt)
{
os << "floating_format_info{";
os << "fmt = " << fmt.fmt << ", ";
os << "prec = " << fmt.prec << ", ";
os << "suffix = \"" << fmt.suffix << "\"}";
return os;
}
std::ostream& operator<<(std::ostream& os, const string_format_info& fmt)
{
os << "string_format_info{";
os << "fmt = " << fmt.fmt << ", ";
os << "start_with_newline = " << fmt.start_with_newline << "}";
return os;
}
std::ostream& operator<<(std::ostream& os, const offset_datetime_format_info& fmt)
{
os << "offset_datetime_format_info{";
os << std::boolalpha;
os << "delimiter = " << fmt.delimiter << ", ";
os << "has_seconds = " << fmt.has_seconds << ", ";
os << "subsecond_precision = " << fmt.subsecond_precision << "}";
return os;
}
std::ostream& operator<<(std::ostream& os, const local_datetime_format_info& fmt)
{
os << "local_datetime_format_info{";
os << std::boolalpha;
os << "delimiter = " << fmt.delimiter << ", ";
os << "has_seconds = " << fmt.has_seconds << ", ";
os << "subsecond_precision = " << fmt.subsecond_precision << "}";
return os;
}
std::ostream& operator<<(std::ostream& os, const local_date_format_info&)
{
os << "local_date_format_info{}";
return os;
}
std::ostream& operator<<(std::ostream& os, const local_time_format_info& fmt)
{
os << "local_time_format_info{";
os << std::boolalpha;
os << "has_seconds = " << fmt.has_seconds << ", ";
os << "subsecond_precision = " << fmt.subsecond_precision << "}";
return os;
}
std::ostream& operator<<(std::ostream& os, const array_format_info& fmt)
{
os << "array_format_info{";
os << "fmt = " << fmt.fmt << ", ";
os << "indent_type = " << fmt.indent_type << ", ";
os << "body_indent = " << fmt.body_indent << ", ";
os << "closing_indent = " << fmt.closing_indent << "}";
return os;
}
std::ostream& operator<<(std::ostream& os, const table_format_info& fmt)
{
os << "table_format_info{";
os << "fmt = " << fmt.fmt << ", ";
os << "indent_type = " << fmt.indent_type << ", ";
os << "name_indent = " << fmt.name_indent << ", ";
os << "body_indent = " << fmt.body_indent << ", ";
os << "closing_indent = " << fmt.closing_indent << "}";
return os;
}
} // toml

107
tests/utility.hpp Normal file
View File

@@ -0,0 +1,107 @@
#ifndef TOML11_TEST_UTILITY_HPP
#define TOML11_TEST_UTILITY_HPP
#include <toml11/context.hpp>
#include <toml11/format.hpp>
#include <toml11/parser.hpp>
#include <toml11/region.hpp>
#include <toml11/scanner.hpp>
#include <toml11/serializer.hpp>
#include <toml11/value.hpp>
#include "doctest.h"
#include <ostream>
#include <string>
#include <utility>
#include <vector>
#include <iostream>
template<typename TC>
toml::basic_value<TC> const& as_const(toml::basic_value<TC>& v) noexcept
{
return v;
}
template<typename ... Ts>
std::vector<std::string> comments(Ts ... args)
{
return std::vector<std::string>{std::move(args)...};
}
void test_scan_success(const toml::detail::scanner_base& s,
const std::string& in, const std::string& out);
void test_scan_failure(const toml::detail::scanner_base& s,
const std::string& in);
template<toml::value_t VT, typename T, typename Format, typename TC>
void toml11_test_parse_success(
std::string in, const T& out,
const std::vector<std::string>& com,
const Format& fmt,
toml::detail::context<TC> ctx)
{
auto loc = toml::detail::make_temporary_location(in);
const auto res = toml::detail::parse_value(loc, ctx);
if(res.is_err())
{
std::cerr << toml::format_error(res.unwrap_err()) << std::endl;
}
REQUIRE_UNARY(res.is_ok());
const auto val = res.unwrap();
REQUIRE(val.is(VT));
REQUIRE_EQ(val.type(), VT);
CHECK_EQ(val.template as<VT>(), out);
const std::vector<std::string> com_actual(
val.comments().begin(), val.comments().end());
CHECK_EQ(com_actual, com);
const auto fmt_actual = val.template as_fmt<VT>();
CHECK_EQ(fmt_actual, fmt);
}
template<typename F, typename TC>
void toml11_test_parse_failure(F fn, std::string in, toml::detail::context<TC> ctx)
{
using namespace toml::detail;
auto loc = toml::detail::make_temporary_location(in);
const auto res = fn(loc, ctx);
REQUIRE_UNARY(res.is_err());
ctx.report_error(res.unwrap_err());
std::cerr << "-------- error messages about: `" << in.substr(0, in.find('\n')) << "` --------" << std::endl;
for(const auto& e : ctx.errors())
{
std::cerr << toml::format_error(e) << std::endl;
}
std::cerr << "-------- end --------" << std::endl;
}
namespace toml
{
template<typename TC>
std::ostream& operator<<(std::ostream& os, const toml::basic_value<TC>& v)
{
os << toml::format(v);
return os;
}
std::ostream& operator<<(std::ostream& os, const integer_format_info&);
std::ostream& operator<<(std::ostream& os, const floating_format_info&);
std::ostream& operator<<(std::ostream& os, const string_format_info&);
std::ostream& operator<<(std::ostream& os, const offset_datetime_format_info&);
std::ostream& operator<<(std::ostream& os, const local_datetime_format_info&);
std::ostream& operator<<(std::ostream& os, const local_date_format_info&);
std::ostream& operator<<(std::ostream& os, const local_time_format_info&);
std::ostream& operator<<(std::ostream& os, const array_format_info&);
std::ostream& operator<<(std::ostream& os, const table_format_info&);
} // toml
#endif// TOML11_TEST_UTILITY_HPP