fc8c8f924a2a6876f3f954579e2ad170834a71de
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

1) # SPDX-FileCopyrightText: 2024 Marco Ricci <m@the13thletter.info>
2) #
3) # SPDX-License-Identifier: MIT
4) 
5) """Test passphrase generation via derivepassphrase.Vault."""
6) 
7) from __future__ import annotations
8) 
9) import math
10) from typing import Any
11) 
12) import pytest
13) 
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

14) import derivepassphrase
15) 
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

16) Vault = derivepassphrase.Vault
17) 
18) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

19) class TestVault:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

20)     phrase = b'She cells C shells bye the sea shoars'
21)     google_phrase = rb': 4TVH#5:aZl8LueOT\{'
22)     twitter_phrase = rb"[ (HN_N:lI&<ro=)3'g9"
23) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

24)     @pytest.mark.parametrize(
25)         ['service', 'expected'],
26)         [
27)             (b'google', google_phrase),
28)             ('twitter', twitter_phrase),
29)         ],
30)     )
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

31)     def test_200_basic_configuration(
32)         self, service: bytes | str, expected: bytes
33)     ) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

34)         assert Vault(phrase=self.phrase).generate(service) == expected
35) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

36)     def test_201_phrase_dependence(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

37)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

38)             Vault(phrase=(self.phrase + b'X')).generate('google')
39)             == b'n+oIz6sL>K*lTEWYRO%7'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

40)         )
41) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

42)     def test_202_reproducibility_and_bytes_service_name(self) -> None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

43)         assert Vault(phrase=self.phrase).generate(b'google') == Vault(
44)             phrase=self.phrase
45)         ).generate('google')
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

46) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

47)     def test_203_reproducibility_and_bytearray_service_name(self) -> None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

48)         assert Vault(phrase=self.phrase).generate(b'google') == Vault(
49)             phrase=self.phrase
50)         ).generate(bytearray(b'google'))
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

51) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

52)     def test_210_nonstandard_length(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

53)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

54)             Vault(phrase=self.phrase, length=4).generate('google') == b'xDFu'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

55)         )
56) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

57)     def test_211_repetition_limit(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

58)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

59)             Vault(
60)                 phrase=b'', length=24, symbol=0, number=0, repeat=1
61)             ).generate('asd')
62)             == b'IVTDzACftqopUXqDHPkuCIhV'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

63)         )
64) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

65)     def test_212_without_symbols(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

66)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

67)             Vault(phrase=self.phrase, symbol=0).generate('google')
68)             == b'XZ4wRe0bZCazbljCaMqR'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

69)         )
70) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

71)     def test_213_no_numbers(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

72)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

73)             Vault(phrase=self.phrase, number=0).generate('google')
74)             == b'_*$TVH.%^aZl(LUeOT?>'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

75)         )
76) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

77)     def test_214_no_lowercase_letters(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

78)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

79)             Vault(phrase=self.phrase, lower=0).generate('google')
80)             == b':{?)+7~@OA:L]!0E$)(+'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

81)         )
82) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

83)     def test_215_at_least_5_digits(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

84)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

85)             Vault(phrase=self.phrase, length=8, number=5).generate('songkick')
86)             == b'i0908.7['
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

87)         )
88) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

89)     def test_216_lots_of_spaces(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

90)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

91)             Vault(phrase=self.phrase, space=12).generate('songkick')
92)             == b' c   6 Bq  % 5fR    '
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

93)         )
94) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

95)     def test_217_all_character_classes(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

96)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

97)             Vault(
98)                 phrase=self.phrase,
99)                 lower=2,
100)                 upper=2,
101)                 number=1,
102)                 space=3,
103)                 dash=2,
104)                 symbol=1,
105)             ).generate('google')
106)             == b': : fv_wqt>a-4w1S  R'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

107)         )
108) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

109)     def test_218_only_numbers_and_very_high_repetition_limit(self) -> None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

110)         generated = Vault(
111)             phrase=b'',
112)             length=40,
113)             lower=0,
114)             upper=0,
115)             space=0,
116)             dash=0,
117)             symbol=0,
118)             repeat=4,
119)         ).generate('abcdef')
120)         forbidden_substrings = {
121)             b'0000',
122)             b'1111',
123)             b'2222',
124)             b'3333',
125)             b'4444',
126)             b'5555',
127)             b'6666',
128)             b'7777',
129)             b'8888',
130)             b'9999',
131)         }
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

132)         for substring in forbidden_substrings:
133)             assert substring not in generated
134) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

135)     def test_219_very_limited_character_set(self) -> None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

136)         generated = Vault(
137)             phrase=b'', length=24, lower=0, upper=0, space=0, symbol=0
138)         ).generate('testing')
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

139)         assert generated == b'763252593304946694588866'
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

140) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

141)     def test_220_character_set_subtraction(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

142)         assert Vault._subtract(b'be', b'abcdef') == bytearray(b'acdf')
143) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

