Toolbox snapshot
The Reactive C++ Toolbox
Loading...
Searching...
No Matches
Parser.ut.cpp
Go to the documentation of this file.
1// The Reactive C++ Toolbox.
2// Copyright (C) 2013-2019 Swirly Cloud Limited
3// Copyright (C) 2021 Reactive Markets Limited
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17#include "Parser.hpp"
18
19#include <boost/test/unit_test.hpp>
20
21using namespace std;
22using namespace toolbox;
23
24namespace {
26class Parser : BasicParser<Parser> {
27 friend class BasicParser<Parser>;
28
29 public:
43 std::string parse(string_view data)
44 {
45 for (const auto c : data) {
46 // Intercept special character that sets the except flag.
47 if (c == '!') {
48 except_ = true;
49 continue;
50 }
51 try {
52 put(c);
53 } catch (const resp::Exception&) {
54 throw;
55 } catch (const exception& e) {
56 result_ += '!';
57 }
58 }
59 return result_;
60 }
61
62 private:
63 void on_resp_command_line(const string& line)
64 {
66 result_ = line;
67 }
68 void on_resp_string(const string& s)
69 {
70 if (!result_.empty() && result_.back() != '[') {
71 result_ += ',';
72 }
74 result_ += '+';
75 result_ += s;
76 }
77 void on_resp_error(const string& e)
78 {
79 if (!result_.empty() && result_.back() != '[') {
80 result_ += ',';
81 }
83 result_ += '-';
84 result_ += e;
85 }
87 {
88 if (!result_.empty() && result_.back() != '[') {
89 result_ += ',';
90 }
92 result_ += ':';
93 result_ += to_string(i);
94 }
95 void on_resp_array_begin(int /*n*/)
96 {
97 if (!result_.empty() && result_.back() != '[') {
98 result_ += ',';
99 }
101 result_ += '[';
102 }
103 void on_resp_array_end()
104 {
106 result_ += ']';
107 }
108 void on_resp_reset() noexcept { result_ += '~'; }
109 void throw_if_except()
110 {
111 if (!except_) {
112 return;
113 }
114 except_ = false;
115 throw exception{};
116 }
117 // Setting to true causes the next handler to throw.
118 bool except_{false};
119 string result_;
120};
121
122std::string parse(string_view data)
123{
124 Parser p;
125 return p.parse(data);
126}
127
128} // namespace
129
131
133{
134 BOOST_CHECK_EQUAL(parse("+\r\n"sv), "+");
135 BOOST_CHECK_EQUAL(parse("+OK\r\n"sv), "+OK");
136 BOOST_CHECK_EQUAL(parse("+OK\r"sv), "");
137 BOOST_CHECK_EQUAL(parse("+foo bar\r\n"sv), "+foo bar");
138 BOOST_CHECK_EQUAL(parse("+foo bar!\r\n+OK\r\n"sv), "!,+OK");
139}
140
142{
143 BOOST_CHECK_EQUAL(parse("-\r\n"sv), "-");
144 BOOST_CHECK_EQUAL(parse("-Error message\r\n"sv), "-Error message");
145 BOOST_CHECK_EQUAL(parse("-Error message\r"sv), "");
146 BOOST_CHECK_EQUAL(parse("-ERR unknown command 'foobar'\r\n"sv),
147 "-ERR unknown command 'foobar'");
148 BOOST_CHECK_EQUAL(parse("-ERR unknown command 'foobar'!\r\n+OK\r\n"sv), "!,+OK");
149}
150
152{
153 BOOST_CHECK_EQUAL(parse(":\r\n"sv), ":0");
154 BOOST_CHECK_EQUAL(parse(":0\r\n"sv), ":0");
155 BOOST_CHECK_EQUAL(parse(":0\r"sv), "");
156 BOOST_CHECK_EQUAL(parse(":123\r\n"sv), ":123");
157 BOOST_CHECK_EQUAL(parse(":+123\r\n"sv), ":123");
158 BOOST_CHECK_EQUAL(parse(":-123\r\n"sv), ":-123");
159 BOOST_CHECK_EQUAL(parse(":-123!\r\n+OK\r\n"sv), "!,+OK");
160
162}
163
165{
166 BOOST_CHECK_EQUAL(parse("$0\r\n\r\n"sv), "+");
167 BOOST_CHECK_EQUAL(parse("$6\r\nfoobar\r\n"sv), "+foobar");
168 BOOST_CHECK_EQUAL(parse("$7\r\nfoo bar\r\n"sv), "+foo bar");
169 BOOST_CHECK_EQUAL(parse("$7\r\nfoo bar!\r\n+OK\r\n"sv), "!,+OK");
170 BOOST_CHECK_EQUAL(parse("$7\r\nfoo bar!\r\n+OK\r\n"sv), "!,+OK");
171
172 BOOST_CHECK_THROW(parse("$6x\r\nfoobar\r\n"sv), resp::Exception);
173}
174
176{
177 BOOST_CHECK_EQUAL(parse("+OK\r\n-ERR\r\n:123\r\n$6\r\nfoobar\r\n"sv), "+OK,-ERR,:123,+foobar");
178}
179
181{
182 BOOST_CHECK_EQUAL(parse("*0\r\n"sv), "[]");
183 BOOST_CHECK_EQUAL(parse("*0!\r\n+OK\r\n"sv), "~!,+OK");
184 BOOST_CHECK_EQUAL(parse("*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"sv), "[+foo,+bar]");
185 BOOST_CHECK_EQUAL(parse("*2\r\n$3\r\nfoo!\r\n$3\r\nbar\r\n+OK\r\n"sv), "[!~,+OK");
186 BOOST_CHECK_EQUAL(parse("*3\r\n:1\r\n:2\r\n:3\r\n"sv), "[:1,:2,:3]");
187 BOOST_CHECK_EQUAL(parse("*3\r\n:1\r\n:2\r\n:3!\r\n+OK\r\n"sv), "[:1,:2,~!,+OK");
188 BOOST_CHECK(parse("*5\r\n:1\r\n:2\r\n:3\r\n:4\r\n$6\r\nfoobar\r\n"sv)
189 == "[:1,:2,:3,:4,+foobar]");
190 BOOST_CHECK(parse("*5\r\n:1\r\n:2\r\n:3!\r\n:4\r\n$6\r\nfoobar\r\n+OK\r\n"sv)
191 == "[:1,:2,!~,+OK");
192
193 BOOST_CHECK_THROW(parse("*1x\r\n$3\r\nfoo\r\n"sv), resp::Exception);
194}
195
197{
198 BOOST_CHECK_EQUAL(parse("*1\r\n*0\r\n"sv), "[[]]");
199 BOOST_CHECK_EQUAL(parse("*2\r\n*0\r\n*0\r\n"sv), "[[],[]]");
200 BOOST_CHECK_EQUAL(parse("*1\r\n*1\r\n*0\r\n"sv), "[[[]]]");
201 BOOST_CHECK_EQUAL(parse("*1\r\n*1\r\n+OK\r\n"sv), "[[+OK]]");
202 BOOST_CHECK_EQUAL(parse("*1\r\n*1\r\n+OK!\r\n+OK\r\n"sv), "[[~!,+OK");
203 BOOST_CHECK_EQUAL(parse("*2\r\n*1\r\n+OK\r\n*1\r\n-ERR\r\n"sv), "[[+OK],[-ERR]]");
204 BOOST_CHECK_EQUAL(parse("*2\r\n*1\r\n+OK\r\n*1\r\n-ERR!\r\n+OK\r\n"sv), "[[+OK],[~!,+OK");
205 BOOST_CHECK(parse("*3\r\n:1\r\n*3\r\n:11\r\n*2\r\n:111\r\n:222\r\n:22\r\n:2\r\n"sv)
206 == "[:1,[:11,[:111,:222],:22],:2]");
207 BOOST_CHECK(parse("*3\r\n:1\r\n*3\r\n:11\r\n*2\r\n:111!\r\n:222\r\n:22\r\n:2\r\n+OK\r\n"sv)
208 == "[:1,[:11,[!~,+OK");
209}
210
BOOST_CHECK_EQUAL(v.size(), 10U)
STL namespace.
const DataT & data(const MsgEvent &ev) noexcept
Definition Event.hpp:54
std::string to_string(ValueT &&val)
Definition String.hpp:54
std::string_view sv
Definition Tokeniser.hpp:26
constexpr auto bind() noexcept
Definition Slot.hpp:92
BOOST_AUTO_TEST_CASE(SimpleStringCase)
BOOST_CHECK(isnan(stod(""sv, numeric_limits< double >::quiet_NaN())))