comparison test/common/rand-sig.lua @ 494:d45c582b5457

- sharing sig generator between call_suite and call_suite_aggrs tests
author Tassilo Philipp
date Mon, 21 Mar 2022 16:06:16 +0100
parents
children 45ac093ca822
comparison
equal deleted inserted replaced
493:75cb8f79d725 494:d45c582b5457
1 -- following knobs control generation:
2
3 -- required to be defined by who is using this:
4 -- minargs
5 -- maxargs
6 -- ncases
7 -- types
8 -- seed
9
10 -- optional (when including aggregate generation):
11 -- minaggrfields
12 -- maxaggrfields
13 -- maxarraylen
14 -- arraydice
15 -- maxaggrdepth
16 -- reqaggrinsig
17
18
19 --------------------------------
20
21 if maxaggrdepth == nil then
22 maxaggrdepth = 3
23 end
24
25
26 -- assure aggr chars are present in pairs (can be weighted, though), to avoid
27 -- inf loops; closing chars are allowed to appear alone, as they are ignored
28 -- without any opening char (does not make a lot of sense, though)
29 pairs_op = { '{', '<' } --, '[' }
30 pairs_cl = { '}', '>' } --, ']' }
31
32 for i = 1, #pairs_op do
33 if string.find(types, '%'..pairs_op[i]) and not string.find(types, '%'..pairs_cl[i]) then
34 types = types..pairs_cl[i]
35 end
36 end
37
38
39 rtypes = "v"..types
40
41 function mkaggr(n_nest, maxdepth, o, c)
42 local s = o
43 local nfields = 0
44
45 repeat
46 local t = c
47 if nfields < maxaggrfields then
48 repeat
49 local id = math.random(#types)
50 t = types:sub(id,id)
51 until t ~= c or nfields >= minaggrfields
52 end
53
54 s_ = mktype(t, n_nest, maxdepth, o)
55 if(#s_ > 0) then
56 nfields = nfields + 1
57 end
58 s = s..s_
59
60 -- member (which cannot be first char) as array? Disallow multidimensional arrays @@@STRUCT allow multidim?
61 if #s > 1 and t ~= c and s:sub(-1) ~= ']' and math.random(arraydice) == 1 then
62 s = s..'['..math.random(maxarraylen)..']'
63 end
64 until t == c
65
66 return s
67 end
68
69 function mktype(t, n_nest, maxdepth, aggr_open)
70 -- aggregate opener?
71 local aggr_i = 0
72 for i = 1, #pairs_op do
73 if pairs_op[i] == t then
74 aggr_i = i
75 break
76 end
77 end
78
79 -- ignore new aggregates if above depth limit
80 if aggr_i ~= 0 and t == pairs_op[aggr_i] then
81 if n_nest < maxdepth then
82 return mkaggr(n_nest + 1, maxdepth, pairs_op[aggr_i], pairs_cl[aggr_i])
83 else
84 return ''
85 end
86 end
87
88 -- aggregate closer?
89 for i = 1, #pairs_cl do
90 if pairs_cl[i] == t then
91 aggr_i = i
92 break
93 end
94 end
95
96 -- if closing char, without any open, ignore
97 if aggr_i ~= 0 and (aggr_open == nil or pairs_op[aggr_i] ~= aggr_open) then
98 return ''
99 end
100
101 return t
102 end
103
104 -- pattern matching aggregate start chars
105 local aggr_op_pattern = '[%'..table.concat(pairs_op,'%')..']'
106
107 math.randomseed(seed)
108 local id
109 local uniq_sigs = { }
110 for i = 1, ncases do
111 local l = ''
112 repeat
113 local nargs = math.random(minargs,maxargs)
114 id = math.random(#rtypes)
115 local sig = { mktype(rtypes:sub(id,id), 0, math.random(maxaggrdepth), nil) } -- random depth avoids excessive nesting
116 for j = 1, nargs do
117 id = math.random(#types)
118 sig[#sig+1] = mktype(types:sub(id,id), 0, math.random(maxaggrdepth), nil) -- random depth avoids excessive nesting
119 end
120 l = table.concat(sig)
121 -- reject dupes, sigs without any aggregate (as this is about aggrs after all), and empty ones (if not wanted)
122 until (reqaggrinsig ~= true or string.match(l, aggr_op_pattern) ~= nil) and uniq_sigs[l] == nil
123 uniq_sigs[l] = 1
124 io.write(l.."\n")
125 end
126