]> git.codecow.com Git - nano25519.git/commitdiff
Add comprehensive equalbytes unit tests to check byte pairs that would cancel each...
authorChris Duncan <chris@codecow.com>
Fri, 4 Sep 2026 18:18:11 +0000 (11:18 -0700)
committerChris Duncan <chris@codecow.com>
Fri, 4 Sep 2026 18:18:11 +0000 (11:18 -0700)
src/assembly/tests.ts

index cefee970f077d1ef5b8f8d90b00153004dcfaebc..635a32425e089f51c4d7abb76ed339c57e103432 100644 (file)
@@ -6,22 +6,38 @@ import { equalbytes } from './utils'
 /**
  * Tests run on initialization to ensure build is correct.
  */
+function err (fname: string, vector: string, expected: string, actual: string): void {
+       throw new Error(`${fname} build error from "${vector}": expected ${expected}; actual ${actual}`)
+}
+
+function xpass_equalbytes (vector: string, expected: StaticArray<u8>, actual: StaticArray<u8>): void {
+       if (!equalbytes(expected, actual, 32)) {
+               err('equalbytes', vector, `pass [${expected}]`, `fail [${actual}]`)
+       }
+}
+
+function xfail_equalbytes (vector: string, expected: StaticArray<u8>, actual: StaticArray<u8>): void {
+       if (equalbytes(expected, actual, 32)) {
+               err('equalbytes', vector, `fail [${expected}]`, `pass [${actual}]`)
+       }
+}
 
 /**
- * equalbytes - checks masked bytes against the following test keys:
- * - random bytes
- * - all zeros
- * - all ones
+ * equalbytes must report "unequal" for every difference regardless of shape
+ * - `zeros`: lower boundary with every bit cleared
+ * - `ones`: upper boundary with every bit set
+ * - `spread`: all bytes distinct from each other and setting each bit to 0 or 1
  */
 const zeros = new StaticArray<u8>(32).fill(0)
 const ones = new StaticArray<u8>(32).fill(255)
-const random = new StaticArray<u8>(32)
+const spread = new StaticArray<u8>(32)
+// 37 is large enough prime to cover all bit positions as either 0 or 1
 for (let i = 0; i < 32; i++) {
-       random[i] = u8(Math.random() * 256)
+       spread[i] = u8(i * 37)
 }
 
-const vectors = ['zeros', 'ones', 'random',]
-const expecteds = [zeros, ones, random,]
+const vectors = ['zeros', 'ones', 'spread',]
+const expecteds = [zeros, ones, spread,]
 
 const actual = new StaticArray<u8>(32)
 
@@ -29,15 +45,27 @@ for (let v = 0; v < vectors.length; v++) {
        const vector = vectors[v]
        const expected = expecteds[v]
        memory.copy(changetype<usize>(actual), changetype<usize>(expected), 32)
-       if (!equalbytes(actual, expected, 32)) {
-               throw new Error(`equalbytes build error: ${vector} failed instead of passing (expected [${expected}], actual [${actual}])`)
-       }
+       xpass_equalbytes('equal bytes', expected, actual)
+
        for (let i = 0; i < 32; i++) {
                for (let j = 1; j < 256; j++) {
-                       actual[i] ^= u8(j)
-                       if (equalbytes(actual, expected, 32)) {
-                               throw new Error(`equalbytes build error: ${vector} passed instead of failing (expected [${expected}], actual [${actual}])`)
+                       const p = u8(j)
+                       const q = u8(256 - j)
+
+                       // check that any individual bit difference fails
+                       actual[i] ^= p
+                       xfail_equalbytes(vector, expected, actual)
+
+                       // check that |= was not replaced by ^= or += due to a typo
+                       // only necessary to check once per vector, for all bit positions
+                       if (i === 0) {
+                               actual[i + 1] ^= p
+                               xfail_equalbytes(vector, expected, actual)
+                               actual[i + 1] ^= p ^ q
+                               xfail_equalbytes(vector, expected, actual)
+                               actual[i + 1] = expected[i + 1]
                        }
+
                        actual[i] = expected[i]
                }
        }