1 <!DOCTYPE html> 2 <!-- 3 Copyright (c) 2014 The Chromium Authors. All rights reserved. 4 Use of this source code is governed by a BSD-style license that can be 5 found in the LICENSE file. 6 --> 7 <link rel="import" href="/tracing/base/raf.html"> 8 <script> 9 'use strict'; 10 11 tr.b.unittest.testSuite(function() { 12 if (tr.isHeadless) 13 return; 14 15 test('idleCallbackWorks', function() { 16 return new Promise(function(resolve, reject) { 17 tr.b.requestIdleCallback(resolve); 18 }); 19 }); 20 21 test('forceAllPendingTasksToRunForTest', function() { 22 var rafRan = false; 23 tr.b.requestAnimationFrame(function() { 24 rafRan = true; 25 }); 26 var idleRan = false; 27 tr.b.requestIdleCallback(function() { 28 idleRan = true; 29 }); 30 assert.isFalse(rafRan); 31 assert.isFalse(idleRan); 32 tr.b.forceAllPendingTasksToRunForTest(); 33 assert.isTrue(rafRan); 34 assert.isTrue(idleRan); 35 }); 36 37 test('forcePendingRAFTasksToRun', function() { 38 var rafRan = false; 39 tr.b.requestAnimationFrame(function() { 40 rafRan = true; 41 }); 42 var idleRan = false; 43 tr.b.requestIdleCallback(function() { 44 idleRan = true; 45 }); 46 tr.b.forcePendingRAFTasksToRun(); 47 assert.isTrue(rafRan); 48 assert.isFalse(idleRan); 49 }); 50 51 var fakeNow = undefined; 52 function withFakeWindowPerformanceNow(func) { 53 var oldNow = window.performance.now; 54 try { 55 window.performance.now = function() { return fakeNow; }; 56 func(); 57 } finally { 58 window.performance.now = oldNow; 59 } 60 } 61 62 // None of the following tests are relevant if the browser supports idle 63 // callbacks natively. Nevertheless, run them without native idle support to 64 // make sure the fallback keeps working. 65 function withoutNativeIdleCallbacks(func) { 66 var oldRIC = window.requestIdleCallback; 67 try { 68 window.requestIdleCallback = undefined; 69 func(); 70 } finally { 71 window.requestIdleCallback = oldRIC; 72 } 73 } 74 75 function withMockedScheduling(func) { 76 withFakeWindowPerformanceNow(function() { 77 withoutNativeIdleCallbacks(func); 78 }); 79 } 80 81 test('runIdleTaskWhileIdle', function() { 82 withMockedScheduling(function() { 83 tr.b.forceAllPendingTasksToRunForTest(); 84 85 var rafRan = false; 86 tr.b.requestAnimationFrame(function() { 87 rafRan = true; 88 }); 89 var idleRan = false; 90 tr.b.requestIdleCallback(function() { 91 idleRan = true; 92 }); 93 fakeNow = 0; 94 tr.b.forcePendingRAFTasksToRun(fakeNow); 95 assert.isFalse(idleRan); 96 assert.isTrue(rafRan); 97 tr.b.forcePendingRAFTasksToRun(fakeNow); 98 assert.isTrue(idleRan); 99 }); 100 }); 101 102 test('twoShortIdleCallbacks', function() { 103 withMockedScheduling(function() { 104 tr.b.forceAllPendingTasksToRunForTest(); 105 106 var idle1Ran = false; 107 var idle2Ran = false; 108 tr.b.requestIdleCallback(function() { 109 fakeNow += 1; 110 idle1Ran = true; 111 }); 112 tr.b.requestIdleCallback(function() { 113 fakeNow += 1; 114 idle2Ran = true; 115 }); 116 fakeNow = 0; 117 tr.b.forcePendingRAFTasksToRun(fakeNow); 118 assert.isTrue(idle1Ran); 119 assert.isTrue(idle2Ran); 120 }); 121 }); 122 123 124 test('oneLongOneShortIdleCallback', function() { 125 withMockedScheduling(function() { 126 tr.b.forceAllPendingTasksToRunForTest(); 127 128 var idle1Ran = false; 129 var idle2Ran = false; 130 tr.b.requestIdleCallback(function() { 131 fakeNow += 100; 132 idle1Ran = true; 133 }); 134 tr.b.requestIdleCallback(function() { 135 fakeNow += 1; 136 idle2Ran = true; 137 }); 138 fakeNow = 0; 139 tr.b.forcePendingRAFTasksToRun(fakeNow); 140 assert.isTrue(idle1Ran); 141 assert.isFalse(idle2Ran); 142 143 // Reset idle1Ran to verify that it dosn't run again. 144 idle1Ran = false; 145 146 // Now run. idle2 should now run. 147 tr.b.forcePendingRAFTasksToRun(fakeNow); 148 assert.isFalse(idle1Ran); 149 assert.isTrue(idle2Ran); 150 }); 151 }); 152 153 test('buggyPerformanceNowDoesNotBlockIdleTasks', function() { 154 withMockedScheduling(function() { 155 tr.b.forcePendingRAFTasksToRun(); // Clear current RAF task queue. 156 157 var idle1Ran = false; 158 var idle2Ran = false; 159 tr.b.requestIdleCallback(function() { 160 fakeNow += 100; 161 idle1Ran = true; 162 }); 163 tr.b.requestIdleCallback(function() { 164 fakeNow += 1; 165 idle2Ran = true; 166 }); 167 fakeNow = 10000; 168 tr.b.forcePendingRAFTasksToRun(0); 169 assert.isTrue(idle1Ran); 170 assert.isFalse(idle2Ran); 171 172 // Reset idle1Ran to verify that it dosn't run again. 173 idle1Ran = false; 174 175 // Now run. idle2 should now run. 176 tr.b.forcePendingRAFTasksToRun(0); 177 assert.isFalse(idle1Ran); 178 assert.isTrue(idle2Ran); 179 }); 180 }); 181 182 function withFixedIdleTimeRemaining(idleTime, func) { 183 var oldRIC = window.requestIdleCallback; 184 try { 185 var pendingIdleCallbacks = []; 186 window.requestIdleCallback = function(callback) { 187 var deadline = { 188 timeRemaining: function() { 189 return idleTime; 190 } 191 }; 192 pendingIdleCallbacks.push(function() { 193 callback(deadline, false /* didTimeout */); 194 }); 195 }; 196 func(pendingIdleCallbacks); 197 } finally { 198 window.requestIdleCallback = oldRIC; 199 } 200 } 201 202 test('idleCallbackWithIdletime', function() { 203 withFixedIdleTimeRemaining(1000, function(pendingIdleCallbacks) { 204 var idle1Ran = false; 205 var idle2Ran = false; 206 tr.b.requestIdleCallback(function() { 207 idle1Ran = true; 208 }); 209 tr.b.requestIdleCallback(function() { 210 idle2Ran = true; 211 }); 212 assert.lengthOf(pendingIdleCallbacks, 1); 213 pendingIdleCallbacks.shift()(); 214 215 // Both callbacks should have run since there was idle time. 216 assert.isTrue(idle1Ran); 217 assert.isTrue(idle2Ran); 218 }); 219 }); 220 221 test('idleCallbackWithoutIdletime', function() { 222 withFixedIdleTimeRemaining(0, function(pendingIdleCallbacks) { 223 var idle1Ran = false; 224 var idle2Ran = false; 225 tr.b.requestIdleCallback(function() { 226 idle1Ran = true; 227 }); 228 tr.b.requestIdleCallback(function() { 229 idle2Ran = true; 230 }); 231 assert.lengthOf(pendingIdleCallbacks, 1); 232 pendingIdleCallbacks.shift()(); 233 234 // Only the first idle callback should have run since there was no idle 235 // time left. 236 assert.isTrue(idle1Ran); 237 assert.isFalse(idle2Ran); 238 239 // Run the remaining idle task. 240 assert.lengthOf(pendingIdleCallbacks, 1); 241 pendingIdleCallbacks.shift()(); 242 assert.isTrue(idle2Ran); 243 }); 244 }); 245 246 }); 247 </script> 248