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