summaryrefslogtreecommitdiffstats
path: root/src/parser/stream_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser/stream_test.cpp')
-rw-r--r--src/parser/stream_test.cpp144
1 files changed, 144 insertions, 0 deletions
diff --git a/src/parser/stream_test.cpp b/src/parser/stream_test.cpp
new file mode 100644
index 0000000..1a6e9fb
--- /dev/null
+++ b/src/parser/stream_test.cpp
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "test_global.hpp"
+#include "orcus/stream.hpp"
+
+#include <cstdlib>
+#include <string>
+#include <vector>
+
+using namespace std;
+using namespace orcus;
+
+void test_stream_create_error_output()
+{
+ test::stack_printer __sp__(__func__);
+
+ string output = create_parse_error_output("{}", 1);
+ cout << output << endl;
+ const char* expected = "1:2: {}\n ^";
+ assert(output == expected);
+}
+
+void test_stream_locate_first_different_char()
+{
+ test::stack_printer __sp__(__func__);
+
+ struct test_case
+ {
+ const char* left;
+ const char* right;
+ size_t expected;
+ };
+
+ std::vector<test_case> test_cases = {
+ { "", "a", 0 },
+ { "a", "", 0 },
+ { "", "", 0 },
+ { " ", "b", 0 },
+ { "abc", "abc", 3 },
+ { "abcd", "abce", 3 },
+ { "abc", "bbc", 0 },
+ { "abc", "acc", 1 },
+ };
+
+ for (const test_case& tc : test_cases)
+ {
+ size_t actual = locate_first_different_char(tc.left, tc.right);
+ assert(actual == tc.expected);
+ }
+}
+
+void test_stream_logical_string_length()
+{
+ test::stack_printer __sp__(__func__);
+
+ struct check
+ {
+ std::string_view value;
+ std::size_t length;
+ };
+
+ constexpr check checks[] = {
+ { "東京", 2 },
+ { "大阪は暑い", 5 },
+ { "New York", 8 },
+ { "日本は英語で言うとJapan", 14 },
+ { "fabriqué", 8 },
+ { "garçon", 6 },
+ { "вход", 4 },
+ { "выход", 5 },
+ { "помогите", 8 },
+ { "Nähe", 4 },
+ };
+
+ for (auto [value, expected_len] : checks)
+ {
+ std::size_t len = calc_logical_string_length(value);
+ std::cout << "'" << value << "' (length=" << len << ")" << std::endl;
+ assert(len == expected_len);
+ }
+}
+
+void test_stream_locate_line_with_offset()
+{
+ test::stack_printer __sp__(__func__);
+
+ std::string strm = "one\ntwo\nthree";
+
+ struct check
+ {
+ std::ptrdiff_t offset;
+ line_with_offset expected;
+ };
+
+ const std::vector<check> checks = {
+ { 0, { "one", 0, 0 } },
+ { 1, { "one", 0, 1 } },
+ { 2, { "one", 0, 2 } },
+ { 3, { "one", 0, 3 } }, // on line break
+ { 4, { "two", 1, 0 } },
+ { 5, { "two", 1, 1 } },
+ { 6, { "two", 1, 2 } },
+ { 7, { "two", 1, 3 } }, // on line break
+ { 8, { "three", 2, 0 } },
+ { 9, { "three", 2, 1 } },
+ { 10, { "three", 2, 2 } },
+ { 11, { "three", 2, 3 } },
+ { 12, { "three", 2, 4 } },
+ };
+
+ for (const auto& c : checks)
+ {
+ auto res = locate_line_with_offset(strm, c.offset);
+ assert(res == c.expected);
+ }
+
+ try
+ {
+ auto res = locate_line_with_offset(strm, strm.size());
+ assert(!"exception should have been thrown for out-of-bound offset!");
+ }
+ catch (const std::invalid_argument& e)
+ {
+ // expected
+ cout << "exception thrown as expected: '" << e.what() << "'" << endl;
+ }
+}
+
+int main()
+{
+ test_stream_create_error_output();
+ test_stream_locate_first_different_char();
+ test_stream_logical_string_length();
+ test_stream_locate_line_with_offset();
+
+ return EXIT_SUCCESS;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */