| #!/usr/bin/env python |
| # Copyright 2014 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import os |
| import unittest |
| |
| from checker import Checker |
| from processor import FileCache, Processor |
| |
| |
| CR_FILE = os.path.join("..", "..", "ui", "webui", "resources", "js", "cr.js") |
| |
| |
| def rel_to_abs(rel_path): |
| script_path = os.path.dirname(os.path.abspath(__file__)) |
| return os.path.join(script_path, rel_path) |
| |
| |
| class CompilerCustomizationTest(unittest.TestCase): |
| _CR_DEFINE_DEFINITION = Processor(rel_to_abs(CR_FILE)).contents |
| |
| def setUp(self): |
| self._checker = Checker() |
| |
| def _runChecker(self, source_code): |
| file_path = "/script.js" |
| FileCache._cache[file_path] = source_code |
| return self._checker.check(file_path) |
| |
| def _runCheckerTestExpectError(self, source_code, expected_error): |
| _, output = self._runChecker(source_code) |
| |
| self.assertTrue(expected_error in output, |
| msg="Expected chunk: \n%s\n\nOutput:\n%s\n" % ( |
| expected_error, output)) |
| |
| def _runCheckerTestExpectSuccess(self, source_code): |
| return_code, output = self._runChecker(source_code) |
| |
| self.assertTrue(return_code == 0, |
| msg="Expected success, got return code %d\n\nOutput:\n%s\n" % ( |
| return_code, output)) |
| |
| def testGetInstance(self): |
| self._runCheckerTestExpectError(""" |
| var cr = { |
| /** @param {!Function} ctor */ |
| addSingletonGetter: function(ctor) { |
| ctor.getInstance = function() { |
| return ctor.instance_ || (ctor.instance_ = new ctor()); |
| }; |
| } |
| }; |
| |
| /** @constructor */ |
| function Class() { |
| /** @param {number} num */ |
| this.needsNumber = function(num) {}; |
| } |
| |
| cr.addSingletonGetter(Class); |
| Class.getInstance().needsNumber("wrong type"); |
| """, "ERROR - actual parameter 1 of Class.needsNumber does not match formal " |
| "parameter") |
| |
| def testCrDefineFunctionDefinition(self): |
| self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ |
| cr.define('a.b.c', function() { |
| /** @param {number} num */ |
| function internalName(num) {} |
| |
| return { |
| needsNumber: internalName |
| }; |
| }); |
| |
| a.b.c.needsNumber("wrong type"); |
| """, "ERROR - actual parameter 1 of a.b.c.needsNumber does not match formal " |
| "parameter") |
| |
| def testCrDefineFunctionAssignment(self): |
| self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ |
| cr.define('a.b.c', function() { |
| /** @param {number} num */ |
| var internalName = function(num) {}; |
| |
| return { |
| needsNumber: internalName |
| }; |
| }); |
| |
| a.b.c.needsNumber("wrong type"); |
| """, "ERROR - actual parameter 1 of a.b.c.needsNumber does not match formal " |
| "parameter") |
| |
| def testCrDefineConstructorDefinitionPrototypeMethod(self): |
| self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ |
| cr.define('a.b.c', function() { |
| /** @constructor */ |
| function ClassInternalName() {} |
| |
| ClassInternalName.prototype = { |
| /** @param {number} num */ |
| method: function(num) {} |
| }; |
| |
| return { |
| ClassExternalName: ClassInternalName |
| }; |
| }); |
| |
| new a.b.c.ClassExternalName().method("wrong type"); |
| """, "ERROR - actual parameter 1 of a.b.c.ClassExternalName.prototype.method " |
| "does not match formal parameter") |
| |
| def testCrDefineConstructorAssignmentPrototypeMethod(self): |
| self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ |
| cr.define('a.b.c', function() { |
| /** @constructor */ |
| var ClassInternalName = function() {}; |
| |
| ClassInternalName.prototype = { |
| /** @param {number} num */ |
| method: function(num) {} |
| }; |
| |
| return { |
| ClassExternalName: ClassInternalName |
| }; |
| }); |
| |
| new a.b.c.ClassExternalName().method("wrong type"); |
| """, "ERROR - actual parameter 1 of a.b.c.ClassExternalName.prototype.method " |
| "does not match formal parameter") |
| |
| def testCrDefineEnum(self): |
| self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ |
| cr.define('a.b.c', function() { |
| /** @enum {string} */ |
| var internalNameForEnum = {key: 'wrong_type'}; |
| |
| return { |
| exportedEnum: internalNameForEnum |
| }; |
| }); |
| |
| /** @param {number} num */ |
| function needsNumber(num) {} |
| |
| needsNumber(a.b.c.exportedEnum.key); |
| """, "ERROR - actual parameter 1 of needsNumber does not match formal " |
| "parameter") |
| |
| def testObjectDefineProperty(self): |
| self._runCheckerTestExpectSuccess(""" |
| /** @constructor */ |
| function Class() {} |
| |
| Object.defineProperty(Class.prototype, 'myProperty', {}); |
| |
| alert(new Class().myProperty); |
| """) |
| |
| def testCrDefineProperty(self): |
| self._runCheckerTestExpectSuccess(self._CR_DEFINE_DEFINITION + """ |
| /** @constructor */ |
| function Class() {} |
| |
| cr.defineProperty(Class.prototype, 'myProperty', cr.PropertyKind.JS); |
| |
| alert(new Class().myProperty); |
| """) |
| |
| def testCrDefinePropertyTypeChecking(self): |
| self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """ |
| /** @constructor */ |
| function Class() {} |
| |
| cr.defineProperty(Class.prototype, 'booleanProp', cr.PropertyKind.BOOL_ATTR); |
| |
| /** @param {number} num */ |
| function needsNumber(num) {} |
| |
| needsNumber(new Class().booleanProp); |
| """, "ERROR - actual parameter 1 of needsNumber does not match formal " |
| "parameter") |
| |
| def testCrDefineOnCrWorks(self): |
| self._runCheckerTestExpectSuccess(self._CR_DEFINE_DEFINITION + """ |
| cr.define('cr', function() { |
| return {}; |
| }); |
| """) |
| |
| |
| if __name__ == "__main__": |
| unittest.main() |