~ubuntu-branches/ubuntu/karmic/gears/karmic

« back to all changes in this revision

Viewing changes to gears/test/tester/assert.js

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Lesicnik
  • Date: 2009-04-30 19:15:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090430191525-0790sb5wzg8ou0xb
Tags: upstream-0.5.21.0~svn3334+dfsg
ImportĀ upstreamĀ versionĀ 0.5.21.0~svn3334+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2007, Google Inc.
 
2
//
 
3
// Redistribution and use in source and binary forms, with or without
 
4
// modification, are permitted provided that the following conditions are met:
 
5
//
 
6
//  1. Redistributions of source code must retain the above copyright notice,
 
7
//     this list of conditions and the following disclaimer.
 
8
//  2. Redistributions in binary form must reproduce the above copyright notice,
 
9
//     this list of conditions and the following disclaimer in the documentation
 
10
//     and/or other materials provided with the distribution.
 
11
//  3. Neither the name of Google Inc. nor the names of its contributors may be
 
12
//     used to endorse or promote products derived from this software without
 
13
//     specific prior written permission.
 
14
//
 
15
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
16
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
17
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 
18
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
19
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
20
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
21
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
22
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
23
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
24
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
25
 
 
26
// This file defines all the builtins that can be used inside Gears unit tests.
 
27
 
 
28
/**
 
29
 * Whether the installed Gears extension is a debug build.
 
30
 */
 
31
var isDebug = google.gears.factory.getBuildInfo().indexOf('dbg') > -1;
 
32
 
 
33
/**
 
34
 * Whether the installed Gears extension is an official build.
 
35
 */
 
36
var isOfficial = google.gears.factory.getBuildInfo().indexOf('official') > -1;
 
37
 
 
38
/**
 
39
 * Whether the installed Gears extension is for a particular platform.
 
40
 */
 
41
var isWin32 = google.gears.factory.getBuildInfo().indexOf('win32') > -1;
 
42
var isWince = google.gears.factory.getBuildInfo().indexOf('wince') > -1;
 
43
var isOsx = google.gears.factory.getBuildInfo().indexOf('osx') > -1;
 
44
var isAndroid = google.gears.factory.getBuildInfo().indexOf('android') > -1;
 
45
 
 
46
/**
 
47
 * Whether the installed Gears extension is for a particular browser.
 
48
 */
 
49
var isIE = google.gears.factory.getBuildInfo().indexOf(';ie') > -1;
 
50
var isFirefox = google.gears.factory.getBuildInfo().indexOf(';firefox') > -1;
 
51
var isSafari = google.gears.factory.getBuildInfo().indexOf(';safari') > -1;
 
52
var isNPAPI = google.gears.factory.getBuildInfo().indexOf(';npapi') > -1;
 
53
var isOpera = google.gears.factory.getBuildInfo().indexOf(';opera') > -1;
 
54
 
 
55
/**
 
56
 * Whether the installed Gears extension has the test scriptable object.
 
57
 * See also the definition of USING_CCTESTS in gears\tools\config.mk.
 
58
 */
 
59
var isUsingCCTests = isDebug || !isOfficial;
 
60
 
 
61
/**
 
62
 * A shared timer tests can use.
 
63
 */
 
64
var timer = google.gears.factory.create('beta.timer');
 
65
 
 
66
/**
 
67
 * Assert that something is true and throw an error if not.
 
68
 *
 
69
 * @param expr The expression to test. This will be coerced to bool if it isn't
 
70
 * already.
 
71
 * @param optMessage The message to display if expr is not true, or a function
 
72
 * which will return the message.
 
73
 */
 
74
function assert(expr, optMessage) {
 
75
  if (!expr) {
 
76
    if (isFunction(optMessage)) {
 
77
      throw new Error(optMessage());
 
78
    } else if (isString(optMessage)) {
 
79
      throw new Error(optMessage);
 
80
    } else {
 
81
      throw new Error('Assertion failed');
 
82
    }
 
83
  }
 
84
}
 
