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