aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/ryml/test/test_suite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/ryml/test/test_suite.cpp')
-rw-r--r--thirdparty/ryml/test/test_suite.cpp612
1 files changed, 0 insertions, 612 deletions
diff --git a/thirdparty/ryml/test/test_suite.cpp b/thirdparty/ryml/test/test_suite.cpp
deleted file mode 100644
index 22dabf8c4..000000000
--- a/thirdparty/ryml/test/test_suite.cpp
+++ /dev/null
@@ -1,612 +0,0 @@
-#ifndef RYML_SINGLE_HEADER
-#include <c4/yml/std/std.hpp>
-#include <c4/yml/tree.hpp>
-#include <c4/yml/parse.hpp>
-#include <c4/yml/emit.hpp>
-#include <c4/yml/detail/print.hpp>
-#include <c4/yml/detail/checks.hpp>
-#endif
-#include "test_case.hpp"
-#include "test_suite/test_suite_common.hpp"
-#include "test_suite/test_suite_parts.hpp"
-#include "test_suite/test_suite_events.hpp"
-#include <c4/fs/fs.hpp>
-#include <c4/log/log.hpp>
-#include <gtest/gtest.h>
-
-
-/* Each case from the test suite contains:
- *
- * - (awkward) input yaml (in_yaml)
- * - (somewhat standard) output equivalent (out_yaml)
- * - (when meaningful/possible) json equivalent (in_json)
- * - yaml parsing events (events)
- *
- * Running a test consists of parsing the contents above into a data
- * structure, and then repeatedly parsing and emitting yaml in a sort
- * of pipe. Ie, (eg for in_yaml) parse in_yaml, emit corresponding
- * yaml, then parse this emitted yaml, and so on. Each parse/emit pair
- * is named a processing level in this test. */
-
-
-C4_SUPPRESS_WARNING_MSVC_PUSH
-C4_SUPPRESS_WARNING_MSVC(4702) // unreachable code
-
-#define NLEVELS 4
-
-namespace c4 {
-namespace yml {
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-struct Events
-{
- csubstr filename = {};
- std::string src = {};
- std::string emitted_events = {};
- Tree tree = {};
- mutable Tree adjusted_tree = {};
- mutable Tree tree_from_emitted_events = {};
- bool was_parsed = false;
- bool enabled = false;
-
- void init(csubstr filename_, csubstr src_)
- {
- filename = filename_;
- src.assign(src_.begin(), src_.end());
- tree.clear();
- tree.clear_arena();
- tree.reserve(10);
- was_parsed = false;
- enabled = true;
- }
-
- void compare_trees(csubstr actual_src, Tree const& actual_tree) const
- {
- if(actual_src.empty())
- GTEST_SKIP();
- _nfo_logf("SRC:\n{}", actual_src);
- _nfo_print_tree("EXPECTED", tree);
- _nfo_print_tree("ACTUAL", actual_tree);
- test_compare(actual_tree, tree);
- }
-
- void compare_emitted_events(csubstr actual_src, Tree const& tree_from_actual_src)
- {
- C4_UNUSED(actual_src);
- emit_events(&emitted_events, tree_from_actual_src);
- _nfo_logf("EXPECTED_EVENTS:\n{}", src);
- _nfo_logf("ACTUAL_EVENTS:\n{}", emitted_events);
- // we cannot directly compare the event strings,
- // so we create a tree from the emitted events,
- // and then compare the trees:
- tree_from_emitted_events.clear();
- tree_from_emitted_events.reserve(16);
- parser.parse(c4::to_csubstr(emitted_events), &tree_from_emitted_events);
- _nfo_logf("SRC:\n{}", actual_src);
- _nfo_print_tree("ACTUAL_FROM_SOURCE", tree_from_actual_src);
- _nfo_print_tree("ACTUAL_FROM_EMITTED_EVENTS", tree_from_emitted_events);
- _nfo_print_tree("EXPECTED_FROM_EVENTS", tree);
- test_compare(tree_from_emitted_events, tree);
- }
-
- EventsParser parser;
- void parse_events(csubstr actual_src)
- {
- if(was_parsed)
- return;
- if(actual_src.empty())
- GTEST_SKIP();
- parser.parse(c4::to_csubstr(src), &tree);
- if(tree.empty())
- tree.reserve(10);
- _nfo_print_tree("EXPECTED", tree);
- was_parsed = true;
- }
-};
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-/** a processing level */
-struct ProcLevel
-{
- size_t level;
- ProcLevel *prev;
- csubstr filename;
- std::string src;
- c4::yml::Parser parser;
- c4::yml::Tree tree;
- std::string emitted;
-
- bool immutable = false;
- bool reuse = false;
- bool was_parsed = false;
- bool was_emitted = false;
-
- void init(size_t level_, ProcLevel *prev_, csubstr filename_, csubstr src_, bool immutable_, bool reuse_)
- {
- level = level_;
- prev = prev_;
- filename = filename_;
- src.assign(src_.begin(), src_.end());
- immutable = immutable_;
- reuse = reuse_;
- was_parsed = false;
- was_emitted = false;
- }
-
- void receive_src(ProcLevel & prev_)
- {
- RYML_ASSERT(&prev_ == prev);
- if(!prev_.was_emitted)
- {
- _nfo_logf("level[{}] not emitted. emit!", prev_.level);
- prev_.emit();
- }
- if(src != prev_.emitted)
- {
- was_parsed = false;
- was_emitted = false;
- src = prev_.emitted;
- }
- }
-
- template<class T>
- void log(const char* context, T const& v)
- {
- C4_UNUSED(context);
- C4_UNUSED(v);
- #if RYML_NFO
- constexpr const char sep[] = "+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n";
- c4::log("{}:\n{}{}{}", context, sep, v, sep);
- #endif
- }
-
- void parse()
- {
- if(was_parsed)
- return;
- if(prev)
- {
- receive_src(*prev);
- }
- _nfo_logf("level[{}]: parsing source:\n{}", level, src);
- if(reuse)
- {
- tree.clear();
- if(immutable)
- parser.parse_in_arena(filename, c4::to_csubstr(src), &tree);
- else
- parser.parse_in_place(filename, c4::to_substr(src), &tree);
- }
- else
- {
- if(immutable)
- tree = parse_in_arena(filename, c4::to_csubstr(src));
- else
- tree = parse_in_place(filename, c4::to_substr(src));
- }
- _nfo_print_tree("PARSED", tree);
- tree.resolve_tags();
- _nfo_print_tree("RESOLVED TAGS", tree);
- was_parsed = true;
- //_resolve_if_needed();
- }
-
- void _resolve_if_needed()
- {
- ConstNodeRef root = tree.rootref();
- bool has_anchors_or_refs = root.visit([](ConstNodeRef const& node, size_t /*level*/){
- return (node.is_anchor() || node.is_ref());
- });
- if(has_anchors_or_refs)
- {
- tree.resolve();
- _nfo_print_tree("RESOLVED", tree);
- }
- }
-
- void emit()
- {
- if(was_emitted)
- return;
- if(!was_parsed)
- {
- _nfo_logf("level[{}] not parsed. parse!", level);
- parse();
- }
- emitrs_yaml(tree, &emitted);
- csubstr ss = to_csubstr(emitted);
- if(ss.ends_with("\n...\n"))
- emitted.resize(emitted.size() - 4);
- was_emitted = true;
- _nfo_logf("EMITTED:\n{}", emitted);
- }
-
- void compare_trees(ProcLevel & prev_)
- {
- RYML_ASSERT(&prev_ == prev);
- if(!prev_.was_parsed)
- {
- _nfo_logf("level[{}] not parsed. parse!", prev_.level);
- prev_.parse();
- }
- if(!was_parsed)
- {
- _nfo_logf("level[{}] not parsed. parse!", level);
- parse();
- }
- _nfo_print_tree("PREV_", prev_.tree);
- _nfo_print_tree("CURR", tree);
- test_compare(prev_.tree, tree);
- }
-
- void compare_emitted(ProcLevel & prev_)
- {
- RYML_ASSERT(&prev_ == prev);
- if(!prev_.was_emitted)
- {
- _nfo_logf("level[{}] not emitted. emit!", prev_.level);
- prev_.emit();
- }
- if(!was_emitted)
- {
- _nfo_logf("level[{}] not emitted. emit!", level);
- emit();
- }
- _nfo_logf("level[{}]: EMITTED:\n{}", prev_.level, prev_.emitted);
- _nfo_logf("level[{}]: EMITTED:\n{}", level, emitted);
- if(emitted != prev_.emitted)
- {
- // workaround for lack of idempotency in tag normalization.
- Tree from_prev = parse_in_arena(to_csubstr(prev_.emitted));
- Tree from_this = parse_in_arena(to_csubstr(emitted));
- from_prev.resolve_tags();
- from_this.resolve_tags();
- test_compare(from_prev, from_this);
- }
- }
-};
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-/** holds data for one particular test suite approach. */
-struct Approach
-{
- csubstr casename;
- csubstr filename;
- ProcLevel levels[NLEVELS] = {};
- AllowedFailure allowed_failure = {};
- bool enabled = false;
- bool expect_error = false;
-
- void init(csubstr casename_, csubstr filename_, csubstr src_, bool immutable_, bool reuse_, bool expect_error_)
- {
- casename = casename_;
- filename = filename_;
- allowed_failure = is_failure_expected(casename);
- size_t level_index = 0;
- ProcLevel *prev = nullptr;
- for(ProcLevel &l : levels)
- {
- l.init(level_index++, prev, filename, src_, immutable_, reuse_);
- prev = &l;
- }
- expect_error = expect_error_;
- }
-
- csubstr src() const { return c4::to_csubstr(levels[0].src); }
- bool skip() const { return allowed_failure; }
-
- void parse(size_t num, bool emit)
- {
- if(allowed_failure)
- GTEST_SKIP();
- for(size_t i = 0; i < num; ++i)
- {
- levels[i].parse();
- if(emit)
- levels[i].emit();
- if(i + 1 < num)
- levels[i+1].receive_src(levels[i]);
- }
- }
-
- void compare_trees(size_t num)
- {
- if(allowed_failure)
- GTEST_SKIP();
- for(size_t i = 1; i < num; ++i)
- levels[i].compare_trees(levels[i-1]);
- }
- void compare_trees(size_t num, Approach & other)
- {
- if(allowed_failure)
- GTEST_SKIP();
- for(size_t i = 0; i < num; ++i)
- levels[i].compare_trees(other.levels[i]);
- }
-
- void compare_emitted(size_t num)
- {
- if(allowed_failure)
- GTEST_SKIP();
- for(size_t i = 1; i < num; ++i)
- levels[i].compare_emitted(levels[i-1]);
- }
- void compare_emitted(size_t num, Approach & other)
- {
- if(allowed_failure)
- GTEST_SKIP();
- for(size_t i = 0; i < num; ++i)
- levels[i].compare_emitted(other.levels[i]);
- }
-
- void compare_events(Events *events)
- {
- if(allowed_failure || filename.ends_with(".json"))
- GTEST_SKIP();
- events->parse_events(src());
- parse(1, /*emit*/false);
- events->compare_trees(src(), levels[0].tree);
- }
-
- void compare_emitted_events(Events *events)
- {
- if(allowed_failure || filename.ends_with(".json"))
- GTEST_SKIP();
- events->parse_events(src());
- parse(1, /*emit*/false);
- events->compare_emitted_events(src(), levels[0].tree);
- }
-
- void check_expected_error()
- {
- if(allowed_failure)
- GTEST_SKIP();
- ExpectError::do_check(&levels[0].tree, [this]{
- levels[0].parse();
- });
- }
-
-};
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-/** Each approach can be read from mutable/immutable yaml source and
- * with/without reuse. */
-struct Subject
-{
- Approach unix_arena;
- Approach unix_arena_reuse;
- Approach unix_inplace;
- Approach unix_inplace_reuse;
-
- Approach windows_arena;
- Approach windows_arena_reuse;
- Approach windows_inplace;
- Approach windows_inplace_reuse;
-
- std::string unix_src;
- std::string windows_src;
-
- void init(csubstr casename, csubstr filename, csubstr src, bool expect_error)
- {
- src = replace_all("\r", "", src, &unix_src);
-
- unix_arena .init(casename, filename, src, /*immutable*/true , /*reuse*/false, expect_error);
- unix_arena_reuse.init(casename, filename, src, /*immutable*/true , /*reuse*/true , expect_error);
- unix_inplace .init(casename, filename, src, /*immutable*/false, /*reuse*/false, expect_error);
- unix_inplace_reuse.init(casename, filename, src, /*immutable*/false, /*reuse*/true , expect_error);
-
- src = replace_all("\n", "\r\n", src, &windows_src);
-
- windows_arena .init(casename, filename, src, /*immutable*/true , /*reuse*/false, expect_error);
- windows_arena_reuse.init(casename, filename, src, /*immutable*/true , /*reuse*/true , expect_error);
- windows_inplace .init(casename, filename, src, /*immutable*/false, /*reuse*/false, expect_error);
- windows_inplace_reuse.init(casename, filename, src, /*immutable*/false, /*reuse*/true , expect_error);
- }
-};
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-// some utility functions, used below
-
-/** all the ways to process a test case are available through this
- * class. Tests are defined below and use only one of these. */
-struct SuiteCase
-{
- csubstr case_title;
- csubstr case_dir;
- std::string filename;
- std::string file_contents;
- std::string events_filename;
- std::string events_file_contents;
-
- Subject input;
- Events events;
- bool expect_error;
-
- /** loads the several types of tests from an input test suite file */
- SuiteCase(const char *case_title_, const char* case_dir_, const char *input_file)
- {
- using namespace c4;
- using c4::to_csubstr;
-
- if(to_csubstr(input_file) == "error")
- input_file = "in.yaml";
-
- case_title = to_csubstr(case_title_);
-
- case_dir = to_csubstr(case_dir_);
- RYML_CHECK(case_dir.find('\\') == yml::npos);
- C4_CHECK_MSG(fs::dir_exists(case_dir.str), "dir not found: '%s'", case_dir);
-
- filename = catrs<std::string>(case_dir, '/', to_csubstr(input_file));
- C4_CHECK_MSG(fs::file_exists(filename.c_str()), "file not found: '%s'", filename.c_str());
- log("testing suite case: {} {} ({})", case_title, filename, case_dir);
-
- std::string errfile = catrs<std::string>(to_csubstr(case_dir_), "/error");
- expect_error = fs::file_exists(errfile.c_str());
-
- fs::file_get_contents(filename.c_str(), &file_contents);
- input.init(case_title, to_csubstr(filename), to_csubstr(file_contents), expect_error);
-
- events_filename = catrs<std::string>(case_dir, "/test.event");
- C4_CHECK(fs::file_exists(events_filename.c_str()));
- fs::file_get_contents(events_filename.c_str(), &events_file_contents);
- events.init(to_csubstr(events_filename), to_csubstr(events_file_contents));
-
- dump("~~~ case: " , case_title , "~~~\n",
- "~~~ file: " , filename , "~~~\n",
- "~~~ input:\n" , to_csubstr(input.unix_arena.levels[0].src), "~~~\n",
- "~~~ events:\n" , events.src , "~~~\n");
- }
-
-};
-
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-
-// a global holding the test case data
-SuiteCase* g_suite_case = nullptr;
-bool g_do_subcases = true;
-
-
-
-#define DEFINE_TESTS(which) \
- \
- \
-struct which : public ::testing::TestWithParam<size_t> \
-{ \
-}; \
- \
- \
-TEST_P(which, parse) \
-{ \
- RYML_CHECK(GetParam() < NLEVELS); \
- if(g_suite_case->expect_error) \
- GTEST_SKIP(); \
- g_suite_case->input.which.parse(1 + GetParam(), false); \
-} \
- \
- \
-TEST_P(which, compare_trees) \
-{ \
- RYML_CHECK(GetParam() < NLEVELS); \
- if(g_suite_case->expect_error) \
- GTEST_SKIP(); \
- g_suite_case->input.which.compare_trees(1 + GetParam()); \
-} \
- \
- \
-TEST_P(which, emit) \
-{ \
- RYML_CHECK(GetParam() < NLEVELS); \
- if(g_suite_case->expect_error) \
- GTEST_SKIP(); \
- g_suite_case->input.which.parse(1 + GetParam(), true); \
-} \
- \
- \
-TEST_P(which, compare_emitted) \
-{ \
- RYML_CHECK(GetParam() < NLEVELS); \
- if(g_suite_case->expect_error) \
- GTEST_SKIP(); \
- g_suite_case->input.which.compare_emitted(1 + GetParam()); \
-} \
- \
-/*-----------------------------------------------*/ \
- \
-TEST(which##_events, compare) \
-{ \
- if(g_suite_case->expect_error) \
- GTEST_SKIP(); \
- g_suite_case->input.which.compare_events(&g_suite_case->events); \
-} \
- \
-TEST(which##_events, emit_events) \
-{ \
- if(g_suite_case->expect_error) \
- GTEST_SKIP(); \
- g_suite_case->input.which.compare_emitted_events(&g_suite_case->events); \
-} \
- \
-/*-----------------------------------------------*/ \
- \
-TEST(which##_errors, check_expected_error) \
-{ \
- if(!g_suite_case->expect_error) \
- GTEST_SKIP(); \
- g_suite_case->input.which.check_expected_error(); \
-} \
- \
- \
-INSTANTIATE_TEST_SUITE_P(_, which, testing::Range<size_t>(0, NLEVELS))
-
-
-DEFINE_TESTS(unix_arena);
-DEFINE_TESTS(unix_inplace);
-DEFINE_TESTS(unix_arena_reuse);
-DEFINE_TESTS(unix_inplace_reuse);
-DEFINE_TESTS(windows_arena);
-DEFINE_TESTS(windows_inplace);
-DEFINE_TESTS(windows_arena_reuse);
-DEFINE_TESTS(windows_inplace_reuse);
-
-
-//-------------------------------------------
-// this is needed to use the test case library
-Case const* get_case(csubstr /*name*/) { return nullptr; }
-
-} // namespace yml
-} // namespace c4
-
-
-
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-int main(int argc, char* argv[])
-{
- c4::dump("$");
- for(int i = 0; i < argc; ++i)
- c4::dump(' ', c4::to_csubstr(argv[i]));
- c4::dump("\n");
-
- // make gtest parse its args
- testing::InitGoogleTest(&argc, argv);
-
- // now we have only our args to consider
- if(argc != 4)
- {
- log("usage:\n{} <test_name> <test-dir> <input-file>", c4::to_csubstr(argv[0]));
- return 1;
- }
-
- // load the test case from the suite file
- c4::yml::SuiteCase suite_case(argv[1], argv[2], argv[3]);
- c4::yml::g_suite_case = &suite_case;
-
- return RUN_ALL_TESTS();
-}
-
-C4_SUPPRESS_WARNING_MSVC_PUSH