-
Notifications
You must be signed in to change notification settings - Fork 14
/
test.cpp
162 lines (150 loc) · 5.8 KB
/
test.cpp
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "ginger.h"
#include <iostream>
#include <ios>
#include <vector>
#include <string>
#include <list>
#include <unordered_map>
int failed = 0;
template<class Input>
void print_error(int line, Input input, std::string expected, std::string actual, std::string error = "") {
std::cerr << "------------- TEST ERROR (" << line << ") ---------------" << std::endl;
/*
for (auto c: expected)
std::cout << (int)c << std::endl;
std::cout << "---" << std::endl;
for (auto c: actual)
std::cout << (int)c << std::endl;
*/
std::cerr << "input: " << std::string(std::begin(input), std::end(input)) << std::endl;
std::cerr << "expected: " << expected << std::endl;
std::cerr << "actual: " << actual << std::endl;
std::cerr << error << std::endl;
++failed;
}
void print_error(int line, const char* input, std::string expected, std::string actual, std::string error = "") {
print_error(line, std::string(input), expected, actual, error);
}
template<class Input, class Dict>
void test_eq(Input input, std::string expected, Dict dic, int line) {
try {
std::stringstream ss;
ginger::parse(input, dic, ginger::from_ios(ss));
auto actual = ss.str();
if (actual != expected) {
print_error(line, input, expected, actual, "");
}
} catch (const ginger::parse_error& error) {
print_error(line, input, expected, "PARSE ERROR", error.long_error());
} catch (...) {
print_error(line, input, expected, "UNKNOWN EXCEPTION", "");
}
}
template<class Input, class Dict>
void test_exc(Input input, Dict dic, int line) {
try {
std::stringstream ss;
ginger::parse(input, dic, ginger::from_ios(ss));
auto actual = ss.str();
print_error(line, input, "THROW PARSE ERROR", actual, "");
} catch (ginger::parse_error& error) {
//visible errors.
//std::cout << error.long_error();
} catch (...) {
print_error(line, input, "THROW PARSE ERROR", "UNKNOWN EXCEPTION", "");
}
}
#define TEST_EQ(input, expected) test_eq(input, expected, ginger::temple(), __LINE__)
#define TEST_EQ_T(input, expected, t) test_eq(input, expected, t, __LINE__)
#define TEST_EXC(input) test_exc(input, ginger::temple(), __LINE__)
#define TEST_EXC_T(input, t) test_exc(input, t, __LINE__)
int main() {
TEST_EQ("", "");
TEST_EQ("Hello", "Hello");
TEST_EQ("${{", "{{");
TEST_EQ("$}}", "}}");
TEST_EQ("$$", "$");
TEST_EQ("$# comment", "");
TEST_EQ("$# comment\n", "\n");
TEST_EXC("$x");
TEST_EXC("${");
TEST_EXC("$}");
// test ${variable}
{
ginger::temple t;
t["value"] = 100;
t["map"] = std::map<std::string, int>{ { "hoge", 1 }, { "fuga", 2 } };
TEST_EQ_T("${value}", "100", t);
TEST_EQ_T("${map.hoge}, ${map.fuga}", "1, 2", t);
TEST_EQ_T("${ map.hoge }, ${ map.fuga }", "1, 2", t);
TEST_EXC_T("${ map. hoge }", t);
TEST_EXC_T("${ map .hoge }", t);
TEST_EXC_T("${undefined}", t);
}
// test $for
{
ginger::temple t;
t["xs"] = std::vector<int>{ 1, 2 };
t["ys"] = std::map<std::string, std::vector<int>>{ { "hoge", { 1, 2, 3 } } };
TEST_EQ_T("$for x in xs{{test}}", "testtest", t);
TEST_EQ_T("$for x in xs {{ test }}", " test test ", t);
TEST_EQ_T("$for x in xs{{$for x in xs{{test}}}}", "testtesttesttest", t);
TEST_EQ_T("$for y in ys.hoge{{${y}}}", "123", t);
TEST_EQ_T("$for y in \t ys.hoge {{${y}\n}}", "1\n2\n3\n", t);
TEST_EXC_T("$forx in xs{{}}", t);
TEST_EXC_T("$for xin xs{{}}", t);
TEST_EXC_T("$for x inxs{{}}", t);
TEST_EXC_T("$for x in xs{}}", t);
TEST_EXC_T("$for x in xs{{}", t);
}
// test $if
{
ginger::temple t;
t["true"] = true;
t["false"] = false;
// $if
TEST_EQ_T("$if true {{hoge}}", "hoge", t);
TEST_EQ_T("$if false{{hoge}}", "", t);
TEST_EXC_T("$iffalse {{hoge}}", t);
// $elseif
TEST_EQ_T("$if true{{hoge}}$elseif true{{fuga}}", "hoge", t);
TEST_EQ_T("$if true{{hoge}}$elseif undefined{{${undefined}}}", "hoge", t);
TEST_EQ_T("$if false{{hoge}}$elseif true{{fuga}}", "fuga", t);
TEST_EQ_T("$if false{{hoge}}$elseif true{{fuga}} $elseif undefined {{ fuga2 }}", "fuga", t);
TEST_EQ_T("$if false{{hoge}}$elseif false{{fuga}} $elseif true {{ fuga2 }}", " fuga2 ", t);
TEST_EXC_T("$if true{{hoge}}$elseiftrue{{fuga}}", t);
TEST_EXC_T("$if true{{hoge}}$else if true{{fuga}}", t);
// $else
TEST_EQ_T("$if true {{hoge}}$else{{moke}}", "hoge", t);
TEST_EQ_T("$if true {{hoge}} $else {{${undefined}}}", "hoge", t);
TEST_EQ_T("$if false {{hoge}} $elseif true {{fuga}} $else{{moke}}", "fuga", t);
TEST_EQ_T("$if false {{hoge}} $elseif false {{fuga}} $else{{moke}}", "moke", t);
TEST_EXC_T("$if true {{}}$else${{}}", t);
// confusing case
TEST_EQ_T("$if true {{hoge}} ${true}", "hoge 1", t);
TEST_EQ_T("$if true {{hoge}}${{", "hoge{{", t);
TEST_EQ_T("$if true {{hoge}} ", "hoge ", t);
TEST_EQ_T("$if true {{hoge}} a", "hoge a", t);
TEST_EXC_T("$if true {{hoge}} $", t);
}
// test ForwardIterator
{
ginger::temple t;
t["true"] = true;
t["false"] = false;
std::string str = "$if true {{hoge}} ${true}";
std::list<char> input{str.begin(), str.end()};
TEST_EQ_T(input, "hoge 1", t);
}
// test Generic Dictionary
{
std::unordered_map<std::string, ginger::object> t;
t["value"] = 100;
TEST_EQ_T("${value}", "100", t);
}
if (failed != 0) {
std::cerr << "------- TEST FAILED --------" << std::endl;
std::cerr << "FAILED COUNT: " << failed << std::endl;
std::exit(1);
}
}