summaryrefslogtreecommitdiff
path: root/test/util
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/util
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/util')
-rw-r--r--test/util/UtilTest.mc66
1 files changed, 66 insertions, 0 deletions
diff --git a/test/util/UtilTest.mc b/test/util/UtilTest.mc
new file mode 100644
index 0000000..ea689a6
--- /dev/null
+++ b/test/util/UtilTest.mc
@@ -0,0 +1,66 @@
+// Author: cirakg & claude ai
+// Summary: Tests for the byte helpers, the 2038-safe clock widening and the job runner.
+
+import Toybox.Lang;
+import Toybox.Test;
+
+(:test)
+function bytesConversions(logger as Test.Logger) as Boolean {
+ return Bytes.toHex(Bytes.fromHex("00FFa5")).equals("00ffa5")
+ && Bytes.equal(Bytes.fromUtf8("é"), [0xc3, 0xa9]b)
+ && Bytes.fromHex("").size() == 0 && Bytes.toHex([]b).equals("")
+ && Bytes.equal(Bytes.concat([1]b, [2, 3]b), [1, 2, 3]b)
+ && Bytes.equal(Bytes.uint64BigEndian(1l), [0, 0, 0, 0, 0, 0, 0, 1]b)
+ && Bytes.equal(Bytes.uint64BigEndian(-1l), [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]b)
+ && Bytes.equal(Bytes.uint64BigEndian(20000000000l / 30), [0, 0, 0, 0, 0x27, 0xbc, 0x86, 0xaa]b)
+ && Bytes.equal(Bytes.uint32BigEndian(0x01020304), [1, 2, 3, 4]b);
+}
+
+(:test)
+function bytesEqualWipeAndXor(logger as Test.Logger) as Boolean {
+ var a = [1, 2, 3]b;
+ var copy = Bytes.copy(a);
+ Bytes.xorInto(copy, [1, 2, 3]b);
+ var wiped = [5, 6]b;
+ Bytes.wipe(wiped);
+ Bytes.wipe(null);
+ return Bytes.equal(a, [1, 2, 3]b) && !Bytes.equal(a, [1, 2]b) && !Bytes.equal(a, [1, 2, 4]b)
+ && Bytes.equal(copy, [0, 0, 0]b) && Bytes.equal(wiped, [0, 0]b);
+}
+
+// After 2038-01-19 the watch's 32-bit clock value is negative; read as
+// unsigned it keeps counting up to 2106.
+(:test)
+function clockWidensTo64Bits(logger as Test.Logger) as Boolean {
+ return Clock.toUnsigned(0x7FFFFFFF) == 2147483647l
+ && Clock.toUnsigned(0x7FFFFFFF + 1) == 2147483648l
+ && Clock.toUnsigned(-1) == 4294967295l
+ && Clock.toUnsigned(0) == 0l
+ && Clock.nowUnix(0) > 1700000000l
+ && Clock.nowUnix(60) - Clock.nowUnix(0) >= 59l;
+}
+
+(:test)
+module JobFixtures {
+ class CountingJob extends Jobs.Job {
+ var done as Number = 0;
+ var calls as Number = 0;
+
+ function initialize() {
+ Job.initialize();
+ }
+
+ function step(budget as Number) as Boolean {
+ calls++;
+ done += budget;
+ return done >= 10;
+ }
+ }
+}
+
+(:test)
+function jobsRunToCompletion(logger as Test.Logger) as Boolean {
+ var job = new JobFixtures.CountingJob();
+ Jobs.runToCompletion(job, 3);
+ return job.calls == 4 && job.done == 12;
+}