85
 
 
86
/**
 
87
 * Format error message with optional error message.
 
88
 *
 
89
 * @param message The original error message.
 
90
 * @param optDescription An optional description of what went wrong.
 
91
 */
 
92
function formatErrorMessage(message, optDescription) {
 
93
  if (optDescription) {
 
94
    return optDescription + ' - ' + message;
 
95
  } else {
 
96
    return message;
 
97
  }
 
98
}
 
99
 
 
100
/**
 
101
 * Assert that two values are equal, as defined by ===. A strict equality test
 
102
 * is used; 4 and "4" are not equal. Also two different objects with the same
 
103
 * properties compare as false.
 
104
 *
 
105
 * @param expected The expected value.
 
106
 * @param actual The actual value.
 
107
 * @param optDescription An optional description of what went wrong.
 
108
 */
 
109
function assertEqual(expected, actual, optDescription) {
 
110
  // === seems to be buggy on Safari:
 
111
  // https://bugs.webkit.org/show_bug.cgi?id=20305 . Work around this by
 
112
  // comparing object addresses. Converting an NPObject to a string returns a
 
113
  // string with the address embedded, so we compare these.
 
114
 
 
115
  // toString() doesn't seem to be defined for Gears objects in Safari.
 
116
  function asString(object) {
 
117
    return '%s'.subs(object);
 
118
  }
 
119
 
 
120
  function isNPObject(object) {
 
121
    if (object) {
 
122
      var string = asString(object);
 
123
      return string && string.indexOf('NPObject') == 0;
 
124
    }
 
125
  }
 
126
 
 
127
  function generateMessage() {
 
128
    var message = 'Expected: %s (%s), actual: %s (%s)'.subs(
 
129
        expected, typeof expected, actual, typeof actual);
 
130
    return formatErrorMessage(message, optDescription);
 
131
  }
 
132
 
 
133
  if (isSafari && isNPObject(expected) && isNPObject(actual)) {
 
134
    assert(asString(expected) == asString(actual), generateMessage);
 
135
  } else {
 
136
    assert(expected === actual, generateMessage);
 
137
  }
 
138
}
 
139
 
 
140
 
 
141
/**
 
142
 * Assert that two values are equal. This function will inspect object
 
143
 * object properties and array members. Is a function is encountered the only
 
144
 * check that is performed is to assert that they expected and actual are of
 
145
 * type function. Otherwise, a strict equality test is used; 4 and "4" are not
 
146
 * equal.
 
147
 *
 
148
 * @param expected Any type containing the expected value.
 
149
 * @param actual Any type containing the actual value.
 
150
 * @param optDescription An optional description of what went wrong.
 
151
 */
 
152
function assertEqualAnyType(expected, actual, optDescription) {
 
153
  if (isArray(expected) && isArray(actual)) {
 
154
    assertArrayEqual(expected, actual, optDescription);
 
155
  } else if (isObject(expected) && isObject(actual)) {
 
156
    assertObjectEqual(expected, actual, optDescription);
 
157
  } else if (isFunction(expected) && isFunction(actual)) {
 
158
    // functions are only tested for type
 
159
  } else {
 
160
    assertEqual(expected, actual, optDescription);
 
161
  }
 
162
}
 
163
 
 
164
/**
 
165
 * Assert that all values in two arrays are equal. A strict equality test is
 
166
 * used; 4 and "4" are not equal.
 
167
 *
 
168
 * @param expected The array containing expected values.
 
169
 * @param actual The array containing actual values.
 
170
 * @param optDescription An optional description of what went wrong.
 
171
 */
 
