1import filecmp 2import os 3import shutil 4import tempfile 5import unittest 6 7from test import support 8from test.support import os_helper 9 10 11class FileCompareTestCase(unittest.TestCase): 12 def setUp(self): 13 self.name = os_helper.TESTFN 14 self.name_same = os_helper.TESTFN + '-same' 15 self.name_diff = os_helper.TESTFN + '-diff' 16 data = 'Contents of file go here.\n' 17 for name in [self.name, self.name_same, self.name_diff]: 18 with open(name, 'w', encoding="utf-8") as output: 19 output.write(data) 20 21 with open(self.name_diff, 'a+', encoding="utf-8") as output: 22 output.write('An extra line.\n') 23 self.dir = tempfile.gettempdir() 24 25 def tearDown(self): 26 os.unlink(self.name) 27 os.unlink(self.name_same) 28 os.unlink(self.name_diff) 29 30 def test_matching(self): 31 self.assertTrue(filecmp.cmp(self.name, self.name), 32 "Comparing file to itself fails") 33 self.assertTrue(filecmp.cmp(self.name, self.name, shallow=False), 34 "Comparing file to itself fails") 35 self.assertTrue(filecmp.cmp(self.name, self.name_same), 36 "Comparing file to identical file fails") 37 self.assertTrue(filecmp.cmp(self.name, self.name_same, shallow=False), 38 "Comparing file to identical file fails") 39 40 def test_different(self): 41 self.assertFalse(filecmp.cmp(self.name, self.name_diff), 42 "Mismatched files compare as equal") 43 self.assertFalse(filecmp.cmp(self.name, self.dir), 44 "File and directory compare as equal") 45 46 def test_cache_clear(self): 47 first_compare = filecmp.cmp(self.name, self.name_same, shallow=False) 48 second_compare = filecmp.cmp(self.name, self.name_diff, shallow=False) 49 filecmp.clear_cache() 50 self.assertTrue(len(filecmp._cache) == 0, 51 "Cache not cleared after calling clear_cache") 52 53class DirCompareTestCase(unittest.TestCase): 54 def setUp(self): 55 tmpdir = tempfile.gettempdir() 56 self.dir = os.path.join(tmpdir, 'dir') 57 self.dir_same = os.path.join(tmpdir, 'dir-same') 58 self.dir_diff = os.path.join(tmpdir, 'dir-diff') 59 60 # Another dir is created under dir_same, but it has a name from the 61 # ignored list so it should not affect testing results. 62 self.dir_ignored = os.path.join(self.dir_same, '.hg') 63 64 self.caseinsensitive = os.path.normcase('A') == os.path.normcase('a') 65 data = 'Contents of file go here.\n' 66 for dir in (self.dir, self.dir_same, self.dir_diff, self.dir_ignored): 67 shutil.rmtree(dir, True) 68 os.mkdir(dir) 69 subdir_path = os.path.join(dir, 'subdir') 70 os.mkdir(subdir_path) 71 if self.caseinsensitive and dir is self.dir_same: 72 fn = 'FiLe' # Verify case-insensitive comparison 73 else: 74 fn = 'file' 75 with open(os.path.join(dir, fn), 'w', encoding="utf-8") as output: 76 output.write(data) 77 78 with open(os.path.join(self.dir_diff, 'file2'), 'w', encoding="utf-8") as output: 79 output.write('An extra file.\n') 80 81 def tearDown(self): 82 for dir in (self.dir, self.dir_same, self.dir_diff): 83 shutil.rmtree(dir) 84 85 def test_default_ignores(self): 86 self.assertIn('.hg', filecmp.DEFAULT_IGNORES) 87 88 def test_cmpfiles(self): 89 self.assertTrue(filecmp.cmpfiles(self.dir, self.dir, ['file']) == 90 (['file'], [], []), 91 "Comparing directory to itself fails") 92 self.assertTrue(filecmp.cmpfiles(self.dir, self.dir_same, ['file']) == 93 (['file'], [], []), 94 "Comparing directory to same fails") 95 96 # Try it with shallow=False 97 self.assertTrue(filecmp.cmpfiles(self.dir, self.dir, ['file'], 98 shallow=False) == 99 (['file'], [], []), 100 "Comparing directory to itself fails") 101 self.assertTrue(filecmp.cmpfiles(self.dir, self.dir_same, ['file'], 102 shallow=False), 103 "Comparing directory to same fails") 104 105 # Add different file2 106 with open(os.path.join(self.dir, 'file2'), 'w', encoding="utf-8") as output: 107 output.write('Different contents.\n') 108 109 self.assertFalse(filecmp.cmpfiles(self.dir, self.dir_same, 110 ['file', 'file2']) == 111 (['file'], ['file2'], []), 112 "Comparing mismatched directories fails") 113 114 115 def _assert_lists(self, actual, expected): 116 """Assert that two lists are equal, up to ordering.""" 117 self.assertEqual(sorted(actual), sorted(expected)) 118 119 120 def test_dircmp(self): 121 # Check attributes for comparison of two identical directories 122 left_dir, right_dir = self.dir, self.dir_same 123 d = filecmp.dircmp(left_dir, right_dir) 124 self.assertEqual(d.left, left_dir) 125 self.assertEqual(d.right, right_dir) 126 if self.caseinsensitive: 127 self._assert_lists(d.left_list, ['file', 'subdir']) 128 self._assert_lists(d.right_list, ['FiLe', 'subdir']) 129 else: 130 self._assert_lists(d.left_list, ['file', 'subdir']) 131 self._assert_lists(d.right_list, ['file', 'subdir']) 132 self._assert_lists(d.common, ['file', 'subdir']) 133 self._assert_lists(d.common_dirs, ['subdir']) 134 self.assertEqual(d.left_only, []) 135 self.assertEqual(d.right_only, []) 136 self.assertEqual(d.same_files, ['file']) 137 self.assertEqual(d.diff_files, []) 138 expected_report = [ 139 "diff {} {}".format(self.dir, self.dir_same), 140 "Identical files : ['file']", 141 "Common subdirectories : ['subdir']", 142 ] 143 self._assert_report(d.report, expected_report) 144 145 # Check attributes for comparison of two different directories (right) 146 left_dir, right_dir = self.dir, self.dir_diff 147 d = filecmp.dircmp(left_dir, right_dir) 148 self.assertEqual(d.left, left_dir) 149 self.assertEqual(d.right, right_dir) 150 self._assert_lists(d.left_list, ['file', 'subdir']) 151 self._assert_lists(d.right_list, ['file', 'file2', 'subdir']) 152 self._assert_lists(d.common, ['file', 'subdir']) 153 self._assert_lists(d.common_dirs, ['subdir']) 154 self.assertEqual(d.left_only, []) 155 self.assertEqual(d.right_only, ['file2']) 156 self.assertEqual(d.same_files, ['file']) 157 self.assertEqual(d.diff_files, []) 158 expected_report = [ 159 "diff {} {}".format(self.dir, self.dir_diff), 160 "Only in {} : ['file2']".format(self.dir_diff), 161 "Identical files : ['file']", 162 "Common subdirectories : ['subdir']", 163 ] 164 self._assert_report(d.report, expected_report) 165 166 # Check attributes for comparison of two different directories (left) 167 left_dir, right_dir = self.dir, self.dir_diff 168 shutil.move( 169 os.path.join(self.dir_diff, 'file2'), 170 os.path.join(self.dir, 'file2') 171 ) 172 d = filecmp.dircmp(left_dir, right_dir) 173 self.assertEqual(d.left, left_dir) 174 self.assertEqual(d.right, right_dir) 175 self._assert_lists(d.left_list, ['file', 'file2', 'subdir']) 176 self._assert_lists(d.right_list, ['file', 'subdir']) 177 self._assert_lists(d.common, ['file', 'subdir']) 178 self.assertEqual(d.left_only, ['file2']) 179 self.assertEqual(d.right_only, []) 180 self.assertEqual(d.same_files, ['file']) 181 self.assertEqual(d.diff_files, []) 182 expected_report = [ 183 "diff {} {}".format(self.dir, self.dir_diff), 184 "Only in {} : ['file2']".format(self.dir), 185 "Identical files : ['file']", 186 "Common subdirectories : ['subdir']", 187 ] 188 self._assert_report(d.report, expected_report) 189 190 # Add different file2 191 with open(os.path.join(self.dir_diff, 'file2'), 'w', encoding="utf-8") as output: 192 output.write('Different contents.\n') 193 d = filecmp.dircmp(self.dir, self.dir_diff) 194 self.assertEqual(d.same_files, ['file']) 195 self.assertEqual(d.diff_files, ['file2']) 196 expected_report = [ 197 "diff {} {}".format(self.dir, self.dir_diff), 198 "Identical files : ['file']", 199 "Differing files : ['file2']", 200 "Common subdirectories : ['subdir']", 201 ] 202 self._assert_report(d.report, expected_report) 203 204 def test_dircmp_subdirs_type(self): 205 """Check that dircmp.subdirs respects subclassing.""" 206 class MyDirCmp(filecmp.dircmp): 207 pass 208 d = MyDirCmp(self.dir, self.dir_diff) 209 sub_dirs = d.subdirs 210 self.assertEqual(list(sub_dirs.keys()), ['subdir']) 211 sub_dcmp = sub_dirs['subdir'] 212 self.assertEqual(type(sub_dcmp), MyDirCmp) 213 214 def test_report_partial_closure(self): 215 left_dir, right_dir = self.dir, self.dir_same 216 d = filecmp.dircmp(left_dir, right_dir) 217 left_subdir = os.path.join(left_dir, 'subdir') 218 right_subdir = os.path.join(right_dir, 'subdir') 219 expected_report = [ 220 "diff {} {}".format(self.dir, self.dir_same), 221 "Identical files : ['file']", 222 "Common subdirectories : ['subdir']", 223 '', 224 "diff {} {}".format(left_subdir, right_subdir), 225 ] 226 self._assert_report(d.report_partial_closure, expected_report) 227 228 def test_report_full_closure(self): 229 left_dir, right_dir = self.dir, self.dir_same 230 d = filecmp.dircmp(left_dir, right_dir) 231 left_subdir = os.path.join(left_dir, 'subdir') 232 right_subdir = os.path.join(right_dir, 'subdir') 233 expected_report = [ 234 "diff {} {}".format(self.dir, self.dir_same), 235 "Identical files : ['file']", 236 "Common subdirectories : ['subdir']", 237 '', 238 "diff {} {}".format(left_subdir, right_subdir), 239 ] 240 self._assert_report(d.report_full_closure, expected_report) 241 242 def _assert_report(self, dircmp_report, expected_report_lines): 243 with support.captured_stdout() as stdout: 244 dircmp_report() 245 report_lines = stdout.getvalue().strip().split('\n') 246 self.assertEqual(report_lines, expected_report_lines) 247 248 249if __name__ == "__main__": 250 unittest.main() 251