size: 2 KiB

1local djot = require("djot")
2local to_html = function(s)
3 local doc = djot.parse(s)
4 return djot.render_html(doc)
5end
6local signal = require("posix.signal")
7local resource = require("posix.sys.resource")
8local times = require 'posix.sys.times'.times
9
10-- if you want to be able to interrupt stuck fuzz tests.
11
12math.randomseed(os.time())
13
14local MAXLINES = 5
15local MAXLENGTH = 5
16local NUMTESTS = arg[1] or 200000
17
18local activechars = {
19 '\t', ' ', '[', ']', '1', '2', 'a', 'b',
20 'A', 'B', 'I', 'V', 'i', 'v', '.', ')', '(',
21 '{', '}', '=', '+', '_', '-', '*', '!', '>',
22 '<', '`', '~'
23}
24
25local function randomstring()
26 local numlines = math.random(1,MAXLINES)
27 local buffer = {}
28 for j=1,numlines do
29 -- -1 to privilege blank lines
30 local res = ""
31 local len = math.random(-1,MAXLENGTH)
32 if len < 0 then len = 0 end
33 for i=1,len do
34 local charclass = math.random(1, 4)
35 if charclass < 4 then
36 res = res .. activechars[math.random(1, #activechars)]
37 elseif utf8 then
38 res = res .. utf8.char(math.random(1, 200))
39 else
40 res = res .. string.char(math.random(1, 127))
41 end
42 end
43 buffer[#buffer + 1] = res
44 end
45 local res = table.concat(buffer, "\n")
46 return res
47end
48
49local failures = 0
50
51io.stderr:write("Running fuzz tests: ")
52for i=1,NUMTESTS do
53 local s = randomstring()
54 if i % 1000 == 0 then
55 io.stderr:write(".");
56 end
57 local ok, err = pcall(function ()
58 signal.signal(signal.SIGINT, function(signum)
59 io.stderr:write(string.format("\nInterrupted processing on input %q\n", s))
60 io.stderr:flush()
61 os.exit(128 + signum)
62 end)
63 return to_html(s)
64 end)
65 if not ok then
66 -- try to minimize case
67 local minimal = false
68 local trim_from_front = true
69 while not minimal do
70 local s2
71 if trim_from_front then
72 s2 = string.sub(s, 2, -1)
73 else
74 s2 = string.sub(s, 1, -2)
75 end
76 local ok2, _ = pcall(function () return to_html(s2) end)
77 if ok2 then
78 if trim_from_front then
79 trim_from_front = false
80 else
81 minimal = true
82 end
83 else
84 s = s2
85 end
86 end
87 failures = failures + 1
88 io.stderr:write(string.format("\nFAILURE on\n%q\n", s))
89 io.stderr:write(err .. "\n")
90 end
91end
92
93io.stderr:write("\n")
94os.exit(failures)
95