88from test .support import os_helper
99
1010
11+ def _create_file_shallow_equal (template_path ,new_path ):
12+ """create a file with the same size and mtime but different content."""
13+ shutil .copy2 (template_path ,new_path )
14+ with open (new_path ,'r+b' )as f :
15+ next_char = bytearray (f .read (1 ))
16+ next_char [0 ]= (next_char [0 ]+ 1 )% 256
17+ f .seek (0 )
18+ f .write (next_char )
19+ shutil .copystat (template_path ,new_path )
20+ assert os .stat (new_path ).st_size == os .stat (template_path ).st_size
21+ assert os .stat (new_path ).st_mtime == os .stat (template_path ).st_mtime
22+
1123class FileCompareTestCase (unittest .TestCase ):
1224def setUp (self ):
1325self .name = os_helper .TESTFN
1426self .name_same = os_helper .TESTFN + '-same'
1527self .name_diff = os_helper .TESTFN + '-diff'
28+ self .name_same_shallow = os_helper .TESTFN + '-same-shallow'
1629data = 'Contents of file go here.\n '
1730for name in [self .name ,self .name_same ,self .name_diff ]:
1831with open (name ,'w' ,encoding = "utf-8" )as output :
1932output .write (data )
2033
2134with open (self .name_diff ,'a+' ,encoding = "utf-8" )as output :
2235output .write ('An extra line.\n ' )
36+
37+ for name in [self .name_same ,self .name_diff ]:
38+ shutil .copystat (self .name ,name )
39+
40+ _create_file_shallow_equal (self .name ,self .name_same_shallow )
41+
2342self .dir = tempfile .gettempdir ()
2443
2544def tearDown (self ):
2645os .unlink (self .name )
2746os .unlink (self .name_same )
2847os .unlink (self .name_diff )
48+ os .unlink (self .name_same_shallow )
2949
3050def test_matching (self ):
3151self .assertTrue (filecmp .cmp (self .name ,self .name ),
@@ -36,12 +56,17 @@ def test_matching(self):
3656"Comparing file to identical file fails" )
3757self .assertTrue (filecmp .cmp (self .name ,self .name_same ,shallow = False ),
3858"Comparing file to identical file fails" )
59+ self .assertTrue (filecmp .cmp (self .name ,self .name_same_shallow ),
60+ "Shallow identical files should be considered equal" )
3961
4062def test_different (self ):
4163self .assertFalse (filecmp .cmp (self .name ,self .name_diff ),
4264"Mismatched files compare as equal" )
4365self .assertFalse (filecmp .cmp (self .name ,self .dir ),
4466"File and directory compare as equal" )
67+ self .assertFalse (filecmp .cmp (self .name ,self .name_same_shallow ,
68+ shallow = False ),
69+ "Mismatched file to shallow identical file compares as equal" )
4570
4671def test_cache_clear (self ):
4772first_compare = filecmp .cmp (self .name ,self .name_same ,shallow = False )
@@ -56,14 +81,26 @@ def setUp(self):
5681self .dir = os .path .join (tmpdir ,'dir' )
5782self .dir_same = os .path .join (tmpdir ,'dir-same' )
5883self .dir_diff = os .path .join (tmpdir ,'dir-diff' )
84+ self .dir_diff_file = os .path .join (tmpdir ,'dir-diff-file' )
85+ self .dir_same_shallow = os .path .join (tmpdir ,'dir-same-shallow' )
5986
6087# Another dir is created under dir_same, but it has a name from the
6188# ignored list so it should not affect testing results.
6289self .dir_ignored = os .path .join (self .dir_same ,'.hg' )
6390
6491self .caseinsensitive = os .path .normcase ('A' )== os .path .normcase ('a' )
6592data = 'Contents of file go here.\n '
66- for dir in (self .dir ,self .dir_same ,self .dir_diff ,self .dir_ignored ):
93+
94+ shutil .rmtree (self .dir ,True )
95+ os .mkdir (self .dir )
96+ subdir_path = os .path .join (self .dir ,'subdir' )
97+ os .mkdir (subdir_path )
98+ dir_file_path = os .path .join (self .dir ,"file" )
99+ with open (dir_file_path ,'w' ,encoding = "utf-8" )as output :
100+ output .write (data )
101+
102+ for dir in (self .dir_same ,self .dir_same_shallow ,
103+ self .dir_diff ,self .dir_diff_file ):
67104shutil .rmtree (dir ,True )
68105os .mkdir (dir )
69106subdir_path = os .path .join (dir ,'subdir' )
@@ -72,14 +109,25 @@ def setUp(self):
72109fn = 'FiLe' # Verify case-insensitive comparison
73110else :
74111fn = 'file'
75- with open (os .path .join (dir ,fn ),'w' ,encoding = "utf-8" )as output :
76- output .write (data )
112+
113+ file_path = os .path .join (dir ,fn )
114+
115+ if dir is self .dir_same_shallow :
116+ _create_file_shallow_equal (dir_file_path ,file_path )
117+ else :
118+ shutil .copy2 (dir_file_path ,file_path )
77119
78120with open (os .path .join (self .dir_diff ,'file2' ),'w' ,encoding = "utf-8" )as output :
79121output .write ('An extra file.\n ' )
80122
123+ # Add different file2 with respect to dir_diff
124+ with open (os .path .join (self .dir_diff_file ,'file2' ),'w' ,encoding = "utf-8" )as output :
125+ output .write ('Different contents.\n ' )
126+
127+
81128def tearDown (self ):
82- for dir in (self .dir ,self .dir_same ,self .dir_diff ):
129+ for dir in (self .dir ,self .dir_same ,self .dir_diff ,
130+ self .dir_same_shallow ,self .dir_diff_file ):
83131shutil .rmtree (dir )
84132
85133def test_default_ignores (self ):
@@ -102,11 +150,7 @@ def test_cmpfiles(self):
102150shallow = False ),
103151"Comparing directory to same fails" )
104152
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 ,
153+ self .assertFalse (filecmp .cmpfiles (self .dir ,self .dir_diff_file ,
110154 ['file' ,'file2' ])==
111155 (['file' ], ['file2' ], []),
112156"Comparing mismatched directories fails" )
@@ -116,11 +160,22 @@ def _assert_lists(self, actual, expected):
116160"""Assert that two lists are equal, up to ordering."""
117161self .assertEqual (sorted (actual ),sorted (expected ))
118162
163+ def test_dircmp_identical_directories (self ):
164+ self ._assert_dircmp_identical_directories ()
165+ self ._assert_dircmp_identical_directories (shallow = False )
119166
120- def test_dircmp (self ):
167+ def test_dircmp_different_file (self ):
168+ self ._assert_dircmp_different_file ()
169+ self ._assert_dircmp_different_file (shallow = False )
170+
171+ def test_dircmp_different_directories (self ):
172+ self ._assert_dircmp_different_directories ()
173+ self ._assert_dircmp_different_directories (shallow = False )
174+
175+ def _assert_dircmp_identical_directories (self ,** options ):
121176# Check attributes for comparison of two identical directories
122177left_dir ,right_dir = self .dir ,self .dir_same
123- d = filecmp .dircmp (left_dir ,right_dir )
178+ d = filecmp .dircmp (left_dir ,right_dir , ** options )
124179self .assertEqual (d .left ,left_dir )
125180self .assertEqual (d .right ,right_dir )
126181if self .caseinsensitive :
@@ -142,9 +197,10 @@ def test_dircmp(self):
142197 ]
143198self ._assert_report (d .report ,expected_report )
144199
200+ def _assert_dircmp_different_directories (self ,** options ):
145201# Check attributes for comparison of two different directories (right)
146202left_dir ,right_dir = self .dir ,self .dir_diff
147- d = filecmp .dircmp (left_dir ,right_dir )
203+ d = filecmp .dircmp (left_dir ,right_dir , ** options )
148204self .assertEqual (d .left ,left_dir )
149205self .assertEqual (d .right ,right_dir )
150206self ._assert_lists (d .left_list , ['file' ,'subdir' ])
@@ -164,12 +220,8 @@ def test_dircmp(self):
164220self ._assert_report (d .report ,expected_report )
165221
166222# 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 )
223+ left_dir ,right_dir = self .dir_diff ,self .dir
224+ d = filecmp .dircmp (left_dir ,right_dir ,** options )
173225self .assertEqual (d .left ,left_dir )
174226self .assertEqual (d .right ,right_dir )
175227self ._assert_lists (d .left_list , ['file' ,'file2' ,'subdir' ])
@@ -180,27 +232,51 @@ def test_dircmp(self):
180232self .assertEqual (d .same_files , ['file' ])
181233self .assertEqual (d .diff_files , [])
182234expected_report = [
183- "diff {} {}" .format (self .dir ,self .dir_diff ),
184- "Only in {} : ['file2']" .format (self .dir ),
235+ "diff {} {}" .format (self .dir_diff ,self .dir ),
236+ "Only in {} : ['file2']" .format (self .dir_diff ),
185237"Identical files : ['file']" ,
186238"Common subdirectories : ['subdir']" ,
187239 ]
188240self ._assert_report (d .report ,expected_report )
189241
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 )
242+
243+ def _assert_dircmp_different_file ( self , ** options ) :
244+ # A different file2
245+ d = filecmp .dircmp (self .dir_diff ,self .dir_diff_file , ** options )
194246self .assertEqual (d .same_files , ['file' ])
195247self .assertEqual (d .diff_files , ['file2' ])
196248expected_report = [
197- "diff {} {}" .format (self .dir ,self .dir_diff ),
249+ "diff {} {}" .format (self .dir_diff ,self .dir_diff_file ),
198250"Identical files : ['file']" ,
199251"Differing files : ['file2']" ,
200252"Common subdirectories : ['subdir']" ,
201253 ]
202254self ._assert_report (d .report ,expected_report )
203255
256+ def test_dircmp_no_shallow_different_file (self ):
257+ # A non shallow different file2
258+ d = filecmp .dircmp (self .dir ,self .dir_same_shallow ,shallow = False )
259+ self .assertEqual (d .same_files , [])
260+ self .assertEqual (d .diff_files , ['file' ])
261+ expected_report = [
262+ "diff {} {}" .format (self .dir ,self .dir_same_shallow ),
263+ "Differing files : ['file']" ,
264+ "Common subdirectories : ['subdir']" ,
265+ ]
266+ self ._assert_report (d .report ,expected_report )
267+
268+ def test_dircmp_shallow_same_file (self ):
269+ # A non shallow different file2
270+ d = filecmp .dircmp (self .dir ,self .dir_same_shallow )
271+ self .assertEqual (d .same_files , ['file' ])
272+ self .assertEqual (d .diff_files , [])
273+ expected_report = [
274+ "diff {} {}" .format (self .dir ,self .dir_same_shallow ),
275+ "Identical files : ['file']" ,
276+ "Common subdirectories : ['subdir']" ,
277+ ]
278+ self ._assert_report (d .report ,expected_report )
279+
204280def test_dircmp_subdirs_type (self ):
205281"""Check that dircmp.subdirs respects subclassing."""
206282class MyDirCmp (filecmp .dircmp ):