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