172
function assertArrayEqual(expected, actual, optDescription) {
 
173
  function notArrayErrorMessage(array, optDescription) {
 
174
    return function() {
 
175
      var message = 'Expected array, actual: %s (%s)'.subs(array, typeof array);
 
176
      return formatErrorMessage(message, optDescription);
 
177
    };
 
178
  }
 
179
 
 
180
  assert(isArray(expected), notArrayErrorMessage(expected, optDescription));
 
181
  assert(isArray(actual), notArrayErrorMessage(actual, optDescription));
 
182
  assert(expected.length == actual.length, function() {
 
183
    var message = 'Expected array length: %s actual length: %s'.subs(
 
184
        expected.length, actual.length);
 
185
    return formatErrorMessage(message, optDescription);
 
186
  });
 
187
 
 
188
  for (var i = 0; i < expected.length; ++expected) {
 
189
    assertEqualAnyType(expected[i], actual[i], function() {
 
190
      var message = 'Expected element in array at %s: %s (%s) actual: %s (%s)'
 
191
          .subs(i, expected[i], typeof expected[i], actual[i],
 
192
          typeof actual[i]);
 
193
      return formatErrorMessage(message, optDescription);
 
194
    });
 
195
  }
 
196
}
 
197
 
 
198
/**
 
199
 * Assert that all properties in two objects are equal. A strict equality test
 
200
 * is used; 4 and "4" are not equal.
 
201
 *
 
202
 * @param expected The object containing expected values.
 
203
 * @param actual The object containing actual values.
 
204
 * @param optDescription An optional description of what went wrong.
 
205
 */
 
206
function assertObjectEqual(expected, actual, optDescription) {
 
207
  function notObjectErrorMessage(array, optDescription) {
 
208
    return function() {
 
209
      var message = 'Expected object, actual: %s (%s)'.subs(
 
210
          array, typeof array);
 
211
      return formatErrorMessage(message, optDescription);
 
212
    };
 
213
  }
 
214
 
 
215
  assert(isObject(expected), notObjectErrorMessage(expected, optDescription));
 
216
  assert(isObject(actual), notObjectErrorMessage(actual, optDescription));
 
217
 
 
218
  for (property in expected) {
 
219
    assertEqualAnyType(expected[property], actual[property], optDescription);
 
220
  }
 
221
 
 
222
  for (property in actual) {
 
223
    assertEqualAnyType(expected[property], actual[property], optDescription);
 
224
  }
 
225
}
 
226
 
 
227
/**
 
228
 * Assert that two blobs probably have the same content. Checks the content of
 
229
 * the blob in debug mode, and the lengths in release mode.
 
230
 *
 
231
 * @param expected The expected blob.
 
232
 * @param actual The actual blob.
 
233
 * @param optDescription An optional description of what went wrong.
 
234
 */
 
235
function assertBlobProbablyEqual(expected, actual, optDescription) {
 
236
  if (optDescription) {
 
237
    optDescription += ' ';
 
238
  } else {
 
239
    optDescription = '';
 
240
  }
 
241
  assert(expected.length == actual.length, optDescription +
 
242
      'Mismatched blob: expected: %s bytes, actual: %s bytes'.
 
243
          subs(expected.length, actual.length));
 
244
 
 
245
  if (isDebug) {
 
246
    assert(actual.hasSameContentsAs(expected), optDescription +
 
247
        'Mismatched blob: same size, different contents');
 
248
  }
 
249
}
 
250
 
 
251
/**
 
252
 * Assert that two values are not equal. A strict equality test is used; 4 and
 
253
 * "4" are not equal.
 
254
 *
 
255
 * @param unexpected The unexpected value.
 
256
 * @param actual The actual value.
 
257
 * @param optDescription An optional description of what went wrong.
 
258
 */
 
259
function assertNotEqual(unexpected, actual, optDescription) {
 
260
  assert(unexpected !== actual, function() {
 
261
    var message = 'Expected value other than "%s" (%s)'.subs(
 
262
       unexpected, typeof unexpected);
 
263
    return formatErrorMessage(message, optDescription);
 
264
  });
 
265
}
 
