Skip to content

Commit 88fd71a

Browse files
committed
feat: Add simple framework for regression tests
1 parent 95a0ae5 commit 88fd71a

File tree

2 files changed

+168
-16
lines changed

2 files changed

+168
-16
lines changed

.github/workflows/test_basic.yaml

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,14 @@ jobs:
6161
- name: Run examples
6262
run: |
6363
python3 test.py --tests simple0_m55,simple1_m55,simple0_loop_m55,simple1_loop_m55
64-
examples_ntt_kyber_dilithium_helium_core:
65-
runs-on: ubuntu-latest
66-
steps:
67-
- uses: actions/checkout@v3
68-
- uses: ./.github/actions/setup-ubuntu
69-
- name: Run examples
70-
run: |
71-
python3 example.py --examples ntt_kyber_1_23_45_67_m55,ntt_dilithium_12_34_56_78_m55 --timeout=300
72-
examples_ntt_kyber_dilithium_neon_core:
73-
runs-on: ubuntu-latest
74-
steps:
75-
- uses: actions/checkout@v3
76-
- uses: ./.github/actions/setup-ubuntu
77-
- name: Run examples
78-
run: |
79-
python3 example.py --examples ntt_kyber_123_4567_a55,ntt_dilithium_123_45678_a55 --timeout=300
64+
regression:
65+
runs-on: ubuntu-latest
66+
steps:
67+
- uses: actions/checkout@v3
68+
- uses: ./.github/actions/setup-ubuntu
69+
- name: Run regression tests
70+
run: |
71+
python3 regression.py --iterations 5
8072
sqmag:
8173
runs-on: ubuntu-latest
8274
steps:

