-
Notifications
You must be signed in to change notification settings - Fork 0
/
autogenerate_tests.py
133 lines (109 loc) · 4.14 KB
/
autogenerate_tests.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: fenc=utf-8:et:ts=4:sts=4:sw=4:fdm=marker
import os
from shutil import which
import subprocess
from typing import List, Optional
VALIDATION_CONSTANTS = [3, 2, 7, 6, 5, 4, 3, 2]
def validation_digit(first_eight: str) -> int:
dot_product = 0
for i, char in enumerate(first_eight):
dot_product += VALIDATION_CONSTANTS[i] * int(char)
mod = dot_product % 11
if mod == 0:
return 0
if mod == 1:
# If the modulus returns 1 then the random number is not usable
return None
else:
return 11 - mod
def generate_kennitala(first_six: str, randoms: str, century: str) -> Optional[str]:
first_eight = str(first_six) + str(randoms)
validation = validation_digit(first_eight)
kt = None
if validation is not None:
kt = first_eight + str(validation) + str(century)
return kt
def generate_kennitalas(
first_six: str, century: str, random_from: int = 20, random_to: int = 99
) -> List[str]:
kennitalas = []
for n in range(random_from, random_to + 1):
kt = generate_kennitala(first_six, n, century)
if kt is not None:
kennitalas.append(kt)
return kennitalas
def rust_from_kennitalas(kennitalas: List[str]) -> str:
num = len(kennitalas)
test = f"const KENNITALAS: [&'static str; {num}] = [\n"
for kt in kennitalas:
test += f' "{kt}",\n'
test += "];\n"
return test
def test_from_kennitalas(test_name: str, kennitalas: List[str], bad=True) -> str:
assert len(test_name) > 0
assert all(ord(c) < 128 for c in test_name)
test = "#[test]\n"
test += f"fn {test_name}()" + "{\n"
test += rust_from_kennitalas(kennitalas)
test += " for kt_str in KENNITALAS.iter()" + "{\n"
test += " let kt_result = Kennitala::new(kt_str);\n"
if bad:
test += " assert!(kt_result.is_err());\n"
else:
test += "let kt = kt_result.unwrap();\n"
if not bad:
test += " assert_eq!(kt.to_string(), kt_str.to_owned());"
test += " }\n"
test += "}\n"
return test
def run_rustfmt(rust_code):
"""
Run `rustfmt` on the given Rust code if it is available on the current
system.
"""
if which("rustfmt"):
rustfmt = subprocess.Popen(
["rustfmt"], stdin=subprocess.PIPE, stdout=subprocess.PIPE
)
rust_code = rustfmt.communicate(rust_code.encode("utf-8"))[0].decode("utf-8")
return rust_code
def dump_to_file(string: str, file_path: str):
with open(file_path, "w", encoding="utf-8") as f:
f.write(string)
def main():
BAD_PARAMS = [
["month_is_zero_1", "220001", "0"],
["month_is_zero_2", "030012", "9"],
["day_is_zero_1", "000300", "9"],
["day_is_zero_2", "001175", "0"],
["leap_day_in_2001", "290201", "0"],
]
GOOD_PARAMS = [
["new_years_1999", "311299", "9"],
["new_years_2000", "311200", "0"],
["first_january_2001", "010101", "0"],
["leap_day_in_2000", "290200", "0"],
]
file_contents = "// DO NOT EDIT! This file was automatically generated by"
file_contents += " the\n// `autogenerate_tests.py` Python script.\n"
file_contents += "use kennitolur::Kennitala;\n"
file_contents += "use std::string::ToString;\n\n"
for (test_name, first_six, century) in BAD_PARAMS:
kennitalas = generate_kennitalas(first_six, century)
file_contents += test_from_kennitalas(test_name, kennitalas, bad=True)
for (test_name, first_six, century) in GOOD_PARAMS:
kennitalas = generate_kennitalas(first_six, century)
file_contents += test_from_kennitalas(test_name, kennitalas, bad=False)
# Run rustfmt on the generated code
file_contents = run_rustfmt(file_contents)
# Generate the tests/ directory
this_dir = os.path.abspath(os.path.dirname(__file__))
target_dir = os.path.join(this_dir, "tests")
os.makedirs(target_dir, exist_ok=True)
# Dump the generated tests to tests/autogenerated_tests.rs
file_path = os.path.join(target_dir, "autogenerated_tests.rs")
dump_to_file(file_contents, file_path)
if __name__ == "__main__":
main()