266
 
 
267
/**
 
268
 * Assert a value is null. This tests for strict equality to null, no coercion
 
269
 * is done.
 
270
 *
 
271
 * @param val The value expected to be null.
 
272
 * @param optDescription An optional description of what went wrong.
 
273
 */
 
274
function assertNull(val, optDescription) {
 
275
  assert(val === null, function() {
 
276
    var message = "Expected null value.";
 
277
    return formatErrorMessage(message, optDescription);
 
278
  });
 
279
}
 
280
 
 
281
/**
 
282
 * Assert a value is not null. This tests for strict equality to null, no
 
283
 * coercion is done.
 
284
 *
 
285
 * @param val The value expected to be non-null.
 
286
 * @param optDescription An optional description of what went wrong.
 
287
 */
 
288
function assertNotNull(val, optDescription) {
 
289
  assert(val !== null, function() {
 
290
    var message = "Unexpected null value.";
 
291
    return formatErrorMessage(message, optDescription);
 
292
  });
 
293
}
 
294
 
 
295
/**
 
296
 * Assert that a function produces an error.
 
297
 *
 
298
 * @param fn This function will be run. If it produces an error, the assert
 
299
 * succeeds. Otherwise, it fails.
 
300
 * @param optExpectedError An optional error message that is expected. If the
 
301
 * message that results from running fn contains this substring, the assert
 
302
 * succeeds. Otherwise, it fails.
 
303
 * @param optDescription An optional description of what went wrong.
 
304
 */
 
305
function assertError(fn, optExpectedError, optDescription) {
 
306
  try {
 
307
    fn();
 
308
  } catch (e) {
 
309
    if (!optExpectedError) {
 
310
      return;
 
311
    } else {
 
312
      var actualError = e.message || e.toString();
 
313
      if (actualError.indexOf(optExpectedError) > -1) {
 
314
        return;
 
315
      }
 
316
    }
 
317
  }
 
318
 
 
319
  var message = 'Did not receive expected error';
 
320
 
 
321
  if (optExpectedError) {
 
322
    message += ': "' + optExpectedError + '"';
 
323
  }
 
324
 
 
325
  throw new Error(formatErrorMessage(message, optDescription));
 
326
}
 
327
 
 
328
/**
 
329
 * Starts the current test running asynchronously. The next test will not be
 
330
 * started until completeAsync() is called.
 
331
 */
 
332
function startAsync() {
 
333
  Harness.current_.startAsync();
 
334
}
 
335
 
 
336
/**
 
337
 * Marks the currently running asynchronous test as successful and starts the
 
338
 * next test.
 
339
 */
 
340
function completeAsync() {
 
341
  Harness.current_.completeAsync();
 
342
}
 
343
 
 
344
/**
 
345
 * Wait for one or more global errors to occur before starting the next test. If
 
346
 * the errors do not occur, occur out of order, or if some other error occurs,
 
347
 * the test is marked failed.
 
348
 *
 
349
 * @param errorMessages Array of expected error substrings. When an error occurs
 
350
 * the first item in this array is removed and compared to the full error text.
 
351
 * If it occurs as a substring, the expected error is considered found.
 
352
 * Otherwise the test is marked failed.
 
353
 */
 
354
function waitForGlobalErrors(errorMessages) {
 
355
  Harness.current_.waitForGlobalErrors(errorMessages);
 
356
}
 
357
 
 
358
/**
 
359
 * Process a resultset and ensure it is closed, even if there is an error.
 
360
 * @param rs The resultset to process.
 
361
 * @param fn A function that will receive the resultset as an argument.
 
362
 */
 
363
function handleResult(rs, fn) {
 
364
  try {
 
365
    fn(rs);
 
366
  } finally {
 
367
    rs.close();
 
368
  }
 
369
}
 
