1 /*
2 * Copyright (C) 2004-2020 ZNC, see the NOTICE file for details.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gtest/gtest.h>
18 #include <znc/ZNCString.h>
19
20 class EscapeTest : public ::testing::Test {
21 protected:
testEncode(const CString & in,const CString & expectedOut,const CString & sformat)22 void testEncode(const CString& in, const CString& expectedOut,
23 const CString& sformat) {
24 CString::EEscape format = CString::ToEscape(sformat);
25 CString out;
26
27 SCOPED_TRACE("Format: " + sformat);
28
29 // Encode, then decode again and check we still got the same string
30 out = in.Escape_n(CString::EASCII, format);
31 EXPECT_EQ(out, expectedOut);
32 out = out.Escape_n(format, CString::EASCII);
33 EXPECT_EQ(out, in);
34 }
35
testString(const CString & in,const CString & url,const CString & html,const CString & sql,const CString & tag)36 void testString(const CString& in, const CString& url, const CString& html,
37 const CString& sql, const CString& tag) {
38 SCOPED_TRACE("String: " + in);
39
40 testEncode(in, url, "URL");
41 testEncode(in, html, "HTML");
42 testEncode(in, sql, "SQL");
43 testEncode(in, tag, "MSGTAG");
44 }
45 };
46
TEST_F(EscapeTest,Test)47 TEST_F(EscapeTest, Test) {
48 // clang-format off
49 // input url html sql msgtag
50 testString("abcdefg","abcdefg", "abcdefg", "abcdefg", "abcdefg");
51 testString("\n\t\r", "%0A%09%0D", "\n\t\r", "\\n\\t\\r", "\\n\t\\r");
52 testString("'\"", "%27%22", "'"", "\\'\\\"", "'\"");
53 testString("&<>", "%26%3C%3E", "&<>", "&<>", "&<>");
54 testString(" ;", "+%3B", " ;", " ;", "\\s\\:");
55 // clang-format on
56 EXPECT_EQ(CString("a<.b>c").Escape_n(CString::EHTML, CString::EASCII),
57 "a<.b>c");
58 }
59
TEST(StringTest,Bool)60 TEST(StringTest, Bool) {
61 EXPECT_TRUE(CString(true).ToBool());
62 EXPECT_FALSE(CString(false).ToBool());
63 }
64
65 #define CS(s) (CString((s), sizeof(s) - 1))
66
TEST(StringTest,Cmp)67 TEST(StringTest, Cmp) {
68 CString s = "Bbb";
69
70 EXPECT_EQ(s, CString("Bbb"));
71 EXPECT_LT(CString("Aaa"), s);
72 EXPECT_GT(CString("Ccc"), s);
73 EXPECT_EQ(s.StrCmp("Bbb"), 0);
74 EXPECT_GT(0, s.StrCmp("bbb"));
75 EXPECT_LT(0, s.StrCmp("Aaa"));
76 EXPECT_GT(0, s.StrCmp("Ccc"));
77 EXPECT_EQ(s.CaseCmp("Bbb"), 0);
78 EXPECT_EQ(s.CaseCmp("bbb"), 0);
79 EXPECT_LT(0, s.CaseCmp("Aaa"));
80 EXPECT_GT(0, s.CaseCmp("Ccc"));
81
82 EXPECT_TRUE(s.Equals("bbb"));
83 EXPECT_FALSE(s.Equals("bbb", true));
84 EXPECT_FALSE(s.Equals("bb"));
85 }
86
TEST(StringTest,Wild)87 TEST(StringTest, Wild) {
88 EXPECT_TRUE(CString::WildCmp("", "", CString::CaseSensitive));
89 EXPECT_TRUE(CString::WildCmp("", "", CString::CaseInsensitive));
90
91 EXPECT_FALSE(CString::WildCmp("*a*b*c*", "xy", CString::CaseSensitive));
92 EXPECT_FALSE(CString::WildCmp("*a*b*c*", "xy", CString::CaseInsensitive));
93
94 EXPECT_TRUE(CString::WildCmp("*!?bar@foo", "I_am!~bar@foo",
95 CString::CaseSensitive));
96 EXPECT_TRUE(CString::WildCmp("*!?bar@foo", "I_am!~bar@foo",
97 CString::CaseInsensitive));
98
99 EXPECT_FALSE(CString::WildCmp("*!?BAR@foo", "I_am!~bar@foo",
100 CString::CaseSensitive));
101 EXPECT_TRUE(CString::WildCmp("*!?BAR@foo", "I_am!~bar@foo",
102 CString::CaseInsensitive));
103
104 EXPECT_TRUE(CString::WildCmp("*a*b*c*", "abc", CString::CaseSensitive));
105 EXPECT_TRUE(CString::WildCmp("*a*b*c*", "abc", CString::CaseInsensitive));
106
107 EXPECT_FALSE(CString::WildCmp("*A*b*c*", "abc", CString::CaseSensitive));
108 EXPECT_TRUE(CString::WildCmp("*A*b*c*", "abc", CString::CaseInsensitive));
109
110 EXPECT_FALSE(CString::WildCmp("*a*b*c*", "Abc", CString::CaseSensitive));
111 EXPECT_TRUE(CString::WildCmp("*a*b*c*", "Abc", CString::CaseInsensitive));
112
113 EXPECT_TRUE(CString::WildCmp("*a*b*c*", "axbyc", CString::CaseSensitive));
114 EXPECT_TRUE(CString::WildCmp("*a*b*c*", "axbyc", CString::CaseInsensitive));
115
116 EXPECT_FALSE(CString::WildCmp("*a*B*c*", "AxByC", CString::CaseSensitive));
117 EXPECT_TRUE(CString::WildCmp("*a*B*c*", "AxByC", CString::CaseInsensitive));
118 }
119
TEST(StringTest,Case)120 TEST(StringTest, Case) {
121 CString x = CS("xx");
122 CString X = CS("XX");
123 EXPECT_EQ(x.AsUpper(), X);
124 EXPECT_EQ(X.AsLower(), x);
125 }
126
TEST(StringTest,Replace)127 TEST(StringTest, Replace) {
128 EXPECT_EQ(CString("(a()a)").Replace_n("a", "b"), "(b()b)");
129 EXPECT_EQ(CString("(a()a)").Replace_n("a", "b", "(", ")"), "(a()b)");
130 EXPECT_EQ(CString("(a()a)").Replace_n("a", "b", "(", ")", true), "a(b)");
131 }
132
TEST(StringTest,Misc)133 TEST(StringTest, Misc) {
134 EXPECT_EQ(CString("Hello, I'm Bob").Ellipsize(9), "Hello,...");
135 EXPECT_EQ(CString("Hello, I'm Bob").Ellipsize(90), "Hello, I'm Bob");
136 EXPECT_EQ(CString("Hello, I'm Bob").Ellipsize(2), "..");
137
138 EXPECT_EQ(CS("Xyz").Left(2), "Xy");
139 EXPECT_EQ(CS("Xyz").Left(20), "Xyz");
140
141 EXPECT_EQ(CS("Xyz").Right(2), "yz");
142 EXPECT_EQ(CS("Xyz").Right(20), "Xyz");
143 }
144
TEST(StringTest,Split)145 TEST(StringTest, Split) {
146 EXPECT_EQ(CS("a b c").Token(0), "a");
147 EXPECT_EQ(CS("a b c").Token(1), "b");
148 EXPECT_EQ(CS("a b c").Token(100), "");
149 EXPECT_EQ(CS("a b c").Token(1, true), "b c");
150 EXPECT_EQ(CS("a c").Token(1), "c");
151 EXPECT_EQ(CS("a c").Token(1, false, " ", true), "");
152 EXPECT_EQ(CS("a c").Token(1, false, " "), "c");
153 EXPECT_EQ(CS("a c").Token(1, false, " "), " c");
154 EXPECT_EQ(CS("a c").Token(1, false, " "), "c");
155 EXPECT_EQ(CS("a (b c) d").Token(1, false, " ", false, "(", ")"), "b c");
156 EXPECT_EQ(CS("a (b c) d").Token(1, false, " ", false, "(", ")", false),
157 "(b c)");
158 EXPECT_EQ(CS("a (b c) d").Token(2, false, " ", false, "(", ")", false),
159 "d");
160
161 VCString vexpected;
162 VCString vresult;
163
164 vexpected.push_back("a");
165 vexpected.push_back("b");
166 vexpected.push_back("c");
167 CS("a b c").Split(" ", vresult);
168 EXPECT_EQ(vresult, vexpected);
169
170 MCString mexpected = {{"a", "b"}, {"c", "d"}};
171 MCString mresult;
172
173 CS("a=x&c=d&a=b").URLSplit(mresult);
174 EXPECT_EQ(mexpected, mresult) << "URLSplit";
175 }
176
TEST(StringTest,NamedFormat)177 TEST(StringTest, NamedFormat) {
178 MCString m = {{"a", "b"}};
179 EXPECT_EQ(CString::NamedFormat(CS("\\{x{a}y{a}"), m), "{xbyb");
180 }
181
TEST(StringTest,Hash)182 TEST(StringTest, Hash) {
183 EXPECT_EQ(CS("").MD5(), "d41d8cd98f00b204e9800998ecf8427e");
184 EXPECT_EQ(CS("a").MD5(), "0cc175b9c0f1b6a831c399e269772661");
185
186 EXPECT_EQ(
187 CS("").SHA256(),
188 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
189 EXPECT_EQ(
190 CS("a").SHA256(),
191 "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb");
192 }
193
TEST(StringTest,Equals)194 TEST(StringTest, Equals) {
195 EXPECT_TRUE(CS("ABC").Equals("abc"));
196 EXPECT_TRUE(CS("ABC").Equals("abc", CString::CaseInsensitive));
197 EXPECT_FALSE(CS("ABC").Equals("abc", CString::CaseSensitive));
198 EXPECT_TRUE(CS("ABC").Equals("abc", false)); // deprecated
199 EXPECT_FALSE(CS("ABC").Equals("abc", true)); // deprecated
200 }
201
TEST(StringTest,Find)202 TEST(StringTest, Find) {
203 EXPECT_EQ(CString("Hello, I'm Bob").Find("Hello"), 0u);
204 EXPECT_EQ(CString("Hello, I'm Bob").Find("Hello", CString::CaseInsensitive),
205 0u);
206 EXPECT_EQ(CString("Hello, I'm Bob").Find("Hello", CString::CaseSensitive),
207 0u);
208
209 EXPECT_EQ(CString("Hello, I'm Bob").Find("i'm"), 7u);
210 EXPECT_EQ(CString("Hello, I'm Bob").Find("i'm", CString::CaseInsensitive),
211 7u);
212 EXPECT_EQ(CString("Hello, I'm Bob").Find("i'm", CString::CaseSensitive),
213 CString::npos);
214 }
215
TEST(StringTest,StartsWith)216 TEST(StringTest, StartsWith) {
217 EXPECT_TRUE(CString("Hello, I'm Bob").StartsWith("Hello"));
218 EXPECT_TRUE(CString("Hello, I'm Bob")
219 .StartsWith("Hello", CString::CaseInsensitive));
220 EXPECT_TRUE(
221 CString("Hello, I'm Bob").StartsWith("Hello", CString::CaseSensitive));
222
223 EXPECT_TRUE(CString("Hello, I'm Bob").StartsWith("hello"));
224 EXPECT_TRUE(CString("Hello, I'm Bob")
225 .StartsWith("hello", CString::CaseInsensitive));
226 EXPECT_FALSE(
227 CString("Hello, I'm Bob").StartsWith("hello", CString::CaseSensitive));
228 }
229
TEST(StringTest,EndsWith)230 TEST(StringTest, EndsWith) {
231 EXPECT_TRUE(CString("Hello, I'm Bob").EndsWith("Bob"));
232 EXPECT_TRUE(
233 CString("Hello, I'm Bob").EndsWith("Bob", CString::CaseInsensitive));
234 EXPECT_TRUE(
235 CString("Hello, I'm Bob").EndsWith("Bob", CString::CaseSensitive));
236
237 EXPECT_TRUE(CString("Hello, I'm Bob").EndsWith("bob"));
238 EXPECT_TRUE(
239 CString("Hello, I'm Bob").EndsWith("bob", CString::CaseInsensitive));
240 EXPECT_FALSE(
241 CString("Hello, I'm Bob").EndsWith("bob", CString::CaseSensitive));
242 }
243
TEST(StringTest,Contains)244 TEST(StringTest, Contains) {
245 EXPECT_TRUE(CString("Hello, I'm Bob").Contains("Hello"));
246 EXPECT_TRUE(
247 CString("Hello, I'm Bob").Contains("Hello", CString::CaseInsensitive));
248 EXPECT_TRUE(
249 CString("Hello, I'm Bob").Contains("Hello", CString::CaseSensitive));
250
251 EXPECT_TRUE(CString("Hello, I'm Bob").Contains("i'm"));
252 EXPECT_TRUE(
253 CString("Hello, I'm Bob").Contains("i'm", CString::CaseInsensitive));
254 EXPECT_FALSE(
255 CString("Hello, I'm Bob").Contains("i'm", CString::CaseSensitive));
256
257 EXPECT_TRUE(CString("Hello, I'm Bob").Contains("i'm bob"));
258 EXPECT_TRUE(CString("Hello, I'm Bob")
259 .Contains("i'm bob", CString::CaseInsensitive));
260 EXPECT_FALSE(
261 CString("Hello, I'm Bob").Contains("i'm bob", CString::CaseSensitive));
262 }
263
TEST(StringTest,StripControls)264 TEST(StringTest, StripControls) {
265 // Strips reset colours
266 EXPECT_EQ(CString("\x03test").StripControls(), "test");
267
268 // Strips reset foreground and set new background colour
269 EXPECT_EQ(CString("\x03,03test").StripControls(), "test");
270
271 // Strips foreground and background colour
272 EXPECT_EQ(CString("\x03\x30,03test").StripControls(), "test");
273
274 // Strips reset
275 EXPECT_EQ(CString("\x0Ftest").StripControls(), "test");
276
277 // Strips reverse
278 EXPECT_EQ(CString("\x12test").StripControls(), "test");
279
280 // Strips bold
281 EXPECT_EQ(CString("\x02test").StripControls(), "test");
282
283 // Strips italics
284 EXPECT_EQ(CString("\x16test").StripControls(), "test");
285
286 // Strips underline
287 EXPECT_EQ(CString("\x1Ftest").StripControls(), "test");
288 }
289