Skip to content

Commit 604635f

Browse files
authored
Add pytest coverage for length, between, uuid, MAC, IBAN, cron, encodings and card brands (220 tests)
1 parent 6a488fc commit 604635f

1 file changed

Lines changed: 180 additions & 0 deletions

File tree

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
"""Extended coverage for cron and the base16/32/58/64 encodings.
2+
3+
Existing cron tests are 59 lines and only exercise the happy path plus a
4+
few out-of-range fields; the step/list grammar below is probed, not
5+
assumed. Encoding tests in the repo are 151 lines but leave padding
6+
and alphabet edge cases unpinned.
7+
"""
8+
9+
import pytest
10+
11+
from validators import (
12+
ValidationError,
13+
base16,
14+
base32,
15+
base58,
16+
base64,
17+
cron,
18+
)
19+
20+
21+
# ---------------------------------------------------------------- cron
22+
23+
24+
@pytest.mark.parametrize(
25+
"value",
26+
[
27+
"0 0 * * *",
28+
"*/15 * * * *", # step over the whole range
29+
"0 9-17 * * 1-5", # ranges in two fields
30+
"5/10 * * * *", # a single value with a step is accepted
31+
"0 0 * * 7", # Sunday may be written as 7
32+
"1,2,3 * * * *", # comma list
33+
"0 0 1,15 * *",
34+
"*/2 0-23/2 * * *", # step over a range
35+
" 0 0 * * * ", # extra whitespace is stripped/split away
36+
"30 4 1 * *",
37+
"59 23 31 12 7", # every field at its maximum
38+
"0 0 1 1 0", # every field at its minimum
39+
],
40+
)
41+
def test_cron_returns_true_on_valid_expressions(value):
42+
assert cron(value) is True
43+
44+
45+
@pytest.mark.parametrize(
46+
"value",
47+
[
48+
"*/0 * * * *", # step must be >= 1
49+
"*/abc * * * *", # step must be decimal
50+
"30-20 * * * *", # reversed range
51+
"1,,2 * * * *", # empty list item
52+
"1- * * * *", # dangling range end
53+
"1-2-3 * * * *", # three-part range
54+
"0 0 * * MON", # month/weekday names are not supported
55+
"0 0 0 * *", # day of month starts at 1
56+
"0 0 * 0 *", # month starts at 1
57+
"0 0 * * 8", # weekday ends at 7
58+
"60 * * * *", # minute ends at 59
59+
"0 24 * * *", # hour ends at 23
60+
"0 0 32 * *", # day of month ends at 31
61+
"0 0 * 13 *", # month ends at 12
62+
"-1 * * * *", # negatives are not decimal
63+
"* * * *", # four fields: badly formatted
64+
"0 0 * * * *", # six fields: badly formatted
65+
"",
66+
],
67+
)
68+
def test_cron_returns_failed_validation_on_invalid_expressions(value):
69+
assert isinstance(cron(value), ValidationError)
70+
71+
72+
def test_cron_wrong_field_count_carries_the_reason():
73+
result = cron("* * * *")
74+
assert isinstance(result, ValidationError)
75+
assert result.reason == "Badly formatted cron string"
76+
77+
78+
# ---------------------------------------------------------------- base16
79+
80+
81+
@pytest.mark.parametrize("value", ["00ff", "FF", "a3f4b2", "00" * 10])
82+
def test_base16_returns_true_on_valid_values(value):
83+
assert base16(value) is True
84+
85+
86+
@pytest.mark.parametrize("value", ["", "0", "abc", "0x12", "a3f4Z1", "ff "])
87+
def test_base16_returns_failed_validation_on_invalid_values(value):
88+
assert isinstance(base16(value), ValidationError)
89+
90+
91+
# ---------------------------------------------------------------- base32
92+
93+
94+
@pytest.mark.parametrize(
95+
"value",
96+
[
97+
"MY======", # 1 byte + padding
98+
"MZXW6===", # 2 bytes + padding
99+
"MZXW6YQ=", # 4 bytes + padding
100+
"MZXW6YTBOI======", # 8-char group + padding
101+
"MZXW6", # padding is optional for the short forms
102+
"MZXW6YQ", # 6 chars, no padding needed
103+
"ABCDEFGHIJKLMNOP", # two full 8-char groups
104+
],
105+
)
106+
def test_base32_returns_true_on_valid_values(value):
107+
assert base32(value) is True
108+
109+
110+
@pytest.mark.parametrize(
111+
"value",
112+
[
113+
"",
114+
"MfZW3zLT9Q======", # lower case is not in the alphabet
115+
"MZXW6Y==", # 6 chars may not take "==" padding
116+
"MZXW6YQ==", # 7 chars may take at most one "="
117+
"MZXW6YQ===", # too much padding
118+
"MZXW68==", # '8' is not in the base32 alphabet
119+
"MZXW6YQ=extra",
120+
],
121+
)
122+
def test_base32_returns_failed_validation_on_invalid_values(value):
123+
assert isinstance(base32(value), ValidationError)
124+
125+
126+
# ---------------------------------------------------------------- base58
127+
128+
129+
@pytest.mark.parametrize("value", ["StV1DL6CwTryKyV", "cUSECm5YzcXJwP", "1111111111"])
130+
def test_base58_returns_true_on_valid_values(value):
131+
assert base58(value) is True
132+
133+
134+
@pytest.mark.parametrize(
135+
"value",
136+
[
137+
"",
138+
"0abc", # '0' is excluded from base58
139+
"Oabc", # 'O' is excluded
140+
"Iabc", # 'I' is excluded
141+
"labc", # 'l' is excluded
142+
"abc def", # spaces are excluded
143+
"abc+def", # '+' is excluded
144+
],
145+
)
146+
def test_base58_returns_failed_validation_on_invalid_values(value):
147+
assert isinstance(base58(value), ValidationError)
148+
149+
150+
# ---------------------------------------------------------------- base64
151+
152+
153+
@pytest.mark.parametrize(
154+
"value",
155+
[
156+
"YQ==", # 1 byte
157+
"YWI=", # 2 bytes
158+
"TWFu", # 3 bytes, no padding
159+
"Y2hhcmFjdGVyIHNldA==",
160+
"TWFuTWFu", # two full groups
161+
],
162+
)
163+
def test_base64_returns_true_on_valid_values(value):
164+
assert base64(value) is True
165+
166+
167+
@pytest.mark.parametrize(
168+
"value",
169+
[
170+
"",
171+
"YQ=", # 1 byte needs "==", not "="
172+
"YWI", # missing padding
173+
"YQ==YQ==", # padding may only appear at the end
174+
"Y W I=", # spaces are not in the alphabet
175+
"YQ==\n",
176+
"YQ*=",
177+
],
178+
)
179+
def test_base64_returns_failed_validation_on_invalid_values(value):
180+
assert isinstance(base64(value), ValidationError)

0 commit comments

Comments
 (0)