1
1
import filecmp
2
+ import getopt
2
3
import os
3
4
import re
4
5
import shutil
6
+ import sys
5
7
import tempfile
6
8
import unittest
7
9
@@ -21,7 +23,9 @@ def _create_file_shallow_equal(template_path, new_path):
21
23
assert os .stat (new_path ).st_size == os .stat (template_path ).st_size
22
24
assert os .stat (new_path ).st_mtime == os .stat (template_path ).st_mtime
23
25
26
+
24
27
class FileCompareTestCase (unittest .TestCase ):
28
+
25
29
def setUp (self ):
26
30
self .name = os_helper .TESTFN
27
31
self .name_same = os_helper .TESTFN + '-same'
@@ -367,5 +371,198 @@ def _assert_report(self, dircmp_report, expected_report_lines):
367
371
self .assertEqual (report_lines , expected_report_lines )
368
372
369
373
374
+ class TestFilecmpCLI (unittest .TestCase ):
375
+ """Test the command line interface of filecmp module"""
376
+
377
+ def setUp (self ):
378
+ self .temp_dir = tempfile .mkdtemp ()
379
+ self .addCleanup (shutil .rmtree , self .temp_dir )
380
+
381
+ # Create test directories and files
382
+ self .dir1 = os .path .join (self .temp_dir , 'dir1' )
383
+ self .dir2 = os .path .join (self .temp_dir , 'dir2' )
384
+ os .makedirs (self .dir1 )
385
+ os .makedirs (self .dir2 )
386
+
387
+ # Create identical files
388
+ with open (os .path .join (self .dir1 , 'same.txt' ), 'w' ) as f :
389
+ f .write ('same content' )
390
+ with open (os .path .join (self .dir2 , 'same.txt' ), 'w' ) as f :
391
+ f .write ('same content' )
392
+
393
+ # Create different files
394
+ with open (os .path .join (self .dir1 , 'different.txt' ), 'w' ) as f :
395
+ f .write ('content in dir1' )
396
+ with open (os .path .join (self .dir2 , 'different.txt' ), 'w' ) as f :
397
+ f .write ('content in dir2' )
398
+
399
+ # Create file only in dir1
400
+ with open (os .path .join (self .dir1 , 'only_in_dir1.txt' ), 'w' ) as f :
401
+ f .write ('unique to dir1' )
402
+
403
+ # Create file only in dir2
404
+ with open (os .path .join (self .dir2 , 'only_in_dir2.txt' ), 'w' ) as f :
405
+ f .write ('unique to dir2' )
406
+
407
+ # Create subdirectories for recursive testing
408
+ self .subdir1 = os .path .join (self .dir1 , 'subdir' )
409
+ self .subdir2 = os .path .join (self .dir2 , 'subdir' )
410
+ os .makedirs (self .subdir1 )
411
+ os .makedirs (self .subdir2 )
412
+
413
+ with open (os .path .join (self .subdir1 , 'subfile.txt' ), 'w' ) as f :
414
+ f .write ('sub content' )
415
+ with open (os .path .join (self .subdir2 , 'subfile.txt' ), 'w' ) as f :
416
+ f .write ('different sub content' )
417
+
418
+ def test_demo_basic_comparison (self ):
419
+ """Test basic directory comparison via demo()"""
420
+ old_argv = sys .argv
421
+ try :
422
+ sys .argv = ['filecmp' , self .dir1 , self .dir2 ]
423
+ with support .captured_stdout () as stdout :
424
+ filecmp .__dict__ ['demo' ]()
425
+ output = stdout .getvalue ()
426
+
427
+ # Check that output contains expected comparison results
428
+ self .assertIn ('diff' , output )
429
+ self .assertIn ('same.txt' , output )
430
+ self .assertIn ('different.txt' , output )
431
+ self .assertIn ('only_in_dir1.txt' , output )
432
+ self .assertIn ('only_in_dir2.txt' , output )
433
+ finally :
434
+ sys .argv = old_argv
435
+
436
+ def test_demo_recursive_comparison (self ):
437
+ """Test recursive directory comparison via demo() with -r flag"""
438
+ old_argv = sys .argv
439
+ try :
440
+ sys .argv = ['filecmp' , '-r' , self .dir1 , self .dir2 ]
441
+ with support .captured_stdout () as stdout :
442
+ filecmp .__dict__ ['demo' ]()
443
+ output = stdout .getvalue ()
444
+
445
+ # Check that output contains subdirectory comparison
446
+ self .assertIn ('subdir' , output )
447
+ self .assertIn ('subfile.txt' , output )
448
+ finally :
449
+ sys .argv = old_argv
450
+
451
+ def test_demo_long_flag (self ):
452
+ """Test demo with long --recursive flag (should fail as only -r is supported)"""
453
+ old_argv = sys .argv
454
+ try :
455
+ sys .argv = ['filecmp' , '--recursive' , self .dir1 , self .dir2 ]
456
+ with self .assertRaises (getopt .GetoptError ):
457
+ filecmp .__dict__ ['demo' ]()
458
+ finally :
459
+ sys .argv = old_argv
460
+
461
+ def test_demo_no_arguments (self ):
462
+ """Test demo with no arguments (should raise GetoptError)"""
463
+ old_argv = sys .argv
464
+ try :
465
+ sys .argv = ['filecmp' ]
466
+ with self .assertRaises (getopt .GetoptError ) as cm :
467
+ filecmp .__dict__ ['demo' ]()
468
+ self .assertIn ('need exactly two args' , str (cm .exception ))
469
+ finally :
470
+ sys .argv = old_argv
471
+
472
+ def test_demo_one_argument (self ):
473
+ """Test demo with only one directory argument (should raise GetoptError)"""
474
+ old_argv = sys .argv
475
+ try :
476
+ sys .argv = ['filecmp' , self .dir1 ]
477
+ with self .assertRaises (getopt .GetoptError ) as cm :
478
+ filecmp .__dict__ ['demo' ]()
479
+ self .assertIn ('need exactly two args' , str (cm .exception ))
480
+ finally :
481
+ sys .argv = old_argv
482
+
483
+ def test_demo_three_arguments (self ):
484
+ """Test demo with three arguments (should raise GetoptError)"""
485
+ old_argv = sys .argv
486
+ try :
487
+ sys .argv = ['filecmp' , self .dir1 , self .dir2 , 'extra' ]
488
+ with self .assertRaises (getopt .GetoptError ) as cm :
489
+ filecmp .__dict__ ['demo' ]()
490
+ self .assertIn ('need exactly two args' , str (cm .exception ))
491
+ finally :
492
+ sys .argv = old_argv
493
+
494
+ def test_demo_nonexistent_directory (self ):
495
+ """Test demo with nonexistent directory"""
496
+ old_argv = sys .argv
497
+ try :
498
+ sys .argv = ['filecmp' , self .dir1 , '/nonexistent/path' ]
499
+ # This should raise an exception during comparison
500
+ with self .assertRaises ((FileNotFoundError , OSError )):
501
+ filecmp .__dict__ ['demo' ]()
502
+ finally :
503
+ sys .argv = old_argv
504
+
505
+ def test_demo_identical_directories (self ):
506
+ """Test demo with identical directories"""
507
+
508
+ dir3 = os .path .join (self .temp_dir , 'dir3' )
509
+ dir4 = os .path .join (self .temp_dir , 'dir4' )
510
+ os .makedirs (dir3 )
511
+ os .makedirs (dir4 )
512
+
513
+ with open (os .path .join (dir3 , 'file1.txt' ), 'w' ) as f :
514
+ f .write ('same content' )
515
+ with open (os .path .join (dir4 , 'file1.txt' ), 'w' ) as f :
516
+ f .write ('same content' )
517
+
518
+ old_argv = sys .argv
519
+ try :
520
+ sys .argv = ['filecmp' , dir3 , dir4 ]
521
+ with support .captured_stdout () as stdout :
522
+ filecmp .__dict__ ['demo' ]()
523
+ output = stdout .getvalue ()
524
+
525
+ # Should indicate identical files
526
+ self .assertIn ('Identical files' , output )
527
+ self .assertIn ('file1.txt' , output )
528
+ finally :
529
+ sys .argv = old_argv
530
+
531
+ def test_demo_empty_directories (self ):
532
+ """Test demo with empty directories"""
533
+
534
+ dir3 = os .path .join (self .temp_dir , 'empty1' )
535
+ dir4 = os .path .join (self .temp_dir , 'empty2' )
536
+ os .makedirs (dir3 )
537
+ os .makedirs (dir4 )
538
+
539
+ old_argv = sys .argv
540
+ try :
541
+ sys .argv = ['filecmp' , dir3 , dir4 ]
542
+ with support .captured_stdout () as stdout :
543
+ filecmp .__dict__ ['demo' ]()
544
+ output = stdout .getvalue ()
545
+
546
+ # Should handle empty directories gracefully
547
+ self .assertTrue (len (output ) > 0 )
548
+ finally :
549
+ sys .argv = old_argv
550
+
551
+ def test_demo_with_files_instead_of_directories (self ):
552
+ """Test demo when file paths are given instead of directories"""
553
+
554
+ file1 = os .path .join (self .dir1 , 'same.txt' )
555
+ file2 = os .path .join (self .dir2 , 'same.txt' )
556
+
557
+ old_argv = sys .argv
558
+ try :
559
+ sys .argv = ['filecmp' , file1 , file2 ]
560
+ # This should raise an exception as files are not directories
561
+ with self .assertRaises ((NotADirectoryError , OSError )):
562
+ filecmp .__dict__ ['demo' ]()
563
+ finally :
564
+ sys .argv = old_argv
565
+
566
+
370
567
if __name__ == "__main__" :
371
568
unittest .main ()
0 commit comments