|
1 # Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org) |
|
2 # |
|
3 # Redistribution and use in source and binary forms, with or without |
|
4 # modification, are permitted provided that the following conditions |
|
5 # are met: |
|
6 # 1. Redistributions of source code must retain the above copyright |
|
7 # notice, this list of conditions and the following disclaimer. |
|
8 # 2. Redistributions in binary form must reproduce the above copyright |
|
9 # notice, this list of conditions and the following disclaimer in the |
|
10 # documentation and/or other materials provided with the distribution. |
|
11 # |
|
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND |
|
13 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
14 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
15 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR |
|
16 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
17 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
18 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
19 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
|
20 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
21 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
22 |
|
23 """Contains unit tests for filereader.py.""" |
|
24 |
|
25 from __future__ import with_statement |
|
26 |
|
27 import codecs |
|
28 import os |
|
29 import shutil |
|
30 import tempfile |
|
31 import unittest |
|
32 |
|
33 from webkitpy.common.system.logtesting import LoggingTestCase |
|
34 from webkitpy.style.checker import ProcessorBase |
|
35 from webkitpy.style.filereader import TextFileReader |
|
36 |
|
37 |
|
38 class TextFileReaderTest(LoggingTestCase): |
|
39 |
|
40 class MockProcessor(ProcessorBase): |
|
41 |
|
42 """A processor for test purposes. |
|
43 |
|
44 This processor simply records the parameters passed to its process() |
|
45 method for later checking by the unittest test methods. |
|
46 |
|
47 """ |
|
48 |
|
49 def __init__(self): |
|
50 self.processed = [] |
|
51 """The parameters passed for all calls to the process() method.""" |
|
52 |
|
53 def should_process(self, file_path): |
|
54 return not file_path.endswith('should_not_process.txt') |
|
55 |
|
56 def process(self, lines, file_path, test_kwarg=None): |
|
57 self.processed.append((lines, file_path, test_kwarg)) |
|
58 |
|
59 def setUp(self): |
|
60 LoggingTestCase.setUp(self) |
|
61 processor = TextFileReaderTest.MockProcessor() |
|
62 |
|
63 temp_dir = tempfile.mkdtemp() |
|
64 |
|
65 self._file_reader = TextFileReader(processor) |
|
66 self._processor = processor |
|
67 self._temp_dir = temp_dir |
|
68 |
|
69 def tearDown(self): |
|
70 LoggingTestCase.tearDown(self) |
|
71 shutil.rmtree(self._temp_dir) |
|
72 |
|
73 def _create_file(self, rel_path, text, encoding="utf-8"): |
|
74 """Create a file with given text and return the path to the file.""" |
|
75 # FIXME: There are better/more secure APIs for creatin tmp file paths. |
|
76 file_path = os.path.join(self._temp_dir, rel_path) |
|
77 with codecs.open(file_path, "w", encoding) as file: |
|
78 file.write(text) |
|
79 return file_path |
|
80 |
|
81 def _passed_to_processor(self): |
|
82 """Return the parameters passed to MockProcessor.process().""" |
|
83 return self._processor.processed |
|
84 |
|
85 def _assert_file_reader(self, passed_to_processor, file_count): |
|
86 """Assert the state of the file reader.""" |
|
87 self.assertEquals(passed_to_processor, self._passed_to_processor()) |
|
88 self.assertEquals(file_count, self._file_reader.file_count) |
|
89 |
|
90 def test_process_file__does_not_exist(self): |
|
91 try: |
|
92 self._file_reader.process_file('does_not_exist.txt') |
|
93 except SystemExit, err: |
|
94 self.assertEquals(str(err), '1') |
|
95 else: |
|
96 self.fail('No Exception raised.') |
|
97 self._assert_file_reader([], 1) |
|
98 self.assertLog(["ERROR: File does not exist: 'does_not_exist.txt'\n"]) |
|
99 |
|
100 def test_process_file__is_dir(self): |
|
101 temp_dir = os.path.join(self._temp_dir, 'test_dir') |
|
102 os.mkdir(temp_dir) |
|
103 |
|
104 self._file_reader.process_file(temp_dir) |
|
105 |
|
106 # Because the log message below contains exception text, it is |
|
107 # possible that the text varies across platforms. For this reason, |
|
108 # we check only the portion of the log message that we control, |
|
109 # namely the text at the beginning. |
|
110 log_messages = self.logMessages() |
|
111 # We remove the message we are looking at to prevent the tearDown() |
|
112 # from raising an exception when it asserts that no log messages |
|
113 # remain. |
|
114 message = log_messages.pop() |
|
115 |
|
116 self.assertTrue(message.startswith('WARNING: Could not read file. ' |
|
117 "Skipping: '%s'\n " % temp_dir)) |
|
118 |
|
119 self._assert_file_reader([], 1) |
|
120 |
|
121 def test_process_file__should_not_process(self): |
|
122 file_path = self._create_file('should_not_process.txt', 'contents') |
|
123 |
|
124 self._file_reader.process_file(file_path) |
|
125 self._assert_file_reader([], 1) |
|
126 |
|
127 def test_process_file__multiple_lines(self): |
|
128 file_path = self._create_file('foo.txt', 'line one\r\nline two\n') |
|
129 |
|
130 self._file_reader.process_file(file_path) |
|
131 processed = [(['line one\r', 'line two', ''], file_path, None)] |
|
132 self._assert_file_reader(processed, 1) |
|
133 |
|
134 def test_process_file__file_stdin(self): |
|
135 file_path = self._create_file('-', 'file contents') |
|
136 |
|
137 self._file_reader.process_file(file_path=file_path, test_kwarg='foo') |
|
138 processed = [(['file contents'], file_path, 'foo')] |
|
139 self._assert_file_reader(processed, 1) |
|
140 |
|
141 def test_process_file__with_kwarg(self): |
|
142 file_path = self._create_file('foo.txt', 'file contents') |
|
143 |
|
144 self._file_reader.process_file(file_path=file_path, test_kwarg='foo') |
|
145 processed = [(['file contents'], file_path, 'foo')] |
|
146 self._assert_file_reader(processed, 1) |
|
147 |
|
148 def test_process_paths(self): |
|
149 # We test a list of paths that contains both a file and a directory. |
|
150 dir = os.path.join(self._temp_dir, 'foo_dir') |
|
151 os.mkdir(dir) |
|
152 |
|
153 file_path1 = self._create_file('file1.txt', 'foo') |
|
154 |
|
155 rel_path = os.path.join('foo_dir', 'file2.txt') |
|
156 file_path2 = self._create_file(rel_path, 'bar') |
|
157 |
|
158 self._file_reader.process_paths([dir, file_path1]) |
|
159 processed = [(['bar'], file_path2, None), |
|
160 (['foo'], file_path1, None)] |
|
161 self._assert_file_reader(processed, 2) |