OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright 2008 The Closure Linter Authors. All Rights Reserved. | |
3 # | |
4 # Licensed under the Apache License, Version 2.0 (the "License"); | |
5 # you may not use this file except in compliance with the License. | |
6 # You may obtain a copy of the License at | |
7 # | |
8 # http://www.apache.org/licenses/LICENSE-2.0 | |
9 # | |
10 # Unless required by applicable law or agreed to in writing, software | |
11 # distributed under the License is distributed on an "AS-IS" BASIS, | |
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 # See the License for the specific language governing permissions and | |
14 # limitations under the License. | |
15 | |
16 """Medium tests for the gpylint auto-fixer.""" | |
17 | |
18 __author__ = 'robbyw@google.com (Robby Walker)' | |
19 | |
20 import StringIO | |
21 | |
22 import gflags as flags | |
23 import unittest as googletest | |
24 from closure_linter import error_fixer | |
25 from closure_linter import runner | |
26 | |
27 | |
28 _RESOURCE_PREFIX = 'closure_linter/testdata' | |
29 | |
30 flags.FLAGS.strict = True | |
31 flags.FLAGS.limited_doc_files = ('dummy.js', 'externs.js') | |
32 flags.FLAGS.closurized_namespaces = ('goog', 'dummy') | |
33 | |
34 | |
35 class FixJsStyleTest(googletest.TestCase): | |
36 """Test case to for gjslint auto-fixing.""" | |
37 | |
38 def setUp(self): | |
39 flags.FLAGS.dot_on_next_line = True | |
40 | |
41 def tearDown(self): | |
42 flags.FLAGS.dot_on_next_line = False | |
43 | |
44 def testFixJsStyle(self): | |
45 test_cases = [ | |
46 ['fixjsstyle.in.js', 'fixjsstyle.out.js'], | |
47 ['indentation.js', 'fixjsstyle.indentation.out.js'], | |
48 ['fixjsstyle.html.in.html', 'fixjsstyle.html.out.html'], | |
49 ['fixjsstyle.oplineend.in.js', 'fixjsstyle.oplineend.out.js']] | |
50 for [running_input_file, running_output_file] in test_cases: | |
51 print 'Checking %s vs %s' % (running_input_file, running_output_file) | |
52 input_filename = None | |
53 golden_filename = None | |
54 current_filename = None | |
55 try: | |
56 input_filename = '%s/%s' % (_RESOURCE_PREFIX, running_input_file) | |
57 current_filename = input_filename | |
58 | |
59 golden_filename = '%s/%s' % (_RESOURCE_PREFIX, running_output_file) | |
60 current_filename = golden_filename | |
61 except IOError as ex: | |
62 raise IOError('Could not find testdata resource for %s: %s' % | |
63 (current_filename, ex)) | |
64 | |
65 if running_input_file == 'fixjsstyle.in.js': | |
66 with open(input_filename) as f: | |
67 for line in f: | |
68 # Go to last line. | |
69 pass | |
70 self.assertTrue(line == line.rstrip(), '%s file should not end ' | |
71 'with a new line.' % (input_filename)) | |
72 | |
73 # Autofix the file, sending output to a fake file. | |
74 actual = StringIO.StringIO() | |
75 runner.Run(input_filename, error_fixer.ErrorFixer(actual)) | |
76 | |
77 # Now compare the files. | |
78 actual.seek(0) | |
79 expected = open(golden_filename, 'r') | |
80 | |
81 # Uncomment to generate new golden files and run | |
82 # open('/'.join(golden_filename.split('/')[4:]), 'w').write(actual.read()) | |
83 # actual.seek(0) | |
84 | |
85 self.assertEqual(actual.readlines(), expected.readlines()) | |
86 | |
87 def testAddProvideFirstLine(self): | |
88 """Tests handling of case where goog.provide is added.""" | |
89 original = [ | |
90 'dummy.bb.cc = 1;', | |
91 ] | |
92 | |
93 expected = [ | |
94 'goog.provide(\'dummy.bb\');', | |
95 '', | |
96 'dummy.bb.cc = 1;', | |
97 ] | |
98 | |
99 self._AssertFixes(original, expected, include_header=False) | |
100 | |
101 original = [ | |
102 '', | |
103 'dummy.bb.cc = 1;', | |
104 ] | |
105 | |
106 self._AssertFixes(original, expected, include_header=False) | |
107 | |
108 def testAddRequireFirstLine(self): | |
109 """Tests handling of case where goog.require is added.""" | |
110 original = [ | |
111 'a = dummy.bb.cc;', | |
112 ] | |
113 | |
114 expected = [ | |
115 'goog.require(\'dummy.bb\');', | |
116 '', | |
117 'a = dummy.bb.cc;', | |
118 ] | |
119 | |
120 self._AssertFixes(original, expected, include_header=False) | |
121 | |
122 original = [ | |
123 '', | |
124 'a = dummy.bb.cc;', | |
125 ] | |
126 | |
127 self._AssertFixes(original, expected, include_header=False) | |
128 | |
129 def testDeleteProvideAndAddProvideFirstLine(self): | |
130 """Tests handling of case where goog.provide is deleted and added. | |
131 | |
132 Bug 14832597. | |
133 """ | |
134 original = [ | |
135 'goog.provide(\'dummy.aa\');', | |
136 '', | |
137 'dummy.bb.cc = 1;', | |
138 ] | |
139 | |
140 expected = [ | |
141 'goog.provide(\'dummy.bb\');', | |
142 '', | |
143 'dummy.bb.cc = 1;', | |
144 ] | |
145 | |
146 self._AssertFixes(original, expected, include_header=False) | |
147 | |
148 original = [ | |
149 'goog.provide(\'dummy.aa\');', | |
150 'dummy.bb.cc = 1;', | |
151 ] | |
152 | |
153 self._AssertFixes(original, expected, include_header=False) | |
154 | |
155 def testDeleteProvideAndAddRequireFirstLine(self): | |
156 """Tests handling where goog.provide is deleted and goog.require added. | |
157 | |
158 Bug 14832597. | |
159 """ | |
160 original = [ | |
161 'goog.provide(\'dummy.aa\');', | |
162 '', | |
163 'a = dummy.bb.cc;', | |
164 ] | |
165 | |
166 expected = [ | |
167 'goog.require(\'dummy.bb\');', | |
168 '', | |
169 'a = dummy.bb.cc;', | |
170 ] | |
171 | |
172 self._AssertFixes(original, expected, include_header=False) | |
173 | |
174 original = [ | |
175 'goog.provide(\'dummy.aa\');', | |
176 'a = dummy.bb.cc;', | |
177 ] | |
178 | |
179 self._AssertFixes(original, expected, include_header=False) | |
180 | |
181 def testDeleteRequireAndAddRequireFirstLine(self): | |
182 """Tests handling of case where goog.require is deleted and added. | |
183 | |
184 Bug 14832597. | |
185 """ | |
186 original = [ | |
187 'goog.require(\'dummy.aa\');', | |
188 '', | |
189 'a = dummy.bb.cc;', | |
190 ] | |
191 | |
192 expected = [ | |
193 'goog.require(\'dummy.bb\');', | |
194 '', | |
195 'a = dummy.bb.cc;', | |
196 ] | |
197 | |
198 self._AssertFixes(original, expected, include_header=False) | |
199 | |
200 original = [ | |
201 'goog.require(\'dummy.aa\');', | |
202 'a = dummy.bb.cc;', | |
203 ] | |
204 | |
205 self._AssertFixes(original, expected, include_header=False) | |
206 | |
207 def testDeleteRequireAndAddProvideFirstLine(self): | |
208 """Tests handling where goog.require is deleted and goog.provide added. | |
209 | |
210 Bug 14832597. | |
211 """ | |
212 original = [ | |
213 'goog.require(\'dummy.aa\');', | |
214 '', | |
215 'dummy.bb.cc = 1;', | |
216 ] | |
217 | |
218 expected = [ | |
219 'goog.provide(\'dummy.bb\');', | |
220 '', | |
221 'dummy.bb.cc = 1;', | |
222 ] | |
223 | |
224 self._AssertFixes(original, expected, include_header=False) | |
225 | |
226 original = [ | |
227 'goog.require(\'dummy.aa\');', | |
228 'dummy.bb.cc = 1;', | |
229 ] | |
230 | |
231 self._AssertFixes(original, expected, include_header=False) | |
232 | |
233 def testMultipleProvideInsert(self): | |
234 original = [ | |
235 'goog.provide(\'dummy.bb\');', | |
236 'goog.provide(\'dummy.dd\');', | |
237 '', | |
238 'dummy.aa.ff = 1;', | |
239 'dummy.bb.ff = 1;', | |
240 'dummy.cc.ff = 1;', | |
241 'dummy.dd.ff = 1;', | |
242 'dummy.ee.ff = 1;', | |
243 ] | |
244 | |
245 expected = [ | |
246 'goog.provide(\'dummy.aa\');', | |
247 'goog.provide(\'dummy.bb\');', | |
248 'goog.provide(\'dummy.cc\');', | |
249 'goog.provide(\'dummy.dd\');', | |
250 'goog.provide(\'dummy.ee\');', | |
251 '', | |
252 'dummy.aa.ff = 1;', | |
253 'dummy.bb.ff = 1;', | |
254 'dummy.cc.ff = 1;', | |
255 'dummy.dd.ff = 1;', | |
256 'dummy.ee.ff = 1;', | |
257 ] | |
258 | |
259 self._AssertFixes(original, expected, include_header=False) | |
260 | |
261 def testMultipleRequireInsert(self): | |
262 original = [ | |
263 'goog.require(\'dummy.bb\');', | |
264 'goog.require(\'dummy.dd\');', | |
265 '', | |
266 'a = dummy.aa.ff;', | |
267 'b = dummy.bb.ff;', | |
268 'c = dummy.cc.ff;', | |
269 'd = dummy.dd.ff;', | |
270 'e = dummy.ee.ff;', | |
271 ] | |
272 | |
273 expected = [ | |
274 'goog.require(\'dummy.aa\');', | |
275 'goog.require(\'dummy.bb\');', | |
276 'goog.require(\'dummy.cc\');', | |
277 'goog.require(\'dummy.dd\');', | |
278 'goog.require(\'dummy.ee\');', | |
279 '', | |
280 'a = dummy.aa.ff;', | |
281 'b = dummy.bb.ff;', | |
282 'c = dummy.cc.ff;', | |
283 'd = dummy.dd.ff;', | |
284 'e = dummy.ee.ff;', | |
285 ] | |
286 | |
287 self._AssertFixes(original, expected, include_header=False) | |
288 | |
289 def testUnsortedRequires(self): | |
290 """Tests handling of unsorted goog.require statements without header. | |
291 | |
292 Bug 8398202. | |
293 """ | |
294 original = [ | |
295 'goog.require(\'dummy.aa\');', | |
296 'goog.require(\'dummy.Cc\');', | |
297 'goog.require(\'dummy.Dd\');', | |
298 '', | |
299 'function a() {', | |
300 ' dummy.aa.i = 1;', | |
301 ' dummy.Cc.i = 1;', | |
302 ' dummy.Dd.i = 1;', | |
303 '}', | |
304 ] | |
305 | |
306 expected = [ | |
307 'goog.require(\'dummy.Cc\');', | |
308 'goog.require(\'dummy.Dd\');', | |
309 'goog.require(\'dummy.aa\');', | |
310 '', | |
311 'function a() {', | |
312 ' dummy.aa.i = 1;', | |
313 ' dummy.Cc.i = 1;', | |
314 ' dummy.Dd.i = 1;', | |
315 '}', | |
316 ] | |
317 | |
318 self._AssertFixes(original, expected, include_header=False) | |
319 | |
320 def testMissingExtraAndUnsortedRequires(self): | |
321 """Tests handling of missing extra and unsorted goog.require statements.""" | |
322 original = [ | |
323 'goog.require(\'dummy.aa\');', | |
324 'goog.require(\'dummy.Cc\');', | |
325 'goog.require(\'dummy.Dd\');', | |
326 '', | |
327 'var x = new dummy.Bb();', | |
328 'dummy.Cc.someMethod();', | |
329 'dummy.aa.someMethod();', | |
330 ] | |
331 | |
332 expected = [ | |
333 'goog.require(\'dummy.Bb\');', | |
334 'goog.require(\'dummy.Cc\');', | |
335 'goog.require(\'dummy.aa\');', | |
336 '', | |
337 'var x = new dummy.Bb();', | |
338 'dummy.Cc.someMethod();', | |
339 'dummy.aa.someMethod();', | |
340 ] | |
341 | |
342 self._AssertFixes(original, expected) | |
343 | |
344 def testExtraRequireOnFirstLine(self): | |
345 """Tests handling of extra goog.require statement on the first line. | |
346 | |
347 There was a bug when fixjsstyle quits with an exception. It happened if | |
348 - the first line of the file is an extra goog.require() statement, | |
349 - goog.require() statements are not sorted. | |
350 """ | |
351 original = [ | |
352 'goog.require(\'dummy.aa\');', | |
353 'goog.require(\'dummy.cc\');', | |
354 'goog.require(\'dummy.bb\');', | |
355 '', | |
356 'var x = new dummy.bb();', | |
357 'var y = new dummy.cc();', | |
358 ] | |
359 | |
360 expected = [ | |
361 'goog.require(\'dummy.bb\');', | |
362 'goog.require(\'dummy.cc\');', | |
363 '', | |
364 'var x = new dummy.bb();', | |
365 'var y = new dummy.cc();', | |
366 ] | |
367 | |
368 self._AssertFixes(original, expected, include_header=False) | |
369 | |
370 def testUnsortedProvides(self): | |
371 """Tests handling of unsorted goog.provide statements without header. | |
372 | |
373 Bug 8398202. | |
374 """ | |
375 original = [ | |
376 'goog.provide(\'dummy.aa\');', | |
377 'goog.provide(\'dummy.Cc\');', | |
378 'goog.provide(\'dummy.Dd\');', | |
379 '', | |
380 'dummy.aa = function() {};' | |
381 'dummy.Cc = function() {};' | |
382 'dummy.Dd = function() {};' | |
383 ] | |
384 | |
385 expected = [ | |
386 'goog.provide(\'dummy.Cc\');', | |
387 'goog.provide(\'dummy.Dd\');', | |
388 'goog.provide(\'dummy.aa\');', | |
389 '', | |
390 'dummy.aa = function() {};' | |
391 'dummy.Cc = function() {};' | |
392 'dummy.Dd = function() {};' | |
393 ] | |
394 | |
395 self._AssertFixes(original, expected, include_header=False) | |
396 | |
397 def testMissingExtraAndUnsortedProvides(self): | |
398 """Tests handling of missing extra and unsorted goog.provide statements.""" | |
399 original = [ | |
400 'goog.provide(\'dummy.aa\');', | |
401 'goog.provide(\'dummy.Cc\');', | |
402 'goog.provide(\'dummy.Dd\');', | |
403 '', | |
404 'dummy.Cc = function() {};', | |
405 'dummy.Bb = function() {};', | |
406 'dummy.aa.someMethod = function();', | |
407 ] | |
408 | |
409 expected = [ | |
410 'goog.provide(\'dummy.Bb\');', | |
411 'goog.provide(\'dummy.Cc\');', | |
412 'goog.provide(\'dummy.aa\');', | |
413 '', | |
414 'dummy.Cc = function() {};', | |
415 'dummy.Bb = function() {};', | |
416 'dummy.aa.someMethod = function();', | |
417 ] | |
418 | |
419 self._AssertFixes(original, expected) | |
420 | |
421 def testNoRequires(self): | |
422 """Tests positioning of missing requires without existing requires.""" | |
423 original = [ | |
424 'goog.provide(\'dummy.Something\');', | |
425 '', | |
426 'dummy.Something = function() {};', | |
427 '', | |
428 'var x = new dummy.Bb();', | |
429 ] | |
430 | |
431 expected = [ | |
432 'goog.provide(\'dummy.Something\');', | |
433 '', | |
434 'goog.require(\'dummy.Bb\');', | |
435 '', | |
436 'dummy.Something = function() {};', | |
437 '', | |
438 'var x = new dummy.Bb();', | |
439 ] | |
440 | |
441 self._AssertFixes(original, expected) | |
442 | |
443 def testNoProvides(self): | |
444 """Tests positioning of missing provides without existing provides.""" | |
445 original = [ | |
446 'goog.require(\'dummy.Bb\');', | |
447 '', | |
448 'dummy.Something = function() {};', | |
449 '', | |
450 'var x = new dummy.Bb();', | |
451 ] | |
452 | |
453 expected = [ | |
454 'goog.provide(\'dummy.Something\');', | |
455 '', | |
456 'goog.require(\'dummy.Bb\');', | |
457 '', | |
458 'dummy.Something = function() {};', | |
459 '', | |
460 'var x = new dummy.Bb();', | |
461 ] | |
462 | |
463 self._AssertFixes(original, expected) | |
464 | |
465 def testOutputOkayWhenFirstTokenIsDeleted(self): | |
466 """Tests that autofix output is is correct when first token is deleted. | |
467 | |
468 Regression test for bug 4581567 | |
469 """ | |
470 original = ['"use strict";'] | |
471 expected = ["'use strict';"] | |
472 | |
473 self._AssertFixes(original, expected, include_header=False) | |
474 | |
475 def testGoogScopeIndentation(self): | |
476 """Tests Handling a typical end-of-scope indentation fix.""" | |
477 original = [ | |
478 'goog.scope(function() {', | |
479 ' // TODO(brain): Take over the world.', | |
480 '}); // goog.scope', | |
481 ] | |
482 | |
483 expected = [ | |
484 'goog.scope(function() {', | |
485 '// TODO(brain): Take over the world.', | |
486 '}); // goog.scope', | |
487 ] | |
488 | |
489 self._AssertFixes(original, expected) | |
490 | |
491 def testMissingEndOfScopeComment(self): | |
492 """Tests Handling a missing comment at end of goog.scope.""" | |
493 original = [ | |
494 'goog.scope(function() {', | |
495 '});', | |
496 ] | |
497 | |
498 expected = [ | |
499 'goog.scope(function() {', | |
500 '}); // goog.scope', | |
501 ] | |
502 | |
503 self._AssertFixes(original, expected) | |
504 | |
505 def testMissingEndOfScopeCommentWithOtherComment(self): | |
506 """Tests handling an irrelevant comment at end of goog.scope.""" | |
507 original = [ | |
508 'goog.scope(function() {', | |
509 "}); // I don't belong here!", | |
510 ] | |
511 | |
512 expected = [ | |
513 'goog.scope(function() {', | |
514 '}); // goog.scope', | |
515 ] | |
516 | |
517 self._AssertFixes(original, expected) | |
518 | |
519 def testMalformedEndOfScopeComment(self): | |
520 """Tests Handling a malformed comment at end of goog.scope.""" | |
521 original = [ | |
522 'goog.scope(function() {', | |
523 '}); // goog.scope FTW', | |
524 ] | |
525 | |
526 expected = [ | |
527 'goog.scope(function() {', | |
528 '}); // goog.scope', | |
529 ] | |
530 | |
531 self._AssertFixes(original, expected) | |
532 | |
533 def testEndsWithIdentifier(self): | |
534 """Tests Handling case where script ends with identifier. Bug 7643404.""" | |
535 original = [ | |
536 'goog.provide(\'xyz\');', | |
537 '', | |
538 'abc' | |
539 ] | |
540 | |
541 expected = [ | |
542 'goog.provide(\'xyz\');', | |
543 '', | |
544 'abc;' | |
545 ] | |
546 | |
547 self._AssertFixes(original, expected) | |
548 | |
549 def testFileStartsWithSemicolon(self): | |
550 """Tests handling files starting with semicolon. | |
551 | |
552 b/10062516 | |
553 """ | |
554 original = [ | |
555 ';goog.provide(\'xyz\');', | |
556 '', | |
557 'abc;' | |
558 ] | |
559 | |
560 expected = [ | |
561 'goog.provide(\'xyz\');', | |
562 '', | |
563 'abc;' | |
564 ] | |
565 | |
566 self._AssertFixes(original, expected, include_header=False) | |
567 | |
568 def testCodeStartsWithSemicolon(self): | |
569 """Tests handling code in starting with semicolon after comments. | |
570 | |
571 b/10062516 | |
572 """ | |
573 original = [ | |
574 ';goog.provide(\'xyz\');', | |
575 '', | |
576 'abc;' | |
577 ] | |
578 | |
579 expected = [ | |
580 'goog.provide(\'xyz\');', | |
581 '', | |
582 'abc;' | |
583 ] | |
584 | |
585 self._AssertFixes(original, expected) | |
586 | |
587 def _AssertFixes(self, original, expected, include_header=True): | |
588 """Asserts that the error fixer corrects original to expected.""" | |
589 if include_header: | |
590 original = self._GetHeader() + original | |
591 expected = self._GetHeader() + expected | |
592 | |
593 actual = StringIO.StringIO() | |
594 runner.Run('testing.js', error_fixer.ErrorFixer(actual), original) | |
595 actual.seek(0) | |
596 | |
597 expected = [x + '\n' for x in expected] | |
598 | |
599 self.assertListEqual(actual.readlines(), expected) | |
600 | |
601 def _GetHeader(self): | |
602 """Returns a fake header for a JavaScript file.""" | |
603 return [ | |
604 '// Copyright 2011 Google Inc. All Rights Reserved.', | |
605 '', | |
606 '/**', | |
607 ' * @fileoverview Fake file overview.', | |
608 ' * @author fake@google.com (Fake Person)', | |
609 ' */', | |
610 '' | |
611 ] | |
612 | |
613 | |
614 if __name__ == '__main__': | |
615 googletest.main() | |
OLD | NEW |