aboutsummaryrefslogtreecommitdiff
path: root/test/BenchTest.mc
diff options
context:
space:
mode:
authorcirakg <cirakg@cirakg.xyz>2026-10-18 23:44:18 +0200
committercirakg <cirakg@cirakg.xyz>2026-10-18 23:44:18 +0200
commit93aa7e3aa291f3328cf34a5a2f86172f41d0affd (patch)
treeac44438e7340fde609ad6458e31e122612cf35d1 /test/BenchTest.mc
parent5646ae7f40dc53c9ebed0b3b6e907cc85fcd5993 (diff)
test: add cross-checked crypto/OTP vectors, unit tests and stricter screenshots
- gen_vectors.py: RFC/FIPS/NIST vectors recomputed with Python's stdlib (openssl for AES) before use, plus seeded cases around SHA padding boundaries, 2038 and 2100; generates test/data/Vectors.mc. - 31 Monkey C tests (hashes, HMAC, PBKDF2, HKDF, AES, sealed records incl. every-byte tamper detection, Base32 errors, 100 OTP and 12 Steam vectors, clock, jobs) and a benchmark; pass on all four test devices. - Screenshot tolerance 0.01 %: one changed character no longer passes. - Golden images updated for version 0.2.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'test/BenchTest.mc')
-rw-r--r--test/BenchTest.mc70
1 files changed, 70 insertions, 0 deletions
diff --git a/test/BenchTest.mc b/test/BenchTest.mc
new file mode 100644
index 0000000..7e1f612
--- /dev/null
+++ b/test/BenchTest.mc
@@ -0,0 +1,70 @@
+// Author: cirakg & claude ai
+// Summary: Benchmarks of the crypto and OTP primitives; logs BENCH lines for docs/PERFORMANCE.md, never fails.
+//
+// Simulator timings run on the PC's CPU, so they only compare primitives with
+// each other (for example how much SHA-512 costs against native SHA-1).
+// Watch timings come from the on-watch benchmark in M4.
+
+import Toybox.Lang;
+import Toybox.System;
+import Toybox.Test;
+
+(:test)
+module Bench {
+ // Run fn `times` times and log the average in microseconds.
+ function measure(logger as Test.Logger, name as String, times as Number, fn as Method() as Void) as Void {
+ var start = System.getTimer();
+ for (var i = 0; i < times; i++) {
+ fn.invoke();
+ }
+ var elapsed = System.getTimer() - start;
+ logger.debug("BENCH " + name + " us_per_call=" + (elapsed * 1000 / times));
+ }
+
+ class Cases {
+ var secret20 as ByteArray = new [20]b;
+ var secret64 as ByteArray = new [64]b;
+ var keys as SealedBox.Keys = new SealedBox.Keys(new [32]b);
+ var box as ByteArray = []b;
+
+ function initialize() {
+ box = SealedBox.seal(keys, []b, new [20]b);
+ }
+
+ function totpSha1() as Void {
+ Otp.totp(Hashes.SHA1, secret20, 1700000000l, 30, 6);
+ }
+
+ function totpSha256() as Void {
+ Otp.totp(Hashes.SHA256, secret20, 1700000000l, 30, 6);
+ }
+
+ function totpSha512() as Void {
+ Otp.totp(Hashes.SHA512, secret64, 1700000000l, 30, 6);
+ }
+
+ function pbkdf2Thousand() as Void {
+ Kdf.pbkdf2([1, 2, 3, 4, 5, 6]b, new [16]b, 1000, 32);
+ }
+
+ function sealOpen() as Void {
+ SealedBox.open(keys, []b, SealedBox.seal(keys, []b, new [20]b));
+ }
+
+ function selfTest() as Void {
+ SelfTest.run();
+ }
+ }
+}
+
+(:test)
+function benchmarkPrimitives(logger as Test.Logger) as Boolean {
+ var c = new Bench.Cases();
+ Bench.measure(logger, "totp_sha1", 20, c.method(:totpSha1));
+ Bench.measure(logger, "totp_sha256", 20, c.method(:totpSha256));
+ Bench.measure(logger, "totp_sha512", 20, c.method(:totpSha512));
+ Bench.measure(logger, "pbkdf2_1000_iterations", 3, c.method(:pbkdf2Thousand));
+ Bench.measure(logger, "sealedbox_seal_open", 20, c.method(:sealOpen));
+ Bench.measure(logger, "self_test", 3, c.method(:selfTest));
+ return true;
+}