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 6 import os 7 import unittest 8 9 from checker import Checker 10 from processor import FileCache, Processor 11 12 13 ASSERT_FILE = os.path.join("..", "..", "ui", "webui", "resources", "js", 14 "assert.js") 15 CR_FILE = os.path.join("..", "..", "ui", "webui", "resources", "js", "cr.js") 16 UI_FILE = os.path.join("..", "..", "ui", "webui", "resources", "js", "cr", 17 "ui.js") 18 19 20 def 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 25 class 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(""" 54 var 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 */ 64 function Class() { 65 /** @param {number} num */ 66 this.needsNumber = function(num) {}; 67 } 68 69 cr.addSingletonGetter(Class); 70 Class.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 + """ 76 cr.define('a.b.c', function() { 77 /** @param {number} num */ 78 function internalName(num) {} 79 80 return { 81 needsNumber: internalName 82 }; 83 }); 84 85 a.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 + """ 91 cr.define('a.b.c', function() { 92 /** @param {number} num */ 93 var internalName = function(num) {}; 94 95 return { 96 needsNumber: internalName 97 }; 98 }); 99 100 a.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 + """ 106 cr.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 120 new 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 + """ 126 cr.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 140 new 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 + """ 146 cr.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 */ 156 function needsNumber(num) {} 157 158 needsNumber(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 */ 165 function Class() {} 166 167 Object.defineProperty(Class.prototype, 'myProperty', {}); 168 169 alert(new Class().myProperty); 170 """) 171 172 def testCrDefineProperty(self): 173 self._runCheckerTestExpectSuccess(self._CR_DEFINE_DEFINITION + """ 174 /** @constructor */ 175 function Class() {} 176 177 cr.defineProperty(Class.prototype, 'myProperty', cr.PropertyKind.JS); 178 179 alert(new Class().myProperty); 180 """) 181 182 def testCrDefinePropertyTypeChecking(self): 183 self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ 184 /** @constructor */ 185 function Class() {} 186 187 cr.defineProperty(Class.prototype, 'booleanProp', cr.PropertyKind.BOOL_ATTR); 188 189 /** @param {number} num */ 190 function needsNumber(num) {} 191 192 needsNumber(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 + """ 198 cr.define('cr', function() { 199 return {}; 200 }); 201 """) 202 203 def testAssertWorks(self): 204 self._runCheckerTestExpectSuccess(self._ASSERT_DEFINITION + """ 205 /** @return {?string} */ 206 function f() { 207 return "string"; 208 } 209 210 /** @type {!string} */ 211 var a = assert(f()); 212 """) 213 214 def testAssertInstanceofWorks(self): 215 self._runCheckerTestExpectSuccess(self._ASSERT_DEFINITION + """ 216 /** @constructor */ 217 function Class() {} 218 219 /** @return {Class} */ 220 function 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 */ 230 function Class() {} 231 232 /** @return {Class} */ 233 function f() { 234 var a = document.createElement('div'); 235 cr.ui.decorate(a, Class); 236 return a; 237 } 238 """) 239 240 241 if __name__ == "__main__": 242 unittest.main() 243