1#!/usr/bin/env python 2# Copyright 2014 The Chromium Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import os 7import unittest 8 9from checker import Checker 10from processor import FileCache, Processor 11 12 13ASSERT_FILE = os.path.join("..", "..", "ui", "webui", "resources", "js", 14 "assert.js") 15CR_FILE = os.path.join("..", "..", "ui", "webui", "resources", "js", "cr.js") 16UI_FILE = os.path.join("..", "..", "ui", "webui", "resources", "js", "cr", 17 "ui.js") 18 19 20def rel_to_abs(rel_path): 21 script_path = os.path.dirname(os.path.abspath(__file__)) 22 return os.path.join(script_path, rel_path) 23 24 25class CompilerCustomizationTest(unittest.TestCase): 26 _ASSERT_DEFINITION = Processor(rel_to_abs(ASSERT_FILE)).contents 27 _CR_DEFINE_DEFINITION = Processor(rel_to_abs(CR_FILE)).contents 28 _CR_UI_DECORATE_DEFINITION = Processor(rel_to_abs(UI_FILE)).contents 29 30 def setUp(self): 31 self._checker = Checker() 32 33 def _runChecker(self, source_code): 34 file_path = "/script.js" 35 FileCache._cache[file_path] = source_code 36 return self._checker.check(file_path) 37 38 def _runCheckerTestExpectError(self, source_code, expected_error): 39 _, output = self._runChecker(source_code) 40 41 self.assertTrue(expected_error in output, 42 msg="Expected chunk: \n%s\n\nOutput:\n%s\n" % ( 43 expected_error, output)) 44 45 def _runCheckerTestExpectSuccess(self, source_code): 46 return_code, output = self._runChecker(source_code) 47 48 self.assertTrue(return_code == 0, 49 msg="Expected success, got return code %d\n\nOutput:\n%s\n" % ( 50 return_code, output)) 51 52 def testGetInstance(self): 53 self._runCheckerTestExpectError(""" 54var cr = { 55 /** @param {!Function} ctor */ 56 addSingletonGetter: function(ctor) { 57 ctor.getInstance = function() { 58 return ctor.instance_ || (ctor.instance_ = new ctor()); 59 }; 60 } 61}; 62 63/** @constructor */ 64function Class() { 65 /** @param {number} num */ 66 this.needsNumber = function(num) {}; 67} 68 69cr.addSingletonGetter(Class); 70Class.getInstance().needsNumber("wrong type"); 71""", "ERROR - actual parameter 1 of Class.needsNumber does not match formal " 72 "parameter") 73 74 def testCrDefineFunctionDefinition(self): 75 self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ 76cr.define('a.b.c', function() { 77 /** @param {number} num */ 78 function internalName(num) {} 79 80 return { 81 needsNumber: internalName 82 }; 83}); 84 85a.b.c.needsNumber("wrong type"); 86""", "ERROR - actual parameter 1 of a.b.c.needsNumber does not match formal " 87 "parameter") 88 89 def testCrDefineFunctionAssignment(self): 90 self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ 91cr.define('a.b.c', function() { 92 /** @param {number} num */ 93 var internalName = function(num) {}; 94 95 return { 96 needsNumber: internalName 97 }; 98}); 99 100a.b.c.needsNumber("wrong type"); 101""", "ERROR - actual parameter 1 of a.b.c.needsNumber does not match formal " 102 "parameter") 103 104 def testCrDefineConstructorDefinitionPrototypeMethod(self): 105 self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ 106cr.define('a.b.c', function() { 107 /** @constructor */ 108 function ClassInternalName() {} 109 110 ClassInternalName.prototype = { 111 /** @param {number} num */ 112 method: function(num) {} 113 }; 114 115 return { 116 ClassExternalName: ClassInternalName 117 }; 118}); 119 120new a.b.c.ClassExternalName().method("wrong type"); 121""", "ERROR - actual parameter 1 of a.b.c.ClassExternalName.prototype.method " 122 "does not match formal parameter") 123 124 def testCrDefineConstructorAssignmentPrototypeMethod(self): 125 self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ 126cr.define('a.b.c', function() { 127 /** @constructor */ 128 var ClassInternalName = function() {}; 129 130 ClassInternalName.prototype = { 131 /** @param {number} num */ 132 method: function(num) {} 133 }; 134 135 return { 136 ClassExternalName: ClassInternalName 137 }; 138}); 139 140new a.b.c.ClassExternalName().method("wrong type"); 141""", "ERROR - actual parameter 1 of a.b.c.ClassExternalName.prototype.method " 142 "does not match formal parameter") 143 144 def testCrDefineEnum(self): 145 self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ 146cr.define('a.b.c', function() { 147 /** @enum {string} */ 148 var internalNameForEnum = {key: 'wrong_type'}; 149 150 return { 151 exportedEnum: internalNameForEnum 152 }; 153}); 154 155/** @param {number} num */ 156function needsNumber(num) {} 157 158needsNumber(a.b.c.exportedEnum.key); 159""", "ERROR - actual parameter 1 of needsNumber does not match formal " 160 "parameter") 161 162 def testObjectDefineProperty(self): 163 self._runCheckerTestExpectSuccess(""" 164/** @constructor */ 165function Class() {} 166 167Object.defineProperty(Class.prototype, 'myProperty', {}); 168 169alert(new Class().myProperty); 170""") 171 172 def testCrDefineProperty(self): 173 self._runCheckerTestExpectSuccess(self._CR_DEFINE_DEFINITION + """ 174/** @constructor */ 175function Class() {} 176 177cr.defineProperty(Class.prototype, 'myProperty', cr.PropertyKind.JS); 178 179alert(new Class().myProperty); 180""") 181 182 def testCrDefinePropertyTypeChecking(self): 183 self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ 184/** @constructor */ 185function Class() {} 186 187cr.defineProperty(Class.prototype, 'booleanProp', cr.PropertyKind.BOOL_ATTR); 188 189/** @param {number} num */ 190function needsNumber(num) {} 191 192needsNumber(new Class().booleanProp); 193""", "ERROR - actual parameter 1 of needsNumber does not match formal " 194 "parameter") 195 196 def testCrDefineOnCrWorks(self): 197 self._runCheckerTestExpectSuccess(self._CR_DEFINE_DEFINITION + """ 198cr.define('cr', function() { 199 return {}; 200}); 201""") 202 203 def testAssertWorks(self): 204 self._runCheckerTestExpectSuccess(self._ASSERT_DEFINITION + """ 205/** @return {?string} */ 206function f() { 207 return "string"; 208} 209 210/** @type {!string} */ 211var a = assert(f()); 212""") 213 214 def testAssertInstanceofWorks(self): 215 self._runCheckerTestExpectSuccess(self._ASSERT_DEFINITION + """ 216/** @constructor */ 217function Class() {} 218 219/** @return {Class} */ 220function f() { 221 var a = document.createElement('div'); 222 return assertInstanceof(a, Class); 223} 224""") 225 226 def testCrUiDecorateWorks(self): 227 self._runCheckerTestExpectSuccess(self._CR_DEFINE_DEFINITION + 228 self._CR_UI_DECORATE_DEFINITION + """ 229/** @constructor */ 230function Class() {} 231 232/** @return {Class} */ 233function f() { 234 var a = document.createElement('div'); 235 cr.ui.decorate(a, Class); 236 return a; 237} 238""") 239 240 241if __name__ == "__main__": 242 unittest.main() 243