UltrafastSecp256k1 3.50.0
Ultra high-performance secp256k1 elliptic curve cryptography library
Loading...
Searching...
No Matches
test_framework.hpp
Go to the documentation of this file.
1#ifndef SECP256K1_TEST_FRAMEWORK_HPP
2#define SECP256K1_TEST_FRAMEWORK_HPP
3#pragma once
4
5// ============================================================================
6// UltrafastSecp256k1 -- Built-in Test Framework
7// ============================================================================
8//
9// Self-contained test infrastructure that is an organic part of the library.
10// No external test frameworks needed. Portable to ANY platform.
11//
12// Architecture:
13// TestCategory (enum) -> groups related tests (field, scalar, point, ...)
14// TestResult -> per-check pass/fail with message
15// TestSuite -> collects results, runs categories, reports
16//
17// Usage:
18// secp256k1::test::TestSuite suite;
19// suite.run(TestCategory::All); // run everything
20// suite.run(TestCategory::FieldArith); // single category
21// suite.run({TestCategory::Point, TestCategory::CT}); // multiple
22// suite.summary(); // print results
23// return suite.failed() ? 1 : 0;
24//
25// On embedded/RTOS, individual categories can run standalone without
26// any I/O dependency -- results are stored in a POD counter struct.
27// ============================================================================
28
29#include <cstdint>
30#include <cstddef>
31
32namespace secp256k1::test {
33
34// -- Test Categories ----------------------------------------------------------
35// Each enum maps to a logical group of tests. Port authors can select
36// which categories to run based on platform capabilities.
37
38enum class TestCategory : uint32_t {
39 // -- Core Arithmetic --
40 FieldArith = 0x0001, // FieldElement +, -, *, sqr, inv, normalize
41 FieldConversions = 0x0002, // from_hex, to_hex, from_bytes, to_bytes, from_limbs
42 FieldEdgeCases = 0x0004, // zero, one, p-1, max limbs, double overflow
43 FieldInverse = 0x0008, // standalone inverse, batch inverse, all algos
44 FieldRepresentations= 0x0010, // 4x64 vs 5x52 vs 10x26 cross-check
45 FieldBranchless = 0x0020, // cmov, cmovznz, select, is_zero, eq
46 FieldOptimal = 0x0040, // to_optimal / from_optimal roundtrip
47
48 ScalarArith = 0x0100, // Scalar +, -, *, inv, neg, is_zero
49 ScalarConversions = 0x0200, // from_hex, to_hex, from_bytes, to_bytes, bit()
50 ScalarEdgeCases = 0x0400, // 0, 1, n-1, n (wraps to 0), n+1 (wraps to 1)
51 ScalarEncoding = 0x0800, // NAF, wNAF encoding correctness
52
53 // -- Point Operations --
54 PointBasic = 0x1000, // add, dbl, negate, infinity, generator
55 PointScalarMul = 0x2000, // scalar_mul, known vectors, iterated
56 PointInplace = 0x4000, // next/prev/dbl/negate_inplace, add_inplace
57 PointPrecomputed = 0x8000, // KPlan, predecomposed, precomputed_wnaf
58 PointSerialization = 0x00010000, // to_compressed, to_uncompressed, from_affine
59 PointEdgeCases = 0x00020000, // P+O, O+P, P+(-P), O+O, 2*O, n*G=O
60
61 // -- Constant-Time Layer --
62 CTOps = 0x00040000, // cmov, cswap, select, masks
63 CTField = 0x00080000, // ct field arithmetic
64 CTScalar = 0x00100000, // ct scalar arithmetic
65 CTPoint = 0x00200000, // complete add, ct scalar_mul
66
67 // -- Advanced Algorithms --
68 GLV = 0x00400000, // GLV decomposition, endomorphism
69 MSM = 0x00800000, // Strauss, Pippenger, unified MSM
70 CombGen = 0x01000000, // Comb generator, CT comb, cache I/O
71 BatchInverse = 0x02000000, // Montgomery batch inverse, SIMD batch
72
73 // -- Protocols --
74 ECDSA = 0x04000000, // sign, verify, deterministic nonce
75 Schnorr = 0x08000000, // BIP-340 sign/verify
76 ECDH = 0x10000000, // shared secret computation
77 Recovery = 0x20000000, // recoverable sig, key recovery
78
79 // -- Aggregate categories --
80 // Use these helper values programmatically:
81 AllField = 0x007F, // all field tests
82 AllScalar = 0x0F00, // all scalar tests
83 AllPoint = 0x003F0000 & 0xFFFF0000, // all point tests -- computed below
84 AllCT = 0x003C0000, // all CT tests
85 AllCore = 0x0FFFFFFF, // field + scalar + point + CT + algorithms
86
87 All = 0xFFFFFFFF, // everything
88};
89
90// Bitwise operators for combining categories
92 return static_cast<TestCategory>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
93}
95 return static_cast<TestCategory>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
96}
97inline constexpr bool has_flag(TestCategory set, TestCategory flag) {
98 return (static_cast<uint32_t>(set) & static_cast<uint32_t>(flag)) != 0;
99}
100
101// -- Test Counters (POD, embeddable) ------------------------------------------
103 uint32_t passed = 0;
104 uint32_t failed = 0;
105 uint32_t skipped = 0;
106
107 uint32_t total() const { return passed + failed + skipped; }
108 bool all_pass() const { return failed == 0; }
109
110 void merge(const TestCounters& other) {
111 passed += other.passed;
112 failed += other.failed;
113 skipped += other.skipped;
114 }
115};
116
117// -- Category name mapping ----------------------------------------------------
118inline const char* category_name(TestCategory cat) {
119 switch (cat) {
120 case TestCategory::FieldArith: return "Field Arithmetic";
121 case TestCategory::FieldConversions: return "Field Conversions";
122 case TestCategory::FieldEdgeCases: return "Field Edge Cases";
123 case TestCategory::FieldInverse: return "Field Inverse";
124 case TestCategory::FieldRepresentations:return "Field Representations";
125 case TestCategory::FieldBranchless: return "Field Branchless";
126 case TestCategory::FieldOptimal: return "Field Optimal Dispatch";
127 case TestCategory::ScalarArith: return "Scalar Arithmetic";
128 case TestCategory::ScalarConversions: return "Scalar Conversions";
129 case TestCategory::ScalarEdgeCases: return "Scalar Edge Cases";
130 case TestCategory::ScalarEncoding: return "Scalar NAF/wNAF";
131 case TestCategory::PointBasic: return "Point Basic";
132 case TestCategory::PointScalarMul: return "Point Scalar Mul";
133 case TestCategory::PointInplace: return "Point In-Place";
134 case TestCategory::PointPrecomputed: return "Point Precomputed";
135 case TestCategory::PointSerialization: return "Point Serialization";
136 case TestCategory::PointEdgeCases: return "Point Edge Cases";
137 case TestCategory::CTOps: return "CT Primitives";
138 case TestCategory::CTField: return "CT Field";
139 case TestCategory::CTScalar: return "CT Scalar";
140 case TestCategory::CTPoint: return "CT Point";
141 case TestCategory::GLV: return "GLV Endomorphism";
142 case TestCategory::MSM: return "Multi-Scalar Mul";
143 case TestCategory::CombGen: return "Comb Generator";
144 case TestCategory::BatchInverse: return "Batch Inverse";
145 case TestCategory::ECDSA: return "ECDSA";
146 case TestCategory::Schnorr: return "Schnorr";
147 case TestCategory::ECDH: return "ECDH";
148 case TestCategory::Recovery: return "Key Recovery";
149 default: return "Unknown";
150 }
151}
152
153// -- Complete list of individual categories for iteration ---------------------
185inline constexpr int NUM_CATEGORIES = sizeof(ALL_CATEGORIES) / sizeof(ALL_CATEGORIES[0]);
186
187} // namespace secp256k1::test
188
189#endif // SECP256K1_TEST_FRAMEWORK_HPP
constexpr bool has_flag(TestCategory set, TestCategory flag)
constexpr TestCategory operator|(TestCategory a, TestCategory b)
constexpr TestCategory operator&(TestCategory a, TestCategory b)
const char * category_name(TestCategory cat)
constexpr int NUM_CATEGORIES
constexpr TestCategory ALL_CATEGORIES[]
void merge(const TestCounters &other)