regression.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#
2+
# Copyright (c) 2022 Arm Limited
3+
# Copyright (c) 2022 Hanno Becker
4+
# Copyright (c) 2023 Amin Abdulrahman, Matthias Kannwischer
5+
# Copyright (c) 2025 Amin Abdulrahman
6+
# SPDX-License-Identifier: MIT
7+
#
8+
# Permission is hereby granted, free of charge, to any person obtaining a copy
9+
# of this software and associated documentation files (the "Software"), to deal
10+
# in the Software without restriction, including without limitation the rights
11+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
# copies of the Software, and to permit persons to whom the Software is
13+
# furnished to do so, subject to the following conditions:
14+
#
15+
# The above copyright notice and this permission notice shall be included in all
16+
# copies or substantial portions of the Software.
17+
#
18+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
# SOFTWARE.
25+
#
26+
# Author: Amin Abdulrahman <amin@abdulrahman.de>
27+
#
28+
29+
import argparse
30+
import os
31+
import time
32+
33+
from common.OptimizationRunner import OptimizationRunnerException
34+
35+
import slothy.targets.arm_v7m.cortex_m7 as Target_CortexM7
36+
import slothy.targets.arm_v81m.cortex_m55r1 as Target_CortexM55r1
37+
import slothy.targets.arm_v81m.cortex_m85r1 as Target_CortexM85r1
38+
39+
import slothy.targets.aarch64.cortex_a55 as Target_CortexA55
40+
import slothy.targets.aarch64.cortex_a72_frontend as Target_CortexA72
41+
import slothy.targets.aarch64.aarch64_big_experimental as Target_AArch64Big
42+
import slothy.targets.aarch64.apple_m1_firestorm_experimental as Target_AppleM1_firestorm
43+
import slothy.targets.aarch64.apple_m1_icestorm_experimental as Target_AppleM1_icestorm
44+
45+
##########################################################################################
46+
47+
from examples.naive.aarch64.dilithium._example import ntt_dilithium_123_45678
48+
from examples.naive.aarch64.kyber._example import ntt_kyber_123_4567
49+
from examples.naive.aarch64.keccak._example import neon_keccak_x1_no_symbolic
50+
51+
from examples.naive.armv7m.dilithium._example import ntt_dilithium
52+
from examples.naive.armv7m.keccak._example import Keccak
53+
from examples.naive.armv7m.kyber._example import ntt_kyber
54+
55+
from examples.naive.armv8m.kyber._example import (
56+
ntt_kyber_1_23_45_67
57+
)
58+
from examples.naive.armv8m.dilithium._example import (
59+
ntt_dilithium_12_34_56_78
60+
)
61+
62+
def main():
63+
regression_tests = (
64+
neon_keccak_x1_no_symbolic(), # aarch64 spilling
65+
ntt_dilithium_123_45678(), # aarch64 NEON
66+
ntt_kyber_123_4567(), # aarch64 NEON
67+
Keccak(var="xkcp"), # armv7m
68+
ntt_dilithium(), # armv7m
69+
ntt_kyber(), # armv7m
70+
ntt_kyber_1_23_45_67(), # armv8m
71+
ntt_dilithium_12_34_56_78 # armv8m
72+
)
73+
74+
all_regression_test_names = [e.name for e in regression_tests]
75+
76+
parser = argparse.ArgumentParser(
77+
formatter_class=argparse.ArgumentDefaultsHelpFormatter
78+
)
79+
parser.add_argument(
80+
"--regression_tests",
81+
type=str,
82+
default="all",
83+
help=f"The list of regression_tests to be run, comma-separated list from "
84+
f"{all_regression_test_names}. "
85+
f"Format: {{name}}_{{variant}}_{{target}}, e.g., "
86+
"ntt_kyber_123_4567_scalar_load_a55",
87+
)
88+
parser.add_argument("--dry-run", default=False, action="store_true")
89+
parser.add_argument("--debug", default=False, action="store_true")
90+
parser.add_argument("--silent", default=False, action="store_true")
91+
parser.add_argument("--iterations", type=int, default=1)
92+
parser.add_argument("--timeout", type=int, default=0)
93+
parser.add_argument("--debug-logfile", type=str, default=None)
94+
parser.add_argument("--log-model", default=False, action="store_true")
95+
parser.add_argument("--log-model-dir", type=str, default="models")
96+
parser.add_argument(
97+
"--only-target",
98+
type=str,
99+
choices=[
100+
Target_CortexM7.__name__,
101+
Target_CortexM55r1.__name__,
102+
Target_CortexM85r1.__name__,
103+
Target_CortexA55.__name__,
104+
Target_CortexA72.__name__,
105+
Target_AppleM1_firestorm.__name__,
106+
Target_AppleM1_icestorm.__name__,
107+
Target_AArch64Big.__name__,
108+
],
109+
)
110+
args = parser.parse_args()
111+
if args.regression_tests != "all":
112+
todo = args.regression_tests.split(",")
113+
else:
114+
todo = all_regression_test_names
115+
iterations = args.iterations
116+
117+
def run_reg_test(name, **kwargs):
118+
ex = None
119+
for e in regression_tests:
120+
if e.name == name:
121+
ex = e
122+
break
123+
if ex is None:
124+
raise OptimizationRunnerException(f"Could not find regression test {name}")
125+
start_time = time.time()
126+
for _ in range(iterations):
127+
ex.run(**kwargs)
128+
end_time = time.time()
129+
130+
avg_time = (end_time - start_time) / iterations
131+
132+
return e.name, avg_time
133+
134+
reg_res = {}
135+
136+
for e in todo:
137+
n, t = run_reg_test(
138+
e,
139+
debug=args.debug,
140+
dry_run=args.dry_run,
141+
silent=args.silent,
142+
log_model=args.log_model,
143+
debug_logfile=args.debug_logfile,
144+
log_model_dir=args.log_model_dir,
145+
timeout=args.timeout,
146+
only_target=args.only_target,
147+
)
148+
reg_res[n] = t
149+
150+
summary_file = os.environ.get("GITHUB_STEP_SUMMARY")
151+
with open(summary_file, "w") as f:
152+
s = ""
153+
s += "# Regression Test Result\n"
154+
for k, v in reg_res.items():
155+
s += f"{k}: {v}\n"
156+
f.write(s)
157+
158+
159+
if __name__ == "__main__":
160+
main()

0 commit comments

Comments
 (0)