Marco Ricci commited on 2025-08-14 19:10:17
Zeige 1 geänderte Dateien mit 107 Einfügungen und 38 Löschungen.
As in a2c0a0b3b6f000d824787dabc011041549bda206, introduce further classes/groupings for the `vault` derivation scheme tests, trimming test names appropriately.
| ... | ... |
@@ -121,6 +121,10 @@ class TestVault: |
| 121 | 121 |
|
| 122 | 122 |
phrase = PHRASE |
| 123 | 123 |
|
| 124 |
+ |
|
| 125 |
+class TestPhraseDependence: |
|
| 126 |
+ """Test the dependence of the internal hash on the master passphrase.""" |
|
| 127 |
+ |
|
| 124 | 128 |
@hypothesis.given( |
| 125 | 129 |
phrases=strategies.lists( |
| 126 | 130 |
strategies.binary(min_size=1, max_size=BLOCK_SIZE // 2), |
| ... | ... |
@@ -134,7 +138,7 @@ class TestVault: |
| 134 | 138 |
max_size=BLOCK_SIZE // 2, |
| 135 | 139 |
), |
| 136 | 140 |
) |
| 137 |
- def test_100a_create_hash_phrase_dependence_small( |
|
| 141 |
+ def test_small( |
|
| 138 | 142 |
self, |
| 139 | 143 |
phrases: list[bytes], |
| 140 | 144 |
service: str, |
| ... | ... |
@@ -161,7 +165,7 @@ class TestVault: |
| 161 | 165 |
max_size=BLOCK_SIZE // 2, |
| 162 | 166 |
), |
| 163 | 167 |
) |
| 164 |
- def test_100b_create_hash_phrase_dependence_medium( |
|
| 168 |
+ def test_medium( |
|
| 165 | 169 |
self, |
| 166 | 170 |
phrases: list[bytes], |
| 167 | 171 |
service: str, |
| ... | ... |
@@ -190,7 +194,7 @@ class TestVault: |
| 190 | 194 |
max_size=BLOCK_SIZE // 2, |
| 191 | 195 |
), |
| 192 | 196 |
) |
| 193 |
- def test_100c_create_hash_phrase_dependence_large( |
|
| 197 |
+ def test_large( |
|
| 194 | 198 |
self, |
| 195 | 199 |
phrases: tuple[bytes, bytes], |
| 196 | 200 |
service: str, |
| ... | ... |
@@ -223,7 +227,7 @@ class TestVault: |
| 223 | 227 |
max_size=BLOCK_SIZE // 2, |
| 224 | 228 |
), |
| 225 | 229 |
) |
| 226 |
- def test_100d_create_hash_phrase_dependence_mixed( |
|
| 230 |
+ def test_mixed( |
|
| 227 | 231 |
self, |
| 228 | 232 |
phrases: list[bytes], |
| 229 | 233 |
service: str, |
| ... | ... |
@@ -237,6 +241,10 @@ class TestVault: |
| 237 | 241 |
phrase=phrases[0], service=service |
| 238 | 242 |
) != vault.Vault.create_hash(phrase=phrases[1], service=service) |
| 239 | 243 |
|
| 244 |
+ |
|
| 245 |
+class TestServiceNameDependence: |
|
| 246 |
+ """Test the dependence of the internal hash on the service name.""" |
|
| 247 |
+ |
|
| 240 | 248 |
@hypothesis.given( |
| 241 | 249 |
phrase=strategies.text( |
| 242 | 250 |
strategies.characters(min_codepoint=32, max_codepoint=126), |
| ... | ... |
@@ -250,7 +258,7 @@ class TestVault: |
| 250 | 258 |
unique=True, |
| 251 | 259 |
), |
| 252 | 260 |
) |
| 253 |
- def test_101_create_hash_service_name_dependence( |
|
| 261 |
+ def test_service_name_dependence( |
|
| 254 | 262 |
self, |
| 255 | 263 |
phrase: str, |
| 256 | 264 |
services: list[bytes], |
| ... | ... |
@@ -260,6 +268,10 @@ class TestVault: |
| 260 | 268 |
phrase=phrase, service=services[0] |
| 261 | 269 |
) != vault.Vault.create_hash(phrase=phrase, service=services[1]) |
| 262 | 270 |
|
| 271 |
+ |
|
| 272 |
+class TestInterchangablePhrases: |
|
| 273 |
+ """Test the interchangability of certain master passphrases.""" |
|
| 274 |
+ |
|
| 263 | 275 |
@hypothesis.given( |
| 264 | 276 |
phrases=strategies.binary(max_size=BLOCK_SIZE // 2).flatmap( |
| 265 | 277 |
lambda bs: strategies.tuples( |
| ... | ... |
@@ -276,7 +288,7 @@ class TestVault: |
| 276 | 288 |
max_size=32, |
| 277 | 289 |
), |
| 278 | 290 |
) |
| 279 |
- def test_102a_interchangable_phrases_small( |
|
| 291 |
+ def test_small( |
|
| 280 | 292 |
self, |
| 281 | 293 |
phrases: tuple[bytes, bytes], |
| 282 | 294 |
service: str, |
| ... | ... |
@@ -307,7 +319,7 @@ class TestVault: |
| 307 | 319 |
max_size=32, |
| 308 | 320 |
), |
| 309 | 321 |
) |
| 310 |
- def test_102b_interchangable_phrases_large( |
|
| 322 |
+ def test_large( |
|
| 311 | 323 |
self, |
| 312 | 324 |
phrases: tuple[bytes, bytes], |
| 313 | 325 |
service: str, |
| ... | ... |
@@ -318,20 +330,27 @@ class TestVault: |
| 318 | 330 |
phrase=phrases[0], service=service |
| 319 | 331 |
) == vault.Vault.create_hash(phrase=phrases[1], service=service) |
| 320 | 332 |
|
| 333 |
+ |
|
| 334 |
+class TestBasicFunctionalityFromUpstream(TestVault): |
|
| 335 |
+ """Test passphrase derivation with the "vault" scheme: upstream tests.""" |
|
| 336 |
+ |
|
| 321 | 337 |
@Parametrize.SAMPLE_SERVICES_AND_PHRASES |
| 322 |
- def test_200_basic_configuration( |
|
| 338 |
+ def test_basic_configuration( |
|
| 323 | 339 |
self, service: bytes | str, expected: bytes |
| 324 | 340 |
) -> None: |
| 325 | 341 |
"""Deriving a passphrase principally works.""" |
| 326 | 342 |
assert vault.Vault(phrase=self.phrase).generate(service) == expected |
| 327 | 343 |
|
| 328 |
- def test_201_phrase_dependence(self) -> None: |
|
| 344 |
+ def test_phrase_dependence(self) -> None: |
|
| 329 | 345 |
"""The derived passphrase is dependent on the master passphrase.""" |
| 330 | 346 |
assert ( |
| 331 | 347 |
vault.Vault(phrase=(self.phrase + b"X")).generate("google")
|
| 332 | 348 |
== b"n+oIz6sL>K*lTEWYRO%7" |
| 333 | 349 |
) |
| 334 | 350 |
|
| 351 |
+ # TODO(the-13th-letter): Retire this test in favor of |
|
| 352 |
+ # TestPhraseDependence. The first example is a "short" example, the |
|
| 353 |
+ # second is a "mixed" one. |
|
| 335 | 354 |
@hypothesis.given( |
| 336 | 355 |
phrases=strategies.lists( |
| 337 | 356 |
strategies.binary(min_size=1, max_size=32), |
| ... | ... |
@@ -366,7 +385,7 @@ class TestVault: |
| 366 | 385 |
), |
| 367 | 386 |
raises=AssertionError, |
| 368 | 387 |
) |
| 369 |
- def test_201a_phrase_dependence( |
|
| 388 |
+ def test_xxx_phrase_dependence( |
|
| 370 | 389 |
self, |
| 371 | 390 |
phrases: list[bytes], |
| 372 | 391 |
service: str, |
| ... | ... |
@@ -384,19 +403,28 @@ class TestVault: |
| 384 | 403 |
phrase=phrases[1] |
| 385 | 404 |
).generate(service) |
| 386 | 405 |
|
| 387 |
- def test_202a_reproducibility_and_bytes_service_name(self) -> None: |
|
| 406 |
+ |
|
| 407 |
+class TestStringAndBinaryExchangability(TestVault): |
|
| 408 |
+ """Test the exchangability of text and byte strings in the "vault" scheme. |
|
| 409 |
+ |
|
| 410 |
+ This specifically refers to ASCII-cleanliness, and buffer-type |
|
| 411 |
+ independence. |
|
| 412 |
+ |
|
| 413 |
+ """ |
|
| 414 |
+ |
|
| 415 |
+ def test_bytes_service_name(self) -> None: |
|
| 388 | 416 |
"""Deriving a passphrase works equally for byte strings.""" |
| 389 | 417 |
assert vault.Vault(phrase=self.phrase).generate( |
| 390 | 418 |
b"google" |
| 391 | 419 |
) == vault.Vault(phrase=self.phrase).generate("google")
|
| 392 | 420 |
|
| 393 |
- def test_202b_reproducibility_and_bytearray_service_name(self) -> None: |
|
| 421 |
+ def test_bytearray_service_name(self) -> None: |
|
| 394 | 422 |
"""Deriving a passphrase works equally for byte arrays.""" |
| 395 | 423 |
assert vault.Vault(phrase=self.phrase).generate( |
| 396 | 424 |
b"google" |
| 397 | 425 |
) == vault.Vault(phrase=self.phrase).generate(bytearray(b"google")) |
| 398 | 426 |
|
| 399 |
- def test_202c_reproducibility_and_buffer_like_service_name(self) -> None: |
|
| 427 |
+ def test_buffer_like_service_name(self) -> None: |
|
| 400 | 428 |
"""Deriving a passphrase works equally for memory views.""" |
| 401 | 429 |
assert vault.Vault(phrase=self.phrase).generate( |
| 402 | 430 |
b"google" |
| ... | ... |
@@ -414,7 +442,7 @@ class TestVault: |
| 414 | 442 |
max_size=32, |
| 415 | 443 |
), |
| 416 | 444 |
) |
| 417 |
- def test_203a_reproducibility_and_binary_phrases( |
|
| 445 |
+ def test_binary_phrases( |
|
| 418 | 446 |
self, |
| 419 | 447 |
phrase: str, |
| 420 | 448 |
service: str, |
| ... | ... |
@@ -450,7 +478,7 @@ class TestVault: |
| 450 | 478 |
max_size=32, |
| 451 | 479 |
), |
| 452 | 480 |
) |
| 453 |
- def test_203b_reproducibility_and_binary_service_name( |
|
| 481 |
+ def test_binary_service_name( |
|
| 454 | 482 |
self, |
| 455 | 483 |
phrase: str, |
| 456 | 484 |
service: str, |
| ... | ... |
@@ -474,6 +502,8 @@ class TestVault: |
| 474 | 502 |
"service name generate different passphrases" |
| 475 | 503 |
) |
| 476 | 504 |
|
| 505 |
+ # TODO(the-13th-letter): Retire this test in favor of |
|
| 506 |
+ # TestServiceNameDependence. |
|
| 477 | 507 |
@hypothesis.given( |
| 478 | 508 |
phrase=strategies.text( |
| 479 | 509 |
strategies.characters(min_codepoint=32, max_codepoint=126), |
| ... | ... |
@@ -487,7 +517,7 @@ class TestVault: |
| 487 | 517 |
unique=True, |
| 488 | 518 |
), |
| 489 | 519 |
) |
| 490 |
- def test_204a_service_name_dependence( |
|
| 520 |
+ def test_xxx_service_name_dependence( |
|
| 491 | 521 |
self, |
| 492 | 522 |
phrase: str, |
| 493 | 523 |
services: list[bytes], |
| ... | ... |
@@ -497,6 +527,9 @@ class TestVault: |
| 497 | 527 |
phrase=phrase |
| 498 | 528 |
).generate(services[1]) |
| 499 | 529 |
|
| 530 |
+ # TODO(the-13th-letter): Move this test into TestServiceNameDependence |
|
| 531 |
+ # and write a counterpart for TestPhraseDependence. Or, generalize |
|
| 532 |
+ # this test into a class TestConfigDependence. |
|
| 500 | 533 |
@hypothesis.given( |
| 501 | 534 |
phrase=strategies.text( |
| 502 | 535 |
strategies.characters(min_codepoint=32, max_codepoint=126), |
| ... | ... |
@@ -511,7 +544,7 @@ class TestVault: |
| 511 | 544 |
unique=True, |
| 512 | 545 |
), |
| 513 | 546 |
) |
| 514 |
- def test_204b_service_name_dependence_with_config( |
|
| 547 |
+ def test_service_name_dependence_with_config( |
|
| 515 | 548 |
self, |
| 516 | 549 |
phrase: str, |
| 517 | 550 |
config: dict[str, int], |
| ... | ... |
@@ -533,13 +566,25 @@ class TestVault: |
| 533 | 566 |
# implementation, and should be raised. |
| 534 | 567 |
raise |
| 535 | 568 |
|
| 536 |
- def test_210_nonstandard_length(self) -> None: |
|
| 569 |
+ |
|
| 570 |
+# TODO(the-13th-letter): State machine, for master passphrase, service |
|
| 571 |
+# name and config dependence? |
|
| 572 |
+ |
|
| 573 |
+ |
|
| 574 |
+class TestConstraintSatisfactionFromUpstream001(TestVault): |
|
| 575 |
+ """Test passphrase derivation with the "vault" scheme: upstream tests.""" |
|
| 576 |
+ |
|
| 577 |
+ def test_nonstandard_length(self) -> None: |
|
| 537 | 578 |
"""Deriving a passphrase adheres to imposed length limits.""" |
| 538 | 579 |
assert ( |
| 539 | 580 |
vault.Vault(phrase=self.phrase, length=4).generate("google")
|
| 540 | 581 |
== b"xDFu" |
| 541 | 582 |
) |
| 542 | 583 |
|
| 584 |
+ |
|
| 585 |
+class TestConstraintSatisfactionThoroughness001(TestVault): |
|
| 586 |
+ """Test passphrase derivation with the "vault" scheme: constraint satisfaction.""" |
|
| 587 |
+ |
|
| 543 | 588 |
@hypothesis.given( |
| 544 | 589 |
phrase=strategies.one_of( |
| 545 | 590 |
strategies.binary(min_size=1, max_size=100), |
| ... | ... |
@@ -552,7 +597,7 @@ class TestVault: |
| 552 | 597 |
length=strategies.integers(min_value=1, max_value=200), |
| 553 | 598 |
service=strategies.text(min_size=1, max_size=100), |
| 554 | 599 |
) |
| 555 |
- def test_210a_password_with_length( |
|
| 600 |
+ def test_password_with_length( |
|
| 556 | 601 |
self, |
| 557 | 602 |
phrase: str | bytes, |
| 558 | 603 |
length: int, |
| ... | ... |
@@ -562,7 +607,11 @@ class TestVault: |
| 562 | 607 |
password = vault.Vault(phrase=phrase, length=length).generate(service) |
| 563 | 608 |
assert len(password) == length |
| 564 | 609 |
|
| 565 |
- def test_211_repetition_limit(self) -> None: |
|
| 610 |
+ |
|
| 611 |
+class TestConstraintSatisfactionFromUpstream002(TestVault): |
|
| 612 |
+ """Test passphrase derivation with the "vault" scheme: upstream tests.""" |
|
| 613 |
+ |
|
| 614 |
+ def test_repetition_limit(self) -> None: |
|
| 566 | 615 |
"""Deriving a passphrase adheres to imposed repetition limits.""" |
| 567 | 616 |
assert ( |
| 568 | 617 |
vault.Vault( |
| ... | ... |
@@ -571,21 +620,21 @@ class TestVault: |
| 571 | 620 |
== b"IVTDzACftqopUXqDHPkuCIhV" |
| 572 | 621 |
) |
| 573 | 622 |
|
| 574 |
- def test_212_without_symbols(self) -> None: |
|
| 623 |
+ def test_without_symbols(self) -> None: |
|
| 575 | 624 |
"""Deriving a passphrase adheres to imposed limits on symbols.""" |
| 576 | 625 |
assert ( |
| 577 | 626 |
vault.Vault(phrase=self.phrase, symbol=0).generate("google")
|
| 578 | 627 |
== b"XZ4wRe0bZCazbljCaMqR" |
| 579 | 628 |
) |
| 580 | 629 |
|
| 581 |
- def test_213_no_numbers(self) -> None: |
|
| 630 |
+ def test_no_numbers(self) -> None: |
|
| 582 | 631 |
"""Deriving a passphrase adheres to imposed limits on numbers.""" |
| 583 | 632 |
assert ( |
| 584 | 633 |
vault.Vault(phrase=self.phrase, number=0).generate("google")
|
| 585 | 634 |
== b"_*$TVH.%^aZl(LUeOT?>" |
| 586 | 635 |
) |
| 587 | 636 |
|
| 588 |
- def test_214_no_lowercase_letters(self) -> None: |
|
| 637 |
+ def test_no_lowercase_letters(self) -> None: |
|
| 589 | 638 |
""" |
| 590 | 639 |
Deriving a passphrase adheres to imposed limits on lowercase letters. |
| 591 | 640 |
""" |
| ... | ... |
@@ -594,7 +643,7 @@ class TestVault: |
| 594 | 643 |
== b":{?)+7~@OA:L]!0E$)(+"
|
| 595 | 644 |
) |
| 596 | 645 |
|
| 597 |
- def test_215_at_least_5_digits(self) -> None: |
|
| 646 |
+ def test_at_least_5_digits(self) -> None: |
|
| 598 | 647 |
"""Deriving a passphrase adheres to imposed counts of numbers.""" |
| 599 | 648 |
assert ( |
| 600 | 649 |
vault.Vault(phrase=self.phrase, length=8, number=5).generate( |
| ... | ... |
@@ -603,14 +652,14 @@ class TestVault: |
| 603 | 652 |
== b"i0908.7[" |
| 604 | 653 |
) |
| 605 | 654 |
|
| 606 |
- def test_216_lots_of_spaces(self) -> None: |
|
| 655 |
+ def test_lots_of_spaces(self) -> None: |
|
| 607 | 656 |
"""Deriving a passphrase adheres to imposed counts of spaces.""" |
| 608 | 657 |
assert ( |
| 609 | 658 |
vault.Vault(phrase=self.phrase, space=12).generate("songkick")
|
| 610 | 659 |
== b" c 6 Bq % 5fR " |
| 611 | 660 |
) |
| 612 | 661 |
|
| 613 |
- def test_217_all_character_classes(self) -> None: |
|
| 662 |
+ def test_all_character_classes(self) -> None: |
|
| 614 | 663 |
"""Deriving a passphrase adheres to imposed counts of all types.""" |
| 615 | 664 |
assert ( |
| 616 | 665 |
vault.Vault( |
| ... | ... |
@@ -625,6 +674,10 @@ class TestVault: |
| 625 | 674 |
== b": : fv_wqt>a-4w1S R" |
| 626 | 675 |
) |
| 627 | 676 |
|
| 677 |
+ |
|
| 678 |
+class TestConstraintSatisfactionHeavyDuty001(TestVault): |
|
| 679 |
+ """Test passphrase derivation with the "vault" scheme: constraint satisfaction.""" |
|
| 680 |
+ |
|
| 628 | 681 |
@hypothesis.given( |
| 629 | 682 |
phrase=strategies.one_of( |
| 630 | 683 |
strategies.binary(min_size=1), strategies.text(min_size=1) |
| ... | ... |
@@ -674,7 +727,7 @@ class TestVault: |
| 674 | 727 |
}, |
| 675 | 728 |
service="0", |
| 676 | 729 |
).via('branch coverage (test function): "no repeats" case')
|
| 677 |
- def test_217a_all_length_character_and_occurrence_constraints_satisfied( |
|
| 730 |
+ def test_all_length_character_and_occurrence_constraints_satisfied( |
|
| 678 | 731 |
self, |
| 679 | 732 |
phrase: str | bytes, |
| 680 | 733 |
config: dict[str, int], |
| ... | ... |
@@ -726,7 +779,11 @@ class TestVault: |
| 726 | 779 |
"Password does not satisfy character repeat constraints." |
| 727 | 780 |
) |
| 728 | 781 |
|
| 729 |
- def test_218_only_numbers_and_very_high_repetition_limit(self) -> None: |
|
| 782 |
+ |
|
| 783 |
+class TestConstraintSatisfactionFromUpstream003(TestVault): |
|
| 784 |
+ """Test passphrase derivation with the "vault" scheme: upstream tests.""" |
|
| 785 |
+ |
|
| 786 |
+ def test_only_numbers_and_very_high_repetition_limit(self) -> None: |
|
| 730 | 787 |
"""Deriving a passphrase adheres to imposed repetition limits. |
| 731 | 788 |
|
| 732 | 789 |
This example is checked explicitly against forbidden substrings. |
| ... | ... |
@@ -757,6 +814,10 @@ class TestVault: |
| 757 | 814 |
for substring in forbidden_substrings: |
| 758 | 815 |
assert substring not in generated |
| 759 | 816 |
|
| 817 |
+ |
|
| 818 |
+class TestConstraintSatisfactionThoroughness002(TestVault): |
|
| 819 |
+ """Test passphrase derivation with the "vault" scheme: constraint satisfaction.""" |
|
| 820 |
+ |
|
| 760 | 821 |
# This test has time complexity `O(length * repeat)`, both of which |
| 761 | 822 |
# are chosen by hypothesis and thus outside our control. |
| 762 | 823 |
@hypothesis.settings(deadline=None) |
| ... | ... |
@@ -787,19 +848,27 @@ class TestVault: |
| 787 | 848 |
for i in range((length + 1) - (repeat + 1)): |
| 788 | 849 |
assert len(set(password[i : i + repeat + 1])) > 1 |
| 789 | 850 |
|
| 790 |
- def test_219_very_limited_character_set(self) -> None: |
|
| 851 |
+ |
|
| 852 |
+class TestConstraintSatisfactionFromUpstream004(TestVault): |
|
| 853 |
+ """Test passphrase derivation with the "vault" scheme: upstream tests.""" |
|
| 854 |
+ |
|
| 855 |
+ def test_very_limited_character_set(self) -> None: |
|
| 791 | 856 |
"""Deriving a passphrase works even with limited character sets.""" |
| 792 | 857 |
generated = vault.Vault( |
| 793 | 858 |
phrase=b"", length=24, lower=0, upper=0, space=0, symbol=0 |
| 794 | 859 |
).generate("testing")
|
| 795 | 860 |
assert generated == b"763252593304946694588866" |
| 796 | 861 |
|
| 797 |
- def test_220_character_set_subtraction(self) -> None: |
|
| 862 |
+ |
|
| 863 |
+class TestUtilities(TestVault): |
|
| 864 |
+ """Test passphrase derivation with the "vault" scheme: utility tests.""" |
|
| 865 |
+ |
|
| 866 |
+ def test_character_set_subtraction(self) -> None: |
|
| 798 | 867 |
"""Removing allowed characters internally works.""" |
| 799 | 868 |
assert vault.Vault._subtract(b"be", b"abcdef") == bytearray(b"acdf") |
| 800 | 869 |
|
| 801 | 870 |
@Parametrize.ENTROPY_RESULTS |
| 802 |
- def test_221_entropy( |
|
| 871 |
+ def test_entropy( |
|
| 803 | 872 |
self, length: int, settings: dict[str, int], entropy: int |
| 804 | 873 |
) -> None: |
| 805 | 874 |
"""Estimating the entropy and sufficient hash length works.""" |
| ... | ... |
@@ -812,7 +881,7 @@ class TestVault: |
| 812 | 881 |
) |
| 813 | 882 |
assert v._estimate_sufficient_hash_length(8.0) >= entropy |
| 814 | 883 |
|
| 815 |
- def test_222_hash_length_estimation(self) -> None: |
|
| 884 |
+ def test_hash_length_estimation(self) -> None: |
|
| 816 | 885 |
""" |
| 817 | 886 |
Estimating the entropy and hash length for degenerate cases works. |
| 818 | 887 |
""" |
| ... | ... |
@@ -829,7 +898,7 @@ class TestVault: |
| 829 | 898 |
assert v._estimate_sufficient_hash_length() > 0 |
| 830 | 899 |
|
| 831 | 900 |
@Parametrize.SAMPLE_SERVICES_AND_PHRASES |
| 832 |
- def test_223_hash_length_expansion( |
|
| 901 |
+ def test_hash_length_expansion( |
|
| 833 | 902 |
self, |
| 834 | 903 |
monkeypatch: pytest.MonkeyPatch, |
| 835 | 904 |
service: str | bytes, |
| ... | ... |
@@ -848,7 +917,7 @@ class TestVault: |
| 848 | 917 |
assert v.generate(service) == expected |
| 849 | 918 |
|
| 850 | 919 |
@Parametrize.BINARY_STRINGS |
| 851 |
- def test_224_binary_strings(self, s: str | bytes | bytearray) -> None: |
|
| 920 |
+ def test_binary_strings(self, s: str | bytes | bytearray) -> None: |
|
| 852 | 921 |
"""Byte string conversion is idempotent.""" |
| 853 | 922 |
binstr = vault.Vault._get_binary_string |
| 854 | 923 |
if isinstance(s, str): |
| ... | ... |
@@ -858,14 +927,14 @@ class TestVault: |
| 858 | 927 |
assert binstr(s) == bytes(s) |
| 859 | 928 |
assert binstr(binstr(s)) == bytes(s) |
| 860 | 929 |
|
| 861 |
- def test_310_too_many_symbols(self) -> None: |
|
| 930 |
+ def test_too_many_symbols(self) -> None: |
|
| 862 | 931 |
"""Deriving short passphrases with large length constraints fails.""" |
| 863 | 932 |
with pytest.raises( |
| 864 | 933 |
ValueError, match="requested passphrase length too short" |
| 865 | 934 |
): |
| 866 | 935 |
vault.Vault(phrase=self.phrase, symbol=100) |
| 867 | 936 |
|
| 868 |
- def test_311_no_viable_characters(self) -> None: |
|
| 937 |
+ def test_no_viable_characters(self) -> None: |
|
| 869 | 938 |
"""Deriving passphrases without allowed characters fails.""" |
| 870 | 939 |
with pytest.raises(ValueError, match="no allowed characters left"): |
| 871 | 940 |
vault.Vault( |
| ... | ... |
@@ -878,14 +947,14 @@ class TestVault: |
| 878 | 947 |
symbol=0, |
| 879 | 948 |
) |
| 880 | 949 |
|
| 881 |
- def test_320_character_set_subtraction_duplicate(self) -> None: |
|
| 950 |
+ def test_character_set_subtraction_duplicate(self) -> None: |
|
| 882 | 951 |
"""Character sets do not contain duplicate characters.""" |
| 883 | 952 |
with pytest.raises(ValueError, match="duplicate characters"): |
| 884 | 953 |
vault.Vault._subtract(b"abcdef", b"aabbccddeeff") |
| 885 | 954 |
with pytest.raises(ValueError, match="duplicate characters"): |
| 886 | 955 |
vault.Vault._subtract(b"aabbccddeeff", b"abcdef") |
| 887 | 956 |
|
| 888 |
- def test_322_hash_length_estimation(self) -> None: |
|
| 957 |
+ def test_invalid_hash_length_estimation_safety_factor(self) -> None: |
|
| 889 | 958 |
"""Hash length estimation rejects invalid safety factors.""" |
| 890 | 959 |
v = vault.Vault(phrase=self.phrase) |
| 891 | 960 |
with pytest.raises(ValueError, match="invalid safety factor"): |
| 892 | 961 |