Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(364)

Side by Side Diff: LayoutTests/http/tests/w3c/resources/testharness.js

Issue 14672011: Remove [NoInterfaceObject] extended attribute from several interfaces (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Another attempt Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 Distributed under both the W3C Test Suite License [1] and the W3C 2 Distributed under both the W3C Test Suite License [1] and the W3C
3 3-clause BSD License [2]. To contribute to a W3C Test Suite, see the 3 3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
4 policies and contribution forms [3]. 4 policies and contribution forms [3].
5 5
6 [1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license 6 [1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
7 [2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license 7 [2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
8 [3] http://www.w3.org/2004/10/27-testcases 8 [3] http://www.w3.org/2004/10/27-testcases
9 */ 9 */
10 10
(...skipping 15 matching lines...) Expand all
26 * Within each file one may define one or more tests. Each test is atomic 26 * Within each file one may define one or more tests. Each test is atomic
27 * in the sense that a single test has a single result (pass/fail/timeout). 27 * in the sense that a single test has a single result (pass/fail/timeout).
28 * Within each test one may have a number of asserts. The test fails at the 28 * Within each test one may have a number of asserts. The test fails at the
29 * first failing assert, and the remainder of the test is (typically) not run. 29 * first failing assert, and the remainder of the test is (typically) not run.
30 * 30 *
31 * If the file containing the tests is a HTML file with an element of id "log" 31 * If the file containing the tests is a HTML file with an element of id "log"
32 * this will be populated with a table containing the test results after all 32 * this will be populated with a table containing the test results after all
33 * the tests have run. 33 * the tests have run.
34 * 34 *
35 * NOTE: By default tests must be created before the load event fires. For ways 35 * NOTE: By default tests must be created before the load event fires. For ways
36 * to create tests after the load event, see "Determining when all tests a re 36 * to create tests after the load event, see "Determining when all tests
37 * complete", below 37 * are complete", below
38 * 38 *
39 * == Synchronous Tests == 39 * == Synchronous Tests ==
40 * 40 *
41 * To create a synchronous test use the test() function: 41 * To create a synchronous test use the test() function:
42 * 42 *
43 * test(test_function, name, properties) 43 * test(test_function, name, properties)
44 * 44 *
45 * test_function is a function that contains the code to test. For example a 45 * test_function is a function that contains the code to test. For example a
46 * trivial passing test would be: 46 * trivial passing test would be:
47 * 47 *
48 * test(function() {assert_true(true)}, "assert_true with true") 48 * test(function() {assert_true(true)}, "assert_true with true")
49 * 49 *
50 * The function passed in is run in the test() call. 50 * The function passed in is run in the test() call.
51 * 51 *
52 * properties is an object that overrides default test properties. The recognise d properties 52 * properties is an object that overrides default test properties. The
53 * are: 53 * recognised properties are:
54 * timeout - the test timeout in ms 54 * timeout - the test timeout in ms
55 * 55 *
56 * e.g. 56 * e.g.
57 * test(test_function, "Sample test", {timeout:1000}) 57 * test(test_function, "Sample test", {timeout:1000})
58 * 58 *
59 * would run test_function with a timeout of 1s. 59 * would run test_function with a timeout of 1s.
60 * 60 *
61 * Additionally, test-specific metadata can be passed in the properties. These
62 * are used when the individual test has different metadata from that stored
63 * in the <head>.
64 * The recognized metadata properties are:
65 *
66 * help - The url of the part of the specification being tested
67 *
68 * assert - A human readable description of what the test is attempting
69 * to prove
70 *
71 * author - Name and contact information for the author of the test in the
72 * format: "Name <email_addr>" or "Name http://contact/url"
73 *
61 * == Asynchronous Tests == 74 * == Asynchronous Tests ==
62 * 75 *
63 * Testing asynchronous features is somewhat more complex since the result of 76 * Testing asynchronous features is somewhat more complex since the result of
64 * a test may depend on one or more events or other callbacks. The API provided 77 * a test may depend on one or more events or other callbacks. The API provided
65 * for testing these features is indended to be rather low-level but hopefully 78 * for testing these features is indended to be rather low-level but hopefully
66 * applicable to many situations. 79 * applicable to many situations.
67 * 80 *
68 * To create a test, one starts by getting a Test object using async_test: 81 * To create a test, one starts by getting a Test object using async_test:
69 * 82 *
70 * async_test(name, properties) 83 * async_test(name, properties)
71 * 84 *
72 * e.g. 85 * e.g.
73 * var t = async_test("Simple async test") 86 * var t = async_test("Simple async test")
74 * 87 *
75 * Assertions can be added to the test by calling the step method of the test 88 * Assertions can be added to the test by calling the step method of the test
76 * object with a function containing the test assertions: 89 * object with a function containing the test assertions:
77 * 90 *
78 * t.step(function() {assert_true(true)}); 91 * t.step(function() {assert_true(true)});
79 * 92 *
80 * When all the steps are complete, the done() method must be called: 93 * When all the steps are complete, the done() method must be called:
81 * 94 *
82 * t.done(); 95 * t.done();
83 * 96 *
97 * As a convenience, async_test can also takes a function as first argument.
98 * This function is called with the test object as both its `this` object and
99 * first argument. The above example can be rewritten as:
100 *
101 * async_test(function(t) {
102 * object.some_event = function() {
103 * t.step(function (){assert_true(true); t.done();});
104 * };
105 * }, "Simple async test");
106 *
107 * which avoids cluttering the global scope with references to async
108 * tests instances.
109 *
84 * The properties argument is identical to that for test(). 110 * The properties argument is identical to that for test().
85 * 111 *
86 * In many cases it is convenient to run a step in response to an event or a 112 * In many cases it is convenient to run a step in response to an event or a
87 * callback. A convenient method of doing this is through the step_func method 113 * callback. A convenient method of doing this is through the step_func method
88 * which returns a function that, when called runs a test step. For example 114 * which returns a function that, when called runs a test step. For example
89 * 115 *
90 * object.some_event = t.step_func(function(e) {assert_true(e.a)}); 116 * object.some_event = t.step_func(function(e) {assert_true(e.a)});
91 * 117 *
92 * == Making assertions == 118 * == Making assertions ==
93 * 119 *
(...skipping 23 matching lines...) Expand all
117 * 143 *
118 * The one argument versions may omit either argument. 144 * The one argument versions may omit either argument.
119 * func is a function to be run synchronously. setup() becomes a no-op once 145 * func is a function to be run synchronously. setup() becomes a no-op once
120 * any tests have returned results. Properties are global properties of the test 146 * any tests have returned results. Properties are global properties of the test
121 * harness. Currently recognised properties are: 147 * harness. Currently recognised properties are:
122 * 148 *
123 * timeout - The time in ms after which the harness should stop waiting for 149 * timeout - The time in ms after which the harness should stop waiting for
124 * tests to complete (this is different to the per-test timeout 150 * tests to complete (this is different to the per-test timeout
125 * because async tests do not start their timer until .step is called) 151 * because async tests do not start their timer until .step is called)
126 * 152 *
127 * explicit_done - Wait for an explicit call to done() before declaring all test s 153 * explicit_done - Wait for an explicit call to done() before declaring all
128 * complete (see below) 154 * tests complete (see below)
129 * 155 *
130 * output_document - The document to which results should be logged. By default this is 156 * output_document - The document to which results should be logged. By default
131 * the current document but could be an ancestor document in s ome cases 157 * this is the current document but could be an ancestor
132 * e.g. a SVG test loaded in an HTML wrapper 158 * document in some cases e.g. a SVG test loaded in an HTML
159 * wrapper
160 *
161 * explicit_timeout - disable file timeout; only stop waiting for results
162 * when the timeout() function is called (typically for
163 * use when integrating with some existing test framework
164 * that has its own timeout mechanism).
133 * 165 *
134 * == Determining when all tests are complete == 166 * == Determining when all tests are complete ==
135 * 167 *
136 * By default the test harness will assume there are no more results to come 168 * By default the test harness will assume there are no more results to come
137 * when: 169 * when:
138 * 1) There are no Test objects that have been created but not completed 170 * 1) There are no Test objects that have been created but not completed
139 * 2) The load event on the document has fired 171 * 2) The load event on the document has fired
140 * 172 *
141 * This behaviour can be overridden by setting the explicit_done property to tru e 173 * This behaviour can be overridden by setting the explicit_done property to
142 * in a call to setup(). If explicit_done is true, the test harness will not ass ume 174 * true in a call to setup(). If explicit_done is true, the test harness will
143 * it is done until the global done() function is called. Once done() is called, the 175 * not assume it is done until the global done() function is called. Once done()
144 * two conditions above apply like normal. 176 * is called, the two conditions above apply like normal.
145 * 177 *
146 * == Generating tests == 178 * == Generating tests ==
147 * 179 *
148 * NOTE: this functionality may be removed 180 * NOTE: this functionality may be removed
149 * 181 *
150 * There are scenarios in which is is desirable to create a large number of 182 * There are scenarios in which is is desirable to create a large number of
151 * (synchronous) tests that are internally similar but vary in the parameters 183 * (synchronous) tests that are internally similar but vary in the parameters
152 * used. To make this easier, the generate_tests function allows a single 184 * used. To make this easier, the generate_tests function allows a single
153 * function to be called with each set of parameters in a list: 185 * function to be called with each set of parameters in a list:
154 * 186 *
155 * generate_tests(test_function, parameter_lists) 187 * generate_tests(test_function, parameter_lists, properties)
156 * 188 *
157 * For example: 189 * For example:
158 * 190 *
159 * generate_tests(assert_equals, [ 191 * generate_tests(assert_equals, [
160 * ["Sum one and one", 1+1, 2], 192 * ["Sum one and one", 1+1, 2],
161 * ["Sum one and zero", 1+0, 1] 193 * ["Sum one and zero", 1+0, 1]
162 * ]) 194 * ])
163 * 195 *
164 * Is equivalent to: 196 * Is equivalent to:
165 * 197 *
166 * test(function() {assert_equals(1+1, 2)}, "Sum one and one") 198 * test(function() {assert_equals(1+1, 2)}, "Sum one and one")
167 * test(function() {assert_equals(1+0, 1)}, "Sum one and zero") 199 * test(function() {assert_equals(1+0, 1)}, "Sum one and zero")
168 * 200 *
169 * Note that the first item in each parameter list corresponds to the name of 201 * Note that the first item in each parameter list corresponds to the name of
170 * the test. 202 * the test.
171 * 203 *
204 * The properties argument is identical to that for test(). This may be a
205 * single object (used for all generated tests) or an array.
206 *
172 * == Callback API == 207 * == Callback API ==
173 * 208 *
174 * The framework provides callbacks corresponding to 3 events: 209 * The framework provides callbacks corresponding to 3 events:
175 * 210 *
176 * start - happens when the first Test is created 211 * start - happens when the first Test is created
177 * result - happens when a test result is recieved 212 * result - happens when a test result is recieved
178 * complete - happens when all results are recieved 213 * complete - happens when all results are recieved
179 * 214 *
180 * The page defining the tests may add callbacks for these events by calling 215 * The page defining the tests may add callbacks for these events by calling
181 * the following methods: 216 * the following methods:
(...skipping 11 matching lines...) Expand all
193 * 228 *
194 * The status object gives the overall status of the harness. It has the 229 * The status object gives the overall status of the harness. It has the
195 * following properties: 230 * following properties:
196 * status: Can be compared to the OK, ERROR and TIMEOUT properties 231 * status: Can be compared to the OK, ERROR and TIMEOUT properties
197 * message: An error message set when the status is ERROR 232 * message: An error message set when the status is ERROR
198 * 233 *
199 * == External API == 234 * == External API ==
200 * 235 *
201 * In order to collect the results of multiple pages containing tests, the test 236 * In order to collect the results of multiple pages containing tests, the test
202 * harness will, when loaded in a nested browsing context, attempt to call 237 * harness will, when loaded in a nested browsing context, attempt to call
203 * certain functions in each ancestor browsing context: 238 * certain functions in each ancestor and opener browsing context:
204 * 239 *
205 * start - start_callback 240 * start - start_callback
206 * result - result_callback 241 * result - result_callback
207 * complete - completion_callback 242 * complete - completion_callback
208 * 243 *
209 * These are given the same arguments as the corresponding internal callbacks 244 * These are given the same arguments as the corresponding internal callbacks
210 * described above. 245 * described above.
211 * 246 *
247 * == External API through cross-document messaging ==
248 *
249 * Where supported, the test harness will also send messages using
250 * cross-document messaging to each ancestor and opener browsing context. Since
251 * it uses the wildcard keyword (*), cross-origin communication is enabled and
252 * script on different origins can collect the results.
253 *
254 * This API follows similar conventions as those described above only slightly
255 * modified to accommodate message event API. Each message is sent by the harnes s
256 * is passed a single vanilla object, available as the `data` property of the
257 * event object. These objects are structures as follows:
258 *
259 * start - { type: "start" }
260 * result - { type: "result", test: Test }
261 * complete - { type: "complete", tests: [Test, ...], status: TestsStatus }
262 *
212 * == List of assertions == 263 * == List of assertions ==
213 * 264 *
214 * assert_true(actual, description) 265 * assert_true(actual, description)
215 * asserts that /actual/ is strictly true 266 * asserts that /actual/ is strictly true
216 * 267 *
217 * assert_false(actual, description) 268 * assert_false(actual, description)
218 * asserts that /actual/ is strictly false 269 * asserts that /actual/ is strictly false
219 * 270 *
220 * assert_equals(actual, expected, description) 271 * assert_equals(actual, expected, description)
221 * asserts that /actual/ is the same value as /expected/ 272 * asserts that /actual/ is the same value as /expected/
222 * 273 *
223 * assert_not_equals(actual, expected, description) 274 * assert_not_equals(actual, expected, description)
224 * asserts that /actual/ is a different value to /expected/. Yes, this means 275 * asserts that /actual/ is a different value to /expected/. Yes, this means
225 * that "expected" is a misnomer 276 * that "expected" is a misnomer
226 * 277 *
227 * assert_in_array(actual, expected, description) 278 * assert_in_array(actual, expected, description)
228 * asserts that /expected/ is an Array, and /actual/ is equal to one of the 279 * asserts that /expected/ is an Array, and /actual/ is equal to one of the
229 * members -- expected.indexOf(actual) != -1 280 * members -- expected.indexOf(actual) != -1
230 * 281 *
231 * assert_array_equals(actual, expected, description) 282 * assert_array_equals(actual, expected, description)
232 * asserts that /actual/ and /expected/ have the same length and the value of 283 * asserts that /actual/ and /expected/ have the same length and the value of
233 * each indexed property in /actual/ is the strictly equal to the correspondin g 284 * each indexed property in /actual/ is the strictly equal to the correspondin g
234 * property value in /expected/ 285 * property value in /expected/
235 * 286 *
236 * assert_approx_equals(actual, expected, epsilon, description) 287 * assert_approx_equals(actual, expected, epsilon, description)
237 * asserts that /actual/ is a number within +/- /epsilon/ of /expected/ 288 * asserts that /actual/ is a number within +/- /epsilon/ of /expected/
238 * 289 *
290 * assert_less_than(actual, expected, description)
291 * asserts that /actual/ is a number less than /expected/
292 *
293 * assert_greater_than(actual, expected, description)
294 * asserts that /actual/ is a number greater than /expected/
295 *
296 * assert_less_than_equal(actual, expected, description)
297 * asserts that /actual/ is a number less than or equal to /expected/
298 *
299 * assert_greater_than_equal(actual, expected, description)
300 * asserts that /actual/ is a number greater than or equal to /expected/
301 *
239 * assert_regexp_match(actual, expected, description) 302 * assert_regexp_match(actual, expected, description)
240 * asserts that /actual/ matches the regexp /expected/ 303 * asserts that /actual/ matches the regexp /expected/
241 * 304 *
305 * assert_class_string(object, class_name, description)
306 * asserts that the class string of /object/ as returned in
307 * Object.prototype.toString is equal to /class_name/.
308 *
242 * assert_own_property(object, property_name, description) 309 * assert_own_property(object, property_name, description)
243 * assert that object has own property property_name 310 * assert that object has own property property_name
244 * 311 *
245 * assert_inherits(object, property_name, description) 312 * assert_inherits(object, property_name, description)
246 * assert that object does not have an own property named property_name 313 * assert that object does not have an own property named property_name
247 * but that property_name is present in the prototype chain for object 314 * but that property_name is present in the prototype chain for object
248 * 315 *
249 * assert_idl_attribute(object, attribute_name, description) 316 * assert_idl_attribute(object, attribute_name, description)
250 * assert that an object that is an instance of some interface has the 317 * assert that an object that is an instance of some interface has the
251 * attribute attribute_name following the conditions specified by WebIDL 318 * attribute attribute_name following the conditions specified by WebIDL
252 * 319 *
253 * assert_readonly(object, property_name, description) 320 * assert_readonly(object, property_name, description)
254 * assert that property property_name on object is readonly 321 * assert that property property_name on object is readonly
255 * 322 *
256 * assert_throws(code, func, description) 323 * assert_throws(code, func, description)
257 * code - a DOMException/RangeException code as a string, e.g. "HIERARCHY_REQU EST_ERR" 324 * code - the expected exception:
325 * o string: the thrown exception must be a DOMException with the given
326 * name, e.g., "TimeoutError" (for compatibility with existing
327 * tests, a constant is also supported, e.g., "TIMEOUT_ERR")
328 * o object: the thrown exception must have a property called "name" that
329 * matches code.name
330 * o null: allow any exception (in general, one of the options above
331 * should be used)
258 * func - a function that should throw 332 * func - a function that should throw
259 * 333 *
260 * assert that func throws a DOMException or RangeException (as appropriate)
261 * with the given code. If an object is passed for code instead of a string,
262 * checks that the thrown exception has a property called "name" that matches
263 * the property of code called "name". Note, this function will probably be
264 * rewritten sometime to make more sense.
265 *
266 * assert_unreached(description) 334 * assert_unreached(description)
267 * asserts if called. Used to ensure that some codepath is *not* taken e.g. 335 * asserts if called. Used to ensure that some codepath is *not* taken e.g.
268 * an event does not fire. 336 * an event does not fire.
269 * 337 *
338 * assert_any(assert_func, actual, expected_array, extra_arg_1, ... extra_arg_N)
339 * asserts that one assert_func(actual, expected_array_N, extra_arg1, ..., ext ra_arg_N)
340 * is true for some expected_array_N in expected_array. This only works for as sert_func
341 * with signature assert_func(actual, expected, args_1, ..., args_N). Note tha t tests
342 * with multiple allowed pass conditions are bad practice unless the spec spec ifically
343 * allows multiple behaviours. Test authors should not use this method simply to hide
344 * UA bugs.
345 *
270 * assert_exists(object, property_name, description) 346 * assert_exists(object, property_name, description)
271 * *** deprecated *** 347 * *** deprecated ***
272 * asserts that object has an own property property_name 348 * asserts that object has an own property property_name
273 * 349 *
274 * assert_not_exists(object, property_name, description) 350 * assert_not_exists(object, property_name, description)
275 * *** deprecated *** 351 * *** deprecated ***
276 * assert that object does not have own property property_name 352 * assert that object does not have own property property_name
277 */ 353 */
278 354
279 (function () 355 (function ()
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 392
317 /* 393 /*
318 * API functions 394 * API functions
319 */ 395 */
320 396
321 var name_counter = 0; 397 var name_counter = 0;
322 function next_default_name() 398 function next_default_name()
323 { 399 {
324 //Don't use document.title to work around an Opera bug in XHTML document s 400 //Don't use document.title to work around an Opera bug in XHTML document s
325 var prefix = document.getElementsByTagName("title").length > 0 ? 401 var prefix = document.getElementsByTagName("title").length > 0 ?
326 document.getElementsByTagName("title")[0].firstChild.da ta : 402 document.getElementsByTagName("title")[0].textContent :
327 "Untitled"; 403 "Untitled";
328 var suffix = name_counter > 0 ? " " + name_counter : ""; 404 var suffix = name_counter > 0 ? " " + name_counter : "";
329 name_counter++; 405 name_counter++;
330 return prefix + suffix; 406 return prefix + suffix;
331 } 407 }
332 408
333 function test(func, name, properties) 409 function test(func, name, properties)
334 { 410 {
335 var test_name = name ? name : next_default_name(); 411 var test_name = name ? name : next_default_name();
336 properties = properties ? properties : {}; 412 properties = properties ? properties : {};
337 var test_obj = new Test(test_name, properties); 413 var test_obj = new Test(test_name, properties);
338 test_obj.step(func); 414 test_obj.step(func);
339 if (test_obj.status === test_obj.NOTRUN) { 415 if (test_obj.status === test_obj.NOTRUN) {
340 test_obj.done(); 416 test_obj.done();
341 } 417 }
342 } 418 }
343 419
344 function async_test(name, properties) 420 function async_test(func, name, properties)
345 { 421 {
422 if (typeof func !== "function") {
423 properties = name;
424 name = func;
425 func = null;
426 }
346 var test_name = name ? name : next_default_name(); 427 var test_name = name ? name : next_default_name();
347 properties = properties ? properties : {}; 428 properties = properties ? properties : {};
348 var test_obj = new Test(test_name, properties); 429 var test_obj = new Test(test_name, properties);
430 if (func) {
431 test_obj.step(func, test_obj, test_obj);
432 }
349 return test_obj; 433 return test_obj;
350 } 434 }
351 435
352 function setup(func_or_properties, maybe_properties) 436 function setup(func_or_properties, maybe_properties)
353 { 437 {
354 var func = null; 438 var func = null;
355 var properties = {}; 439 var properties = {};
356 if (arguments.length === 2) { 440 if (arguments.length === 2) {
357 func = func_or_properties; 441 func = func_or_properties;
358 properties = maybe_properties; 442 properties = maybe_properties;
359 } else if (func_or_properties instanceof Function){ 443 } else if (func_or_properties instanceof Function){
360 func = func_or_properties; 444 func = func_or_properties;
361 } else { 445 } else {
362 properties = func_or_properties; 446 properties = func_or_properties;
363 } 447 }
364 tests.setup(func, properties); 448 tests.setup(func, properties);
365 output.setup(properties); 449 output.setup(properties);
366 } 450 }
367 451
368 function done() { 452 function done() {
369 tests.end_wait(); 453 tests.end_wait();
370 } 454 }
371 455
372 function generate_tests(func, args) { 456 function generate_tests(func, args, properties) {
373 forEach(args, function(x) 457 forEach(args, function(x, i)
374 { 458 {
375 var name = x[0]; 459 var name = x[0];
376 test(function() 460 test(function()
377 { 461 {
378 func.apply(this, x.slice(1)); 462 func.apply(this, x.slice(1));
379 }, name); 463 },
464 name,
465 Array.isArray(properties) ? properties[i] : properties) ;
380 }); 466 });
381 } 467 }
382 468
383 function on_event(object, event, callback) 469 function on_event(object, event, callback)
384 { 470 {
385 object.addEventListener(event, callback, false); 471 object.addEventListener(event, callback, false);
386 } 472 }
387 473
388 expose(test, 'test'); 474 expose(test, 'test');
389 expose(async_test, 'async_test'); 475 expose(async_test, 'async_test');
390 expose(generate_tests, 'generate_tests'); 476 expose(generate_tests, 'generate_tests');
391 expose(setup, 'setup'); 477 expose(setup, 'setup');
392 expose(done, 'done'); 478 expose(done, 'done');
393 expose(on_event, 'on_event'); 479 expose(on_event, 'on_event');
394 480
395 /* 481 /*
396 * Return a string truncated to the given length, with ... added at the end 482 * Return a string truncated to the given length, with ... added at the end
397 * if it was longer. 483 * if it was longer.
398 */ 484 */
399 function truncate(s, len) 485 function truncate(s, len)
400 { 486 {
401 if (s.length > len) { 487 if (s.length > len) {
402 return s.substring(0, len - 3) + "..."; 488 return s.substring(0, len - 3) + "...";
403 } 489 }
404 return s; 490 return s;
405 } 491 }
406 492
407 function format_string(str) {
408 for (var i = 0; i < 32; i++) {
409 var replace = "\\";
410 switch (i) {
411 case 0: replace += "0"; break;
412 case 1: replace += "x01"; break;
413 case 2: replace += "x02"; break;
414 case 3: replace += "x03"; break;
415 case 4: replace += "x04"; break;
416 case 5: replace += "x05"; break;
417 case 6: replace += "x06"; break;
418 case 7: replace += "x07"; break;
419 case 8: replace += "b"; break;
420 case 9: replace += "t"; break;
421 case 10: replace += "n"; break;
422 case 11: replace += "v"; break;
423 case 12: replace += "f"; break;
424 case 13: replace += "r"; break;
425 case 14: replace += "x0e"; break;
426 case 15: replace += "x0f"; break;
427 case 16: replace += "x10"; break;
428 case 17: replace += "x11"; break;
429 case 18: replace += "x12"; break;
430 case 19: replace += "x13"; break;
431 case 20: replace += "x14"; break;
432 case 21: replace += "x15"; break;
433 case 22: replace += "x16"; break;
434 case 23: replace += "x17"; break;
435 case 24: replace += "x18"; break;
436 case 25: replace += "x19"; break;
437 case 26: replace += "x1a"; break;
438 case 27: replace += "x1b"; break;
439 case 28: replace += "x1c"; break;
440 case 29: replace += "x1d"; break;
441 case 30: replace += "x1e"; break;
442 case 31: replace += "x1f"; break;
443 }
444 str = str.replace(RegExp(String.fromCharCode(i), "g"), replace);
445 }
446 return str.replace(/"/g, '\\"')
447 }
448
449 /* 493 /*
450 * Convert a value to a nice, human-readable string 494 * Convert a value to a nice, human-readable string
451 */ 495 */
452 function format_value(val) 496 function format_value(val, seen)
453 { 497 {
498 » if (!seen) {
499 » seen = [];
500 }
501 if (typeof val === "object" && val !== null)
502 {
503 if (seen.indexOf(val) >= 0)
504 {
505 return "[...]";
506 }
507 » seen.push(val);
508 }
454 if (Array.isArray(val)) 509 if (Array.isArray(val))
455 { 510 {
456 return "[" + val.map(format_value).join(", ") + "]"; 511 return "[" + val.map(function(x) {return format_value(x, seen)}).joi n(", ") + "]";
457 } 512 }
458 513
459 switch (typeof val) 514 switch (typeof val)
460 { 515 {
461 case "string": 516 case "string":
462 return '"' + format_string(val) + '"'; 517 val = val.replace("\\", "\\\\");
518 for (var i = 0; i < 32; i++)
519 {
520 var replace = "\\";
521 switch (i) {
522 case 0: replace += "0"; break;
523 case 1: replace += "x01"; break;
524 case 2: replace += "x02"; break;
525 case 3: replace += "x03"; break;
526 case 4: replace += "x04"; break;
527 case 5: replace += "x05"; break;
528 case 6: replace += "x06"; break;
529 case 7: replace += "x07"; break;
530 case 8: replace += "b"; break;
531 case 9: replace += "t"; break;
532 case 10: replace += "n"; break;
533 case 11: replace += "v"; break;
534 case 12: replace += "f"; break;
535 case 13: replace += "r"; break;
536 case 14: replace += "x0e"; break;
537 case 15: replace += "x0f"; break;
538 case 16: replace += "x10"; break;
539 case 17: replace += "x11"; break;
540 case 18: replace += "x12"; break;
541 case 19: replace += "x13"; break;
542 case 20: replace += "x14"; break;
543 case 21: replace += "x15"; break;
544 case 22: replace += "x16"; break;
545 case 23: replace += "x17"; break;
546 case 24: replace += "x18"; break;
547 case 25: replace += "x19"; break;
548 case 26: replace += "x1a"; break;
549 case 27: replace += "x1b"; break;
550 case 28: replace += "x1c"; break;
551 case 29: replace += "x1d"; break;
552 case 30: replace += "x1e"; break;
553 case 31: replace += "x1f"; break;
554 }
555 val = val.replace(RegExp(String.fromCharCode(i), "g"), replace);
556 }
557 return '"' + val.replace(/"/g, '\\"') + '"';
463 case "boolean": 558 case "boolean":
464 case "undefined": 559 case "undefined":
465 return String(val); 560 return String(val);
466 case "number": 561 case "number":
467 // In JavaScript, -0 === 0 and String(-0) == "0", so we have to 562 // In JavaScript, -0 === 0 and String(-0) == "0", so we have to
468 // special-case. 563 // special-case.
469 if (val === -0 && 1/val === -Infinity) 564 if (val === -0 && 1/val === -Infinity)
470 { 565 {
471 return "-0"; 566 return "-0";
472 } 567 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 return x === y; 650 return x === y;
556 } 651 }
557 } 652 }
558 653
559 function assert_equals(actual, expected, description) 654 function assert_equals(actual, expected, description)
560 { 655 {
561 /* 656 /*
562 * Test if two primitives are equal or two objects 657 * Test if two primitives are equal or two objects
563 * are the same object 658 * are the same object
564 */ 659 */
660 if (typeof actual != typeof expected)
661 {
662 assert(false, "assert_equals", description,
663 "expected (" + typeof expected + ") ${expected} but go t (" + typeof actual + ") ${actual}",
664 {expected:expected, actual:actual});
665 return;
666 }
565 assert(same_value(actual, expected), "assert_equals", description, 667 assert(same_value(actual, expected), "assert_equals", description,
566 "expected ${expected} but got ${act ual}", 668 "expected ${expected} but got ${act ual}",
567 {expected:expected, actual:actual}) ; 669 {expected:expected, actual:actual}) ;
568 }; 670 };
569 expose(assert_equals, "assert_equals"); 671 expose(assert_equals, "assert_equals");
570 672
571 function assert_not_equals(actual, expected, description) 673 function assert_not_equals(actual, expected, description)
572 { 674 {
573 /* 675 /*
574 * Test if two primitives are unequal or two objects 676 * Test if two primitives are unequal or two objects
575 * are different objects 677 * are different objects
576 */ 678 */
577 assert(!same_value(actual, expected), "assert_not_equals", description, 679 assert(!same_value(actual, expected), "assert_not_equals", description,
578 "got disallowed value ${actual}", 680 "got disallowed value ${actual}",
579 {actual:actual}); 681 {actual:actual});
580 }; 682 };
581 expose(assert_not_equals, "assert_not_equals"); 683 expose(assert_not_equals, "assert_not_equals");
582 684
583 function assert_in_array(actual, expected, description) 685 function assert_in_array(actual, expected, description)
584 { 686 {
585 assert(expected.indexOf(actual) != -1, "assert_in_array", description, 687 assert(expected.indexOf(actual) != -1, "assert_in_array", description,
586 "value ${actual} not in array ${e xpected}", 688 "value ${actual} not in array ${e xpected}",
587 {actual:actual, expected:expected }); 689 {actual:actual, expected:expected });
588 } 690 }
589 expose(assert_in_array, "assert_in_array"); 691 expose(assert_in_array, "assert_in_array");
590 692
591 function assert_object_equals(actual, expected, description) 693 function assert_object_equals(actual, expected, description)
592 { 694 {
593 //This needs to be improved a great deal 695 //This needs to be improved a great deal
594 function check_equal(expected, actual, stack) 696 function check_equal(actual, expected, stack)
595 { 697 {
596 stack.push(actual); 698 stack.push(actual);
597 699
598 var p; 700 var p;
599 for (p in actual) 701 for (p in actual)
600 { 702 {
601 assert(expected.hasOwnProperty(p), "assert_object_equals", desc ription, 703 assert(expected.hasOwnProperty(p), "assert_object_equals", desc ription,
602 "unexpected property ${p}", {p:p}); 704 "unexpected property ${p}", {p:p});
603 705
604 if (typeof actual[p] === "object" && actual[p] !== null) 706 if (typeof actual[p] === "object" && actual[p] !== null)
605 { 707 {
606 if (stack.indexOf(actual[p]) === -1) 708 if (stack.indexOf(actual[p]) === -1)
607 { 709 {
608 check_equal(actual[p], expected[p], stack); 710 check_equal(actual[p], expected[p], stack);
609 } 711 }
610 } 712 }
611 else 713 else
612 { 714 {
613 assert(actual[p] === expected[p], "assert_object_equals", d escription, 715 assert(same_value(actual[p], expected[p]), "assert_object_e quals", description,
614 "property ${p} expected $ {expected} got ${actual}", 716 "property ${p} expected $ {expected} got ${actual}",
615 {p:p, expected:expected, actual:actual}); 717 {p:p, expected:expected, actual:actual});
616 } 718 }
617 } 719 }
618 for (p in expected) 720 for (p in expected)
619 { 721 {
620 assert(actual.hasOwnProperty(p), 722 assert(actual.hasOwnProperty(p),
621 "assert_object_equals", description, 723 "assert_object_equals", description,
622 "expected property ${p} missing", {p:p}); 724 "expected property ${p} missing", {p:p});
623 } 725 }
(...skipping 10 matching lines...) Expand all
634 "lengths differ, expected ${expected} got ${actual}", 736 "lengths differ, expected ${expected} got ${actual}",
635 {expected:expected.length, actual:actual.length}); 737 {expected:expected.length, actual:actual.length});
636 738
637 for (var i=0; i < actual.length; i++) 739 for (var i=0; i < actual.length; i++)
638 { 740 {
639 assert(actual.hasOwnProperty(i) === expected.hasOwnProperty(i), 741 assert(actual.hasOwnProperty(i) === expected.hasOwnProperty(i),
640 "assert_array_equals", description, 742 "assert_array_equals", description,
641 "property ${i}, property expected to be $expected but was $ac tual", 743 "property ${i}, property expected to be $expected but was $ac tual",
642 {i:i, expected:expected.hasOwnProperty(i) ? "present" : "miss ing", 744 {i:i, expected:expected.hasOwnProperty(i) ? "present" : "miss ing",
643 actual:actual.hasOwnProperty(i) ? "present" : "missing"}); 745 actual:actual.hasOwnProperty(i) ? "present" : "missing"});
644 assert(expected[i] === actual[i], 746 assert(same_value(expected[i], actual[i]),
645 "assert_array_equals", description, 747 "assert_array_equals", description,
646 "property ${i}, expected ${expected} but got ${actual}", 748 "property ${i}, expected ${expected} but got ${actual}",
647 {i:i, expected:expected[i], actual:actual[i]}); 749 {i:i, expected:expected[i], actual:actual[i]});
648 } 750 }
649 } 751 }
650 expose(assert_array_equals, "assert_array_equals"); 752 expose(assert_array_equals, "assert_array_equals");
651 753
652 function assert_approx_equals(actual, expected, epsilon, description) 754 function assert_approx_equals(actual, expected, epsilon, description)
653 { 755 {
654 /* 756 /*
655 * Test if two primitive numbers are equal withing +/- epsilon 757 * Test if two primitive numbers are equal withing +/- epsilon
656 */ 758 */
657 assert(typeof actual === "number", 759 assert(typeof actual === "number",
658 "assert_approx_equals", description, 760 "assert_approx_equals", description,
659 "expected a number but got a ${type_actual}", 761 "expected a number but got a ${type_actual}",
660 {type_actual:typeof actual}); 762 {type_actual:typeof actual});
661 763
662 assert(Math.abs(actual - expected) <= epsilon, 764 assert(Math.abs(actual - expected) <= epsilon,
663 "assert_approx_equals", description, 765 "assert_approx_equals", description,
664 "expected ${expected} +/- ${epsilon} but got ${actual}", 766 "expected ${expected} +/- ${epsilon} but got ${actual}",
665 {expected:expected, actual:actual, epsilon:epsilon}); 767 {expected:expected, actual:actual, epsilon:epsilon});
666 }; 768 };
667 expose(assert_approx_equals, "assert_approx_equals"); 769 expose(assert_approx_equals, "assert_approx_equals");
668 770
771 function assert_less_than(actual, expected, description)
772 {
773 /*
774 * Test if a primitive number is less than another
775 */
776 assert(typeof actual === "number",
777 "assert_less_than", description,
778 "expected a number but got a ${type_actual}",
779 {type_actual:typeof actual});
780
781 assert(actual < expected,
782 "assert_less_than", description,
783 "expected a number less than ${expected} but got ${actual}",
784 {expected:expected, actual:actual});
785 };
786 expose(assert_less_than, "assert_less_than");
787
788 function assert_greater_than(actual, expected, description)
789 {
790 /*
791 * Test if a primitive number is greater than another
792 */
793 assert(typeof actual === "number",
794 "assert_greater_than", description,
795 "expected a number but got a ${type_actual}",
796 {type_actual:typeof actual});
797
798 assert(actual > expected,
799 "assert_greater_than", description,
800 "expected a number greater than ${expected} but got ${actual}",
801 {expected:expected, actual:actual});
802 };
803 expose(assert_greater_than, "assert_greater_than");
804
805 function assert_less_than_equal(actual, expected, description)
806 {
807 /*
808 * Test if a primitive number is less than or equal to another
809 */
810 assert(typeof actual === "number",
811 "assert_less_than_equal", description,
812 "expected a number but got a ${type_actual}",
813 {type_actual:typeof actual});
814
815 assert(actual <= expected,
816 "assert_less_than", description,
817 "expected a number less than or equal to ${expected} but got ${ac tual}",
818 {expected:expected, actual:actual});
819 };
820 expose(assert_less_than_equal, "assert_less_than_equal");
821
822 function assert_greater_than_equal(actual, expected, description)
823 {
824 /*
825 * Test if a primitive number is greater than or equal to another
826 */
827 assert(typeof actual === "number",
828 "assert_greater_than_equal", description,
829 "expected a number but got a ${type_actual}",
830 {type_actual:typeof actual});
831
832 assert(actual >= expected,
833 "assert_greater_than_equal", description,
834 "expected a number greater than or equal to ${expected} but got $ {actual}",
835 {expected:expected, actual:actual});
836 };
837 expose(assert_greater_than_equal, "assert_greater_than_equal");
838
669 function assert_regexp_match(actual, expected, description) { 839 function assert_regexp_match(actual, expected, description) {
670 /* 840 /*
671 * Test if a string (actual) matches a regexp (expected) 841 * Test if a string (actual) matches a regexp (expected)
672 */ 842 */
673 assert(expected.test(actual), 843 assert(expected.test(actual),
674 "assert_regexp_match", description, 844 "assert_regexp_match", description,
675 "expected ${expected} but got ${actual}", 845 "expected ${expected} but got ${actual}",
676 {expected:expected, actual:actual}); 846 {expected:expected, actual:actual});
677 } 847 }
678 expose(assert_regexp_match, "assert_regexp_match"); 848 expose(assert_regexp_match, "assert_regexp_match");
679 849
850 function assert_class_string(object, class_string, description) {
851 assert_equals({}.toString.call(object), "[object " + class_string + "]",
852 description);
853 }
854 expose(assert_class_string, "assert_class_string");
855
680 856
681 function _assert_own_property(name) { 857 function _assert_own_property(name) {
682 return function(object, property_name, description) 858 return function(object, property_name, description)
683 { 859 {
684 assert(object.hasOwnProperty(property_name), 860 assert(object.hasOwnProperty(property_name),
685 name, description, 861 name, description,
686 "expected property ${p} missing", {p:property_name}); 862 "expected property ${p} missing", {p:property_name});
687 }; 863 };
688 } 864 }
689 expose(_assert_own_property("assert_exists"), "assert_exists"); 865 expose(_assert_own_property("assert_exists"), "assert_exists");
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 expose(_assert_inherits("assert_inherits"), "assert_inherits"); 898 expose(_assert_inherits("assert_inherits"), "assert_inherits");
723 expose(_assert_inherits("assert_idl_attribute"), "assert_idl_attribute"); 899 expose(_assert_inherits("assert_idl_attribute"), "assert_idl_attribute");
724 900
725 function assert_readonly(object, property_name, description) 901 function assert_readonly(object, property_name, description)
726 { 902 {
727 var initial_value = object[property_name]; 903 var initial_value = object[property_name];
728 try { 904 try {
729 //Note that this can have side effects in the case where 905 //Note that this can have side effects in the case where
730 //the property has PutForwards 906 //the property has PutForwards
731 object[property_name] = initial_value + "a"; //XXX use some other v alue here? 907 object[property_name] = initial_value + "a"; //XXX use some other v alue here?
732 assert(object[property_name] === initial_value, 908 assert(same_value(object[property_name], initial_value),
733 "assert_readonly", description, 909 "assert_readonly", description,
734 "changing property ${p} succeeded", 910 "changing property ${p} succeeded",
735 {p:property_name}); 911 {p:property_name});
736 } 912 }
737 finally 913 finally
738 { 914 {
739 object[property_name] = initial_value; 915 object[property_name] = initial_value;
740 } 916 }
741 }; 917 };
742 expose(assert_readonly, "assert_readonly"); 918 expose(assert_readonly, "assert_readonly");
743 919
744 function assert_throws(code, func, description) 920 function assert_throws(code, func, description)
745 { 921 {
746 try 922 try
747 { 923 {
748 func.call(this); 924 func.call(this);
749 assert(false, "assert_throws", description, 925 assert(false, "assert_throws", description,
750 "${func} did not throw", {func:func}); 926 "${func} did not throw", {func:func});
751 } 927 }
752 catch(e) 928 catch(e)
753 { 929 {
754 if (e instanceof AssertionError) { 930 if (e instanceof AssertionError) {
755 throw(e); 931 throw(e);
756 } 932 }
933 if (code === null)
934 {
935 return;
936 }
757 if (typeof code === "object") 937 if (typeof code === "object")
758 { 938 {
759 assert(typeof e == "object" && "name" in e && e.name == code.nam e, 939 assert(typeof e == "object" && "name" in e && e.name == code.nam e,
760 "assert_throws", description, 940 "assert_throws", description,
761 "${func} threw ${actual} (${actual_name}) expected ${expe cted} (${expected_name})", 941 "${func} threw ${actual} (${actual_name}) expected ${expe cted} (${expected_name})",
762 {func:func, actual:e, actual_name:e.name, 942 {func:func, actual:e, actual_name:e.name,
763 expected:code, 943 expected:code,
764 expected_name:code.name}); 944 expected_name:code.name});
765 return; 945 return;
766 } 946 }
767 var required_props = {}; 947
768 required_props.code = { 948 var code_name_map = {
769 INDEX_SIZE_ERR: 1, 949 INDEX_SIZE_ERR: 'IndexSizeError',
770 HIERARCHY_REQUEST_ERR: 3, 950 HIERARCHY_REQUEST_ERR: 'HierarchyRequestError',
771 WRONG_DOCUMENT_ERR: 4, 951 WRONG_DOCUMENT_ERR: 'WrongDocumentError',
772 INVALID_CHARACTER_ERR: 5, 952 INVALID_CHARACTER_ERR: 'InvalidCharacterError',
773 NO_MODIFICATION_ALLOWED_ERR: 7, 953 NO_MODIFICATION_ALLOWED_ERR: 'NoModificationAllowedError',
774 NOT_FOUND_ERR: 8, 954 NOT_FOUND_ERR: 'NotFoundError',
775 NOT_SUPPORTED_ERR: 9, 955 NOT_SUPPORTED_ERR: 'NotSupportedError',
776 INVALID_STATE_ERR: 11, 956 INVALID_STATE_ERR: 'InvalidStateError',
777 SYNTAX_ERR: 12, 957 SYNTAX_ERR: 'SyntaxError',
778 INVALID_MODIFICATION_ERR: 13, 958 INVALID_MODIFICATION_ERR: 'InvalidModificationError',
779 NAMESPACE_ERR: 14, 959 NAMESPACE_ERR: 'NamespaceError',
780 INVALID_ACCESS_ERR: 15, 960 INVALID_ACCESS_ERR: 'InvalidAccessError',
781 TYPE_MISMATCH_ERR: 17, 961 TYPE_MISMATCH_ERR: 'TypeMismatchError',
782 SECURITY_ERR: 18, 962 SECURITY_ERR: 'SecurityError',
783 NETWORK_ERR: 19, 963 NETWORK_ERR: 'NetworkError',
784 ABORT_ERR: 20, 964 ABORT_ERR: 'AbortError',
785 URL_MISMATCH_ERR: 21, 965 URL_MISMATCH_ERR: 'URLMismatchError',
786 QUOTA_EXCEEDED_ERR: 22, 966 QUOTA_EXCEEDED_ERR: 'QuotaExceededError',
787 TIMEOUT_ERR: 23, 967 TIMEOUT_ERR: 'TimeoutError',
788 INVALID_NODE_TYPE_ERR: 24, 968 INVALID_NODE_TYPE_ERR: 'InvalidNodeTypeError',
789 DATA_CLONE_ERR: 25, 969 DATA_CLONE_ERR: 'DataCloneError'
790 }[code]; 970 };
791 if (required_props.code === undefined) 971
972 var name = code in code_name_map ? code_name_map[code] : code;
973
974 var name_code_map = {
975 IndexSizeError: 1,
976 HierarchyRequestError: 3,
977 WrongDocumentError: 4,
978 InvalidCharacterError: 5,
979 NoModificationAllowedError: 7,
980 NotFoundError: 8,
981 NotSupportedError: 9,
982 InvalidStateError: 11,
983 SyntaxError: 12,
984 InvalidModificationError: 13,
985 NamespaceError: 14,
986 InvalidAccessError: 15,
987 TypeMismatchError: 17,
988 SecurityError: 18,
989 NetworkError: 19,
990 AbortError: 20,
991 URLMismatchError: 21,
992 QuotaExceededError: 22,
993 TimeoutError: 23,
994 InvalidNodeTypeError: 24,
995 DataCloneError: 25,
996
997 UnknownError: 0,
998 ConstraintError: 0,
999 DataError: 0,
1000 TransactionInactiveError: 0,
1001 ReadOnlyError: 0,
1002 VersionError: 0
1003 };
1004
1005 if (!(name in name_code_map))
792 { 1006 {
793 throw new AssertionError('Test bug: unrecognized DOMException co de "' + code + '" passed to assert_throws()'); 1007 throw new AssertionError('Test bug: unrecognized DOMException co de "' + code + '" passed to assert_throws()');
794 } 1008 }
795 required_props[code] = required_props.code; 1009
796 //Uncomment this when the latest version of every browser 1010 var required_props = { code: name_code_map[name] };
797 //actually implements the spec; otherwise it just creates 1011
798 //zillions of failures. Also do required_props.type. 1012 if (required_props.code === 0
799 //required_props.name = code; 1013 || ("name" in e && e.name !== e.name.toUpperCase() && e.name !== "DO MException"))
800 // 1014 {
1015 // New style exception: also test the name property.
1016 required_props.name = name;
1017 }
1018
801 //We'd like to test that e instanceof the appropriate interface, 1019 //We'd like to test that e instanceof the appropriate interface,
802 //but we can't, because we don't know what window it was created 1020 //but we can't, because we don't know what window it was created
803 //in. It might be an instanceof the appropriate interface on some 1021 //in. It might be an instanceof the appropriate interface on some
804 //unknown other window. TODO: Work around this somehow? 1022 //unknown other window. TODO: Work around this somehow?
805 1023
806 assert(typeof e == "object", 1024 assert(typeof e == "object",
807 "assert_throws", description, 1025 "assert_throws", description,
808 "${func} threw ${e} with type ${type}, not an object", 1026 "${func} threw ${e} with type ${type}, not an object",
809 {func:func, e:e, type:typeof e}); 1027 {func:func, e:e, type:typeof e});
810 1028
811 for (var prop in required_props) 1029 for (var prop in required_props)
812 { 1030 {
813 assert(typeof e == "object" && prop in e && e[prop] == required_ props[prop], 1031 assert(typeof e == "object" && prop in e && e[prop] == required_ props[prop],
814 "assert_throws", description, 1032 "assert_throws", description,
815 "${func} threw ${e} that is not a DOMException " + code + ": property ${prop} is equal to ${actual}, expected ${expected}", 1033 "${func} threw ${e} that is not a DOMException " + code + ": property ${prop} is equal to ${actual}, expected ${expected}",
816 {func:func, e:e, prop:prop, actual:e[prop], expected:requ ired_props[prop]}); 1034 {func:func, e:e, prop:prop, actual:e[prop], expected:requ ired_props[prop]});
817 } 1035 }
818 } 1036 }
819 } 1037 }
820 expose(assert_throws, "assert_throws"); 1038 expose(assert_throws, "assert_throws");
821 1039
822 function assert_unreached(description) { 1040 function assert_unreached(description) {
823 assert(false, "assert_unreached", description, 1041 assert(false, "assert_unreached", description,
824 "Reached unreachable code"); 1042 "Reached unreachable code");
825 } 1043 }
826 expose(assert_unreached, "assert_unreached"); 1044 expose(assert_unreached, "assert_unreached");
827 1045
1046 function assert_any(assert_func, actual, expected_array)
1047 {
1048 var args = [].slice.call(arguments, 3)
1049 var errors = []
1050 var passed = false;
1051 forEach(expected_array,
1052 function(expected)
1053 {
1054 try {
1055 assert_func.apply(this, [actual, expected].concat(args))
1056 passed = true;
1057 } catch(e) {
1058 errors.push(e.message);
1059 }
1060 });
1061 if (!passed) {
1062 throw new AssertionError(errors.join("\n\n"));
1063 }
1064 }
1065 expose(assert_any, "assert_any");
1066
828 function Test(name, properties) 1067 function Test(name, properties)
829 { 1068 {
830 this.name = name; 1069 this.name = name;
831 this.status = this.NOTRUN; 1070 this.status = this.NOTRUN;
832 this.timeout_id = null; 1071 this.timeout_id = null;
833 this.is_done = false; 1072 this.is_done = false;
834 1073
1074 this.properties = properties;
835 this.timeout_length = properties.timeout ? properties.timeout : settings .test_timeout; 1075 this.timeout_length = properties.timeout ? properties.timeout : settings .test_timeout;
836 1076
837 this.message = null; 1077 this.message = null;
838 1078
839 var this_obj = this; 1079 var this_obj = this;
840 this.steps = []; 1080 this.steps = [];
841 1081
842 tests.push(this); 1082 tests.push(this);
843 } 1083 }
844 1084
845 Test.prototype = { 1085 Test.statuses = {
846 PASS:0, 1086 PASS:0,
847 FAIL:1, 1087 FAIL:1,
848 TIMEOUT:2, 1088 TIMEOUT:2,
849 NOTRUN:3 1089 NOTRUN:3
850 }; 1090 };
851 1091
1092 Test.prototype = merge({}, Test.statuses);
1093
1094 Test.prototype.structured_clone = function()
1095 {
1096 if(!this._structured_clone)
1097 {
1098 var msg = this.message;
1099 msg = msg ? String(msg) : msg;
1100 this._structured_clone = merge({
1101 name:String(this.name),
1102 status:this.status,
1103 message:msg
1104 }, Test.statuses);
1105 }
1106 return this._structured_clone;
1107 };
852 1108
853 Test.prototype.step = function(func, this_obj) 1109 Test.prototype.step = function(func, this_obj)
854 { 1110 {
855 //In case the test has already failed 1111 //In case the test has already failed
856 if (this.status !== this.NOTRUN) 1112 if (this.status !== this.NOTRUN)
857 { 1113 {
858 return; 1114 return;
859 } 1115 }
860 1116
861 tests.started = true; 1117 tests.started = true;
862 1118
863 if (this.timeout_id === null) { 1119 if (this.timeout_id === null) {
864 this.set_timeout(); 1120 this.set_timeout();
865 } 1121 }
866 1122
867 this.steps.push(func); 1123 this.steps.push(func);
868 1124
869 if (arguments.length === 1) 1125 if (arguments.length === 1)
870 { 1126 {
871 this_obj = this; 1127 this_obj = this;
872 } 1128 }
873 1129
874 try 1130 try
875 { 1131 {
876 func.apply(this_obj, Array.prototype.slice.call(arguments, 2)); 1132 return func.apply(this_obj, Array.prototype.slice.call(arguments, 2) );
877 } 1133 }
878 catch(e) 1134 catch(e)
879 { 1135 {
880 //This can happen if something called synchronously invoked another 1136 //This can happen if something called synchronously invoked another
881 //step 1137 //step
882 if (this.status !== this.NOTRUN) 1138 if (this.status !== this.NOTRUN)
883 { 1139 {
884 return; 1140 return;
885 } 1141 }
886 this.status = this.FAIL; 1142 this.status = this.FAIL;
887 this.message = e.message; 1143 this.message = (typeof e === "object" && e !== null) ? e.message : e ;
888 if (typeof e.stack != "undefined" && typeof e.message == "string") { 1144 if (typeof e.stack != "undefined" && typeof e.message == "string") {
889 //Try to make it more informative for some exceptions, at least 1145 //Try to make it more informative for some exceptions, at least
890 //in Gecko and WebKit. This results in a stack dump instead of 1146 //in Gecko and WebKit. This results in a stack dump instead of
891 //just errors like "Cannot read property 'parentNode' of null" 1147 //just errors like "Cannot read property 'parentNode' of null"
892 //or "root is null". Makes it a lot longer, of course. 1148 //or "root is null". Makes it a lot longer, of course.
893 this.message += "(stack: " + e.stack + ")"; 1149 this.message += "(stack: " + e.stack + ")";
894 } 1150 }
895 this.done(); 1151 this.done();
896 if (debug && e.constructor !== AssertionError) { 1152 if (debug && e.constructor !== AssertionError) {
897 throw e; 1153 throw e;
(...skipping 10 matching lines...) Expand all
908 this_obj = test_this; 1164 this_obj = test_this;
909 } 1165 }
910 1166
911 return function() 1167 return function()
912 { 1168 {
913 test_this.step.apply(test_this, [func, this_obj].concat( 1169 test_this.step.apply(test_this, [func, this_obj].concat(
914 Array.prototype.slice.call(arguments))); 1170 Array.prototype.slice.call(arguments)));
915 }; 1171 };
916 }; 1172 };
917 1173
1174 Test.prototype.step_func_done = function(func, this_obj)
1175 {
1176 var test_this = this;
1177
1178 if (arguments.length === 1)
1179 {
1180 this_obj = test_this;
1181 }
1182
1183 return function()
1184 {
1185 test_this.step.apply(test_this, [func, this_obj].concat(
1186 Array.prototype.slice.call(arguments)));
1187 test_this.done();
1188 };
1189 };
1190
918 Test.prototype.set_timeout = function() 1191 Test.prototype.set_timeout = function()
919 { 1192 {
920 var this_obj = this; 1193 var this_obj = this;
921 this.timeout_id = setTimeout(function() 1194 this.timeout_id = setTimeout(function()
922 { 1195 {
923 this_obj.timeout(); 1196 this_obj.timeout();
924 }, this.timeout_length); 1197 }, this.timeout_length);
925 }; 1198 };
926 1199
927 Test.prototype.timeout = function() 1200 Test.prototype.timeout = function()
(...skipping 21 matching lines...) Expand all
949 1222
950 /* 1223 /*
951 * Harness 1224 * Harness
952 */ 1225 */
953 1226
954 function TestsStatus() 1227 function TestsStatus()
955 { 1228 {
956 this.status = null; 1229 this.status = null;
957 this.message = null; 1230 this.message = null;
958 } 1231 }
959 TestsStatus.prototype = { 1232
1233 TestsStatus.statuses = {
960 OK:0, 1234 OK:0,
961 ERROR:1, 1235 ERROR:1,
962 TIMEOUT:2 1236 TIMEOUT:2
963 }; 1237 };
964 1238
1239 TestsStatus.prototype = merge({}, TestsStatus.statuses);
1240
1241 TestsStatus.prototype.structured_clone = function()
1242 {
1243 if(!this._structured_clone)
1244 {
1245 var msg = this.message;
1246 msg = msg ? String(msg) : msg;
1247 this._structured_clone = merge({
1248 status:this.status,
1249 message:msg
1250 }, TestsStatus.statuses);
1251 }
1252 return this._structured_clone;
1253 };
1254
965 function Tests() 1255 function Tests()
966 { 1256 {
967 this.tests = []; 1257 this.tests = [];
968 this.num_pending = 0; 1258 this.num_pending = 0;
969 1259
970 this.phases = { 1260 this.phases = {
971 INITIAL:0, 1261 INITIAL:0,
972 SETUP:1, 1262 SETUP:1,
973 HAVE_TESTS:2, 1263 HAVE_TESTS:2,
974 HAVE_RESULTS:3, 1264 HAVE_RESULTS:3,
975 COMPLETE:4 1265 COMPLETE:4
976 }; 1266 };
977 this.phase = this.phases.INITIAL; 1267 this.phase = this.phases.INITIAL;
978 1268
1269 this.properties = {};
1270
979 //All tests can't be done until the load event fires 1271 //All tests can't be done until the load event fires
980 this.all_loaded = false; 1272 this.all_loaded = false;
981 this.wait_for_finish = false; 1273 this.wait_for_finish = false;
982 this.processing_callbacks = false; 1274 this.processing_callbacks = false;
983 1275
984 this.timeout_length = settings.timeout; 1276 this.timeout_length = settings.timeout;
985 this.timeout_id = null; 1277 this.timeout_id = null;
986 this.set_timeout();
987 1278
988 this.start_callbacks = []; 1279 this.start_callbacks = [];
989 this.test_done_callbacks = []; 1280 this.test_done_callbacks = [];
990 this.all_done_callbacks = []; 1281 this.all_done_callbacks = [];
991 1282
992 this.status = new TestsStatus(); 1283 this.status = new TestsStatus();
993 1284
994 var this_obj = this; 1285 var this_obj = this;
995 1286
996 on_event(window, "load", 1287 on_event(window, "load",
997 function() 1288 function()
998 { 1289 {
999 this_obj.all_loaded = true; 1290 this_obj.all_loaded = true;
1000 if (this_obj.all_done()) 1291 if (this_obj.all_done())
1001 { 1292 {
1002 this_obj.complete(); 1293 this_obj.complete();
1003 } 1294 }
1004 }); 1295 });
1005 this.properties = {}; 1296
1297 this.set_timeout();
1006 } 1298 }
1007 1299
1008 Tests.prototype.setup = function(func, properties) 1300 Tests.prototype.setup = function(func, properties)
1009 { 1301 {
1010 if (this.phase >= this.phases.HAVE_RESULTS) 1302 if (this.phase >= this.phases.HAVE_RESULTS)
1011 { 1303 {
1012 return; 1304 return;
1013 } 1305 }
1014 if (this.phase < this.phases.SETUP) 1306 if (this.phase < this.phases.SETUP)
1015 { 1307 {
1016 this.phase = this.phases.SETUP; 1308 this.phase = this.phases.SETUP;
1017 } 1309 }
1018 1310
1019 for (var p in properties) 1311 for (var p in properties)
1020 { 1312 {
1021 if (properties.hasOwnProperty(p)) 1313 if (properties.hasOwnProperty(p))
1022 { 1314 {
1023 this.properties[p] = properties[p]; 1315 this.properties[p] = properties[p];
1024 } 1316 }
1025 } 1317 }
1026 1318
1027 if (properties.timeout) 1319 if (properties.timeout)
1028 { 1320 {
1029 this.timeout_length = properties.timeout; 1321 this.timeout_length = properties.timeout;
1030 this.set_timeout();
1031 } 1322 }
1032 if (properties.explicit_done) 1323 if (properties.explicit_done)
1033 { 1324 {
1034 this.wait_for_finish = true; 1325 this.wait_for_finish = true;
1035 } 1326 }
1327 if (properties.explicit_timeout) {
1328 this.timeout_length = null;
1329 }
1036 1330
1037 if (func) 1331 if (func)
1038 { 1332 {
1039 try 1333 try
1040 { 1334 {
1041 func(); 1335 func();
1042 } catch(e) 1336 } catch(e)
1043 { 1337 {
1044 this.status.status = this.status.ERROR; 1338 this.status.status = this.status.ERROR;
1045 this.status.message = e; 1339 this.status.message = e;
1046 }; 1340 };
1047 } 1341 }
1342 this.set_timeout();
1048 }; 1343 };
1049 1344
1050 Tests.prototype.set_timeout = function() 1345 Tests.prototype.set_timeout = function()
1051 { 1346 {
1052 var this_obj = this; 1347 var this_obj = this;
1053 clearTimeout(this.timeout_id); 1348 clearTimeout(this.timeout_id);
1054 this.timeout_id = setTimeout(function() { 1349 if (this.timeout_length !== null)
1055 this_obj.timeout(); 1350 {
1056 }, this.timeout_length); 1351 this.timeout_id = setTimeout(function() {
1352 this_obj.timeout();
1353 }, this.timeout_length);
1354 }
1057 }; 1355 };
1058 1356
1059 Tests.prototype.timeout = function() { 1357 Tests.prototype.timeout = function() {
1060 this.status.status = this.status.TIMEOUT; 1358 this.status.status = this.status.TIMEOUT;
1061 this.complete(); 1359 this.complete();
1062 }; 1360 };
1063 1361
1064 Tests.prototype.end_wait = function() 1362 Tests.prototype.end_wait = function()
1065 { 1363 {
1066 this.wait_for_finish = false; 1364 this.wait_for_finish = false;
1067 if (this.all_done()) { 1365 if (this.all_done()) {
1068 this.complete(); 1366 this.complete();
1069 } 1367 }
1070 }; 1368 };
1071 1369
1072 Tests.prototype.push = function(test) 1370 Tests.prototype.push = function(test)
1073 { 1371 {
1074 if (this.phase < this.phases.HAVE_TESTS) { 1372 if (this.phase < this.phases.HAVE_TESTS) {
1075 this.notify_start(); 1373 this.start();
1076 } 1374 }
1077 this.num_pending++; 1375 this.num_pending++;
1078 this.tests.push(test); 1376 this.tests.push(test);
1079 }; 1377 };
1080 1378
1081 Tests.prototype.all_done = function() { 1379 Tests.prototype.all_done = function() {
1082 return (this.all_loaded && this.num_pending === 0 && 1380 return (this.all_loaded && this.num_pending === 0 &&
1083 !this.wait_for_finish && !this.processing_callbacks); 1381 !this.wait_for_finish && !this.processing_callbacks);
1084 }; 1382 };
1085 1383
1086 Tests.prototype.start = function() { 1384 Tests.prototype.start = function() {
1087 this.phase = this.phases.HAVE_TESTS; 1385 this.phase = this.phases.HAVE_TESTS;
1088 this.notify_start(); 1386 this.notify_start();
1089 }; 1387 };
1090 1388
1091 Tests.prototype.notify_start = function() { 1389 Tests.prototype.notify_start = function() {
1092 var this_obj = this; 1390 var this_obj = this;
1093 forEach (this.start_callbacks, 1391 forEach (this.start_callbacks,
1094 function(callback) 1392 function(callback)
1095 { 1393 {
1096 callback(this_obj.properties); 1394 callback(this_obj.properties);
1097 }); 1395 });
1098 forEach(ancestor_windows(), 1396 forEach_windows(
1099 function(w) 1397 function(w, is_same_origin)
1100 { 1398 {
1101 if(w.start_callback) 1399 if(is_same_origin && w.start_callback)
1102 { 1400 {
1103 try 1401 try
1104 { 1402 {
1105 w.start_callback(this_obj.properties); 1403 w.start_callback(this_obj.properties);
1106 } 1404 }
1107 catch(e) 1405 catch(e)
1108 { 1406 {
1109 if (debug) 1407 if (debug)
1110 { 1408 {
1111 throw(e); 1409 throw(e);
1112 } 1410 }
1113 } 1411 }
1114 } 1412 }
1413 if (supports_post_message(w) && w !== self)
1414 {
1415 w.postMessage({
1416 type: "start",
1417 properties: this_obj.properties
1418 }, "*");
1419 }
1115 }); 1420 });
1116 }; 1421 };
1117 1422
1118 Tests.prototype.result = function(test) 1423 Tests.prototype.result = function(test)
1119 { 1424 {
1120 if (this.phase > this.phases.HAVE_RESULTS) 1425 if (this.phase > this.phases.HAVE_RESULTS)
1121 { 1426 {
1122 return; 1427 return;
1123 } 1428 }
1124 this.phase = this.phases.HAVE_RESULTS; 1429 this.phase = this.phases.HAVE_RESULTS;
1125 this.num_pending--; 1430 this.num_pending--;
1126 this.notify_result(test); 1431 this.notify_result(test);
1127 }; 1432 };
1128 1433
1129 Tests.prototype.notify_result = function(test) { 1434 Tests.prototype.notify_result = function(test) {
1130 var this_obj = this; 1435 var this_obj = this;
1131 this.processing_callbacks = true; 1436 this.processing_callbacks = true;
1132 forEach(this.test_done_callbacks, 1437 forEach(this.test_done_callbacks,
1133 function(callback) 1438 function(callback)
1134 { 1439 {
1135 callback(test, this_obj); 1440 callback(test, this_obj);
1136 }); 1441 });
1137 1442
1138 forEach(ancestor_windows(), 1443 forEach_windows(
1139 function(w) 1444 function(w, is_same_origin)
1140 { 1445 {
1141 if(w.result_callback) 1446 if(is_same_origin && w.result_callback)
1142 { 1447 {
1143 try 1448 try
1144 { 1449 {
1145 w.result_callback(test); 1450 w.result_callback(test);
1146 } 1451 }
1147 catch(e) 1452 catch(e)
1148 { 1453 {
1149 if(debug) { 1454 if(debug) {
1150 throw e; 1455 throw e;
1151 } 1456 }
1152 } 1457 }
1153 } 1458 }
1459 if (supports_post_message(w) && w !== self)
1460 {
1461 w.postMessage({
1462 type: "result",
1463 test: test.structured_clone()
1464 }, "*");
1465 }
1154 }); 1466 });
1155 this.processing_callbacks = false; 1467 this.processing_callbacks = false;
1156 if (this_obj.all_done()) 1468 if (this_obj.all_done())
1157 { 1469 {
1158 this_obj.complete(); 1470 this_obj.complete();
1159 } 1471 }
1160 }; 1472 };
1161 1473
1162 Tests.prototype.complete = function() { 1474 Tests.prototype.complete = function() {
1163 if (this.phase === this.phases.COMPLETE) { 1475 if (this.phase === this.phases.COMPLETE) {
1164 return; 1476 return;
1165 } 1477 }
1166 this.phase = this.phases.COMPLETE; 1478 this.phase = this.phases.COMPLETE;
1479 var this_obj = this;
1480 this.tests.forEach(
1481 function(x)
1482 {
1483 if(x.status === x.NOTRUN)
1484 {
1485 this_obj.notify_result(x);
1486 }
1487 }
1488 );
1167 this.notify_complete(); 1489 this.notify_complete();
1168 }; 1490 };
1169 1491
1170 Tests.prototype.notify_complete = function() 1492 Tests.prototype.notify_complete = function()
1171 { 1493 {
1172 clearTimeout(this.timeout_id); 1494 clearTimeout(this.timeout_id);
1173 var this_obj = this; 1495 var this_obj = this;
1496 var tests = map(this_obj.tests,
1497 function(test)
1498 {
1499 return test.structured_clone();
1500 });
1174 if (this.status.status === null) 1501 if (this.status.status === null)
1175 { 1502 {
1176 this.status.status = this.status.OK; 1503 this.status.status = this.status.OK;
1177 } 1504 }
1178 1505
1179 forEach (this.all_done_callbacks, 1506 forEach (this.all_done_callbacks,
1180 function(callback) 1507 function(callback)
1181 { 1508 {
1182 callback(this_obj.tests, this_obj.status); 1509 callback(this_obj.tests, this_obj.status);
1183 }); 1510 });
1184 1511
1185 forEach(ancestor_windows(), 1512 forEach_windows(
1186 function(w) 1513 function(w, is_same_origin)
1187 { 1514 {
1188 if(w.completion_callback) 1515 if(is_same_origin && w.completion_callback)
1189 { 1516 {
1190 try 1517 try
1191 { 1518 {
1192 w.completion_callback(this_obj.tests, this_obj.statu s); 1519 w.completion_callback(this_obj.tests, this_obj.statu s);
1193 } 1520 }
1194 catch(e) 1521 catch(e)
1195 { 1522 {
1196 if (debug) 1523 if (debug)
1197 { 1524 {
1198 throw e; 1525 throw e;
1199 } 1526 }
1200 } 1527 }
1201 } 1528 }
1529 if (supports_post_message(w) && w !== self)
1530 {
1531 w.postMessage({
1532 type: "complete",
1533 tests: tests,
1534 status: this_obj.status.structured_clone()
1535 }, "*");
1536 }
1202 }); 1537 });
1203 }; 1538 };
1204 1539
1205 var tests = new Tests(); 1540 var tests = new Tests();
1206 1541
1542 function timeout() {
1543 if (tests.timeout_length === null)
1544 {
1545 tests.timeout();
1546 }
1547 }
1548 expose(timeout, 'timeout');
1549
1207 function add_start_callback(callback) { 1550 function add_start_callback(callback) {
1208 tests.start_callbacks.push(callback); 1551 tests.start_callbacks.push(callback);
1209 } 1552 }
1210 1553
1211 function add_result_callback(callback) 1554 function add_result_callback(callback)
1212 { 1555 {
1213 tests.test_done_callbacks.push(callback); 1556 tests.test_done_callbacks.push(callback);
1214 } 1557 }
1215 1558
1216 function add_completion_callback(callback) 1559 function add_completion_callback(callback)
1217 { 1560 {
1218 tests.all_done_callbacks.push(callback); 1561 tests.all_done_callbacks.push(callback);
1219 } 1562 }
1220 1563
1221 expose(add_start_callback, 'add_start_callback'); 1564 expose(add_start_callback, 'add_start_callback');
1222 expose(add_result_callback, 'add_result_callback'); 1565 expose(add_result_callback, 'add_result_callback');
1223 expose(add_completion_callback, 'add_completion_callback'); 1566 expose(add_completion_callback, 'add_completion_callback');
1224 1567
1225 /* 1568 /*
1226 * Output listener 1569 * Output listener
1227 */ 1570 */
1228 1571
1229 function Output() { 1572 function Output() {
1230 this.output_document = null; 1573 this.output_document = document;
1231 this.output_node = null; 1574 this.output_node = null;
1232 this.done_count = 0; 1575 this.done_count = 0;
1233 this.enabled = settings.output; 1576 this.enabled = settings.output;
1234 this.phase = this.INITIAL; 1577 this.phase = this.INITIAL;
1235 } 1578 }
1236 1579
1237 Output.prototype.INITIAL = 0; 1580 Output.prototype.INITIAL = 0;
1238 Output.prototype.STARTED = 1; 1581 Output.prototype.STARTED = 1;
1239 Output.prototype.HAVE_RESULTS = 2; 1582 Output.prototype.HAVE_RESULTS = 2;
1240 Output.prototype.COMPLETE = 3; 1583 Output.prototype.COMPLETE = 3;
(...skipping 17 matching lines...) Expand all
1258 if (properties.output_document) { 1601 if (properties.output_document) {
1259 this.output_document = properties.output_document; 1602 this.output_document = properties.output_document;
1260 } else { 1603 } else {
1261 this.output_document = document; 1604 this.output_document = document;
1262 } 1605 }
1263 this.phase = this.STARTED; 1606 this.phase = this.STARTED;
1264 }; 1607 };
1265 1608
1266 Output.prototype.resolve_log = function() 1609 Output.prototype.resolve_log = function()
1267 { 1610 {
1268 if (!this.output_document) { 1611 var output_document;
1612 if (typeof this.output_document === "function")
1613 {
1614 output_document = this.output_document.apply(undefined);
1615 } else
1616 {
1617 output_document = this.output_document;
1618 }
1619 if (!output_document)
1620 {
1269 return; 1621 return;
1270 } 1622 }
1271 var node = this.output_document.getElementById("log"); 1623 var node = output_document.getElementById("log");
1272 if (node) { 1624 if (node)
1625 {
1626 this.output_document = output_document;
1273 this.output_node = node; 1627 this.output_node = node;
1274 } 1628 }
1275 }; 1629 };
1276 1630
1277 Output.prototype.show_status = function(test) 1631 Output.prototype.show_status = function(test)
1278 { 1632 {
1279 if (this.phase < this.STARTED) 1633 if (this.phase < this.STARTED)
1280 { 1634 {
1281 this.init(); 1635 this.init();
1282 } 1636 }
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1391 { 1745 {
1392 e.preventDefault(); 1746 e.preventDefault();
1393 return; 1747 return;
1394 } 1748 }
1395 var result_class = element.parentNode.getAttrib ute("class"); 1749 var result_class = element.parentNode.getAttrib ute("class");
1396 var style_element = output_document.querySelect or("style#hide-" + result_class); 1750 var style_element = output_document.querySelect or("style#hide-" + result_class);
1397 var input_element = element.querySelector("inpu t"); 1751 var input_element = element.querySelector("inpu t");
1398 if (!style_element && !input_element.checked) { 1752 if (!style_element && !input_element.checked) {
1399 style_element = output_document.createEleme ntNS(xhtml_ns, "style"); 1753 style_element = output_document.createEleme ntNS(xhtml_ns, "style");
1400 style_element.id = "hide-" + result_class; 1754 style_element.id = "hide-" + result_class;
1401 style_element.innerHTML = "table#results > tbody > tr."+result_class+"{display:none}"; 1755 style_element.textContent = "table#results > tbody > tr."+result_class+"{display:none}";
1402 output_document.body.appendChild(style_elem ent); 1756 output_document.body.appendChild(style_elem ent);
1403 } else if (style_element && input_element.check ed) { 1757 } else if (style_element && input_element.check ed) {
1404 style_element.parentNode.removeChild(style_ element); 1758 style_element.parentNode.removeChild(style_ element);
1405 } 1759 }
1406 }); 1760 });
1407 }); 1761 });
1408 1762
1409 // This use of innerHTML plus manual escaping is not recommended in 1763 // This use of innerHTML plus manual escaping is not recommended in
1410 // general, but is necessary here for performance. Using textContent 1764 // general, but is necessary here for performance. Using textContent
1411 // on each individual <td> adds tens of seconds of execution time for 1765 // on each individual <td> adds tens of seconds of execution time for
1412 // large test suites (tens of thousands of tests). 1766 // large test suites (tens of thousands of tests).
1413 function escape_html(s) 1767 function escape_html(s)
1414 { 1768 {
1415 return s.replace(/\&/g, "&amp;") 1769 return s.replace(/\&/g, "&amp;")
1416 .replace(/</g, "&lt;") 1770 .replace(/</g, "&lt;")
1417 .replace(/"/g, "&quot;") 1771 .replace(/"/g, "&quot;")
1418 .replace(/'/g, "&#39;"); 1772 .replace(/'/g, "&#39;");
1419 } 1773 }
1420 1774
1421 log.appendChild(document.createElement("section")); 1775 function has_assertions()
1422 var html = "<h2>Details</h2><table id='results'>" 1776 {
1423 + "<thead><tr><th>Result</th><th>Test Name</th><th>Message</th></tr> </thead>" 1777 for (var i = 0; i < tests.length; i++) {
1778 if (tests[i].properties.hasOwnProperty("assert")) {
1779 return true;
1780 }
1781 }
1782 return false;
1783 }
1784
1785 function get_assertion(test)
1786 {
1787 if (test.properties.hasOwnProperty("assert")) {
1788 if (Array.isArray(test.properties.assert)) {
1789 return test.properties.assert.join(' ');
1790 }
1791 return test.properties.assert;
1792 }
1793 return '';
1794 }
1795
1796 log.appendChild(document.createElementNS(xhtml_ns, "section"));
1797 var assertions = has_assertions();
1798 var html = "<h2>Details</h2><table id='results' " + (assertions ? "class ='assertions'" : "" ) + ">"
1799 + "<thead><tr><th>Result</th><th>Test Name</th>"
1800 + (assertions ? "<th>Assertion</th>" : "")
1801 + "<th>Message</th></tr></thead>"
1424 + "<tbody>"; 1802 + "<tbody>";
1425 for (var i = 0; i < tests.length; i++) { 1803 for (var i = 0; i < tests.length; i++) {
1426 html += '<tr class="' 1804 html += '<tr class="'
1427 + escape_html(status_class(status_text[tests[i].status])) 1805 + escape_html(status_class(status_text[tests[i].status]))
1428 + '"><td>' 1806 + '"><td>'
1429 + escape_html(status_text[tests[i].status]) 1807 + escape_html(status_text[tests[i].status])
1430 + "</td><td>" 1808 + "</td><td>"
1431 + escape_html(format_string(tests[i].name)) 1809 + escape_html(tests[i].name)
1432 + "</td><td>" 1810 + "</td><td>"
1433 + escape_html(tests[i].message ? format_string(tests[i].message) : " ") 1811 + (assertions ? escape_html(get_assertion(tests[i])) + "</td><td >" : "")
1812 + escape_html(tests[i].message ? tests[i].message : " ")
1434 + "</td></tr>"; 1813 + "</td></tr>";
1435 } 1814 }
1436 log.lastChild.innerHTML = html + "</tbody></table>"; 1815 html += "</tbody></table>";
1816 try {
1817 log.lastChild.innerHTML = html;
1818 } catch (e) {
1819 log.appendChild(document.createElementNS(xhtml_ns, "p"))
1820 .textContent = "Setting innerHTML for the log threw an exception. ";
1821 log.appendChild(document.createElementNS(xhtml_ns, "pre"))
1822 .textContent = html;
1823 }
1437 }; 1824 };
1438 1825
1439 var output = new Output(); 1826 var output = new Output();
1440 add_start_callback(function (properties) {output.init(properties);}); 1827 add_start_callback(function (properties) {output.init(properties);});
1441 add_result_callback(function (test) {output.show_status(tests);}); 1828 add_result_callback(function (test) {output.show_status(tests);});
1442 add_completion_callback(function (tests, harness_status) {output.show_result s(tests, harness_status);}); 1829 add_completion_callback(function (tests, harness_status) {output.show_result s(tests, harness_status);});
1443 1830
1444 /* 1831 /*
1445 * Template code 1832 * Template code
1446 * 1833 *
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
1733 { 2120 {
1734 if (!(components[i] in target)) 2121 if (!(components[i] in target))
1735 { 2122 {
1736 target[components[i]] = {}; 2123 target[components[i]] = {};
1737 } 2124 }
1738 target = target[components[i]]; 2125 target = target[components[i]];
1739 } 2126 }
1740 target[components[components.length - 1]] = object; 2127 target[components[components.length - 1]] = object;
1741 } 2128 }
1742 2129
1743 function ancestor_windows() { 2130 function forEach_windows(callback) {
1744 //Get the windows [self ... top] as an array 2131 // Iterate of the the windows [self ... top, opener]. The callback is pa ssed
1745 if ("result_cache" in ancestor_windows) 2132 // two objects, the first one is the windows object itself, the second o ne
1746 { 2133 // is a boolean indicating whether or not its on the same origin as the
1747 return ancestor_windows.result_cache; 2134 // current window.
1748 } 2135 var cache = forEach_windows.result_cache;
1749 var rv = [self]; 2136 if (!cache) {
1750 var w = self; 2137 cache = [[self, true]];
1751 while (w != w.parent) 2138 var w = self;
1752 { 2139 var i = 0;
1753 w = w.parent; 2140 var so;
1754 rv.push(w); 2141 var origins = location.ancestorOrigins;
1755 } 2142 while (w != w.parent)
1756 ancestor_windows.result_cache = rv; 2143 {
1757 return rv; 2144 w = w.parent;
1758 } 2145 // In WebKit, calls to parent windows' properties that aren't on the same
1759 2146 // origin cause an error message to be displayed in the error co nsole but
2147 // don't throw an exception. This is a deviation from the curren t HTML5
2148 // spec. See: https://bugs.webkit.org/show_bug.cgi?id=43504
2149 // The problem with WebKit's behavior is that it pollutes the er ror console
2150 // with error messages that can't be caught.
2151 //
2152 // This issue can be mitigated by relying on the (for now) propr ietary
2153 // `location.ancestorOrigins` property which returns an ordered list of
2154 // the origins of enclosing windows. See:
2155 // http://trac.webkit.org/changeset/113945.
2156 if(origins) {
2157 so = (location.origin == origins[i]);
2158 }
2159 else
2160 {
2161 so = is_same_origin(w);
2162 }
2163 cache.push([w, so]);
2164 i++;
2165 }
2166 w = window.opener;
2167 if(w)
2168 {
2169 // window.opener isn't included in the `location.ancestorOrigins ` prop.
2170 // We'll just have to deal with a simple check and an error msg on WebKit
2171 // browsers in this case.
2172 cache.push([w, is_same_origin(w)]);
2173 }
2174 forEach_windows.result_cache = cache;
2175 }
2176
2177 forEach(cache,
2178 function(a)
2179 {
2180 callback.apply(null, a);
2181 });
2182 }
2183
2184 function is_same_origin(w) {
2185 try {
2186 'random_prop' in w;
2187 return true;
2188 } catch(e) {
2189 return false;
2190 }
2191 }
2192
2193 function supports_post_message(w)
2194 {
2195 var supports;
2196 var type;
2197 // Given IE implements postMessage across nested iframes but not across
2198 // windows or tabs, you can't infer cross-origin communication from the presence
2199 // of postMessage on the current window object only.
2200 //
2201 // Touching the postMessage prop on a window can throw if the window is
2202 // not from the same origin AND post message is not supported in that
2203 // browser. So just doing an existence test here won't do, you also need
2204 // to wrap it in a try..cacth block.
2205 try
2206 {
2207 type = typeof w.postMessage;
2208 if (type === "function")
2209 {
2210 supports = true;
2211 }
2212 // IE8 supports postMessage, but implements it as a host object whic h
2213 // returns "object" as its `typeof`.
2214 else if (type === "object")
2215 {
2216 supports = true;
2217 }
2218 // This is the case where postMessage isn't supported AND accessing a
2219 // window property across origins does NOT throw (e.g. old Safari br owser).
2220 else
2221 {
2222 supports = false;
2223 }
2224 }
2225 catch(e) {
2226 // This is the case where postMessage isn't supported AND accessing a
2227 // window property across origins throws (e.g. old Firefox browser).
2228 supports = false;
2229 }
2230 return supports;
2231 }
1760 })(); 2232 })();
1761 // vim: set expandtab shiftwidth=4 tabstop=4: 2233 // vim: set expandtab shiftwidth=4 tabstop=4:
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698