|
19 | 19 | )
|
20 | 20 |
|
21 | 21 | if t.TYPE_CHECKING:
|
| 22 | + from pytest import MonkeyPatch |
| 23 | + |
22 | 24 | from libtmux.server import Server
|
23 | 25 | from libtmux.session import Session
|
24 | 26 |
|
@@ -415,3 +417,186 @@ def test_collisions_with_real_objects(
|
415 | 417 | window1.kill()
|
416 | 418 | if window2:
|
417 | 419 | window2.kill()
|
| 420 | + |
| 421 | + |
| 422 | +def test_imports_coverage() -> None: |
| 423 | + """Test coverage for import statements in random.py.""" |
| 424 | + # This test simply ensures the imports are covered |
| 425 | + from libtmux.test import random |
| 426 | + |
| 427 | + assert hasattr(random, "logging") |
| 428 | + assert hasattr(random, "random") |
| 429 | + assert hasattr(random, "t") |
| 430 | + assert hasattr(random, "TEST_SESSION_PREFIX") |
| 431 | + |
| 432 | + |
| 433 | +def test_iterator_protocol() -> None: |
| 434 | + """Test the complete iterator protocol of RandomStrSequence.""" |
| 435 | + # Test the __iter__ method explicitly |
| 436 | + rng = RandomStrSequence() |
| 437 | + iterator = iter(rng) |
| 438 | + |
| 439 | + # Verify __iter__ returns self |
| 440 | + assert iterator is rng |
| 441 | + |
| 442 | + # Verify __next__ method works after explicit __iter__ call |
| 443 | + result = next(iterator) |
| 444 | + assert isinstance(result, str) |
| 445 | + assert len(result) == 8 |
| 446 | + |
| 447 | + |
| 448 | +def test_get_test_session_name_collision_handling( |
| 449 | + server: Server, |
| 450 | + monkeypatch: MonkeyPatch, |
| 451 | +) -> None: |
| 452 | + """Test that get_test_session_name handles collisions properly.""" |
| 453 | + # Mock server.has_session to first return True (collision) then False |
| 454 | + call_count = 0 |
| 455 | + |
| 456 | + def mock_has_session(name: str) -> bool: |
| 457 | + nonlocal call_count |
| 458 | + call_count += 1 |
| 459 | + # First call returns True (collision), second call returns False |
| 460 | + return call_count == 1 |
| 461 | + |
| 462 | + # Mock the server.has_session method |
| 463 | + monkeypatch.setattr(server, "has_session", mock_has_session) |
| 464 | + |
| 465 | + # Should break out of the loop on the second iteration |
| 466 | + session_name = get_test_session_name(server) |
| 467 | + |
| 468 | + # Verify the method was called twice due to the collision |
| 469 | + assert call_count == 2 |
| 470 | + assert session_name.startswith(TEST_SESSION_PREFIX) |
| 471 | + |
| 472 | + |
| 473 | +def test_get_test_window_name_null_prefix() -> None: |
| 474 | + """Test that get_test_window_name with None prefix raises an assertion error.""" |
| 475 | + # Create a mock session |
| 476 | + mock_session = t.cast("Session", object()) |
| 477 | + |
| 478 | + # Verify that None prefix raises an assertion error |
| 479 | + with pytest.raises(AssertionError): |
| 480 | + get_test_window_name(mock_session, prefix=None) |
| 481 | + |
| 482 | + |
| 483 | +def test_import_typing_coverage() -> None: |
| 484 | + """Test coverage for typing imports in random.py.""" |
| 485 | + # This test covers the TYPE_CHECKING imports |
| 486 | + import typing as t |
| 487 | + |
| 488 | + # Import directly from the module to cover lines |
| 489 | + from libtmux.test import random |
| 490 | + |
| 491 | + # Verify the t.TYPE_CHECKING attribute exists |
| 492 | + assert hasattr(t, "TYPE_CHECKING") |
| 493 | + |
| 494 | + # Check for the typing module import |
| 495 | + assert "t" in dir(random) |
| 496 | + |
| 497 | + |
| 498 | +def test_random_str_sequence_direct_instantiation() -> None: |
| 499 | + """Test direct instantiation of RandomStrSequence class.""" |
| 500 | + # This covers lines in the class definition and __init__ method |
| 501 | + rng = RandomStrSequence() |
| 502 | + |
| 503 | + # Check attributes |
| 504 | + assert hasattr(rng, "characters") |
| 505 | + assert rng.characters == "abcdefghijklmnopqrstuvwxyz0123456789_" |
| 506 | + |
| 507 | + # Check methods |
| 508 | + assert hasattr(rng, "__iter__") |
| 509 | + assert hasattr(rng, "__next__") |
| 510 | + |
| 511 | + |
| 512 | +def test_get_test_window_name_collision_handling( |
| 513 | + session: Session, |
| 514 | + monkeypatch: MonkeyPatch, |
| 515 | +) -> None: |
| 516 | + """Test that get_test_window_name handles collisions properly.""" |
| 517 | + # Create a specific prefix for this test |
| 518 | + prefix = "collision_test_" |
| 519 | + |
| 520 | + # Generate a random window name with our prefix |
| 521 | + first_name = prefix + next(namer) |
| 522 | + |
| 523 | + # Create a real window with this name to force a collision |
| 524 | + window = session.new_window(window_name=first_name) |
| 525 | + try: |
| 526 | + # Now when we call get_test_window_name, it should generate a different name |
| 527 | + window_name = get_test_window_name(session, prefix=prefix) |
| 528 | + |
| 529 | + # Verify we got a different name |
| 530 | + assert window_name != first_name |
| 531 | + assert window_name.startswith(prefix) |
| 532 | + |
| 533 | + # Verify the function worked around the collision properly |
| 534 | + assert not any(w.window_name == window_name for w in session.windows) |
| 535 | + assert any(w.window_name == first_name for w in session.windows) |
| 536 | + finally: |
| 537 | + # Clean up the window we created |
| 538 | + if window: |
| 539 | + window.kill() |
| 540 | + |
| 541 | + |
| 542 | +def test_random_str_sequence_return_statements() -> None: |
| 543 | + """Test the return statements in RandomStrSequence methods.""" |
| 544 | + # Test __iter__ return statement (Line 47) |
| 545 | + rng = RandomStrSequence() |
| 546 | + iter_result = iter(rng) |
| 547 | + assert iter_result is rng # Verify it returns self |
| 548 | + |
| 549 | + # Test __next__ return statement (Line 51) |
| 550 | + next_result = next(rng) |
| 551 | + assert isinstance(next_result, str) |
| 552 | + assert len(next_result) == 8 |
| 553 | + |
| 554 | + |
| 555 | +def test_get_test_session_name_implementation_details( |
| 556 | + server: Server, |
| 557 | + monkeypatch: MonkeyPatch, |
| 558 | +) -> None: |
| 559 | + """Test specific implementation details of get_test_session_name function.""" |
| 560 | + # Create a session with a name that will cause a collision |
| 561 | + # This will test the while loop behavior (Lines 56-59) |
| 562 | + prefix = "collision_prefix_" |
| 563 | + first_random = next(namer) |
| 564 | + |
| 565 | + # Create a session that will match our first attempt inside get_test_session_name |
| 566 | + collision_name = prefix + first_random |
| 567 | + |
| 568 | + # Create a real session to force a collision |
| 569 | + with server.new_session(collision_name): |
| 570 | + # Now when we call get_test_session_name, it will need to try again |
| 571 | + # since the first attempt will collide with our created session |
| 572 | + result = get_test_session_name(server, prefix=prefix) |
| 573 | + |
| 574 | + # Verify collision handling |
| 575 | + assert result != collision_name |
| 576 | + assert result.startswith(prefix) |
| 577 | + |
| 578 | + |
| 579 | +def test_get_test_window_name_branch_coverage(session: Session) -> None: |
| 580 | + """Test branch coverage for get_test_window_name function.""" |
| 581 | + # This tests the branch condition on line 130->128 |
| 582 | + |
| 583 | + # Create a window with a name that will cause a collision |
| 584 | + prefix = "branch_test_" |
| 585 | + first_random = next(namer) |
| 586 | + collision_name = prefix + first_random |
| 587 | + |
| 588 | + # Create a real window with this name |
| 589 | + window = session.new_window(window_name=collision_name) |
| 590 | + |
| 591 | + try: |
| 592 | + # Call function that should handle the collision |
| 593 | + result = get_test_window_name(session, prefix=prefix) |
| 594 | + |
| 595 | + # Verify collision handling behavior |
| 596 | + assert result != collision_name |
| 597 | + assert result.startswith(prefix) |
| 598 | + |
| 599 | + finally: |
| 600 | + # Clean up the window |
| 601 | + if window: |
| 602 | + window.kill() |
0 commit comments