1 /***************************************************************************
2 * Copyright (C) 2005-2020 by the Quassel Project *
3 * devel@quassel-irc.org *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
23 #include "testglobal.h"
24 #include "ircencoder.h"
29 std::map<IrcTagKey, std::string> tags;
32 std::vector<std::string> params;
34 explicit IrcMessage(std::map<IrcTagKey, std::string> tags, std::string prefix, std::string cmd, std::vector<std::string> params = {})
35 : tags(std::move(tags)), prefix(std::move(prefix)), cmd(std::move(cmd)), params(std::move(params)) {}
37 explicit IrcMessage(std::initializer_list<std::pair<const IrcTagKey, std::string>> tags, std::string prefix, std::string cmd, std::vector<std::string> params = {})
38 : tags(tags), prefix(std::move(prefix)), cmd(std::move(cmd)), params(std::move(params)) {}
40 explicit IrcMessage(std::string prefix, std::string cmd, std::vector<std::string> params = {})
41 : tags({}), prefix(std::move(prefix)), cmd(std::move(cmd)), params(std::move(params)) {}
43 friend bool operator==(const IrcMessage& a, const IrcMessage& b)
45 return a.tags == b.tags &&
46 a.prefix == b.prefix &&
51 friend std::ostream& operator<<(std::ostream& o, const IrcMessage& m)
54 for (const std::pair<IrcTagKey, std::string> entry: m.tags) {
55 o << entry.first << "='" << entry.second << "', ";
57 o << "}, prefix=" << m.prefix << ", cmd=" << m.cmd << ", params=[";
58 for (const std::string& param : m.params) {
59 o << "'" << param << "', ";
67 std::string write(const IrcMessage& message)
69 QHash<IrcTagKey, QString> tags;
70 QByteArray prefix = QByteArray::fromStdString(message.prefix);
71 QByteArray cmd = QByteArray::fromStdString(message.cmd);
72 QList<QByteArray> params;
74 for (const auto& pair : message.tags) {
75 tags[pair.first] = QString::fromStdString(pair.second);
78 for (const std::string& param : message.params) {
79 params += QByteArray::fromStdString(param);
82 return IrcEncoder::writeMessage(tags, prefix, cmd, params).toStdString();
85 TEST(IrcEncoderTest, simple_test_with_verb_and_params)
91 {"bar", "baz", "asdf"})).data());
94 TEST(IrcEncoderTest, simple_test_with_source_and_no_params)
98 write(IrcMessage("src",
102 TEST(IrcEncoderTest, simple_test_with_source_and_empty_trailing_param)
106 write(IrcMessage("src",
111 TEST(IrcEncoderTest, simple_test_with_source)
114 ":coolguy foo bar baz asdf",
115 write(IrcMessage("coolguy",
117 {"bar", "baz", "asdf"})).data());
120 TEST(IrcEncoderTest, simple_test_with_trailing_param)
123 "foo bar baz :asdf quux",
126 {"bar", "baz", "asdf quux"})).data());
129 TEST(IrcEncoderTest, simple_test_with_empty_trailing_param)
135 {"bar", "baz", ""})).data());
138 TEST(IrcEncoderTest, simple_test_with_trailing_param_containing_colon)
141 "foo bar baz ::asdf",
144 {"bar", "baz", ":asdf"})).data());
147 TEST(IrcEncoderTest, test_with_source_and_trailing_param)
150 ":coolguy foo bar baz :asdf quux",
151 write(IrcMessage("coolguy",
153 {"bar", "baz", "asdf quux"})).data());
156 TEST(IrcEncoderTest, test_with_trailing_containing_beginning_end_whitespace)
159 ":coolguy foo bar baz : asdf quux ",
160 write(IrcMessage("coolguy",
162 {"bar", "baz", " asdf quux "})).data());
165 TEST(IrcEncoderTest, test_with_trailing_containing_what_looks_like_another_trailing_param)
168 ":coolguy PRIVMSG bar :lol :) ",
169 write(IrcMessage("coolguy",
171 {"bar", "lol :) "})).data());
174 TEST(IrcEncoderTest, simple_test_with_source_and_empty_trailing)
177 ":coolguy foo bar baz :",
178 write(IrcMessage("coolguy",
180 {"bar", "baz", ""})).data());
183 TEST(IrcEncoderTest, trailing_contains_only_spaces)
186 ":coolguy foo bar baz : ",
187 write(IrcMessage("coolguy",
189 {"bar", "baz", " "})).data());
192 TEST(IrcEncoderTest, param_containing_tab_tab_is_not_considered_SPACE_for_message_splitting)
195 ":coolguy foo b\tar baz",
196 write(IrcMessage("coolguy",
198 {"b\tar", "baz"})).data());
201 TEST(IrcEncoderTest, tags_with_no_value_and_space_filled_trailing)
204 "@asd :coolguy foo bar baz : ",
205 write(IrcMessage({{IrcTagKey("asd"), ""}},
208 {"bar", "baz", " "})).data());
211 TEST(IrcEncoderTest, tags_with_escaped_values)
213 std::vector<std::string> expected{
214 R"(@d=gh\:764;a=b\\and\nk foo)",
215 R"(@a=b\\and\nk;d=gh\:764 foo)",
217 EXPECT_THAT(expected, testing::Contains(testing::StrCaseEq(
218 write(IrcMessage({{IrcTagKey("a"), "b\\and\nk"},
219 {IrcTagKey("d"), "gh;764"}},
224 TEST(IrcEncoderTest, tags_with_escaped_values_and_params)
226 std::vector<std::string> expected{
227 R"(@d=gh\:764;a=b\\and\nk foo par1 par2)",
228 R"(@a=b\\and\nk;d=gh\:764 foo par1 par2)",
230 EXPECT_THAT(expected, testing::Contains(testing::StrCaseEq(
231 write(IrcMessage({{IrcTagKey("a"), "b\\and\nk"},
232 {IrcTagKey("d"), "gh;764"}},
235 {"par1", "par2"})))));
238 TEST(IrcEncoderTest, tags_with_long_strange_values)
241 R"(@foo=\\\\\:\\s\s\r\n COMMAND)",
242 write(IrcMessage({{IrcTagKey("foo"), "\\\\;\\s \r\n"}},