99863c4d7b2a3ee8f7b0d0d3e3f924afe7d40fb8
Marco Ricci Rename and regroup all test...

Marco Ricci authored 4 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 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 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 3 months ago

24)     @pytest.mark.parametrize(
25)         ['service', 'expected'],
26)         [
27)             (b'google', google_phrase),
28)             ('twitter', twitter_phrase),
29)         ],
30)     )
Marco Ricci Rename and regroup all test...

Marco Ricci authored 4 months ago

31)     def test_200_basic_configuration(self, service, expected):
32)         assert Vault(phrase=self.phrase).generate(service) == expected
33) 
34)     def test_201_phrase_dependence(self):
35)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

38)         )
39) 
40)     def test_202_reproducibility_and_bytes_service_name(self):
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

44) 
45)     def test_203_reproducibility_and_bytearray_service_name(self):
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

49) 
50)     def test_210_nonstandard_length(self):
51)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

53)         )
54) 
55)     def test_211_repetition_limit(self):
56)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

61)         )
62) 
63)     def test_212_without_symbols(self):
64)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

67)         )
68) 
69)     def test_213_no_numbers(self):
70)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

73)         )
74) 
75)     def test_214_no_lowercase_letters(self):
76)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

79)         )
80) 
81)     def test_215_at_least_5_digits(self):
82)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

85)         )
86) 
87)     def test_216_lots_of_spaces(self):
88)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

91)         )
92) 
93)     def test_217_all_character_classes(self):
94)         assert (
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

105)         )
106) 
107)     def test_218_only_numbers_and_very_high_repetition_limit(self):
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

130)         for substring in forbidden_substrings:
131)             assert substring not in generated
132) 
133)     def test_219_very_limited_character_set(self):
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

138) 
139)     def test_220_character_set_subtraction(self):
140)         assert Vault._subtract(b'be', b'abcdef') == bytearray(b'acdf')
141) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

185) 
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

221)             derivepassphrase.AmbiguousByteRepresentationError
222)         )
223)         if raises:
224)             with pytest.raises(AmbiguousByteRepresentationError):
225)                 binstr(s)
226)         elif isinstance(s, str):
227)             assert binstr(s) == s.encode('UTF-8')
228)             assert binstr(binstr(s)) == s.encode('UTF-8')
229)         else:
230)             assert binstr(s) == bytes(s)
231)             assert binstr(binstr(s)) == bytes(s)
232) 
233)     def test_310_too_many_symbols(self):
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

237)             Vault(phrase=self.phrase, symbol=100)
238) 
239)     def test_311_no_viable_characters(self):
Marco Ricci Reformat everything with ruff

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 months ago

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

Marco Ricci authored 4 months ago

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

Marco Ricci authored 3 months ago

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