summaryrefslogtreecommitdiffstats
path: root/src/parser/stream_test.cpp
blob: 1a6e9fbcb48ca1d6bb3cce318fb9623261a7cf30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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: */