144)     @pytest.mark.parametrize(
145)         ['length', 'settings', 'entropy'],
146)         [
147)             (20, {}, math.log2(math.factorial(20)) + 20 * math.log2(94)),
148)             (
149)                 20,
150)                 {'upper': 0, 'number': 0, 'space': 0, 'symbol': 0},
151)                 math.log2(math.factorial(20)) + 20 * math.log2(26),
152)             ),
153)             (0, {}, float('-inf')),
154)             (
155)                 0,
156)                 {'lower': 0, 'number': 0, 'space': 0, 'symbol': 0},
157)                 float('-inf'),
158)             ),
159)             (1, {}, math.log2(94)),
160)             (1, {'upper': 0, 'lower': 0, 'number': 0, 'symbol': 0}, 0.0),
161)         ],
162)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

163)     def test_221_entropy(
164)         self, length: int, settings: dict[str, int], entropy: int
165)     ) -> None:
166)         v = Vault(length=length, **settings)  # type: ignore[arg-type]
167)         assert math.isclose(v._entropy(), entropy)
168)         assert v._estimate_sufficient_hash_length() > 0
169)         if math.isfinite(entropy) and entropy:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

170)             assert v._estimate_sufficient_hash_length(1.0) == math.ceil(
171)                 entropy / 8
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

172)             )
173)         assert v._estimate_sufficient_hash_length(8.0) >= entropy
174) 
175)     def test_222_hash_length_estimation(self) -> None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

176)         v = Vault(
177)             phrase=self.phrase,
178)             lower=0,
179)             upper=0,
180)             number=0,
181)             symbol=0,
182)             space=1,
183)             length=1,
184)         )
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 2 months ago

185)         assert v._entropy() == 0.0
186)         assert v._estimate_sufficient_hash_length() > 0
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

187) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

188)     @pytest.mark.parametrize(
189)         ['service', 'expected'],
190)         [
191)             (b'google', google_phrase),
192)             ('twitter', twitter_phrase),
193)         ],
194)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

195)     def test_223_hash_length_expansion(
196)         self, monkeypatch: Any, service: str | bytes, expected: bytes
197)     ) -> None:
198)         v = Vault(phrase=self.phrase)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

199)         monkeypatch.setattr(
200)             v,
201)             '_estimate_sufficient_hash_length',
202)             lambda *args, **kwargs: 1,  # noqa: ARG005
203)         )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

204)         assert v._estimate_sufficient_hash_length() < len(self.phrase)
205)         assert v.generate(service) == expected
206) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

207)     @pytest.mark.parametrize(
208)         ['s', 'raises'],
209)         [
210)             ('ñ', True),
211)             ('Düsseldorf', True),
212)             ('liberté, egalité, fraternité', True),
213)             ('ASCII', False),
214)             (b'D\xc3\xbcsseldorf', False),
215)             (bytearray([2, 3, 5, 7, 11, 13]), False),
216)         ],
217)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

218)     def test_224_binary_strings(
219)         self, s: str | bytes | bytearray, raises: bool
220)     ) -> None:
221)         binstr = derivepassphrase.Vault._get_binary_string
Marco Ricci Fix style issues with ruff...

Marco Ricci authored 1 month ago

222)         AmbiguousByteRepresentationError = (  # noqa: N806
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

223)             derivepassphrase.AmbiguousByteRepresentationError
224)         )
225)         if raises:
226)             with pytest.raises(AmbiguousByteRepresentationError):
227)                 binstr(s)
228)         elif isinstance(s, str):
229)             assert binstr(s) == s.encode('UTF-8')
230)             assert binstr(binstr(s)) == s.encode('UTF-8')
231)         else:
232)             assert binstr(s) == bytes(s)
233)             assert binstr(binstr(s)) == bytes(s)
234) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

235)     def test_310_too_many_symbols(self) -> None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

236)         with pytest.raises(
237)             ValueError, match='requested passphrase length too short'
238)         ):
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

239)             Vault(phrase=self.phrase, symbol=100)
240) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

241)     def test_311_no_viable_characters(self) -> None:
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

242)         with pytest.raises(ValueError, match='no allowed characters left'):
243)             Vault(
244)                 phrase=self.phrase,
245)                 lower=0,
246)                 upper=0,
247)                 number=0,
248)                 space=0,
249)                 dash=0,
250)                 symbol=0,
251)             )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

252) 
Marco Ricci Fix typing issues in mypy s...

Marco Ricci authored 1 month ago

253)     def test_320_character_set_subtraction_duplicate(self) -> None:
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

254)         with pytest.raises(ValueError, match='duplicate characters'):
255)             Vault._subtract(b'abcdef', b'aabbccddeeff')
256)         with pytest.raises(ValueError, match='duplicate characters'):
257)             Vault._subtract(b'aabbccddeeff', b'abcdef')
258) 
259)     def test_322_hash_length_estimation(self) -> None:
260)         v = Vault(phrase=self.phrase)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

261)         with pytest.raises(ValueError, match='invalid safety factor'):
Marco Ricci Rename and regroup all test...

Marco Ricci authored 2 months ago

262)             assert v._estimate_sufficient_hash_length(-1.0)
Marco Ricci Reformat everything with ruff

Marco Ricci authored 1 month ago

263)         with pytest.raises(
264)             TypeError, match='invalid safety factor: not a float'
265)         ):