Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / closure_compiler / runner / test / com / google / javascript / jscomp / ChromePassTest.java
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package com.google.javascript.jscomp;
6
7 /**
8  * Tests {@link ChromePass}.
9  */
10 public class ChromePassTest extends CompilerTestCase {
11
12     @Override
13     protected CompilerPass getProcessor(Compiler compiler) {
14       return new ChromePass(compiler);
15     }
16
17     @Override
18     protected int getNumRepetitions() {
19       // This pass isn't idempotent and only runs once.
20       return 1;
21     }
22
23     public void testCrDefineCreatesObjectsForQualifiedName() throws Exception {
24         test(
25             "cr.define('my.namespace.name', function() {\n" +
26             "  return {};\n" +
27             "});",
28             "var my = my || {};\n" +
29             "my.namespace = my.namespace || {};\n" +
30             "my.namespace.name = my.namespace.name || {};\n" +
31             "cr.define('my.namespace.name', function() {\n" +
32             "  return {};\n" +
33             "});");
34     }
35
36     public void testCrDefineAssignsExportedFunctionByQualifiedName() throws Exception {
37         test(
38             "cr.define('namespace', function() {\n" +
39             "  function internalStaticMethod() {\n" +
40             "    alert(42);\n" +
41             "  }\n" +
42             "  return {\n" +
43             "    externalStaticMethod: internalStaticMethod\n" +
44             "  };\n" +
45             "});",
46             "var namespace = namespace || {};\n" +
47             "cr.define('namespace', function() {\n" +
48             "  namespace.externalStaticMethod = function internalStaticMethod() {\n" +
49             "    alert(42);\n" +
50             "  }\n" +
51             "  return {\n" +
52             "    externalStaticMethod: namespace.externalStaticMethod\n" +
53             "  };\n" +
54             "});");
55     }
56
57     public void testCrDefineCopiesJSDocForExportedFunction() throws Exception {
58         test("cr.define('namespace', function() {\n" +
59             "  /** I'm function's JSDoc */\n" +
60             "  function internalStaticMethod() {\n" +
61             "    alert(42);\n" +
62             "  }\n" +
63             "  return {\n" +
64             "    externalStaticMethod: internalStaticMethod\n" +
65             "  };\n" +
66             "});",
67             "var namespace = namespace || {};\n" +
68             "cr.define('namespace', function() {\n" +
69             "  /** I'm function's JSDoc */\n" +
70             "  namespace.externalStaticMethod = function internalStaticMethod() {\n" +
71             "    alert(42);\n" +
72             "  }\n" +
73             "  return {\n" +
74             "    externalStaticMethod: namespace.externalStaticMethod\n" +
75             "  };\n" +
76             "});");
77     }
78
79     public void testCrDefineReassignsExportedVarByQualifiedName() throws Exception {
80         test(
81             "cr.define('namespace', function() {\n" +
82             "  var internalStaticMethod = function() {\n" +
83             "    alert(42);\n" +
84             "  }\n" +
85             "  return {\n" +
86             "    externalStaticMethod: internalStaticMethod\n" +
87             "  };\n" +
88             "});",
89             "var namespace = namespace || {};\n" +
90             "cr.define('namespace', function() {\n" +
91             "  namespace.externalStaticMethod = function() {\n" +
92             "    alert(42);\n" +
93             "  }\n" +
94             "  return {\n" +
95             "    externalStaticMethod: namespace.externalStaticMethod\n" +
96             "  };\n" +
97             "});");
98     }
99
100     public void testCrDefineExportsVarsWithoutAssignment() throws Exception {
101         test(
102             "cr.define('namespace', function() {\n" +
103             "  var a;\n" +
104             "  return {\n" +
105             "    a: a\n" +
106             "  };\n" +
107             "});\n",
108             "var namespace = namespace || {};\n" +
109             "cr.define('namespace', function() {\n" +
110             "  namespace.a;\n" +
111             "  return {\n" +
112             "    a: namespace.a\n" +
113             "  };\n" +
114             "});\n");
115     }
116
117     public void testCrDefineExportsVarsWithoutAssignmentWithJSDoc() throws Exception {
118         test(
119             "cr.define('namespace', function() {\n" +
120             "  /** @type {number} */\n" +
121             "  var a;\n" +
122             "  return {\n" +
123             "    a: a\n" +
124             "  };\n" +
125             "});\n",
126             "var namespace = namespace || {};\n" +
127             "cr.define('namespace', function() {\n" +
128             "  /** @type {number} */\n" +
129             "  namespace.a;\n" +
130             "  return {\n" +
131             "    a: namespace.a\n" +
132             "  };\n" +
133             "});\n");
134     }
135
136     public void testCrDefineCopiesJSDocForExportedVariable() throws Exception {
137         test(
138             "cr.define('namespace', function() {\n" +
139             "  /** I'm function's JSDoc */\n" +
140             "  var internalStaticMethod = function() {\n" +
141             "    alert(42);\n" +
142             "  }\n" +
143             "  return {\n" +
144             "    externalStaticMethod: internalStaticMethod\n" +
145             "  };\n" +
146             "});",
147             "var namespace = namespace || {};\n" +
148             "cr.define('namespace', function() {\n" +
149             "  /** I'm function's JSDoc */\n" +
150             "  namespace.externalStaticMethod = function() {\n" +
151             "    alert(42);\n" +
152             "  }\n" +
153             "  return {\n" +
154             "    externalStaticMethod: namespace.externalStaticMethod\n" +
155             "  };\n" +
156             "});");
157     }
158
159     public void testCrDefineDoesNothingWithNonExportedFunction() throws Exception {
160         test(
161             "cr.define('namespace', function() {\n" +
162             "  function internalStaticMethod() {\n" +
163             "    alert(42);\n" +
164             "  }\n" +
165             "  return {};\n" +
166             "});",
167             "var namespace = namespace || {};\n" +
168             "cr.define('namespace', function() {\n" +
169             "  function internalStaticMethod() {\n" +
170             "    alert(42);\n" +
171             "  }\n" +
172             "  return {};\n" +
173             "});");
174     }
175
176     public void testCrDefineDoesNothingWithNonExportedVar() throws Exception {
177         test(
178             "cr.define('namespace', function() {\n" +
179             "  var a;\n" +
180             "  var b;\n" +
181             "  return {\n" +
182             "    a: a\n" +
183             "  };\n" +
184             "});\n",
185             "var namespace = namespace || {};\n" +
186             "cr.define('namespace', function() {\n" +
187             "  namespace.a;\n" +
188             "  var b;\n" +
189             "  return {\n" +
190             "    a: namespace.a\n" +
191             "  };\n" +
192             "});\n");
193     }
194
195     public void testCrDefineChangesReferenceToExportedFunction() throws Exception {
196         test(
197             "cr.define('namespace', function() {\n" +
198             "  function internalStaticMethod() {\n" +
199             "    alert(42);\n" +
200             "  }\n" +
201             "  function letsUseIt() {\n" +
202             "    internalStaticMethod();\n" +
203             "  }\n" +
204             "  return {\n" +
205             "    externalStaticMethod: internalStaticMethod\n" +
206             "  };\n" +
207             "});",
208             "var namespace = namespace || {};\n" +
209             "cr.define('namespace', function() {\n" +
210             "  namespace.externalStaticMethod = function internalStaticMethod() {\n" +
211             "    alert(42);\n" +
212             "  }\n" +
213             "  function letsUseIt() {\n" +
214             "    namespace.externalStaticMethod();\n" +
215             "  }\n" +
216             "  return {\n" +
217             "    externalStaticMethod: namespace.externalStaticMethod\n" +
218             "  };\n" +
219             "});");
220     }
221
222     public void testCrDefineWrongNumberOfArguments() throws Exception {
223         test("cr.define('namespace', function() { return {}; }, 'invalid argument')\n",
224             null, ChromePass.CR_DEFINE_WRONG_NUMBER_OF_ARGUMENTS);
225     }
226
227     public void testCrDefineInvalidFirstArgument() throws Exception {
228         test("cr.define(42, function() { return {}; })\n",
229             null, ChromePass.CR_DEFINE_INVALID_FIRST_ARGUMENT);
230     }
231
232     public void testCrDefineInvalidSecondArgument() throws Exception {
233         test("cr.define('namespace', 42)\n",
234             null, ChromePass.CR_DEFINE_INVALID_SECOND_ARGUMENT);
235     }
236
237     public void testCrDefineInvalidReturnInFunction() throws Exception {
238         test("cr.define('namespace', function() {})\n",
239             null, ChromePass.CR_DEFINE_INVALID_RETURN_IN_FUNCTION);
240     }
241
242     public void testObjectDefinePropertyDefinesUnquotedProperty() throws Exception {
243         test(
244             "Object.defineProperty(a.b, 'c', {});",
245             "Object.defineProperty(a.b, 'c', {});\n" +
246             "/** @type {?} */\n" +
247             "a.b.c;");
248     }
249
250     public void testCrDefinePropertyDefinesUnquotedPropertyWithStringTypeForPropertyKindAttr()
251             throws Exception {
252         test(
253             "cr.defineProperty(a.prototype, 'c', cr.PropertyKind.ATTR);",
254             "cr.defineProperty(a.prototype, 'c', cr.PropertyKind.ATTR);\n" +
255             "/** @type {string} */\n" +
256             "a.prototype.c;");
257     }
258
259     public void testCrDefinePropertyDefinesUnquotedPropertyWithBooleanTypeForPropertyKindBoolAttr()
260             throws Exception {
261         test(
262             "cr.defineProperty(a.prototype, 'c', cr.PropertyKind.BOOL_ATTR);",
263             "cr.defineProperty(a.prototype, 'c', cr.PropertyKind.BOOL_ATTR);\n" +
264             "/** @type {boolean} */\n" +
265             "a.prototype.c;");
266     }
267
268     public void testCrDefinePropertyDefinesUnquotedPropertyWithAnyTypeForPropertyKindJs()
269             throws Exception {
270         test(
271             "cr.defineProperty(a.prototype, 'c', cr.PropertyKind.JS);",
272             "cr.defineProperty(a.prototype, 'c', cr.PropertyKind.JS);\n" +
273             "/** @type {?} */\n" +
274             "a.prototype.c;");
275     }
276
277     public void testCrDefinePropertyCalledWithouthThirdArgumentMeansCrPropertyKindJs()
278             throws Exception {
279         test(
280             "cr.defineProperty(a.prototype, 'c');",
281             "cr.defineProperty(a.prototype, 'c');\n" +
282             "/** @type {?} */\n" +
283             "a.prototype.c;");
284     }
285
286     public void testCrDefinePropertyDefinesUnquotedPropertyOnPrototypeWhenFunctionIsPassed()
287             throws Exception {
288         test(
289             "cr.defineProperty(a, 'c', cr.PropertyKind.JS);",
290             "cr.defineProperty(a, 'c', cr.PropertyKind.JS);\n" +
291             "/** @type {?} */\n" +
292             "a.prototype.c;");
293     }
294
295     public void testCrDefinePropertyInvalidPropertyKind()
296             throws Exception {
297         test(
298             "cr.defineProperty(a.b, 'c', cr.PropertyKind.INEXISTENT_KIND);",
299             null, ChromePass.CR_DEFINE_PROPERTY_INVALID_PROPERTY_KIND);
300     }
301
302     public void testCrExportPath() throws Exception {
303         test(
304             "cr.exportPath('a.b.c');",
305             "var a = a || {};\n" +
306             "a.b = a.b || {};\n" +
307             "a.b.c = a.b.c || {};\n" +
308             "cr.exportPath('a.b.c');");
309     }
310
311     public void testCrDefineCreatesEveryObjectOnlyOnce() throws Exception {
312         test(
313             "cr.define('a.b.c.d', function() {\n" +
314             "  return {};\n" +
315             "});\n" +
316             "cr.define('a.b.e.f', function() {\n" +
317             "  return {};\n" +
318             "});",
319             "var a = a || {};\n" +
320             "a.b = a.b || {};\n" +
321             "a.b.c = a.b.c || {};\n" +
322             "a.b.c.d = a.b.c.d || {};\n" +
323             "cr.define('a.b.c.d', function() {\n" +
324             "  return {};\n" +
325             "});\n" +
326             "a.b.e = a.b.e || {};\n" +
327             "a.b.e.f = a.b.e.f || {};\n" +
328             "cr.define('a.b.e.f', function() {\n" +
329             "  return {};\n" +
330             "});");
331     }
332
333     public void testCrDefineAndCrExportPathCreateEveryObjectOnlyOnce() throws Exception {
334         test(
335             "cr.exportPath('a.b.c.d');\n" +
336             "cr.define('a.b.e.f', function() {\n" +
337             "  return {};\n" +
338             "});",
339             "var a = a || {};\n" +
340             "a.b = a.b || {};\n" +
341             "a.b.c = a.b.c || {};\n" +
342             "a.b.c.d = a.b.c.d || {};\n" +
343             "cr.exportPath('a.b.c.d');\n" +
344             "a.b.e = a.b.e || {};\n" +
345             "a.b.e.f = a.b.e.f || {};\n" +
346             "cr.define('a.b.e.f', function() {\n" +
347             "  return {};\n" +
348             "});");
349     }
350
351     public void testCrDefineDoesntRedefineCrVar() throws Exception {
352         test(
353             "cr.define('cr.ui', function() {\n" +
354             "  return {};\n" +
355             "});",
356             "cr.ui = cr.ui || {};\n" +
357             "cr.define('cr.ui', function() {\n" +
358             "  return {};\n" +
359             "});");
360     }
361
362     public void testCrExportPathInvalidNumberOfArguments() throws Exception {
363         test("cr.exportPath();", null, ChromePass.CR_EXPORT_PATH_WRONG_NUMBER_OF_ARGUMENTS);
364     }
365
366     public void testCrMakePublicWorksOnOneMethodDefinedInPrototypeObject() throws Exception {
367         test(
368             "/** @constructor */\n" +
369             "function Class() {};\n" +
370             "\n" +
371             "Class.prototype = {\n" +
372             "  /** @return {number} */\n" +
373             "  method_: function() { return 42; }\n" +
374             "};\n" +
375             "\n" +
376             "cr.makePublic(Class, ['method']);",
377             "/** @constructor */\n" +
378             "function Class() {};\n" +
379             "\n" +
380             "Class.prototype = {\n" +
381             "  /** @return {number} */\n" +
382             "  method_: function() { return 42; }\n" +
383             "};\n" +
384             "\n" +
385             "/** @return {number} */\n" +
386             "Class.method;\n" +
387             "\n" +
388             "cr.makePublic(Class, ['method']);");
389     }
390
391     public void testCrMakePublicWorksOnTwoMethods() throws Exception {
392         test(
393             "/** @constructor */\n" +
394             "function Class() {}\n" +
395             "\n" +
396             "Class.prototype = {\n" +
397             "  /** @return {number} */\n" +
398             "  m1_: function() { return 42; },\n" +
399             "\n" +
400             "  /** @return {string} */\n" +
401             "  m2_: function() { return ''; }\n" +
402             "};\n" +
403             "\n" +
404             "cr.makePublic(Class, ['m1', 'm2']);",
405             "/** @constructor */\n" +
406             "function Class() {}\n" +
407             "\n" +
408             "Class.prototype = {\n" +
409             "  /** @return {number} */\n" +
410             "  m1_: function() { return 42; },\n" +
411             "\n" +
412             "  /** @return {string} */\n" +
413             "  m2_: function() { return ''; }\n" +
414             "}\n" +
415             "\n" +
416             "/** @return {number} */\n" +
417             "Class.m1;\n" +
418             "\n" +
419             "/** @return {string} */\n" +
420             "Class.m2;\n" +
421             "\n" +
422             "cr.makePublic(Class, ['m1', 'm2']);");
423     }
424
425     public void testCrMakePublicRequiresMethodsToHaveJSDoc() throws Exception {
426         test("/** @constructor */\n" +
427             "function Class() {}\n" +
428             "\n" +
429             "Class.prototype = {\n" +
430             "  method_: function() {}\n" +
431             "}\n" +
432             "\n" +
433             "cr.makePublic(Class, ['method']);", null, ChromePass.CR_MAKE_PUBLIC_HAS_NO_JSDOC);
434     }
435
436     public void testCrMakePublicDoesNothingWithMethodsNotInAPI() throws Exception {
437         test(
438             "/** @constructor */\n" +
439             "function Class() {}\n" +
440             "\n" +
441             "Class.prototype = {\n" +
442             "  method_: function() {}\n" +
443             "}\n" +
444             "\n" +
445             "cr.makePublic(Class, []);",
446             "/** @constructor */\n" +
447             "function Class() {}\n" +
448             "\n" +
449             "Class.prototype = {\n" +
450             "  method_: function() {}\n" +
451             "}\n" +
452             "\n" +
453             "cr.makePublic(Class, []);");
454     }
455
456     public void testCrMakePublicRequiresExportedMethodToBeDeclared() throws Exception {
457         test(
458             "/** @constructor */\n" +
459             "function Class() {}\n" +
460             "\n" +
461             "Class.prototype = {\n" +
462             "}\n" +
463             "\n" +
464             "cr.makePublic(Class, ['method']);", null,
465             ChromePass.CR_MAKE_PUBLIC_MISSED_DECLARATION);
466     }
467
468     public void testCrMakePublicWorksOnOneMethodDefinedDirectlyOnPrototype() throws Exception {
469         test(
470             "/** @constructor */\n" +
471             "function Class() {}\n" +
472             "\n" +
473             "/** @return {number} */\n" +
474             "Class.prototype.method_ = function() {};\n" +
475             "\n" +
476             "cr.makePublic(Class, ['method']);",
477             "/** @constructor */\n" +
478             "function Class() {}\n" +
479             "\n" +
480             "/** @return {number} */\n" +
481             "Class.prototype.method_ = function() {};\n" +
482             "\n" +
483             "/** @return {number} */\n" +
484             "Class.method;\n" +
485             "\n" +
486             "cr.makePublic(Class, ['method']);");
487     }
488
489     public void testCrMakePublicWorksOnDummyDeclaration() throws Exception {
490         test(
491             "/** @constructor */\n" +
492             "function Class() {}\n" +
493             "\n" +
494             "/** @return {number} */\n" +
495             "Class.prototype.method_;\n" +
496             "\n" +
497             "cr.makePublic(Class, ['method']);",
498             "/** @constructor */\n" +
499             "function Class() {}\n" +
500             "\n" +
501             "/** @return {number} */\n" +
502             "Class.prototype.method_;\n" +
503             "\n" +
504             "/** @return {number} */\n" +
505             "Class.method;\n" +
506             "\n" +
507             "cr.makePublic(Class, ['method']);");
508     }
509
510     public void testCrMakePublicReportsInvalidSecondArgumentMissing() throws Exception {
511         test(
512             "cr.makePublic(Class);", null,
513             ChromePass.CR_MAKE_PUBLIC_INVALID_SECOND_ARGUMENT);
514     }
515
516     public void testCrMakePublicReportsInvalidSecondArgumentNotAnArray() throws Exception {
517         test(
518             "cr.makePublic(Class, 42);", null,
519             ChromePass.CR_MAKE_PUBLIC_INVALID_SECOND_ARGUMENT);
520     }
521
522     public void testCrMakePublicReportsInvalidSecondArgumentArrayWithNotAString() throws Exception {
523         test(
524             "cr.makePublic(Class, [42]);", null,
525             ChromePass.CR_MAKE_PUBLIC_INVALID_SECOND_ARGUMENT);
526     }
527
528 }