Mercurial > pub > dyncall > dyncall
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 |