compiler_customization_test.py revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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
13CR_FILE = os.path.join("..", "..", "ui", "webui", "resources", "js", "cr.js")
14
15
16def rel_to_abs(rel_path):
17  script_path = os.path.dirname(os.path.abspath(__file__))
18  return os.path.join(script_path, rel_path)
19
20
21class CompilerCustomizationTest(unittest.TestCase):
22  _CR_DEFINE_DEFINITION = Processor(rel_to_abs(CR_FILE)).contents
23
24  def setUp(self):
25    self._checker = Checker()
26
27  def _runChecker(self, source_code):
28    file_path = "/script.js"
29    FileCache._cache[file_path] = source_code
30    return self._checker.check(file_path)
31
32  def _runCheckerTestExpectError(self, source_code, expected_error):
33    _, output = self._runChecker(source_code)
34
35    self.assertTrue(expected_error in output,
36        msg="Expected chunk: \n%s\n\nOutput:\n%s\n" % (
37            expected_error, output))
38
39  def _runCheckerTestExpectSuccess(self, source_code):
40    return_code, output = self._runChecker(source_code)
41
42    self.assertTrue(return_code == 0,
43        msg="Expected success, got return code %d\n\nOutput:\n%s\n" % (
44            return_code, output))
45
46  def testGetInstance(self):
47    self._runCheckerTestExpectError("""
48var cr = {
49  /** @param {!Function} ctor */
50  addSingletonGetter: function(ctor) {
51    ctor.getInstance = function() {
52      return ctor.instance_ || (ctor.instance_ = new ctor());
53    };
54  }
55};
56
57/** @constructor */
58function Class() {
59  /** @param {number} num */
60  this.needsNumber = function(num) {};
61}
62
63cr.addSingletonGetter(Class);
64Class.getInstance().needsNumber("wrong type");
65""", "ERROR - actual parameter 1 of Class.needsNumber does not match formal "
66        "parameter")
67
68  def testCrDefineFunctionDefinition(self):
69    self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """
70cr.define('a.b.c', function() {
71  /** @param {number} num */
72  function internalName(num) {}
73
74  return {
75    needsNumber: internalName
76  };
77});
78
79a.b.c.needsNumber("wrong type");
80""", "ERROR - actual parameter 1 of a.b.c.needsNumber does not match formal "
81        "parameter")
82
83  def testCrDefineFunctionAssignment(self):
84    self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """
85cr.define('a.b.c', function() {
86  /** @param {number} num */
87  var internalName = function(num) {};
88
89  return {
90    needsNumber: internalName
91  };
92});
93
94a.b.c.needsNumber("wrong type");
95""", "ERROR - actual parameter 1 of a.b.c.needsNumber does not match formal "
96        "parameter")
97
98  def testCrDefineConstructorDefinitionPrototypeMethod(self):
99    self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """
100cr.define('a.b.c', function() {
101  /** @constructor */
102  function ClassInternalName() {}
103
104  ClassInternalName.prototype = {
105    /** @param {number} num */
106    method: function(num) {}
107  };
108
109  return {
110    ClassExternalName: ClassInternalName
111  };
112});
113
114new a.b.c.ClassExternalName().method("wrong type");
115""", "ERROR - actual parameter 1 of a.b.c.ClassExternalName.prototype.method "
116        "does not match formal parameter")
117
118  def testCrDefineConstructorAssignmentPrototypeMethod(self):
119    self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """
120cr.define('a.b.c', function() {
121  /** @constructor */
122  var ClassInternalName = function() {};
123
124  ClassInternalName.prototype = {
125    /** @param {number} num */
126    method: function(num) {}
127  };
128
129  return {
130    ClassExternalName: ClassInternalName
131  };
132});
133
134new a.b.c.ClassExternalName().method("wrong type");
135""", "ERROR - actual parameter 1 of a.b.c.ClassExternalName.prototype.method "
136        "does not match formal parameter")
137
138  def testCrDefineEnum(self):
139    self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """
140cr.define('a.b.c', function() {
141  /** @enum {string} */
142  var internalNameForEnum = {key: 'wrong_type'};
143
144  return {
145    exportedEnum: internalNameForEnum
146  };
147});
148
149/** @param {number} num */
150function needsNumber(num) {}
151
152needsNumber(a.b.c.exportedEnum.key);
153""", "ERROR - actual parameter 1 of needsNumber does not match formal "
154        "parameter")
155
156  def testObjectDefineProperty(self):
157    self._runCheckerTestExpectSuccess("""
158/** @constructor */
159function Class() {}
160
161Object.defineProperty(Class.prototype, 'myProperty', {});
162
163alert(new Class().myProperty);
164""")
165
166  def testCrDefineProperty(self):
167    self._runCheckerTestExpectSuccess(self._CR_DEFINE_DEFINITION + """
168/** @constructor */
169function Class() {}
170
171cr.defineProperty(Class.prototype, 'myProperty', cr.PropertyKind.JS);
172
173alert(new Class().myProperty);
174""")
175
176  def testCrDefinePropertyTypeChecking(self):
177    self._runCheckerTestExpectError(self._CR_DEFINE_DEFINITION + """
178/** @constructor */
179function Class() {}
180
181cr.defineProperty(Class.prototype, 'booleanProp', cr.PropertyKind.BOOL_ATTR);
182
183/** @param {number} num */
184function needsNumber(num) {}
185
186needsNumber(new Class().booleanProp);
187""", "ERROR - actual parameter 1 of needsNumber does not match formal "
188        "parameter")
189
190  def testCrDefineOnCrWorks(self):
191    self._runCheckerTestExpectSuccess(self._CR_DEFINE_DEFINITION + """
192cr.define('cr', function() {
193  return {};
194});
195""")
196
197
198if __name__ == "__main__":
199  unittest.main()
200