diff options
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/testing/mockclock.js')
-rw-r--r-- | contexts/data/lib/closure-library/closure/goog/testing/mockclock.js | 506 |
1 files changed, 0 insertions, 506 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/testing/mockclock.js b/contexts/data/lib/closure-library/closure/goog/testing/mockclock.js deleted file mode 100644 index 5212c12..0000000 --- a/contexts/data/lib/closure-library/closure/goog/testing/mockclock.js +++ /dev/null @@ -1,506 +0,0 @@ -// Copyright 2007 The Closure Library Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS-IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** - * @fileoverview Mock Clock implementation for working with setTimeout, - * setInterval, clearTimeout and clearInterval within unit tests. - * - * Derived from jsUnitMockTimeout.js, contributed to JsUnit by - * Pivotal Computer Systems, www.pivotalsf.com - * - */ - -goog.provide('goog.testing.MockClock'); - -goog.require('goog.Disposable'); -goog.require('goog.testing.PropertyReplacer'); -goog.require('goog.testing.events'); -goog.require('goog.testing.events.Event'); - - - -/** - * Class for unit testing code that uses setTimeout and clearTimeout. - * - * NOTE: If you are using MockClock to test code that makes use of - * goog.fx.Animation, then you must either: - * - * 1. Install and dispose of the MockClock in setUpPage() and tearDownPage() - * respectively (rather than setUp()/tearDown()). - * - * or - * - * 2. Ensure that every test clears the animation queue by calling - * mockClock.tick(x) at the end of each test function (where `x` is large - * enough to complete all animations). - * - * Otherwise, if any animation is left pending at the time that - * MockClock.dispose() is called, that will permanently prevent any future - * animations from playing on the page. - * - * @param {boolean=} opt_autoInstall Install the MockClock at construction time. - * @constructor - * @extends {goog.Disposable} - */ -goog.testing.MockClock = function(opt_autoInstall) { - goog.Disposable.call(this); - - /** - * Reverse-order queue of timers to fire. - * - * The last item of the queue is popped off. Insertion happens from the - * right. For example, the expiration times for each element of the queue - * might be in the order 300, 200, 200. - * - * @type {Array.<Object>} - * @private - */ - this.queue_ = []; - - /** - * Set of timeouts that should be treated as cancelled. - * - * Rather than removing cancelled timers directly from the queue, this set - * simply marks them as deleted so that they can be ignored when their - * turn comes up. The keys are the timeout keys that are cancelled, each - * mapping to true. - * - * @type {Object} - * @private - */ - this.deletedKeys_ = {}; - - if (opt_autoInstall) { - this.install(); - } -}; -goog.inherits(goog.testing.MockClock, goog.Disposable); - - -/** - * Default wait timeout for mocking requestAnimationFrame (in milliseconds). - * - * @type {number} - * @const - */ -goog.testing.MockClock.REQUEST_ANIMATION_FRAME_TIMEOUT = 20; - - -/** - * Count of the number of timeouts made. - * @type {number} - * @private - */ -goog.testing.MockClock.prototype.timeoutsMade_ = 0; - - -/** - * PropertyReplacer instance which overwrites and resets setTimeout, - * setInterval, etc. or null if the MockClock is not installed. - * @type {goog.testing.PropertyReplacer} - * @private - */ -goog.testing.MockClock.prototype.replacer_ = null; - - -/** - * Map of deleted keys. These keys represents keys that were deleted in a - * clearInterval, timeoutid -> object. - * @type {Object} - * @private - */ -goog.testing.MockClock.prototype.deletedKeys_ = null; - - -/** - * The current simulated time in milliseconds. - * @type {number} - * @private - */ -goog.testing.MockClock.prototype.nowMillis_ = 0; - - -/** - * Additional delay between the time a timeout was set to fire, and the time - * it actually fires. Useful for testing workarounds for this Firefox 2 bug: - * https://bugzilla.mozilla.org/show_bug.cgi?id=291386 - * May be negative. - * @type {number} - * @private - */ -goog.testing.MockClock.prototype.timeoutDelay_ = 0; - - -/** - * Installs the MockClock by overriding the global object's implementation of - * setTimeout, setInterval, clearTimeout and clearInterval. - */ -goog.testing.MockClock.prototype.install = function() { - if (!this.replacer_) { - var r = this.replacer_ = new goog.testing.PropertyReplacer(); - r.set(goog.global, 'setTimeout', goog.bind(this.setTimeout_, this)); - r.set(goog.global, 'setInterval', goog.bind(this.setInterval_, this)); - r.set(goog.global, 'clearTimeout', goog.bind(this.clearTimeout_, this)); - r.set(goog.global, 'clearInterval', goog.bind(this.clearInterval_, this)); - - // Replace the requestAnimationFrame functions. - this.replaceRequestAnimationFrame_(); - - // PropertyReplacer#set can't be called with renameable functions. - this.oldGoogNow_ = goog.now; - goog.now = goog.bind(this.getCurrentTime, this); - } -}; - - -/** - * Installs the mocks for requestAnimationFrame and cancelRequestAnimationFrame. - * @private - */ -goog.testing.MockClock.prototype.replaceRequestAnimationFrame_ = function() { - var r = this.replacer_; - var requestFuncs = ['requestAnimationFrame', - 'webkitRequestAnimationFrame', - 'mozRequestAnimationFrame', - 'oRequestAnimationFrame', - 'msRequestAnimationFrame']; - - var cancelFuncs = ['cancelRequestAnimationFrame', - 'webkitCancelRequestAnimationFrame', - 'mozCancelRequestAnimationFrame', - 'oCancelRequestAnimationFrame', - 'msCancelRequestAnimationFrame']; - - for (var i = 0; i < requestFuncs.length; ++i) { - if (goog.global && goog.global[requestFuncs[i]]) { - r.set(goog.global, requestFuncs[i], - goog.bind(this.requestAnimationFrame_, this)); - } - } - - for (var i = 0; i < cancelFuncs.length; ++i) { - if (goog.global && goog.global[cancelFuncs[i]]) { - r.set(goog.global, cancelFuncs[i], - goog.bind(this.cancelRequestAnimationFrame_, this)); - } - } -}; - - -/** - * Removes the MockClock's hooks into the global object's functions and revert - * to their original values. - */ -goog.testing.MockClock.prototype.uninstall = function() { - if (this.replacer_) { - this.replacer_.reset(); - this.replacer_ = null; - goog.now = this.oldGoogNow_; - } -}; - - -/** @override */ -goog.testing.MockClock.prototype.disposeInternal = function() { - this.uninstall(); - this.queue_ = null; - this.deletedKeys_ = null; - goog.testing.MockClock.superClass_.disposeInternal.call(this); -}; - - -/** - * Resets the MockClock, removing all timeouts that are scheduled and resets - * the fake timer count. - */ -goog.testing.MockClock.prototype.reset = function() { - this.queue_ = []; - this.deletedKeys_ = {}; - this.nowMillis_ = 0; - this.timeoutsMade_ = 0; - this.timeoutDelay_ = 0; -}; - - -/** - * Sets the amount of time between when a timeout is scheduled to fire and when - * it actually fires. - * @param {number} delay The delay in milliseconds. May be negative. - */ -goog.testing.MockClock.prototype.setTimeoutDelay = function(delay) { - this.timeoutDelay_ = delay; -}; - - -/** - * @return {number} delay The amount of time between when a timeout is - * scheduled to fire and when it actually fires, in milliseconds. May - * be negative. - */ -goog.testing.MockClock.prototype.getTimeoutDelay = function() { - return this.timeoutDelay_; -}; - - -/** - * Increments the MockClock's time by a given number of milliseconds, running - * any functions that are now overdue. - * @param {number=} opt_millis Number of milliseconds to increment the counter. - * If not specified, clock ticks 1 millisecond. - * @return {number} Current mock time in milliseconds. - */ -goog.testing.MockClock.prototype.tick = function(opt_millis) { - if (typeof opt_millis != 'number') { - opt_millis = 1; - } - var endTime = this.nowMillis_ + opt_millis; - this.runFunctionsWithinRange_(endTime); - this.nowMillis_ = endTime; - return endTime; -}; - - -/** - * @return {number} The number of timeouts that have been scheduled. - */ -goog.testing.MockClock.prototype.getTimeoutsMade = function() { - return this.timeoutsMade_; -}; - - -/** - * @return {number} The MockClock's current time in milliseconds. - */ -goog.testing.MockClock.prototype.getCurrentTime = function() { - return this.nowMillis_; -}; - - -/** - * @param {number} timeoutKey The timeout key. - * @return {boolean} Whether the timer has been set and not cleared, - * independent of the timeout's expiration. In other words, the timeout - * could have passed or could be scheduled for the future. Either way, - * this function returns true or false depending only on whether the - * provided timeoutKey represents a timeout that has been set and not - * cleared. - */ -goog.testing.MockClock.prototype.isTimeoutSet = function(timeoutKey) { - return timeoutKey <= this.timeoutsMade_ && !this.deletedKeys_[timeoutKey]; -}; - - -/** - * Runs any function that is scheduled before a certain time. Timeouts can - * be made to fire early or late if timeoutDelay_ is non-0. - * @param {number} endTime The latest time in the range, in milliseconds. - * @private - */ -goog.testing.MockClock.prototype.runFunctionsWithinRange_ = function( - endTime) { - var adjustedEndTime = endTime - this.timeoutDelay_; - - // Repeatedly pop off the last item since the queue is always sorted. - while (this.queue_.length && - this.queue_[this.queue_.length - 1].runAtMillis <= adjustedEndTime) { - var timeout = this.queue_.pop(); - - if (!(timeout.timeoutKey in this.deletedKeys_)) { - // Only move time forwards. - this.nowMillis_ = Math.max(this.nowMillis_, - timeout.runAtMillis + this.timeoutDelay_); - // Call timeout in global scope and pass the timeout key as the argument. - timeout.funcToCall.call(goog.global, timeout.timeoutKey); - // In case the interval was cleared in the funcToCall - if (timeout.recurring) { - this.scheduleFunction_( - timeout.timeoutKey, timeout.funcToCall, timeout.millis, true); - } - } - } -}; - - -/** - * Schedules a function to be run at a certain time. - * @param {number} timeoutKey The timeout key. - * @param {Function} funcToCall The function to call. - * @param {number} millis The number of milliseconds to call it in. - * @param {boolean} recurring Whether to function call should recur. - * @private - */ -goog.testing.MockClock.prototype.scheduleFunction_ = function( - timeoutKey, funcToCall, millis, recurring) { - var timeout = { - runAtMillis: this.nowMillis_ + millis, - funcToCall: funcToCall, - recurring: recurring, - timeoutKey: timeoutKey, - millis: millis - }; - - goog.testing.MockClock.insert_(timeout, this.queue_); -}; - - -/** - * Inserts a timer descriptor into a descending-order queue. - * - * Later-inserted duplicates appear at lower indices. For example, the - * asterisk in (5,4,*,3,2,1) would be the insertion point for 3. - * - * @param {Object} timeout The timeout to insert, with numerical runAtMillis - * property. - * @param {Array.<Object>} queue The queue to insert into, with each element - * having a numerical runAtMillis property. - * @private - */ -goog.testing.MockClock.insert_ = function(timeout, queue) { - // Although insertion of N items is quadratic, requiring goog.structs.Heap - // from a unit test will make tests more prone to breakage. Since unit - // tests are normally small, scalability is not a primary issue. - - // Find an insertion point. Since the queue is in reverse order (so we - // can pop rather than unshift), and later timers with the same time stamp - // should be executed later, we look for the element strictly greater than - // the one we are inserting. - - for (var i = queue.length; i != 0; i--) { - if (queue[i - 1].runAtMillis > timeout.runAtMillis) { - break; - } - queue[i] = queue[i - 1]; - } - - queue[i] = timeout; -}; - - -/** - * Maximum 32-bit signed integer. - * - * Timeouts over this time return immediately in many browsers, due to integer - * overflow. Such known browsers include Firefox, Chrome, and Safari, but not - * IE. - * - * @type {number} - * @private - */ -goog.testing.MockClock.MAX_INT_ = 2147483647; - - -/** - * Schedules a function to be called after {@code millis} milliseconds. - * Mock implementation for setTimeout. - * @param {Function} funcToCall The function to call. - * @param {number} millis The number of milliseconds to call it after. - * @return {number} The number of timeouts created. - * @private - */ -goog.testing.MockClock.prototype.setTimeout_ = function(funcToCall, millis) { - if (millis > goog.testing.MockClock.MAX_INT_) { - throw Error( - 'Bad timeout value: ' + millis + '. Timeouts over MAX_INT ' + - '(24.8 days) cause timeouts to be fired ' + - 'immediately in most browsers, except for IE.'); - } - this.timeoutsMade_ = this.timeoutsMade_ + 1; - this.scheduleFunction_(this.timeoutsMade_, funcToCall, millis, false); - return this.timeoutsMade_; -}; - - -/** - * Schedules a function to be called every {@code millis} milliseconds. - * Mock implementation for setInterval. - * @param {Function} funcToCall The function to call. - * @param {number} millis The number of milliseconds between calls. - * @return {number} The number of timeouts created. - * @private - */ -goog.testing.MockClock.prototype.setInterval_ = function(funcToCall, millis) { - this.timeoutsMade_ = this.timeoutsMade_ + 1; - this.scheduleFunction_(this.timeoutsMade_, funcToCall, millis, true); - return this.timeoutsMade_; -}; - - -/** - * Schedules a function to be called when an animation frame is triggered. - * Mock implementation for requestAnimationFrame. - * @param {Function} funcToCall The function to call. - * @return {number} The number of timeouts created. - * @private - */ -goog.testing.MockClock.prototype.requestAnimationFrame_ = function(funcToCall) { - return this.setTimeout_(goog.bind(function() { - if (funcToCall) { - funcToCall(this.getCurrentTime()); - } else if (goog.global.mozRequestAnimationFrame) { - var event = new goog.testing.events.Event('MozBeforePaint', goog.global); - event['timeStamp'] = this.getCurrentTime(); - goog.testing.events.fireBrowserEvent(event); - } - }, this), goog.testing.MockClock.REQUEST_ANIMATION_FRAME_TIMEOUT); -}; - - -/** - * Clears a timeout. - * Mock implementation for clearTimeout. - * @param {number} timeoutKey The timeout key to clear. - * @private - */ -goog.testing.MockClock.prototype.clearTimeout_ = function(timeoutKey) { - // Some common libraries register static state with timers. - // This is bad. It leads to all sorts of crazy test problems where - // 1) Test A sets up a new mock clock and a static timer. - // 2) Test B sets up a new mock clock, but re-uses the static timer - // from Test A. - // 3) A timeout key from test A gets cleared, breaking a timeout in - // Test B. - // - // For now, we just hackily fail silently if someone tries to clear a timeout - // key before we've allocated it. - // Ideally, we should throw an exception if we see this happening. - // - // TODO(user): We might also try allocating timeout ids from a global - // pool rather than a local pool. - if (this.isTimeoutSet(timeoutKey)) { - this.deletedKeys_[timeoutKey] = true; - } -}; - - -/** - * Clears an interval. - * Mock implementation for clearInterval. - * @param {number} timeoutKey The interval key to clear. - * @private - */ -goog.testing.MockClock.prototype.clearInterval_ = function(timeoutKey) { - this.clearTimeout_(timeoutKey); -}; - - -/** - * Clears a requestAnimationFrame. - * Mock implementation for cancelRequestAnimationFrame. - * @param {number} timeoutKey The requestAnimationFrame key to clear. - * @private - */ -goog.testing.MockClock.prototype.cancelRequestAnimationFrame_ = - function(timeoutKey) { - this.clearTimeout_(timeoutKey); -}; |