Commitf01eef5aRecorded20 Jul 2026Repositorysigil-markdown
test: add differential fuzz harness for the markdown parser
Message
Deterministically generates ~16k markup-dense documents and prints the serialized SXML for each. Running it against the pre-optimization parser and the optimized parser yields byte-identical output, corroborating the golden corpus with far wider input coverage than the fixed fixtures.
Changed
bench/fuzz.sgl | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)Diff
bench/fuzz.sgladded
@@ -0,0 +1,51 @@
+1
;;; Differential fuzz corpus for (sigil markdown).+2
;;;+3
;;; Usage: sigil bench/fuzz.sgl > out.txt+4
;;;+5
;;; Deterministically generates many small documents drawn from a+6
;;; markup-dense alphabet and prints `~s` of (markdown->sxml doc) for each,+7
;;; one record per line. Run this against the ORIGINAL parser and the+8
;;; optimized parser and diff the two outputs: any divergence is a+9
;;; correctness regression the fixed corpus missed. Deterministic (LCG with+10
;;; a fixed seed), so the two runs are directly comparable.+11
+12
(import (sigil markdown)+13
(sigil io)+14
(sigil string))+15
+16
;; Alphabet heavy in inline/block markers plus a little prose.+17
(define alphabet+18
(list #\a #\b #\space #\* #\_ #\` #\[ #\] #\( #\) #\! #\\ #\#+19
#\- #\+ #\| #\: #\~ #\. #\1 #\newline #\space #\a #\space))+20
+21
(define alen (length alphabet))+22
+23
;; Simple LCG (Numerical Recipes constants); pure, seed threaded explicitly.+24
(define (lcg-next state)+25
(modulo (+ (* state 1664525) 1013904223) 4294967296))+26
+27
(define (nth-char idx)+28
(list-ref alphabet (modulo idx alen)))+29
+30
;; Build one document of LEN chars starting from SEED; returns (doc . state).+31
(define (make-doc seed len)+32
(let loop ((k 0) (state seed) (chars '()))+33
(if (>= k len)+34
(cons (list->string (reverse chars)) state)+35
(let ((s2 (lcg-next state)))+36
(loop (+ k 1) s2 (cons (nth-char s2) chars))))))+37
+38
(define (run seed count max-len)+39
(let loop ((i 0) (state seed))+40
(when (< i count)+41
(let* ((len (+ 1 (modulo state max-len)))+42
(r (make-doc state len))+43
(doc (car r))+44
(state2 (cdr r)))+45
(println "~s" (markdown->sxml doc))+46
(loop (+ i 1) (lcg-next state2))))))+47
+48
;; Several regimes: short markup-dense docs and longer multi-line docs.+49
(run 12345 5000 40)+50
(run 987654321 4000 120)+51
(run 55555 2000 300)