| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |  | 
| 2 // Use of this source code is governed by a BSD-style license that can be |  | 
| 3 // found in the LICENSE file. |  | 
| 4 |  | 
| 5 // test_custom_bindings.js |  | 
| 6 // mini-framework for ExtensionApiTest browser tests |  | 
| 7 |  | 
| 8 var binding = require('binding').Binding.create('test'); |  | 
| 9 |  | 
| 10 var chrome = requireNative('chrome').GetChrome(); |  | 
| 11 var GetExtensionAPIDefinitionsForTest = |  | 
| 12     requireNative('apiDefinitions').GetExtensionAPIDefinitionsForTest; |  | 
| 13 var GetAvailability = requireNative('v8_context').GetAvailability; |  | 
| 14 var GetAPIFeatures = requireNative('test_features').GetAPIFeatures; |  | 
| 15 var uncaughtExceptionHandler = require('uncaught_exception_handler'); |  | 
| 16 var userGestures = requireNative('user_gestures'); |  | 
| 17 |  | 
| 18 binding.registerCustomHook(function(api) { |  | 
| 19   var chromeTest = api.compiledApi; |  | 
| 20   var apiFunctions = api.apiFunctions; |  | 
| 21 |  | 
| 22   chromeTest.tests = chromeTest.tests || []; |  | 
| 23 |  | 
| 24   var currentTest = null; |  | 
| 25   var lastTest = null; |  | 
| 26   var testsFailed = 0; |  | 
| 27   var testCount = 1; |  | 
| 28   var failureException = 'chrome.test.failure'; |  | 
| 29 |  | 
| 30   // Helper function to get around the fact that function names in javascript |  | 
| 31   // are read-only, and you can't assign one to anonymous functions. |  | 
| 32   function testName(test) { |  | 
| 33     return test ? (test.name || test.generatedName) : "(no test)"; |  | 
| 34   } |  | 
| 35 |  | 
| 36   function testDone() { |  | 
| 37     // Use setTimeout here to allow previous test contexts to be |  | 
| 38     // eligible for garbage collection. |  | 
| 39     setTimeout(chromeTest.runNextTest, 0); |  | 
| 40   } |  | 
| 41 |  | 
| 42   function allTestsDone() { |  | 
| 43     if (testsFailed == 0) { |  | 
| 44       chromeTest.notifyPass(); |  | 
| 45     } else { |  | 
| 46       chromeTest.notifyFail('Failed ' + testsFailed + ' of ' + |  | 
| 47                              testCount + ' tests'); |  | 
| 48     } |  | 
| 49   } |  | 
| 50 |  | 
| 51   var pendingCallbacks = 0; |  | 
| 52 |  | 
| 53   apiFunctions.setHandleRequest('callbackAdded', function() { |  | 
| 54     pendingCallbacks++; |  | 
| 55 |  | 
| 56     var called = null; |  | 
| 57     return function() { |  | 
| 58       if (called != null) { |  | 
| 59         var redundantPrefix = 'Error\n'; |  | 
| 60         chrome.test.fail( |  | 
| 61           'Callback has already been run. ' + |  | 
| 62           'First call:\n' + |  | 
| 63           $String.slice(called, redundantPrefix.length) + '\n' + |  | 
| 64           'Second call:\n' + |  | 
| 65           $String.slice(new Error().stack, redundantPrefix.length)); |  | 
| 66       } |  | 
| 67       called = new Error().stack; |  | 
| 68 |  | 
| 69       pendingCallbacks--; |  | 
| 70       if (pendingCallbacks == 0) { |  | 
| 71         chromeTest.succeed(); |  | 
| 72       } |  | 
| 73     }; |  | 
| 74   }); |  | 
| 75 |  | 
| 76   apiFunctions.setHandleRequest('runNextTest', function() { |  | 
| 77     // There may have been callbacks which were interrupted by failure |  | 
| 78     // exceptions. |  | 
| 79     pendingCallbacks = 0; |  | 
| 80 |  | 
| 81     lastTest = currentTest; |  | 
| 82     currentTest = chromeTest.tests.shift(); |  | 
| 83 |  | 
| 84     if (!currentTest) { |  | 
| 85       allTestsDone(); |  | 
| 86       return; |  | 
| 87     } |  | 
| 88 |  | 
| 89     try { |  | 
| 90       chromeTest.log("( RUN      ) " + testName(currentTest)); |  | 
| 91       uncaughtExceptionHandler.setHandler(function(message, e) { |  | 
| 92         if (e !== failureException) |  | 
| 93           chromeTest.fail('uncaught exception: ' + message); |  | 
| 94       }); |  | 
| 95       currentTest.call(); |  | 
| 96     } catch (e) { |  | 
| 97       uncaughtExceptionHandler.handle(e.message, e); |  | 
| 98     } |  | 
| 99   }); |  | 
| 100 |  | 
| 101   apiFunctions.setHandleRequest('fail', function(message) { |  | 
| 102     chromeTest.log("(  FAILED  ) " + testName(currentTest)); |  | 
| 103 |  | 
| 104     var stack = {}; |  | 
| 105     Error.captureStackTrace(stack, chromeTest.fail); |  | 
| 106 |  | 
| 107     if (!message) |  | 
| 108       message = "FAIL (no message)"; |  | 
| 109 |  | 
| 110     message += "\n" + stack.stack; |  | 
| 111     console.log("[FAIL] " + testName(currentTest) + ": " + message); |  | 
| 112     testsFailed++; |  | 
| 113     testDone(); |  | 
| 114 |  | 
| 115     // Interrupt the rest of the test. |  | 
| 116     throw failureException; |  | 
| 117   }); |  | 
| 118 |  | 
| 119   apiFunctions.setHandleRequest('succeed', function() { |  | 
| 120     console.log("[SUCCESS] " + testName(currentTest)); |  | 
| 121     chromeTest.log("(  SUCCESS )"); |  | 
| 122     testDone(); |  | 
| 123   }); |  | 
| 124 |  | 
| 125   apiFunctions.setHandleRequest('assertTrue', function(test, message) { |  | 
| 126     chromeTest.assertBool(test, true, message); |  | 
| 127   }); |  | 
| 128 |  | 
| 129   apiFunctions.setHandleRequest('assertFalse', function(test, message) { |  | 
| 130     chromeTest.assertBool(test, false, message); |  | 
| 131   }); |  | 
| 132 |  | 
| 133   apiFunctions.setHandleRequest('assertBool', |  | 
| 134                                 function(test, expected, message) { |  | 
| 135     if (test !== expected) { |  | 
| 136       if (typeof(test) == "string") { |  | 
| 137         if (message) |  | 
| 138           message = test + "\n" + message; |  | 
| 139         else |  | 
| 140           message = test; |  | 
| 141       } |  | 
| 142       chromeTest.fail(message); |  | 
| 143     } |  | 
| 144   }); |  | 
| 145 |  | 
| 146   apiFunctions.setHandleRequest('checkDeepEq', function(expected, actual) { |  | 
| 147     if ((expected === null) != (actual === null)) |  | 
| 148       return false; |  | 
| 149 |  | 
| 150     if (expected === actual) |  | 
| 151       return true; |  | 
| 152 |  | 
| 153     if (typeof(expected) !== typeof(actual)) |  | 
| 154       return false; |  | 
| 155 |  | 
| 156     for (var p in actual) { |  | 
| 157       if ($Object.hasOwnProperty(actual, p) && |  | 
| 158           !$Object.hasOwnProperty(expected, p)) { |  | 
| 159         return false; |  | 
| 160       } |  | 
| 161     } |  | 
| 162     for (var p in expected) { |  | 
| 163       if ($Object.hasOwnProperty(expected, p) && |  | 
| 164           !$Object.hasOwnProperty(actual, p)) { |  | 
| 165         return false; |  | 
| 166       } |  | 
| 167     } |  | 
| 168 |  | 
| 169     for (var p in expected) { |  | 
| 170       var eq = true; |  | 
| 171       switch (typeof(expected[p])) { |  | 
| 172         case 'object': |  | 
| 173           eq = chromeTest.checkDeepEq(expected[p], actual[p]); |  | 
| 174           break; |  | 
| 175         case 'function': |  | 
| 176           eq = (typeof(actual[p]) != 'undefined' && |  | 
| 177                 expected[p].toString() == actual[p].toString()); |  | 
| 178           break; |  | 
| 179         default: |  | 
| 180           eq = (expected[p] == actual[p] && |  | 
| 181                 typeof(expected[p]) == typeof(actual[p])); |  | 
| 182           break; |  | 
| 183       } |  | 
| 184       if (!eq) |  | 
| 185         return false; |  | 
| 186     } |  | 
| 187     return true; |  | 
| 188   }); |  | 
| 189 |  | 
| 190   apiFunctions.setHandleRequest('assertEq', |  | 
| 191                                 function(expected, actual, message) { |  | 
| 192     var error_msg = "API Test Error in " + testName(currentTest); |  | 
| 193     if (message) |  | 
| 194       error_msg += ": " + message; |  | 
| 195     if (typeof(expected) == 'object') { |  | 
| 196       if (!chromeTest.checkDeepEq(expected, actual)) { |  | 
| 197         // Note: these JSON.stringify calls may fail in tests that explicitly |  | 
| 198         // override JSON.stringfy, so surround in try-catch. |  | 
| 199         try { |  | 
| 200           error_msg += "\nActual: " + JSON.stringify(actual) + |  | 
| 201                        "\nExpected: " + JSON.stringify(expected); |  | 
| 202         } catch (e) {} |  | 
| 203         chromeTest.fail(error_msg); |  | 
| 204       } |  | 
| 205       return; |  | 
| 206     } |  | 
| 207     if (expected != actual) { |  | 
| 208       chromeTest.fail(error_msg + |  | 
| 209                        "\nActual: " + actual + "\nExpected: " + expected); |  | 
| 210     } |  | 
| 211     if (typeof(expected) != typeof(actual)) { |  | 
| 212       chromeTest.fail(error_msg + |  | 
| 213                        " (type mismatch)\nActual Type: " + typeof(actual) + |  | 
| 214                        "\nExpected Type:" + typeof(expected)); |  | 
| 215     } |  | 
| 216   }); |  | 
| 217 |  | 
| 218   apiFunctions.setHandleRequest('assertNoLastError', function() { |  | 
| 219     if (chrome.runtime.lastError != undefined) { |  | 
| 220       chromeTest.fail("lastError.message == " + |  | 
| 221                        chrome.runtime.lastError.message); |  | 
| 222     } |  | 
| 223   }); |  | 
| 224 |  | 
| 225   apiFunctions.setHandleRequest('assertLastError', function(expectedError) { |  | 
| 226     chromeTest.assertEq(typeof(expectedError), 'string'); |  | 
| 227     chromeTest.assertTrue(chrome.runtime.lastError != undefined, |  | 
| 228         "No lastError, but expected " + expectedError); |  | 
| 229     chromeTest.assertEq(expectedError, chrome.runtime.lastError.message); |  | 
| 230   }); |  | 
| 231 |  | 
| 232   apiFunctions.setHandleRequest('assertThrows', |  | 
| 233                                 function(fn, self, args, message) { |  | 
| 234     chromeTest.assertTrue(typeof fn == 'function'); |  | 
| 235     try { |  | 
| 236       fn.apply(self, args); |  | 
| 237       chromeTest.fail('Did not throw error: ' + fn); |  | 
| 238     } catch (e) { |  | 
| 239       if (e != failureException && message !== undefined) { |  | 
| 240         if (message instanceof RegExp) { |  | 
| 241           chromeTest.assertTrue(message.test(e.message), |  | 
| 242                                 e.message + ' should match ' + message) |  | 
| 243         } else { |  | 
| 244           chromeTest.assertEq(message, e.message); |  | 
| 245         } |  | 
| 246       } |  | 
| 247     } |  | 
| 248   }); |  | 
| 249 |  | 
| 250   function safeFunctionApply(func, args) { |  | 
| 251     try { |  | 
| 252       if (func) |  | 
| 253         return $Function.apply(func, undefined, args); |  | 
| 254     } catch (e) { |  | 
| 255       var msg = "uncaught exception " + e; |  | 
| 256       chromeTest.fail(msg); |  | 
| 257     } |  | 
| 258   }; |  | 
| 259 |  | 
| 260   // Wrapper for generating test functions, that takes care of calling |  | 
| 261   // assertNoLastError() and (optionally) succeed() for you. |  | 
| 262   apiFunctions.setHandleRequest('callback', function(func, expectedError) { |  | 
| 263     if (func) { |  | 
| 264       chromeTest.assertEq(typeof(func), 'function'); |  | 
| 265     } |  | 
| 266     var callbackCompleted = chromeTest.callbackAdded(); |  | 
| 267 |  | 
| 268     return function() { |  | 
| 269       if (expectedError == null) { |  | 
| 270         chromeTest.assertNoLastError(); |  | 
| 271       } else { |  | 
| 272         chromeTest.assertLastError(expectedError); |  | 
| 273       } |  | 
| 274 |  | 
| 275       var result; |  | 
| 276       if (func) { |  | 
| 277         result = safeFunctionApply(func, arguments); |  | 
| 278       } |  | 
| 279 |  | 
| 280       callbackCompleted(); |  | 
| 281       return result; |  | 
| 282     }; |  | 
| 283   }); |  | 
| 284 |  | 
| 285   apiFunctions.setHandleRequest('listenOnce', function(event, func) { |  | 
| 286     var callbackCompleted = chromeTest.callbackAdded(); |  | 
| 287     var listener = function() { |  | 
| 288       event.removeListener(listener); |  | 
| 289       safeFunctionApply(func, arguments); |  | 
| 290       callbackCompleted(); |  | 
| 291     }; |  | 
| 292     event.addListener(listener); |  | 
| 293   }); |  | 
| 294 |  | 
| 295   apiFunctions.setHandleRequest('listenForever', function(event, func) { |  | 
| 296     var callbackCompleted = chromeTest.callbackAdded(); |  | 
| 297 |  | 
| 298     var listener = function() { |  | 
| 299       safeFunctionApply(func, arguments); |  | 
| 300     }; |  | 
| 301 |  | 
| 302     var done = function() { |  | 
| 303       event.removeListener(listener); |  | 
| 304       callbackCompleted(); |  | 
| 305     }; |  | 
| 306 |  | 
| 307     event.addListener(listener); |  | 
| 308     return done; |  | 
| 309   }); |  | 
| 310 |  | 
| 311   apiFunctions.setHandleRequest('callbackPass', function(func) { |  | 
| 312     return chromeTest.callback(func); |  | 
| 313   }); |  | 
| 314 |  | 
| 315   apiFunctions.setHandleRequest('callbackFail', function(expectedError, func) { |  | 
| 316     return chromeTest.callback(func, expectedError); |  | 
| 317   }); |  | 
| 318 |  | 
| 319   apiFunctions.setHandleRequest('runTests', function(tests) { |  | 
| 320     chromeTest.tests = tests; |  | 
| 321     testCount = chromeTest.tests.length; |  | 
| 322     chromeTest.runNextTest(); |  | 
| 323   }); |  | 
| 324 |  | 
| 325   apiFunctions.setHandleRequest('getApiDefinitions', function() { |  | 
| 326     return GetExtensionAPIDefinitionsForTest(); |  | 
| 327   }); |  | 
| 328 |  | 
| 329   apiFunctions.setHandleRequest('getApiFeatures', function() { |  | 
| 330     return GetAPIFeatures(); |  | 
| 331   }); |  | 
| 332 |  | 
| 333   apiFunctions.setHandleRequest('isProcessingUserGesture', function() { |  | 
| 334     return userGestures.IsProcessingUserGesture(); |  | 
| 335   }); |  | 
| 336 |  | 
| 337   apiFunctions.setHandleRequest('runWithUserGesture', function(callback) { |  | 
| 338     chromeTest.assertEq(typeof(callback), 'function'); |  | 
| 339     return userGestures.RunWithUserGesture(callback); |  | 
| 340   }); |  | 
| 341 |  | 
| 342   apiFunctions.setHandleRequest('runWithoutUserGesture', function(callback) { |  | 
| 343     chromeTest.assertEq(typeof(callback), 'function'); |  | 
| 344     return userGestures.RunWithoutUserGesture(callback); |  | 
| 345   }); |  | 
| 346 |  | 
| 347   apiFunctions.setHandleRequest('setExceptionHandler', function(callback) { |  | 
| 348     chromeTest.assertEq(typeof(callback), 'function'); |  | 
| 349     uncaughtExceptionHandler.setHandler(callback); |  | 
| 350   }); |  | 
| 351 }); |  | 
| 352 |  | 
| 353 exports.binding = binding.generate(); |  | 
| OLD | NEW | 
|---|