// This file is a part of toml++ and is subject to the the terms of the MIT license. // Copyright (c) Mark Gillard // See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. // SPDX-License-Identifier: MIT #include "tests.h" bool parsing_should_succeed(std::string_view test_file, uint32_t test_line, std::string_view toml_str, pss_func&& func, std::string_view source_path) { INFO("["sv << test_file << ", line "sv << test_line << "] "sv << "parsing_should_succeed(\""sv << toml_str << "\")"sv) constexpr auto validate_table = [](table&& tabl, std::string_view path) -> table&& { INFO("Validating table source information"sv) CHECK(tabl.source().begin != source_position{}); CHECK(tabl.source().end != source_position{}); if (path.empty()) CHECK(tabl.source().path == nullptr); else { REQUIRE(tabl.source().path != nullptr); CHECK(*tabl.source().path == path); } return std::move(tabl); }; #if TOML_EXCEPTIONS try { { INFO("Parsing string directly"sv) if (func) func(validate_table(toml::parse(toml_str, source_path), source_path)); else validate_table(toml::parse(toml_str, source_path), source_path); } { INFO("Parsing from a string stream"sv) std::stringstream ss; ss.write(toml_str.data(), static_cast(toml_str.length())); if (func) func(validate_table(toml::parse(ss, source_path), source_path)); else validate_table(toml::parse(ss, source_path), source_path); } } catch (const parse_error& err) { FORCE_FAIL("Parse error on line "sv << err.source().begin.line << ", column "sv << err.source().begin.column << ":\n"sv << err.description()); return false; } #else { INFO("Parsing string directly"sv) parse_result result = toml::parse(toml_str, source_path); if (result) { if (func) func(validate_table(std::move(result), source_path)); else validate_table(std::move(result), source_path); } else { FORCE_FAIL("Parse error on line "sv << result.error().source().begin.line << ", column "sv << result.error().source().begin.column << ":\n"sv << result.error().description()); } } { INFO("Parsing from a string stream"sv) std::stringstream ss; ss.write(toml_str.data(), static_cast(toml_str.length())); parse_result result = toml::parse(ss, source_path); if (result) { if (func) func(validate_table(std::move(result), source_path)); else validate_table(std::move(result), source_path); } else { FORCE_FAIL("Parse error on line "sv << result.error().source().begin.line << ", column "sv << result.error().source().begin.column << ":\n"sv << result.error().description()); } } #endif return true; } bool parsing_should_fail(std::string_view test_file, uint32_t test_line, std::string_view toml_str, source_index expected_failure_line, source_index expected_failure_column) { INFO("["sv << test_file << ", line "sv << test_line << "] "sv << "parsing_should_fail(\""sv << toml_str << "\")"sv) #if TOML_EXCEPTIONS static constexpr auto run_tests = [](source_index ex_line, source_index ex_col, auto&& fn) { try { fn(); } catch (const parse_error& err) { if (ex_line != static_cast(-1) && err.source().begin.line != ex_line) { FORCE_FAIL("Expected parse_error at line "sv << ex_line << ", actually occured at line "sv << err.source().begin.line); return false; } if (ex_col != static_cast(-1) && err.source().begin.column != ex_col) { FORCE_FAIL("Expected parse_error at column "sv << ex_col << ", actually occured at column "sv << err.source().begin.column); return false; } SUCCEED("parse_error thrown OK"sv); return true; } catch (const std::exception& exc) { FORCE_FAIL("Expected parsing failure, saw exception: "sv << exc.what()); return false; } catch (...) { FORCE_FAIL("Expected parsing failure, saw unspecified exception"sv); return false; } FORCE_FAIL("Expected parsing failure"sv); return false; }; auto result = run_tests(expected_failure_line, expected_failure_column, [=]() { [[maybe_unused]] auto res = toml::parse(toml_str); }); result = result && run_tests(expected_failure_line, expected_failure_column, [=]() { std::stringstream ss; ss.write(toml_str.data(), static_cast(toml_str.length())); [[maybe_unused]] auto res = toml::parse(ss); }); return result; #else static constexpr auto run_tests = [](source_index ex_line, source_index ex_col, auto&& fn) { if (parse_result result = fn(); !result) { if (ex_line != static_cast(-1) && result.error().source().begin.line != ex_line) { FORCE_FAIL("Expected parse_error at line "sv << ex_line << ", actually occured at line "sv << result.error().source().begin.line); } if (ex_col != static_cast(-1) && result.error().source().begin.column != ex_col) { FORCE_FAIL("Expected parse_error at column "sv << ex_col << ", actually occured at column "sv << result.error().source().begin.column); } SUCCEED("parse_error generated OK"sv); return true; } FORCE_FAIL("Expected parsing failure"sv); }; return run_tests(expected_failure_line, expected_failure_column, [=]() { return toml::parse(toml_str); }) && run_tests(expected_failure_line, expected_failure_column, [=]() { std::stringstream ss; ss.write(toml_str.data(), static_cast(toml_str.length())); return toml::parse(ss); }); #endif } template bool parse_expected_value(std::string_view, uint32_t, std::string_view, const int&); template bool parse_expected_value(std::string_view, uint32_t, std::string_view, const unsigned int&); template bool parse_expected_value(std::string_view, uint32_t, std::string_view, const bool&); template bool parse_expected_value(std::string_view, uint32_t, std::string_view, const float&); template bool parse_expected_value(std::string_view, uint32_t, std::string_view, const double&); template bool parse_expected_value(std::string_view, uint32_t, std::string_view, const std::string_view&); namespace std { template class unique_ptr; } namespace Catch { template struct StringMaker>; template struct StringMaker>; template ReusableStringStream& ReusableStringStream::operator<<(toml::node_view const&); template ReusableStringStream& ReusableStringStream::operator<<(toml::node_view const&); namespace Detail { template std::string stringify(const node_view&); template std::string stringify(const node_view&); } }