1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/url-classifier/tests/TestUrlClassifierUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,326 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include <stdio.h> 1.9 +#include <ctype.h> 1.10 +#include "nsEscape.h" 1.11 +#include "nsString.h" 1.12 +#include "nsUrlClassifierUtils.h" 1.13 +#include "nsNetUtil.h" 1.14 +#include "stdlib.h" 1.15 +#include "TestHarness.h" 1.16 + 1.17 +static int gTotalTests = 0; 1.18 +static int gPassedTests = 0; 1.19 + 1.20 +static char int_to_hex_digit(int32_t i) { 1.21 + NS_ASSERTION((i >= 0) && (i <= 15), "int too big in int_to_hex_digit"); 1.22 + return static_cast<char>(((i < 10) ? (i + '0') : ((i - 10) + 'A'))); 1.23 +} 1.24 + 1.25 +static void CheckEquals(nsCString & expected, nsCString & actual) 1.26 +{ 1.27 + if (!(expected).Equals((actual))) { 1.28 + fail("expected |%s| but got |%s|", (expected).get(), (actual).get()); 1.29 + } else { 1.30 + gPassedTests++; 1.31 + } 1.32 + gTotalTests++; 1.33 +} 1.34 + 1.35 +void TestUnescapeHelper(const char* in, const char* expected) 1.36 +{ 1.37 + nsCString out, strIn(in), strExp(expected); 1.38 + nsUrlClassifierUtils utils; 1.39 + 1.40 + NS_UnescapeURL(strIn.get(), strIn.Length(), esc_AlwaysCopy, out); 1.41 + CheckEquals(strExp, out); 1.42 +} 1.43 + 1.44 +// Make sure Unescape from nsEncode.h's unescape does what the server does. 1.45 +void TestUnescape() 1.46 +{ 1.47 + // test empty string 1.48 + TestUnescapeHelper("\0", "\0"); 1.49 + 1.50 + // Test docoding of all characters. 1.51 + nsCString allCharsEncoded, allCharsEncodedLowercase, allCharsAsString; 1.52 + for (int32_t i = 1; i < 256; ++i) { 1.53 + allCharsEncoded.Append('%'); 1.54 + allCharsEncoded.Append(int_to_hex_digit(i / 16)); 1.55 + allCharsEncoded.Append((int_to_hex_digit(i % 16))); 1.56 + 1.57 + allCharsEncodedLowercase.Append('%'); 1.58 + allCharsEncodedLowercase.Append(tolower(int_to_hex_digit(i / 16))); 1.59 + allCharsEncodedLowercase.Append(tolower(int_to_hex_digit(i % 16))); 1.60 + 1.61 + allCharsAsString.Append(static_cast<char>(i)); 1.62 + } 1.63 + 1.64 + nsUrlClassifierUtils utils; 1.65 + nsCString out; 1.66 + NS_UnescapeURL(allCharsEncoded.get(), allCharsEncoded.Length(), esc_AlwaysCopy, out); 1.67 + CheckEquals(allCharsAsString, out); 1.68 + 1.69 + out.Truncate(); 1.70 + NS_UnescapeURL(allCharsEncodedLowercase.get(), allCharsEncodedLowercase.Length(), esc_AlwaysCopy, out); 1.71 + CheckEquals(allCharsAsString, out); 1.72 + 1.73 + // Test %-related edge cases 1.74 + TestUnescapeHelper("%", "%"); 1.75 + TestUnescapeHelper("%xx", "%xx"); 1.76 + TestUnescapeHelper("%%", "%%"); 1.77 + TestUnescapeHelper("%%%", "%%%"); 1.78 + TestUnescapeHelper("%%%%", "%%%%"); 1.79 + TestUnescapeHelper("%1", "%1"); 1.80 + TestUnescapeHelper("%1z", "%1z"); 1.81 + TestUnescapeHelper("a%1z", "a%1z"); 1.82 + TestUnescapeHelper("abc%d%e%fg%hij%klmno%", "abc%d%e%fg%hij%klmno%"); 1.83 + 1.84 + // A few more tests 1.85 + TestUnescapeHelper("%25", "%"); 1.86 + TestUnescapeHelper("%25%32%35", "%25"); 1.87 +} 1.88 + 1.89 +void TestEncodeHelper(const char* in, const char* expected) 1.90 +{ 1.91 + nsCString out, strIn(in), strExp(expected); 1.92 + nsUrlClassifierUtils utils; 1.93 + 1.94 + utils.SpecialEncode(strIn, true, out); 1.95 + CheckEquals(strExp, out); 1.96 +} 1.97 + 1.98 +void TestEnc() 1.99 +{ 1.100 + // Test empty string 1.101 + TestEncodeHelper("", ""); 1.102 + 1.103 + // Test that all characters we shouldn't encode ([33-36],[38,126]) are not. 1.104 + nsCString noenc; 1.105 + for (int32_t i = 33; i < 127; i++) { 1.106 + if (i != 37) { // skip % 1.107 + noenc.Append(static_cast<char>(i)); 1.108 + } 1.109 + } 1.110 + nsUrlClassifierUtils utils; 1.111 + nsCString out; 1.112 + utils.SpecialEncode(noenc, false, out); 1.113 + CheckEquals(noenc, out); 1.114 + 1.115 + // Test that all the chars that we should encode [0,32],37,[127,255] are 1.116 + nsCString yesAsString, yesExpectedString; 1.117 + for (int32_t i = 1; i < 256; i++) { 1.118 + if (i < 33 || i == 37 || i > 126) { 1.119 + yesAsString.Append(static_cast<char>(i)); 1.120 + yesExpectedString.Append('%'); 1.121 + yesExpectedString.Append(int_to_hex_digit(i / 16)); 1.122 + yesExpectedString.Append(int_to_hex_digit(i % 16)); 1.123 + } 1.124 + } 1.125 + 1.126 + out.Truncate(); 1.127 + utils.SpecialEncode(yesAsString, false, out); 1.128 + CheckEquals(yesExpectedString, out); 1.129 + 1.130 + TestEncodeHelper("blah//blah", "blah/blah"); 1.131 +} 1.132 + 1.133 +void TestCanonicalizeHelper(const char* in, const char* expected) 1.134 +{ 1.135 + nsCString out, strIn(in), strExp(expected); 1.136 + nsUrlClassifierUtils utils; 1.137 + 1.138 + utils.CanonicalizePath(strIn, out); 1.139 + CheckEquals(strExp, out); 1.140 +} 1.141 + 1.142 +void TestCanonicalize() 1.143 +{ 1.144 + // Test repeated %-decoding. Note: %25 --> %, %32 --> 2, %35 --> 5 1.145 + TestCanonicalizeHelper("%25", "%25"); 1.146 + TestCanonicalizeHelper("%25%32%35", "%25"); 1.147 + TestCanonicalizeHelper("asdf%25%32%35asd", "asdf%25asd"); 1.148 + TestCanonicalizeHelper("%%%25%32%35asd%%", "%25%25%25asd%25%25"); 1.149 + TestCanonicalizeHelper("%25%32%35%25%32%35%25%32%35", "%25%25%25"); 1.150 + TestCanonicalizeHelper("%25", "%25"); 1.151 + TestCanonicalizeHelper("%257Ea%2521b%2540c%2523d%2524e%25f%255E00%252611%252A22%252833%252944_55%252B", 1.152 + "~a!b@c#d$e%25f^00&11*22(33)44_55+"); 1.153 + 1.154 + TestCanonicalizeHelper("", ""); 1.155 + 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/", 1.156 + "168.188.99.26/.secure/www.ebay.com/"); 1.157 + TestCanonicalizeHelper("195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/", 1.158 + "195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/"); 1.159 + // Added in bug 489455. %00 should no longer be changed to %01. 1.160 + TestCanonicalizeHelper("%00", "%00"); 1.161 +} 1.162 + 1.163 +void TestParseIPAddressHelper(const char *in, const char *expected) 1.164 +{ 1.165 + nsCString out, strIn(in), strExp(expected); 1.166 + nsUrlClassifierUtils utils; 1.167 + utils.Init(); 1.168 + 1.169 + utils.ParseIPAddress(strIn, out); 1.170 + CheckEquals(strExp, out); 1.171 +} 1.172 + 1.173 +void TestParseIPAddress() 1.174 +{ 1.175 + TestParseIPAddressHelper("123.123.0.0.1", ""); 1.176 + TestParseIPAddressHelper("255.0.0.1", "255.0.0.1"); 1.177 + TestParseIPAddressHelper("12.0x12.01234", "12.18.2.156"); 1.178 + TestParseIPAddressHelper("276.2.3", "20.2.0.3"); 1.179 + TestParseIPAddressHelper("012.034.01.055", "10.28.1.45"); 1.180 + TestParseIPAddressHelper("0x12.0x43.0x44.0x01", "18.67.68.1"); 1.181 + TestParseIPAddressHelper("167838211", "10.1.2.3"); 1.182 + TestParseIPAddressHelper("3279880203", "195.127.0.11"); 1.183 + TestParseIPAddressHelper("0x12434401", "18.67.68.1"); 1.184 + TestParseIPAddressHelper("413960661", "24.172.137.213"); 1.185 + TestParseIPAddressHelper("03053104725", "24.172.137.213"); 1.186 + TestParseIPAddressHelper("030.0254.0x89d5", "24.172.137.213"); 1.187 + TestParseIPAddressHelper("1.234.4.0377", "1.234.4.255"); 1.188 + TestParseIPAddressHelper("1.2.3.00x0", ""); 1.189 + TestParseIPAddressHelper("10.192.95.89 xy", "10.192.95.89"); 1.190 + TestParseIPAddressHelper("10.192.95.89 xyz", ""); 1.191 + TestParseIPAddressHelper("1.2.3.0x0", "1.2.3.0"); 1.192 + TestParseIPAddressHelper("1.2.3.4", "1.2.3.4"); 1.193 +} 1.194 + 1.195 +void TestCanonicalNumHelper(const char *in, uint32_t bytes, 1.196 + bool allowOctal, const char *expected) 1.197 +{ 1.198 + nsCString out, strIn(in), strExp(expected); 1.199 + nsUrlClassifierUtils utils; 1.200 + utils.Init(); 1.201 + 1.202 + utils.CanonicalNum(strIn, bytes, allowOctal, out); 1.203 + CheckEquals(strExp, out); 1.204 +} 1.205 + 1.206 +void TestCanonicalNum() 1.207 +{ 1.208 + TestCanonicalNumHelper("", 1, true, ""); 1.209 + TestCanonicalNumHelper("10", 0, true, ""); 1.210 + TestCanonicalNumHelper("45", 1, true, "45"); 1.211 + TestCanonicalNumHelper("0x10", 1, true, "16"); 1.212 + TestCanonicalNumHelper("367", 2, true, "1.111"); 1.213 + TestCanonicalNumHelper("012345", 3, true, "0.20.229"); 1.214 + TestCanonicalNumHelper("0173", 1, true, "123"); 1.215 + TestCanonicalNumHelper("09", 1, false, "9"); 1.216 + TestCanonicalNumHelper("0x120x34", 2, true, ""); 1.217 + TestCanonicalNumHelper("0x12fc", 2, true, "18.252"); 1.218 + TestCanonicalNumHelper("3279880203", 4, true, "195.127.0.11"); 1.219 + TestCanonicalNumHelper("0x0000059", 1, true, "89"); 1.220 + TestCanonicalNumHelper("0x00000059", 1, true, "89"); 1.221 + TestCanonicalNumHelper("0x0000067", 1, true, "103"); 1.222 +} 1.223 + 1.224 +void TestHostnameHelper(const char *in, const char *expected) 1.225 +{ 1.226 + nsCString out, strIn(in), strExp(expected); 1.227 + nsUrlClassifierUtils utils; 1.228 + utils.Init(); 1.229 + 1.230 + utils.CanonicalizeHostname(strIn, out); 1.231 + CheckEquals(strExp, out); 1.232 +} 1.233 + 1.234 +void TestHostname() 1.235 +{ 1.236 + TestHostnameHelper("abcd123;[]", "abcd123;[]"); 1.237 + TestHostnameHelper("abc.123", "abc.123"); 1.238 + TestHostnameHelper("abc..123", "abc.123"); 1.239 + TestHostnameHelper("trailing.", "trailing"); 1.240 + TestHostnameHelper("i love trailing dots....", "i%20love%20trailing%20dots"); 1.241 + TestHostnameHelper(".leading", "leading"); 1.242 + TestHostnameHelper("..leading", "leading"); 1.243 + TestHostnameHelper(".dots.", "dots"); 1.244 + TestHostnameHelper(".both.", "both"); 1.245 + TestHostnameHelper(".both..", "both"); 1.246 + TestHostnameHelper("..both.", "both"); 1.247 + TestHostnameHelper("..both..", "both"); 1.248 + TestHostnameHelper("..a.b.c.d..", "a.b.c.d"); 1.249 + TestHostnameHelper("..127.0.0.1..", "127.0.0.1"); 1.250 + TestHostnameHelper("asdf!@#$a", "asdf!@#$a"); 1.251 + TestHostnameHelper("AB CD 12354", "ab%20cd%2012354"); 1.252 + TestHostnameHelper("\1\2\3\4\112\177", "%01%02%03%04j%7F"); 1.253 + TestHostnameHelper("<>.AS/-+", "<>.as/-+"); 1.254 + // Added in bug 489455. %00 should no longer be changed to %01. 1.255 + TestHostnameHelper("%00", "%00"); 1.256 +} 1.257 + 1.258 +void TestLongHostname() 1.259 +{ 1.260 + static const int kTestSize = 1024 * 150; 1.261 + char *str = static_cast<char*>(malloc(kTestSize + 1)); 1.262 + memset(str, 'x', kTestSize); 1.263 + str[kTestSize] = '\0'; 1.264 + 1.265 + nsUrlClassifierUtils utils; 1.266 + utils.Init(); 1.267 + 1.268 + nsAutoCString out; 1.269 + nsDependentCString in(str); 1.270 + PRIntervalTime clockStart = PR_IntervalNow(); 1.271 + utils.CanonicalizeHostname(in, out); 1.272 + PRIntervalTime clockEnd = PR_IntervalNow(); 1.273 + 1.274 + CheckEquals(in, out); 1.275 + 1.276 + printf("CanonicalizeHostname on long string (%dms)\n", 1.277 + PR_IntervalToMilliseconds(clockEnd - clockStart)); 1.278 +} 1.279 + 1.280 +void TestFragmentSet() 1.281 +{ 1.282 + nsUrlClassifierFragmentSet set; 1.283 + set.Init(3); 1.284 + 1.285 + set.Put(NS_LITERAL_CSTRING("a")); 1.286 + set.Put(NS_LITERAL_CSTRING("b")); 1.287 + set.Put(NS_LITERAL_CSTRING("c")); 1.288 + 1.289 + // At this point, adding a fourth element would push "a" off. 1.290 + // Make sure that set.Has("a") moves it to the front of the list 1.291 + set.Has(NS_LITERAL_CSTRING("a")); 1.292 + 1.293 + // Now add a new item. This should now push "b" off the list, 1.294 + // but leave "a" 1.295 + set.Put(NS_LITERAL_CSTRING("d")); 1.296 + 1.297 + gTotalTests++; 1.298 + if (set.Has(NS_LITERAL_CSTRING("a"))) 1.299 + gPassedTests++; 1.300 + else 1.301 + fail("set.Has(\"a\") failed."); 1.302 + 1.303 + gTotalTests++; 1.304 + if (!set.Has(NS_LITERAL_CSTRING("b"))) 1.305 + gPassedTests++; 1.306 + else 1.307 + fail("!set.Has(\"b\") failed."); 1.308 +} 1.309 + 1.310 +int main(int argc, char **argv) 1.311 +{ 1.312 + ScopedXPCOM xpcom("URLClassiferUtils"); 1.313 + 1.314 + TestUnescape(); 1.315 + TestEnc(); 1.316 + TestCanonicalize(); 1.317 + TestCanonicalNum(); 1.318 + TestParseIPAddress(); 1.319 + TestHostname(); 1.320 + TestLongHostname(); 1.321 + TestFragmentSet(); 1.322 + 1.323 + if (gPassedTests == gTotalTests) 1.324 + passed(__FILE__); 1.325 + printf("%d of %d tests passed\n", gPassedTests, gTotalTests); 1.326 + // Non-zero return status signals test failure to build system. 1.327 + 1.328 + return (gPassedTests != gTotalTests); 1.329 +}