370
 
 
371
 
 
372
/**
 
373
 * Utility to send an HTTP request.
 
374
 * @param url The url to fetch
 
375
 * @param method The http method (ie. 'GET' or 'POST')
 
376
 * @param data The data to send, may be null
 
377
 * @param callback The function which will be called upon completion of the
 
378
 * request.  If cb_request is true, the callback receives the request object.
 
379
 * Otherwise, the callback receives the contents on a 200 response and null on
 
380
 * any other response.
 
381
 * @param cb_request Controls the argument to callback.
 
382
 */
 
383
function sendHttpRequest(url, method, data, callback, cb_request) {
 
384
  var req = google.gears.factory.create('beta.httprequest');
 
385
 
 
386
  // TODO(aa): We are seeing sporadic failures in these tests. A theory is that
 
387
  // HttpRequest is getting gc'd. Remove this test of that theory when it is
 
388
  // proven or disproven.
 
389
  global.kungFuGrip = req;
 
390
 
 
391
  req.onreadystatechange = function() {
 
392
    if (req.readyState == 4) {
 
393
      if (cb_request) {
 
394
        callback(req);
 
395
      } else if (req.status == 200) {
 
396
        callback(req.responseText);
 
397
      } else {
 
398
        callback(null);
 
399
      }
 
400
    }
 
401
  };
 
402
 
 
403
  req.open(method, url, true);  // async
 
404
  req.send(data);
 
405
}
 
406
 
 
407
/**
 
408
 * Utility to asynchronously get a URL and return the content.
 
409
 * @param url The url to fetch
 
410
 * @param callback Will be called with contents of URL, or null if the request
 
411
 * was unsuccessful.
 
412
 */
 
413
function httpGet(url, callback) {
 
414
  sendHttpRequest(url, 'GET', null, callback, false);
 
415
}
 
416
 
 
417
/**
 
418
 * Utility to asynchronously get a URL and return the request object.
 
419
 * @param url The url to fetch
 
420
 * @param callback Will be called with request object.
 
421
 */
 
422
function httpGetAsRequest(url, callback) {
 
423
  sendHttpRequest(url, 'GET', null, callback, true);
 
424
}
 
425
 
 
426
/**
 
427
 * Utility to asynchronously POST to a URL and return the content.
 
428
 * @param url The url to fetch
 
429
 * @param data The data to post
 
430
 * @param callback Will be called with contents of URL, or null if the request
 
431
 * was unsuccessful.
 
432
 */
 
433
function httpPost(url, data, callback) {
 
434
  sendHttpRequest(url, 'POST', data, callback, false);
 
435
}
 
436
 
 
437
/**
 
438
 * Utility to asynchronously POST to a URL and return the request object.
 
439
 * @param url The url to fetch
 
440
 * @param data The data to post
 
441
 * @param callback Will be called with request object.
 
442
 */
 
443
function httpPostAsRequest(url, callback) {
 
444
  sendHttpRequest(url, 'POST', data, callback, true);
 
445
}
 
446
 
 
447
// cookie functions courtesy ppk: http://www.quirksmode.org/js/cookies.html
 
448
 
 
449
function createTestCookie(name, value, optDays) {
 
450
  if (optDays) {
 
451
    var date = new Date();
 
452
    date.setTime(date.getTime()+(optDays*24*60*60*1000));
 
453
    var expires = "; expires="+date.toGMTString();
 
454
  }
 
455
  else var expires = "";
 
456
  document.cookie = name+"="+value+expires+"; path=/";
 
457
}
 
458
 
 
459
function readTestCookie(name) {
 
460
  var nameEQ = name + "=";
 
461
  var ca = document.cookie.split(';');
 
462
  for(var i=0;i < ca.length;i++) {
 
463
    var c = ca[i];
 
464
    while (c.charAt(0)==' ') c = c.substring(1,c.length);
 
465
    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
 
466
  }
 
467
  return null;
 
468
}
 
469
 
 
470
function eraseTestCookie(name) {
 
471
  createTestCookie(name,"",-1);
 
472
}