1// This should output "PROXY success:80" if all the tests pass. 2// Otherwise it will output "PROXY failure:<num-failures>". 3// 4// This aims to unit-test the PAC library functions, which are 5// exposed in the PAC's execution environment. (Namely, dnsDomainLevels, 6// timeRange, etc.) 7 8function FindProxyForURL(url, host) { 9 var numTestsFailed = 0; 10 11 // Run all the tests 12 for (var test in Tests) { 13 var t = new TestContext(test); 14 15 // Run the test. 16 Tests[test](t); 17 18 if (t.failed()) { 19 numTestsFailed++; 20 } 21 } 22 23 if (numTestsFailed == 0) { 24 return "PROXY success:80"; 25 } 26 return "PROXY failure:" + numTestsFailed; 27} 28 29// -------------------------- 30// Tests 31// -------------------------- 32 33var Tests = {}; 34 35Tests.testDnsDomainIs = function(t) { 36 t.expectTrue(dnsDomainIs("google.com", ".com")); 37 t.expectTrue(dnsDomainIs("google.co.uk", ".co.uk")); 38 t.expectFalse(dnsDomainIs("google.com", ".co.uk")); 39 t.expectFalse(dnsDomainIs("www.adobe.com", ".ad")); 40}; 41 42Tests.testDnsDomainLevels = function(t) { 43 t.expectEquals(0, dnsDomainLevels("www")); 44 t.expectEquals(2, dnsDomainLevels("www.google.com")); 45 t.expectEquals(3, dnsDomainLevels("192.168.1.1")); 46}; 47 48Tests.testIsInNet = function(t) { 49 t.expectTrue( 50 isInNet("192.89.132.25", "192.89.132.25", "255.255.255.255")); 51 t.expectFalse( 52 isInNet("193.89.132.25", "192.89.132.25", "255.255.255.255")); 53 54 t.expectTrue(isInNet("192.89.132.25", "192.89.0.0", "255.255.0.0")); 55 t.expectFalse(isInNet("193.89.132.25", "192.89.0.0", "255.255.0.0")); 56 57 t.expectFalse( 58 isInNet("192.89.132.a", "192.89.0.0", "255.255.0.0")); 59}; 60 61Tests.testIsPlainHostName = function(t) { 62 t.expectTrue(isPlainHostName("google")); 63 t.expectFalse(isPlainHostName("google.com")); 64}; 65 66Tests.testLocalHostOrDomainIs = function(t) { 67 t.expectTrue(localHostOrDomainIs("www.google.com", "www.google.com")); 68 t.expectTrue(localHostOrDomainIs("www", "www.google.com")); 69 t.expectFalse(localHostOrDomainIs("maps.google.com", "www.google.com")); 70}; 71 72Tests.testShExpMatch = function(t) { 73 t.expectTrue(shExpMatch("foo.jpg", "*.jpg")); 74 t.expectTrue(shExpMatch("foo5.jpg", "*o?.jpg")); 75 t.expectFalse(shExpMatch("foo.jpg", ".jpg")); 76 t.expectFalse(shExpMatch("foo.jpg", "foo")); 77}; 78 79Tests.testSortIpAddressList = function(t) { 80 t.expectEquals("::1;::2;::3", sortIpAddressList("::2;::3;::1")); 81 t.expectEquals( 82 "2001:4898:28:3:201:2ff:feea:fc14;fe80::5efe:157:9d3b:8b16;157.59.139.22", 83 sortIpAddressList("157.59.139.22;" + 84 "2001:4898:28:3:201:2ff:feea:fc14;" + 85 "fe80::5efe:157:9d3b:8b16")); 86 87 // Single IP address (v4 and v6). 88 t.expectEquals("127.0.0.1", sortIpAddressList("127.0.0.1")); 89 t.expectEquals("::1", sortIpAddressList("::1")) 90 91 // Verify that IPv6 address is not re-written (not reduced). 92 t.expectEquals("0:0::1;192.168.1.1", sortIpAddressList("192.168.1.1;0:0::1")); 93 94 // Input is already sorted. 95 t.expectEquals("::1;192.168.1.3", sortIpAddressList("::1;192.168.1.3")); 96 97 // Same-valued IP addresses (also tests stability). 98 t.expectEquals("0::1;::1;0:0::1", sortIpAddressList("0::1;::1;0:0::1")); 99 100 // Contains extra semi-colons. 101 t.expectEquals("127.0.0.1", sortIpAddressList(";127.0.0.1;")); 102 103 // Contains whitespace (spaces and tabs). 104 t.expectEquals("192.168.0.1;192.168.0.2", 105 sortIpAddressList("192.168.0.1; 192.168.0.2")); 106 t.expectEquals("127.0.0.0;127.0.0.1;127.0.0.2", 107 sortIpAddressList("127.0.0.1; 127.0.0.2; 127.0.0.0")); 108 109 // Empty lists. 110 t.expectFalse(sortIpAddressList("")); 111 t.expectFalse(sortIpAddressList(" ")); 112 t.expectFalse(sortIpAddressList(";")); 113 t.expectFalse(sortIpAddressList(";;")); 114 t.expectFalse(sortIpAddressList(" ; ; ")); 115 116 // Invalid IP addresses. 117 t.expectFalse(sortIpAddressList("256.0.0.1")); 118 t.expectFalse(sortIpAddressList("192.168.1.1;0:0:0:1;127.0.0.1")); 119 120 // Call sortIpAddressList() with wonky arguments. 121 t.expectEquals(null, sortIpAddressList()); 122 t.expectEquals(null, sortIpAddressList(null)); 123 t.expectEquals(null, sortIpAddressList(null, null)); 124}; 125 126Tests.testIsInNetEx = function(t) { 127 t.expectTrue(isInNetEx("198.95.249.79", "198.95.249.79/32")); 128 t.expectTrue(isInNetEx("198.95.115.10", "198.95.0.0/16")); 129 t.expectTrue(isInNetEx("198.95.1.1", "198.95.0.0/16")); 130 t.expectTrue(isInNetEx("198.95.1.1", "198.95.3.3/16")); 131 t.expectTrue(isInNetEx("0:0:0:0:0:0:7f00:1", "0:0:0:0:0:0:7f00:1/32")); 132 t.expectTrue(isInNetEx("3ffe:8311:ffff:abcd:1234:dead:beef:101", 133 "3ffe:8311:ffff::/48")); 134 135 // IPv4 and IPv6 mix. 136 t.expectFalse(isInNetEx("127.0.0.1", "0:0:0:0:0:0:7f00:1/16")); 137 t.expectFalse(isInNetEx("192.168.24.3", "fe80:0:0:0:0:0:c0a8:1803/32")); 138 139 t.expectFalse(isInNetEx("198.95.249.78", "198.95.249.79/32")); 140 t.expectFalse(isInNetEx("198.96.115.10", "198.95.0.0/16")); 141 t.expectFalse(isInNetEx("3fff:8311:ffff:abcd:1234:dead:beef:101", 142 "3ffe:8311:ffff::/48")); 143 144 // Call isInNetEx with wonky arguments. 145 t.expectEquals(null, isInNetEx()); 146 t.expectEquals(null, isInNetEx(null)); 147 t.expectEquals(null, isInNetEx(null, null)); 148 t.expectEquals(null, isInNetEx(null, null, null)); 149 t.expectEquals(null, isInNetEx("198.95.249.79")); 150 151 // Invalid IP address. 152 t.expectFalse(isInNetEx("256.0.0.1", "198.95.249.79")); 153 t.expectFalse(isInNetEx("127.0.0.1 ", "127.0.0.1/32")); // Extra space. 154 155 // Invalid prefix. 156 t.expectFalse(isInNetEx("198.95.115.10", "198.95.0.0/34")); 157 t.expectFalse(isInNetEx("127.0.0.1", "127.0.0.1")); // Missing '/' in prefix. 158}; 159 160Tests.testWeekdayRange = function(t) { 161 // Test with local time. 162 MockDate.setCurrent("Tue Mar 03 2009"); 163 t.expectEquals(true, weekdayRange("MON", "FRI")); 164 t.expectEquals(true, weekdayRange("TUE", "FRI")); 165 t.expectEquals(true, weekdayRange("TUE", "TUE")); 166 t.expectEquals(true, weekdayRange("TUE")); 167 t.expectEquals(false, weekdayRange("WED", "FRI")); 168 t.expectEquals(false, weekdayRange("SUN", "MON")); 169 t.expectEquals(false, weekdayRange("SAT")); 170 t.expectEquals(false, weekdayRange("FRI", "MON")); 171 172 // Test with GMT time. 173 MockDate.setCurrent("Tue Mar 03 2009 GMT"); 174 t.expectEquals(true, weekdayRange("MON", "FRI", "GMT")); 175 t.expectEquals(true, weekdayRange("TUE", "FRI", "GMT")); 176 t.expectEquals(true, weekdayRange("TUE", "TUE", "GMT")); 177 t.expectEquals(true, weekdayRange("TUE", "GMT")); 178 t.expectEquals(false, weekdayRange("WED", "FRI", "GMT")); 179 t.expectEquals(false, weekdayRange("SUN", "MON", "GMT")); 180 t.expectEquals(false, weekdayRange("SAT", "GMT")); 181}; 182 183Tests.testDateRange = function(t) { 184 // dateRange(day) 185 MockDate.setCurrent("Mar 03 2009"); 186 t.expectEquals(true, dateRange(3)); 187 t.expectEquals(false, dateRange(1)); 188 189 // dateRange(day, "GMT") 190 MockDate.setCurrent("Mar 03 2009 GMT"); 191 t.expectEquals(true, dateRange(3, "GMT")); 192 t.expectEquals(false, dateRange(1, "GMT")); 193 194 // dateRange(day1, day2) 195 MockDate.setCurrent("Mar 03 2009"); 196 t.expectEquals(true, dateRange(1, 4)); 197 t.expectEquals(false, dateRange(4, 20)); 198 199 // dateRange(day, month) 200 MockDate.setCurrent("Mar 03 2009"); 201 t.expectEquals(true, dateRange(3, "MAR")); 202 MockDate.setCurrent("Mar 03 2014"); 203 t.expectEquals(true, dateRange(3, "MAR")); 204 // TODO(eroman): 205 //t.expectEquals(false, dateRange(2, "MAR")); 206 //t.expectEquals(false, dateRange(3, "JAN")); 207 208 // dateRange(day, month, year) 209 MockDate.setCurrent("Mar 03 2009"); 210 t.expectEquals(true, dateRange(3, "MAR", 2009)); 211 t.expectEquals(false, dateRange(4, "MAR", 2009)); 212 t.expectEquals(false, dateRange(3, "FEB", 2009)); 213 MockDate.setCurrent("Mar 03 2014"); 214 t.expectEquals(false, dateRange(3, "MAR", 2009)); 215 216 // dateRange(month1, month2) 217 MockDate.setCurrent("Mar 03 2009"); 218 t.expectEquals(true, dateRange("JAN", "MAR")); 219 t.expectEquals(true, dateRange("MAR", "APR")); 220 t.expectEquals(false, dateRange("MAY", "SEP")); 221 222 // dateRange(day1, month1, day2, month2) 223 MockDate.setCurrent("Mar 03 2009"); 224 t.expectEquals(true, dateRange(1, "JAN", 3, "MAR")); 225 t.expectEquals(true, dateRange(3, "MAR", 4, "SEP")); 226 t.expectEquals(false, dateRange(4, "MAR", 4, "SEP")); 227 228 // dateRange(month1, year1, month2, year2) 229 MockDate.setCurrent("Mar 03 2009"); 230 t.expectEquals(true, dateRange("FEB", 2009, "MAR", 2009)); 231 MockDate.setCurrent("Apr 03 2009"); 232 t.expectEquals(true, dateRange("FEB", 2009, "MAR", 2010)); 233 t.expectEquals(false, dateRange("FEB", 2009, "MAR", 2009)); 234 235 // dateRange(day1, month1, year1, day2, month2, year2) 236 MockDate.setCurrent("Mar 03 2009"); 237 t.expectEquals(true, dateRange(1, "JAN", 2009, 3, "MAR", 2009)); 238 t.expectEquals(true, dateRange(3, "MAR", 2009, 4, "SEP", 2009)); 239 t.expectEquals(true, dateRange(3, "JAN", 2009, 4, "FEB", 2010)); 240 t.expectEquals(false, dateRange(4, "MAR", 2009, 4, "SEP", 2009)); 241}; 242 243Tests.testTimeRange = function(t) { 244 // timeRange(hour) 245 MockDate.setCurrent("Mar 03, 2009 03:34:01"); 246 t.expectEquals(true, timeRange(3)); 247 t.expectEquals(false, timeRange(2)); 248 249 // timeRange(hour1, hour2) 250 MockDate.setCurrent("Mar 03, 2009 03:34:01"); 251 t.expectEquals(true, timeRange(2, 3)); 252 t.expectEquals(true, timeRange(2, 4)); 253 t.expectEquals(true, timeRange(3, 5)); 254 t.expectEquals(false, timeRange(1, 2)); 255 t.expectEquals(false, timeRange(11, 12)); 256 257 // timeRange(hour1, min1, hour2, min2) 258 MockDate.setCurrent("Mar 03, 2009 03:34:01"); 259 t.expectEquals(true, timeRange(1, 0, 3, 34)); 260 t.expectEquals(true, timeRange(1, 0, 3, 35)); 261 t.expectEquals(true, timeRange(3, 34, 5, 0)); 262 t.expectEquals(false, timeRange(1, 0, 3, 0)); 263 t.expectEquals(false, timeRange(11, 0, 16, 0)); 264 265 // timeRange(hour1, min1, sec1, hour2, min2, sec2) 266 MockDate.setCurrent("Mar 03, 2009 03:34:14"); 267 t.expectEquals(true, timeRange(1, 0, 0, 3, 34, 14)); 268 t.expectEquals(false, timeRange(1, 0, 0, 3, 34, 0)); 269 t.expectEquals(true, timeRange(1, 0, 0, 3, 35, 0)); 270 t.expectEquals(true, timeRange(3, 34, 0, 5, 0, 0)); 271 t.expectEquals(false, timeRange(1, 0, 0, 3, 0, 0)); 272 t.expectEquals(false, timeRange(11, 0, 0, 16, 0, 0)); 273}; 274 275// -------------------------- 276// TestContext 277// -------------------------- 278 279// |name| is the name of the test being executed, it will be used when logging 280// errors. 281function TestContext(name) { 282 this.numFailures_ = 0; 283 this.name_ = name; 284}; 285 286TestContext.prototype.failed = function() { 287 return this.numFailures_ != 0; 288}; 289 290TestContext.prototype.expectEquals = function(expectation, actual) { 291 if (!(expectation === actual)) { 292 this.numFailures_++; 293 this.log("FAIL: expected: " + expectation + ", actual: " + actual); 294 } 295}; 296 297TestContext.prototype.expectTrue = function(x) { 298 this.expectEquals(true, x); 299}; 300 301TestContext.prototype.expectFalse = function(x) { 302 this.expectEquals(false, x); 303}; 304 305TestContext.prototype.log = function(x) { 306 // Prefix with the test name that generated the log. 307 try { 308 alert(this.name_ + ": " + x); 309 } catch(e) { 310 // In case alert() is not defined. 311 } 312}; 313 314// -------------------------- 315// MockDate 316// -------------------------- 317 318function MockDate() { 319 this.wrappedDate_ = new MockDate.super_(MockDate.currentDateString_); 320}; 321 322// Setup the MockDate so it forwards methods to "this.wrappedDate_" (which is a 323// real Date object). We can't simply chain the prototypes since Date() doesn't 324// allow it. 325MockDate.init = function() { 326 MockDate.super_ = Date; 327 328 function createProxyMethod(methodName) { 329 return function() { 330 return this.wrappedDate_[methodName] 331 .apply(this.wrappedDate_, arguments); 332 } 333 }; 334 335 for (i in MockDate.methodNames_) { 336 var methodName = MockDate.methodNames_[i]; 337 // Don't define the closure directly in the loop body, since Javascript's 338 // crazy scoping rules mean |methodName| actually bleeds out of the loop! 339 MockDate.prototype[methodName] = createProxyMethod(methodName); 340 } 341 342 // Replace the native Date() with our mock. 343 Date = MockDate; 344}; 345 346// Unfortunately Date()'s methods are non-enumerable, therefore list manually. 347MockDate.methodNames_ = [ 348 "toString", "toDateString", "toTimeString", "toLocaleString", 349 "toLocaleDateString", "toLocaleTimeString", "valueOf", "getTime", 350 "getFullYear", "getUTCFullYear", "getMonth", "getUTCMonth", 351 "getDate", "getUTCDate", "getDay", "getUTCDay", "getHours", "getUTCHours", 352 "getMinutes", "getUTCMinutes", "getSeconds", "getUTCSeconds", 353 "getMilliseconds", "getUTCMilliseconds", "getTimezoneOffset", "setTime", 354 "setMilliseconds", "setUTCMilliseconds", "setSeconds", "setUTCSeconds", 355 "setMinutes", "setUTCMinutes", "setHours", "setUTCHours", "setDate", 356 "setUTCDate", "setMonth", "setUTCMonth", "setFullYear", "setUTCFullYear", 357 "toGMTString", "toUTCString", "getYear", "setYear" 358]; 359 360MockDate.setCurrent = function(currentDateString) { 361 MockDate.currentDateString_ = currentDateString; 362} 363 364// Bind the methods to proxy requests to the wrapped Date(). 365MockDate.init(); 366 367