/src/mozilla-central/toolkit/components/url-classifier/tests/gtest/TestUrlClassifierUtils.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #include <stdio.h> |
6 | | #include <ctype.h> |
7 | | |
8 | | #include <mozilla/RefPtr.h> |
9 | | #include "nsString.h" |
10 | | #include "nsEscape.h" |
11 | | #include "nsUrlClassifierUtils.h" |
12 | | #include "stdlib.h" |
13 | | #include "gtest/gtest.h" |
14 | | |
15 | 0 | static char int_to_hex_digit(int32_t i) { |
16 | 0 | NS_ASSERTION((i >= 0) && (i <= 15), "int too big in int_to_hex_digit"); |
17 | 0 | return static_cast<char>(((i < 10) ? (i + '0') : ((i - 10) + 'A'))); |
18 | 0 | } |
19 | | |
20 | | static void CheckEquals(nsCString& expected, nsCString& actual) |
21 | 0 | { |
22 | 0 | ASSERT_TRUE((expected).Equals((actual))); |
23 | 0 | } |
24 | | |
25 | | void TestUnescapeHelper(const char* in, const char* expected) |
26 | 0 | { |
27 | 0 | nsCString out, strIn(in), strExp(expected); |
28 | 0 |
|
29 | 0 | NS_UnescapeURL(strIn.get(), strIn.Length(), esc_AlwaysCopy, out); |
30 | 0 | CheckEquals(strExp, out); |
31 | 0 | } |
32 | | |
33 | | // Make sure Unescape from nsEncode.h's unescape does what the server does. |
34 | | TEST(UrlClassifierUtils, Unescape) |
35 | 0 | { |
36 | 0 | // test empty string |
37 | 0 | TestUnescapeHelper("\0", "\0"); |
38 | 0 |
|
39 | 0 | // Test docoding of all characters. |
40 | 0 | nsCString allCharsEncoded, allCharsEncodedLowercase, allCharsAsString; |
41 | 0 | for (int32_t i = 1; i < 256; ++i) { |
42 | 0 | allCharsEncoded.Append('%'); |
43 | 0 | allCharsEncoded.Append(int_to_hex_digit(i / 16)); |
44 | 0 | allCharsEncoded.Append((int_to_hex_digit(i % 16))); |
45 | 0 |
|
46 | 0 | allCharsEncodedLowercase.Append('%'); |
47 | 0 | allCharsEncodedLowercase.Append(tolower(int_to_hex_digit(i / 16))); |
48 | 0 | allCharsEncodedLowercase.Append(tolower(int_to_hex_digit(i % 16))); |
49 | 0 |
|
50 | 0 | allCharsAsString.Append(static_cast<char>(i)); |
51 | 0 | } |
52 | 0 |
|
53 | 0 | nsCString out; |
54 | 0 | NS_UnescapeURL(allCharsEncoded.get(), |
55 | 0 | allCharsEncoded.Length(), |
56 | 0 | esc_AlwaysCopy, |
57 | 0 | out); |
58 | 0 |
|
59 | 0 | CheckEquals(allCharsAsString, out); |
60 | 0 |
|
61 | 0 | out.Truncate(); |
62 | 0 | NS_UnescapeURL(allCharsEncodedLowercase.get(), |
63 | 0 | allCharsEncodedLowercase.Length(), |
64 | 0 | esc_AlwaysCopy, |
65 | 0 | out); |
66 | 0 | CheckEquals(allCharsAsString, out); |
67 | 0 |
|
68 | 0 | // Test %-related edge cases |
69 | 0 | TestUnescapeHelper("%", "%"); |
70 | 0 | TestUnescapeHelper("%xx", "%xx"); |
71 | 0 | TestUnescapeHelper("%%", "%%"); |
72 | 0 | TestUnescapeHelper("%%%", "%%%"); |
73 | 0 | TestUnescapeHelper("%%%%", "%%%%"); |
74 | 0 | TestUnescapeHelper("%1", "%1"); |
75 | 0 | TestUnescapeHelper("%1z", "%1z"); |
76 | 0 | TestUnescapeHelper("a%1z", "a%1z"); |
77 | 0 | TestUnescapeHelper("abc%d%e%fg%hij%klmno%", "abc%d%e%fg%hij%klmno%"); |
78 | 0 |
|
79 | 0 | // A few more tests |
80 | 0 | TestUnescapeHelper("%25", "%"); |
81 | 0 | TestUnescapeHelper("%25%32%35", "%25"); |
82 | 0 | } |
83 | | |
84 | | void TestEncodeHelper(const char* in, const char* expected) |
85 | 0 | { |
86 | 0 | nsCString out, strIn(in), strExp(expected); |
87 | 0 | RefPtr<nsUrlClassifierUtils> utils = new nsUrlClassifierUtils; |
88 | 0 | utils->Init(); |
89 | 0 |
|
90 | 0 | utils->SpecialEncode(strIn, true, out); |
91 | 0 | CheckEquals(strExp, out); |
92 | 0 | } |
93 | | |
94 | | TEST(UrlClassifierUtils, Enc) |
95 | 0 | { |
96 | 0 | // Test empty string |
97 | 0 | TestEncodeHelper("", ""); |
98 | 0 |
|
99 | 0 | // Test that all characters we shouldn't encode ([33-36],[38,126]) are not. |
100 | 0 | nsCString noenc; |
101 | 0 | for (int32_t i = 33; i < 127; i++) { |
102 | 0 | if (i != 37) { // skip % |
103 | 0 | noenc.Append(static_cast<char>(i)); |
104 | 0 | } |
105 | 0 | } |
106 | 0 | RefPtr<nsUrlClassifierUtils> utils = new nsUrlClassifierUtils; |
107 | 0 | utils->Init(); |
108 | 0 | nsCString out; |
109 | 0 | utils->SpecialEncode(noenc, false, out); |
110 | 0 | CheckEquals(noenc, out); |
111 | 0 |
|
112 | 0 | // Test that all the chars that we should encode [0,32],37,[127,255] are |
113 | 0 | nsCString yesAsString, yesExpectedString; |
114 | 0 | for (int32_t i = 1; i < 256; i++) { |
115 | 0 | if (i < 33 || i == 37 || i > 126) { |
116 | 0 | yesAsString.Append(static_cast<char>(i)); |
117 | 0 | yesExpectedString.Append('%'); |
118 | 0 | yesExpectedString.Append(int_to_hex_digit(i / 16)); |
119 | 0 | yesExpectedString.Append(int_to_hex_digit(i % 16)); |
120 | 0 | } |
121 | 0 | } |
122 | 0 |
|
123 | 0 | out.Truncate(); |
124 | 0 | utils->SpecialEncode(yesAsString, false, out); |
125 | 0 | CheckEquals(yesExpectedString, out); |
126 | 0 |
|
127 | 0 | TestEncodeHelper("blah//blah", "blah/blah"); |
128 | 0 | } |
129 | | |
130 | | void TestCanonicalizeHelper(const char* in, const char* expected) |
131 | 0 | { |
132 | 0 | nsCString out, strIn(in), strExp(expected); |
133 | 0 | RefPtr<nsUrlClassifierUtils> utils = new nsUrlClassifierUtils; |
134 | 0 | utils->Init(); |
135 | 0 |
|
136 | 0 | utils->CanonicalizePath(strIn, out); |
137 | 0 | CheckEquals(strExp, out); |
138 | 0 | } |
139 | | |
140 | | TEST(UrlClassifierUtils, Canonicalize) |
141 | 0 | { |
142 | 0 | // Test repeated %-decoding. Note: %25 --> %, %32 --> 2, %35 --> 5 |
143 | 0 | TestCanonicalizeHelper("%25", "%25"); |
144 | 0 | TestCanonicalizeHelper("%25%32%35", "%25"); |
145 | 0 | TestCanonicalizeHelper("asdf%25%32%35asd", "asdf%25asd"); |
146 | 0 | TestCanonicalizeHelper("%%%25%32%35asd%%", "%25%25%25asd%25%25"); |
147 | 0 | TestCanonicalizeHelper("%25%32%35%25%32%35%25%32%35", "%25%25%25"); |
148 | 0 | TestCanonicalizeHelper("%25", "%25"); |
149 | 0 | TestCanonicalizeHelper("%257Ea%2521b%2540c%2523d%2524e%25f%255E00%252611%252A22%252833%252944_55%252B", |
150 | 0 | "~a!b@c#d$e%25f^00&11*22(33)44_55+"); |
151 | 0 |
|
152 | 0 | TestCanonicalizeHelper("", ""); |
153 | 0 | TestCanonicalizeHelper("%31%36%38%2e%31%38%38%2e%39%39%2e%32%36/%2E%73%65%63%75%72%65/%77%77%77%2E%65%62%61%79%2E%63%6F%6D/", |
154 | 0 | "168.188.99.26/.secure/www.ebay.com/"); |
155 | 0 | TestCanonicalizeHelper("195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/", |
156 | 0 | "195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/"); |
157 | 0 | // Added in bug 489455. %00 should no longer be changed to %01. |
158 | 0 | TestCanonicalizeHelper("%00", "%00"); |
159 | 0 | } |
160 | | |
161 | | void TestParseIPAddressHelper(const char *in, const char *expected) |
162 | 0 | { |
163 | 0 | nsCString out, strIn(in), strExp(expected); |
164 | 0 | RefPtr<nsUrlClassifierUtils> utils = new nsUrlClassifierUtils; |
165 | 0 | utils->Init(); |
166 | 0 |
|
167 | 0 | utils->ParseIPAddress(strIn, out); |
168 | 0 | CheckEquals(strExp, out); |
169 | 0 | } |
170 | | |
171 | | TEST(UrlClassifierUtils, ParseIPAddress) |
172 | 0 | { |
173 | 0 | TestParseIPAddressHelper("123.123.0.0.1", ""); |
174 | 0 | TestParseIPAddressHelper("255.0.0.1", "255.0.0.1"); |
175 | 0 | TestParseIPAddressHelper("12.0x12.01234", "12.18.2.156"); |
176 | 0 | TestParseIPAddressHelper("276.2.3", "20.2.0.3"); |
177 | 0 | TestParseIPAddressHelper("012.034.01.055", "10.28.1.45"); |
178 | 0 | TestParseIPAddressHelper("0x12.0x43.0x44.0x01", "18.67.68.1"); |
179 | 0 | TestParseIPAddressHelper("167838211", "10.1.2.3"); |
180 | 0 | TestParseIPAddressHelper("3279880203", "195.127.0.11"); |
181 | 0 | TestParseIPAddressHelper("0x12434401", "18.67.68.1"); |
182 | 0 | TestParseIPAddressHelper("413960661", "24.172.137.213"); |
183 | 0 | TestParseIPAddressHelper("03053104725", "24.172.137.213"); |
184 | 0 | TestParseIPAddressHelper("030.0254.0x89d5", "24.172.137.213"); |
185 | 0 | TestParseIPAddressHelper("1.234.4.0377", "1.234.4.255"); |
186 | 0 | TestParseIPAddressHelper("1.2.3.00x0", ""); |
187 | 0 | TestParseIPAddressHelper("10.192.95.89 xy", "10.192.95.89"); |
188 | 0 | TestParseIPAddressHelper("10.192.95.89 xyz", ""); |
189 | 0 | TestParseIPAddressHelper("1.2.3.0x0", "1.2.3.0"); |
190 | 0 | TestParseIPAddressHelper("1.2.3.4", "1.2.3.4"); |
191 | 0 | } |
192 | | |
193 | | void TestCanonicalNumHelper(const char *in, uint32_t bytes, |
194 | | bool allowOctal, const char *expected) |
195 | 0 | { |
196 | 0 | nsCString out, strIn(in), strExp(expected); |
197 | 0 | RefPtr<nsUrlClassifierUtils> utils = new nsUrlClassifierUtils; |
198 | 0 | utils->Init(); |
199 | 0 |
|
200 | 0 | utils->CanonicalNum(strIn, bytes, allowOctal, out); |
201 | 0 | CheckEquals(strExp, out); |
202 | 0 | } |
203 | | |
204 | | TEST(UrlClassifierUtils, CanonicalNum) |
205 | 0 | { |
206 | 0 | TestCanonicalNumHelper("", 1, true, ""); |
207 | 0 | TestCanonicalNumHelper("10", 0, true, ""); |
208 | 0 | TestCanonicalNumHelper("45", 1, true, "45"); |
209 | 0 | TestCanonicalNumHelper("0x10", 1, true, "16"); |
210 | 0 | TestCanonicalNumHelper("367", 2, true, "1.111"); |
211 | 0 | TestCanonicalNumHelper("012345", 3, true, "0.20.229"); |
212 | 0 | TestCanonicalNumHelper("0173", 1, true, "123"); |
213 | 0 | TestCanonicalNumHelper("09", 1, false, "9"); |
214 | 0 | TestCanonicalNumHelper("0x120x34", 2, true, ""); |
215 | 0 | TestCanonicalNumHelper("0x12fc", 2, true, "18.252"); |
216 | 0 | TestCanonicalNumHelper("3279880203", 4, true, "195.127.0.11"); |
217 | 0 | TestCanonicalNumHelper("0x0000059", 1, true, "89"); |
218 | 0 | TestCanonicalNumHelper("0x00000059", 1, true, "89"); |
219 | 0 | TestCanonicalNumHelper("0x0000067", 1, true, "103"); |
220 | 0 | } |
221 | | |
222 | | void TestHostnameHelper(const char *in, const char *expected) |
223 | 0 | { |
224 | 0 | nsCString out, strIn(in), strExp(expected); |
225 | 0 | RefPtr<nsUrlClassifierUtils> utils = new nsUrlClassifierUtils; |
226 | 0 | utils->Init(); |
227 | 0 |
|
228 | 0 | utils->CanonicalizeHostname(strIn, out); |
229 | 0 | CheckEquals(strExp, out); |
230 | 0 | } |
231 | | |
232 | | TEST(UrlClassifierUtils, Hostname) |
233 | 0 | { |
234 | 0 | TestHostnameHelper("abcd123;[]", "abcd123;[]"); |
235 | 0 | TestHostnameHelper("abc.123", "abc.123"); |
236 | 0 | TestHostnameHelper("abc..123", "abc.123"); |
237 | 0 | TestHostnameHelper("trailing.", "trailing"); |
238 | 0 | TestHostnameHelper("i love trailing dots....", "i%20love%20trailing%20dots"); |
239 | 0 | TestHostnameHelper(".leading", "leading"); |
240 | 0 | TestHostnameHelper("..leading", "leading"); |
241 | 0 | TestHostnameHelper(".dots.", "dots"); |
242 | 0 | TestHostnameHelper(".both.", "both"); |
243 | 0 | TestHostnameHelper(".both..", "both"); |
244 | 0 | TestHostnameHelper("..both.", "both"); |
245 | 0 | TestHostnameHelper("..both..", "both"); |
246 | 0 | TestHostnameHelper("..a.b.c.d..", "a.b.c.d"); |
247 | 0 | TestHostnameHelper("..127.0.0.1..", "127.0.0.1"); |
248 | 0 | TestHostnameHelper("asdf!@#$a", "asdf!@#$a"); |
249 | 0 | TestHostnameHelper("AB CD 12354", "ab%20cd%2012354"); |
250 | 0 | TestHostnameHelper("\1\2\3\4\112\177", "%01%02%03%04j%7F"); |
251 | 0 | TestHostnameHelper("<>.AS/-+", "<>.as/-+"); |
252 | 0 | // Added in bug 489455. %00 should no longer be changed to %01. |
253 | 0 | TestHostnameHelper("%00", "%00"); |
254 | 0 | } |
255 | | |
256 | | TEST(UrlClassifierUtils, LongHostname) |
257 | 0 | { |
258 | 0 | static const int kTestSize = 1024 * 150; |
259 | 0 | char *str = static_cast<char*>(malloc(kTestSize + 1)); |
260 | 0 | memset(str, 'x', kTestSize); |
261 | 0 | str[kTestSize] = '\0'; |
262 | 0 |
|
263 | 0 | RefPtr<nsUrlClassifierUtils> utils = new nsUrlClassifierUtils; |
264 | 0 | utils->Init(); |
265 | 0 |
|
266 | 0 | nsAutoCString out; |
267 | 0 | nsDependentCString in(str); |
268 | 0 | PRIntervalTime clockStart = PR_IntervalNow(); |
269 | 0 | utils->CanonicalizeHostname(in, out); |
270 | 0 | PRIntervalTime clockEnd = PR_IntervalNow(); |
271 | 0 |
|
272 | 0 | CheckEquals(in, out); |
273 | 0 |
|
274 | 0 | printf("CanonicalizeHostname on long string (%dms)\n", |
275 | 0 | PR_IntervalToMilliseconds(clockEnd - clockStart)); |
276 | 0 | } |