123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631 |
- // 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.
- goog.provide('goog.testing.MockClockTest');
- goog.setTestOnly('goog.testing.MockClockTest');
- goog.require('goog.Promise');
- goog.require('goog.Timer');
- goog.require('goog.events');
- goog.require('goog.functions');
- goog.require('goog.testing.MockClock');
- goog.require('goog.testing.PropertyReplacer');
- goog.require('goog.testing.jsunit');
- goog.require('goog.testing.recordFunction');
- var stubs = new goog.testing.PropertyReplacer();
- function tearDown() {
- stubs.reset();
- }
- function testMockClockWasInstalled() {
- var clock = new goog.testing.MockClock();
- var originalTimeout = window.setTimeout;
- clock.install();
- assertNotEquals(window.setTimeout, originalTimeout);
- setTimeout(function() {}, 100);
- assertEquals(1, clock.getTimeoutsMade());
- setInterval(function() {}, 200);
- assertEquals(2, clock.getTimeoutsMade());
- clock.uninstall();
- assertEquals(window.setTimeout, originalTimeout);
- assertNull(clock.replacer_);
- }
- function testSetTimeoutAndTick() {
- var clock = new goog.testing.MockClock(true);
- var m5 = false, m10 = false, m15 = false, m20 = false;
- setTimeout(function() { m5 = true; }, 5);
- setTimeout(function() { m10 = true; }, 10);
- setTimeout(function() { m15 = true; }, 15);
- setTimeout(function() { m20 = true; }, 20);
- assertEquals(4, clock.getTimeoutsMade());
- assertEquals(4, clock.tick(4));
- assertEquals(4, clock.getCurrentTime());
- assertEquals(0, clock.getCallbacksTriggered());
- assertFalse(m5);
- assertFalse(m10);
- assertFalse(m15);
- assertFalse(m20);
- assertEquals(5, clock.tick(1));
- assertEquals(5, clock.getCurrentTime());
- assertEquals(1, clock.getCallbacksTriggered());
- assertTrue('m5 should now be true', m5);
- assertFalse(m10);
- assertFalse(m15);
- assertFalse(m20);
- assertEquals(10, clock.tick(5));
- assertEquals(10, clock.getCurrentTime());
- assertEquals(2, clock.getCallbacksTriggered());
- assertTrue('m5 should be true', m5);
- assertTrue('m10 should now be true', m10);
- assertFalse(m15);
- assertFalse(m20);
- assertEquals(15, clock.tick(5));
- assertEquals(15, clock.getCurrentTime());
- assertEquals(3, clock.getCallbacksTriggered());
- assertTrue('m5 should be true', m5);
- assertTrue('m10 should be true', m10);
- assertTrue('m15 should now be true', m15);
- assertFalse(m20);
- assertEquals(20, clock.tick(5));
- assertEquals(20, clock.getCurrentTime());
- assertEquals(4, clock.getCallbacksTriggered());
- assertTrue('m5 should be true', m5);
- assertTrue('m10 should be true', m10);
- assertTrue('m15 should be true', m15);
- assertTrue('m20 should now be true', m20);
- clock.uninstall();
- }
- function testSetImmediateAndTick() {
- var clock = new goog.testing.MockClock(true);
- var tick0 = false;
- var tick1 = false;
- setImmediate(function() { tick0 = true; });
- setImmediate(function() { tick1 = true; });
- assertEquals(2, clock.getTimeoutsMade());
- assertEquals(0, clock.getCallbacksTriggered());
- clock.tick(0);
- assertEquals(2, clock.getCallbacksTriggered());
- assertTrue(tick0);
- assertTrue(tick1);
- clock.uninstall();
- }
- function testSetInterval() {
- var clock = new goog.testing.MockClock(true);
- var times = 0;
- setInterval(function() { times++; }, 100);
- clock.tick(500);
- assertEquals(5, clock.getCallbacksTriggered());
- assertEquals(5, times);
- clock.tick(100);
- assertEquals(6, clock.getCallbacksTriggered());
- assertEquals(6, times);
- clock.tick(100);
- assertEquals(7, clock.getCallbacksTriggered());
- assertEquals(7, times);
- clock.tick(50);
- assertEquals(7, clock.getCallbacksTriggered());
- assertEquals(7, times);
- clock.tick(50);
- assertEquals(8, clock.getCallbacksTriggered());
- assertEquals(8, times);
- clock.uninstall();
- }
- function testRequestAnimationFrame() {
- goog.global.requestAnimationFrame = function() {};
- var clock = new goog.testing.MockClock(true);
- var times = [];
- var recFunc = goog.testing.recordFunction(function(now) { times.push(now); });
- goog.global.requestAnimationFrame(recFunc);
- clock.tick(50);
- assertEquals(1, clock.getCallbacksTriggered());
- assertEquals(1, recFunc.getCallCount());
- assertEquals(20, times[0]);
- goog.global.requestAnimationFrame(recFunc);
- clock.tick(100);
- assertEquals(2, clock.getCallbacksTriggered());
- assertEquals(2, recFunc.getCallCount());
- assertEquals(70, times[1]);
- clock.uninstall();
- }
- function testClearTimeout() {
- var clock = new goog.testing.MockClock(true);
- var ran = false;
- var c = setTimeout(function() { ran = true; }, 100);
- clock.tick(50);
- assertFalse(ran);
- clearTimeout(c);
- clock.tick(100);
- assertFalse(ran);
- clock.uninstall();
- }
- function testClearInterval() {
- var clock = new goog.testing.MockClock(true);
- var times = 0;
- var c = setInterval(function() { times++; }, 100);
- clock.tick(500);
- assertEquals(5, times);
- clock.tick(100);
- assertEquals(6, times);
- clock.tick(100);
- clearInterval(c);
- assertEquals(7, times);
- clock.tick(50);
- assertEquals(7, times);
- clock.tick(50);
- assertEquals(7, times);
- clock.uninstall();
- }
- function testClearInterval2() {
- // Tests that we can clear the interval from inside the function
- var clock = new goog.testing.MockClock(true);
- var times = 0;
- var c = setInterval(function() {
- times++;
- if (times == 6) {
- clearInterval(c);
- }
- }, 100);
- clock.tick(500);
- assertEquals(5, times);
- clock.tick(100);
- assertEquals(6, times);
- clock.tick(100);
- assertEquals(6, times);
- clock.tick(50);
- assertEquals(6, times);
- clock.tick(50);
- assertEquals(6, times);
- clock.uninstall();
- }
- function testCancelRequestAnimationFrame() {
- goog.global.requestAnimationFrame = function() {};
- goog.global.cancelRequestAnimationFrame = function() {};
- var clock = new goog.testing.MockClock(true);
- var ran = false;
- var c = goog.global.requestAnimationFrame(function() { ran = true; });
- clock.tick(10);
- assertFalse(ran);
- goog.global.cancelRequestAnimationFrame(c);
- clock.tick(20);
- assertFalse(ran);
- clock.uninstall();
- }
- function testMockGoogNow() {
- assertNotEquals(0, goog.now());
- var clock = new goog.testing.MockClock(true);
- assertEquals(0, goog.now());
- clock.tick(50);
- assertEquals(50, goog.now());
- clock.uninstall();
- assertNotEquals(50, goog.now());
- }
- function testTimeoutDelay() {
- var clock = new goog.testing.MockClock(true);
- var m5 = false, m10 = false, m20 = false;
- setTimeout(function() { m5 = true; }, 5);
- setTimeout(function() { m10 = true; }, 10);
- setTimeout(function() { m20 = true; }, 20);
- // Fire 3ms early, so m5 fires at t=2
- clock.setTimeoutDelay(-3);
- clock.tick(1);
- assertFalse(m5);
- assertFalse(m10);
- clock.tick(1);
- assertTrue(m5);
- assertFalse(m10);
- // Fire 3ms late, so m10 fires at t=13
- clock.setTimeoutDelay(3);
- assertEquals(12, clock.tick(10));
- assertEquals(12, clock.getCurrentTime());
- assertFalse(m10);
- clock.tick(1);
- assertTrue(m10);
- assertFalse(m20);
- // Fire 10ms early, so m20 fires now, since it's after t=10
- clock.setTimeoutDelay(-10);
- assertFalse(m20);
- assertEquals(14, clock.tick(1));
- assertEquals(14, clock.getCurrentTime());
- assertTrue(m20);
- clock.uninstall();
- }
- function testTimerCallbackCanCreateIntermediateTimer() {
- var clock = new goog.testing.MockClock(true);
- var sequence = [];
- // Create 3 timers: 1, 2, and 3. Timer 1 should fire at T=1, timer 2 at
- // T=2, and timer 3 at T=3. The catch: Timer 2 is created by the
- // callback within timer 0.
- // Testing method: Create a simple string sequencing each timer and at
- // what time it fired.
- setTimeout(function() {
- sequence.push('timer1 at T=' + goog.now());
- setTimeout(function() { sequence.push('timer2 at T=' + goog.now()); }, 1);
- }, 1);
- setTimeout(function() { sequence.push('timer3 at T=' + goog.now()); }, 3);
- clock.tick(4);
- assertEquals(
- 'Each timer should fire in sequence at the correct time.',
- 'timer1 at T=1, timer2 at T=2, timer3 at T=3', sequence.join(', '));
- clock.uninstall();
- }
- function testCorrectArgumentsPassedToCallback() {
- var clock = new goog.testing.MockClock(true);
- var timeoutId;
- var timeoutExecuted = false;
- timeoutId = setTimeout(function(arg) {
- assertEquals('"this" must be goog.global', goog.global, this);
- assertEquals('The timeout ID must be the first parameter', timeoutId, arg);
- assertEquals('Exactly one argument must be passed', 1, arguments.length);
- timeoutExecuted = true;
- }, 1);
- clock.tick(4);
- assertTrue('The timeout was not executed', timeoutExecuted);
- clock.uninstall();
- }
- function testTickZero() {
- var clock = new goog.testing.MockClock(true);
- var calls = 0;
- setTimeout(function() {
- assertEquals('I need to be first', 0, calls);
- calls++;
- }, 0);
- setTimeout(function() {
- assertEquals('I need to be second', 1, calls);
- calls++;
- }, 0);
- clock.tick(0);
- assertEquals(2, calls);
- setTimeout(function() {
- assertEquals('I need to be third', 2, calls);
- calls++;
- }, 0);
- clock.tick(0);
- assertEquals(3, calls);
- assertEquals('Time should still be zero', 0, goog.now());
- clock.uninstall();
- }
- function testReset() {
- var clock = new goog.testing.MockClock(true);
- var id = setTimeout(function() {
- fail('Timeouts should be cleared after a reset');
- }, 0);
- clock.reset();
- clock.tick(999999);
- var calls = 0;
- setTimeout(function() { calls++; }, 10);
- clearTimeout(id);
- clock.tick(100);
- assertEquals(
- 'New timeout should still run after clearing from before reset', 1,
- calls);
- clock.uninstall();
- }
- function testNewClockWithOldTimeoutId() {
- var clock = new goog.testing.MockClock(true);
- var id = setTimeout(function() {
- fail('Timeouts should be cleared after uninstall');
- }, 0);
- clock.uninstall();
- clock = new goog.testing.MockClock(true);
- var calls = 0;
- setTimeout(function() { calls++; }, 10);
- clearTimeout(id);
- clock.tick(100);
- assertEquals(
- 'Timeout should still run after cancelling from old clock', 1, calls);
- clock.uninstall();
- }
- function testQueueInsertionHelper() {
- var queue = [];
- function queueToString() {
- var buffer = [];
- for (var i = 0; i < queue.length; i++) {
- buffer.push(queue[i].runAtMillis);
- }
- return buffer.join(',');
- }
- goog.testing.MockClock.insert_({runAtMillis: 2}, queue);
- assertEquals('Only item', '2', queueToString());
- goog.testing.MockClock.insert_({runAtMillis: 4}, queue);
- assertEquals('Biggest item', '4,2', queueToString());
- goog.testing.MockClock.insert_({runAtMillis: 5}, queue);
- assertEquals('An even bigger item', '5,4,2', queueToString());
- goog.testing.MockClock.insert_({runAtMillis: 1}, queue);
- assertEquals('Smallest item', '5,4,2,1', queueToString());
- goog.testing.MockClock.insert_({runAtMillis: 1, dup: true}, queue);
- assertEquals('Duplicate smallest item', '5,4,2,1,1', queueToString());
- assertTrue('Duplicate item comes at a smaller index', queue[3].dup);
- goog.testing.MockClock.insert_({runAtMillis: 3}, queue);
- goog.testing.MockClock.insert_({runAtMillis: 3, dup: true}, queue);
- assertEquals('Duplicate a middle item', '5,4,3,3,2,1,1', queueToString());
- assertTrue('Duplicate item comes at a smaller index', queue[2].dup);
- }
- function testIsTimeoutSet() {
- var clock = new goog.testing.MockClock(true);
- var timeoutKey = setTimeout(function() {}, 1);
- assertTrue(
- 'Timeout ' + timeoutKey + ' should be set',
- clock.isTimeoutSet(timeoutKey));
- var nextTimeoutKey = timeoutKey + 1;
- assertFalse(
- 'Timeout ' + nextTimeoutKey + ' should not be set',
- clock.isTimeoutSet(nextTimeoutKey));
- clearTimeout(timeoutKey);
- assertFalse(
- 'Timeout ' + timeoutKey + ' should no longer be set',
- clock.isTimeoutSet(timeoutKey));
- var newTimeoutKey = setTimeout(function() {}, 1);
- clock.tick(5);
- assertFalse(
- 'Timeout ' + timeoutKey + ' should not be set',
- clock.isTimeoutSet(timeoutKey));
- assertTrue(
- 'Timeout ' + newTimeoutKey + ' should be set',
- clock.isTimeoutSet(newTimeoutKey));
- clock.uninstall();
- }
- function testBalksOnTimeoutsGreaterThanMaxInt() {
- // Browsers have trouble with timeout greater than max int, so we
- // want Mock Clock to fail if this happens.
- var clock = new goog.testing.MockClock(true);
- // Functions on window don't seem to be able to throw exceptions in
- // IE6. Explicitly reading the property makes it work.
- var setTimeout = window.setTimeout;
- assertThrows('Timeouts > MAX_INT should fail', function() {
- setTimeout(goog.nullFunction, 2147483648);
- });
- assertThrows('Timeouts much greater than MAX_INT should fail', function() {
- setTimeout(goog.nullFunction, 2147483648 * 10);
- });
- clock.uninstall();
- }
- function testCorrectSetTimeoutIsRestored() {
- var safe = goog.functions.error('should not have been called');
- stubs.set(window, 'setTimeout', safe);
- var clock = new goog.testing.MockClock(true);
- assertNotEquals('setTimeout is replaced', safe, window.setTimeout);
- clock.uninstall();
- // NOTE: If this assertion proves to be flaky in IE, the string value of
- // the two functions have to be compared as described in
- // goog.testing.TestCase#finalize.
- assertEquals('setTimeout is restored', safe, window.setTimeout);
- }
- function testMozRequestAnimationFrame() {
- // Setting this function will indirectly tell the mock clock to mock it out.
- stubs.set(window, 'mozRequestAnimationFrame', goog.nullFunction);
- var clock = new goog.testing.MockClock(true);
- var mozBeforePaint = goog.testing.recordFunction();
- goog.events.listen(window, 'MozBeforePaint', mozBeforePaint);
- window.mozRequestAnimationFrame(null);
- assertEquals(0, mozBeforePaint.getCallCount());
- clock.tick(goog.testing.MockClock.REQUEST_ANIMATION_FRAME_TIMEOUT);
- assertEquals(1, mozBeforePaint.getCallCount());
- clock.dispose();
- }
- function testClearBeforeSet() {
- var clock = new goog.testing.MockClock(true);
- var expectedId = goog.testing.MockClock.nextId;
- window.clearTimeout(expectedId);
- var fn = goog.testing.recordFunction();
- var actualId = window.setTimeout(fn, 0);
- assertEquals(
- 'In order for this test to work, we have to guess the ids in advance',
- expectedId, actualId);
- clock.tick(1);
- assertEquals(1, fn.getCallCount());
- clock.dispose();
- }
- function testNonFunctionArguments() {
- var clock = new goog.testing.MockClock(true);
- // Unlike normal setTimeout and friends, we only accept functions (not
- // strings, not undefined, etc). Make sure that if we get a non-function, we
- // fail early rather than on the next .tick() operation.
- assertThrows('setTimeout with a non-function value should fail', function() {
- window.setTimeout(undefined, 0);
- });
- clock.tick(1);
- assertThrows('setTimeout with a string should fail', function() {
- window.setTimeout('throw new Error("setTimeout string eval!");', 0);
- });
- clock.tick(1);
- clock.dispose();
- }
- function testUnspecifiedTimeout() {
- var clock = new goog.testing.MockClock(true);
- var m0a = false, m0b = false, m10 = false;
- setTimeout(function() { m0a = true; });
- setTimeout(function() { m10 = true; }, 10);
- assertEquals(2, clock.getTimeoutsMade());
- assertFalse(m0a);
- assertFalse(m0b);
- assertFalse(m10);
- assertEquals(0, clock.tick(0));
- assertEquals(0, clock.getCurrentTime());
- assertTrue(m0a);
- assertFalse(m0b);
- assertFalse(m10);
- setTimeout(function() { m0b = true; });
- assertEquals(3, clock.getTimeoutsMade());
- assertEquals(0, clock.tick(0));
- assertEquals(0, clock.getCurrentTime());
- assertTrue(m0a);
- assertTrue(m0b);
- assertFalse(m10);
- assertEquals(10, clock.tick(10));
- assertEquals(10, clock.getCurrentTime());
- assertTrue(m0a);
- assertTrue(m0b);
- assertTrue(m10);
- clock.uninstall();
- }
- function testUnspecifiedInterval() {
- var clock = new goog.testing.MockClock(true);
- var times = 0;
- var handle = setInterval(function() {
- if (++times >= 5) {
- clearInterval(handle);
- }
- });
- clock.tick(0);
- assertEquals(5, times);
- clock.uninstall();
- }
- function testTickPromise() {
- var clock = new goog.testing.MockClock(true);
- var p = goog.Promise.resolve('foo');
- assertEquals('foo', clock.tickPromise(p));
- var rejected = goog.Promise.reject(new Error('failed'));
- var e = assertThrows(function() { clock.tickPromise(rejected); });
- assertEquals('failed', e.message);
- var delayed = goog.Timer.promise(500, 'delayed');
- e = assertThrows(function() { clock.tickPromise(delayed); });
- assertEquals(
- 'Promise was expected to be resolved after mock clock tick.', e.message);
- assertEquals('delayed', clock.tickPromise(delayed, 500));
- clock.dispose();
- }
|