1
1
package fred
2
2
3
3
import scala .util .Random
4
+ import java .nio .file .Files
5
+ import java .nio .file .Path
4
6
5
7
import org .scalatest .matchers .should
6
8
import org .scalatest .propspec .AnyPropSpec
@@ -14,6 +16,234 @@ import fred.GenUtil.{GenStmt, GeneratedProgram}
14
16
15
17
class FuzzTests
16
18
extends AnyPropSpec with ScalaCheckPropertyChecks with should.Matchers {
19
+
20
+ val bad = GeneratedProgram (
21
+ List (
22
+ TypeDef (
23
+ Spanned (" OptT0" , Span (- 1 , - 1 )),
24
+ List (
25
+ EnumCase (
26
+ Spanned (" SomeT0" , Span (- 1 , - 1 )),
27
+ List (FieldDef (
28
+ false ,
29
+ Spanned (" value" , Span (- 1 , - 1 )),
30
+ TypeRef (" T0" , Span (- 1 , - 1 )),
31
+ Span (- 1 , - 1 )
32
+ )),
33
+ Span (- 1 , - 1 )
34
+ ),
35
+ EnumCase (Spanned (" NoneT0" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
36
+ ),
37
+ Span (- 1 , - 1 )
38
+ ),
39
+ TypeDef (
40
+ Spanned (" OptT1" , Span (- 1 , - 1 )),
41
+ List (
42
+ EnumCase (
43
+ Spanned (" SomeT1" , Span (- 1 , - 1 )),
44
+ List (FieldDef (
45
+ false ,
46
+ Spanned (" value" , Span (- 1 , - 1 )),
47
+ TypeRef (" T1" , Span (- 1 , - 1 )),
48
+ Span (- 1 , - 1 )
49
+ )),
50
+ Span (- 1 , - 1 )
51
+ ),
52
+ EnumCase (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
53
+ ),
54
+ Span (- 1 , - 1 )
55
+ ),
56
+ TypeDef (
57
+ Spanned (" T1" , Span (- 1 , - 1 )),
58
+ List (EnumCase (
59
+ Spanned (" T1" , Span (- 1 , - 1 )),
60
+ List (
61
+ FieldDef (
62
+ true ,
63
+ Spanned (" f0" , Span (- 1 , - 1 )),
64
+ TypeRef (" OptT1" , Span (- 1 , - 1 )),
65
+ Span (- 1 , - 1 )
66
+ ),
67
+ FieldDef (
68
+ true ,
69
+ Spanned (" f1" , Span (- 1 , - 1 )),
70
+ TypeRef (" OptT0" , Span (- 1 , - 1 )),
71
+ Span (- 1 , - 1 )
72
+ ),
73
+ FieldDef (
74
+ true ,
75
+ Spanned (" f2" , Span (- 1 , - 1 )),
76
+ TypeRef (" OptT1" , Span (- 1 , - 1 )),
77
+ Span (- 1 , - 1 )
78
+ ),
79
+ FieldDef (
80
+ true ,
81
+ Spanned (" f3" , Span (- 1 , - 1 )),
82
+ TypeRef (" OptT1" , Span (- 1 , - 1 )),
83
+ Span (- 1 , - 1 )
84
+ )
85
+ ),
86
+ Span (- 1 , - 1 )
87
+ )),
88
+ Span (- 1 , - 1 )
89
+ ),
90
+ TypeDef (
91
+ Spanned (" T0" , Span (- 1 , - 1 )),
92
+ List (EnumCase (
93
+ Spanned (" T0" , Span (- 1 , - 1 )),
94
+ List (
95
+ FieldDef (
96
+ true ,
97
+ Spanned (" f0" , Span (- 1 , - 1 )),
98
+ TypeRef (" OptT0" , Span (- 1 , - 1 )),
99
+ Span (- 1 , - 1 )
100
+ ),
101
+ FieldDef (
102
+ true ,
103
+ Spanned (" f1" , Span (- 1 , - 1 )),
104
+ TypeRef (" OptT1" , Span (- 1 , - 1 )),
105
+ Span (- 1 , - 1 )
106
+ ),
107
+ FieldDef (
108
+ true ,
109
+ Spanned (" f2" , Span (- 1 , - 1 )),
110
+ TypeRef (" OptT0" , Span (- 1 , - 1 )),
111
+ Span (- 1 , - 1 )
112
+ ),
113
+ FieldDef (
114
+ true ,
115
+ Spanned (" f3" , Span (- 1 , - 1 )),
116
+ TypeRef (" OptT1" , Span (- 1 , - 1 )),
117
+ Span (- 1 , - 1 )
118
+ )
119
+ ),
120
+ Span (- 1 , - 1 )
121
+ )),
122
+ Span (- 1 , - 1 )
123
+ )
124
+ ),
125
+ Map (" vT1_0" -> " T1" , " vT1_1" -> " T1" , " vT0_0" -> " T0" , " vT0_1" -> " T0" ),
126
+ List (
127
+ (
128
+ " vT1_0" ,
129
+ CtorCall (
130
+ Spanned (" T1" , Span (- 1 , - 1 )),
131
+ List (
132
+ (
133
+ Spanned (" f0" , Span (- 1 , - 1 )),
134
+ CtorCall (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
135
+ ),
136
+ (
137
+ Spanned (" f1" , Span (- 1 , - 1 )),
138
+ CtorCall (Spanned (" NoneT0" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
139
+ ),
140
+ (
141
+ Spanned (" f2" , Span (- 1 , - 1 )),
142
+ CtorCall (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
143
+ ),
144
+ (
145
+ Spanned (" f3" , Span (- 1 , - 1 )),
146
+ CtorCall (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
147
+ )
148
+ ),
149
+ Span (- 1 , - 1 )
150
+ )
151
+ ),
152
+ (
153
+ " vT1_1" ,
154
+ CtorCall (
155
+ Spanned (" T1" , Span (- 1 , - 1 )),
156
+ List (
157
+ (
158
+ Spanned (" f0" , Span (- 1 , - 1 )),
159
+ CtorCall (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
160
+ ),
161
+ (
162
+ Spanned (" f1" , Span (- 1 , - 1 )),
163
+ CtorCall (Spanned (" NoneT0" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
164
+ ),
165
+ (
166
+ Spanned (" f2" , Span (- 1 , - 1 )),
167
+ CtorCall (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
168
+ ),
169
+ (
170
+ Spanned (" f3" , Span (- 1 , - 1 )),
171
+ CtorCall (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
172
+ )
173
+ ),
174
+ Span (- 1 , - 1 )
175
+ )
176
+ ),
177
+ (
178
+ " vT0_0" ,
179
+ CtorCall (
180
+ Spanned (" T0" , Span (- 1 , - 1 )),
181
+ List (
182
+ (
183
+ Spanned (" f0" , Span (- 1 , - 1 )),
184
+ CtorCall (Spanned (" NoneT0" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
185
+ ),
186
+ (
187
+ Spanned (" f1" , Span (- 1 , - 1 )),
188
+ CtorCall (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
189
+ ),
190
+ (
191
+ Spanned (" f2" , Span (- 1 , - 1 )),
192
+ CtorCall (Spanned (" NoneT0" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
193
+ ),
194
+ (
195
+ Spanned (" f3" , Span (- 1 , - 1 )),
196
+ CtorCall (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
197
+ )
198
+ ),
199
+ Span (- 1 , - 1 )
200
+ )
201
+ ),
202
+ (
203
+ " vT0_1" ,
204
+ CtorCall (
205
+ Spanned (" T0" , Span (- 1 , - 1 )),
206
+ List (
207
+ (
208
+ Spanned (" f0" , Span (- 1 , - 1 )),
209
+ CtorCall (Spanned (" NoneT0" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
210
+ ),
211
+ (
212
+ Spanned (" f1" , Span (- 1 , - 1 )),
213
+ CtorCall (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
214
+ ),
215
+ (
216
+ Spanned (" f2" , Span (- 1 , - 1 )),
217
+ CtorCall (Spanned (" NoneT0" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
218
+ ),
219
+ (
220
+ Spanned (" f3" , Span (- 1 , - 1 )),
221
+ CtorCall (Spanned (" NoneT1" , Span (- 1 , - 1 )), List (), Span (- 1 , - 1 ))
222
+ )
223
+ ),
224
+ Span (- 1 , - 1 )
225
+ )
226
+ )
227
+ ),
228
+ List (
229
+ GenStmt .Assign (" vT0_0" , " f1" , " T1" , " vT1_0" ),
230
+ GenStmt .Assign (" vT0_1" , " f1" , " T1" , " vT1_0" )
231
+ )
232
+ )
233
+
234
+ def fuzz (prog : GeneratedProgram , out : String ): Unit = {
235
+ val ast = prog.asAst
236
+ val settings = Settings (includeMemcheck = true )
237
+ try { ExecTests .valgrindCheck(ast, None , None , settings = settings) }
238
+ catch {
239
+ case e =>
240
+ given typer : Typer = Typer .resolveAllTypes(ast)
241
+ val c = Translator .toC(ast, settings)
242
+ Files .write(Path .of(" fuzz-out" , out), c.getBytes())
243
+ throw e
244
+ }
245
+ }
246
+
17
247
property(" No intermediate checks" , Slow ) {
18
248
given PropertyCheckConfiguration =
19
249
PropertyCheckConfiguration (minSize = 5 , sizeRange = 30 )
@@ -28,47 +258,31 @@ class FuzzTests
28
258
assignExprs <- GenUtil
29
259
.genAssignments(allTypes, allVars.view.mapValues(_.keySet).toMap)
30
260
} yield {
31
- val finalRes = IntLiteral (0 , Span .synth)
32
- val withAssignments = assignExprs.foldRight(finalRes : Expr ) {
33
- (stmt, acc) => BinExpr (stmt.asAst, Spanned (BinOp .Seq , Span .synth), acc)
34
- }
35
- val withVarDefs = sccs.flatMap(
36
- _.filterNot(_.name.startsWith(" Opt" )).flatMap(typ => allVars(typ.name))
37
- ).foldLeft(withAssignments) { case (body, (varName, value)) =>
38
- LetExpr (Spanned (varName, Span .synth), value, body, Span .synth)
39
- }
40
- ParsedFile (
261
+ GeneratedProgram (
41
262
allTypes,
42
- List (FnDef (
43
- Spanned (" main" , Span .synth),
44
- Nil ,
45
- TypeRef (" int" , Span .synth),
46
- withVarDefs,
47
- Span .synth
48
- ))
263
+ allVars.flatMap((typ, vars) => vars.keySet.map(_ -> typ)).toMap,
264
+ sccs.flatMap(
265
+ _.filterNot(_.name.startsWith(" Opt" ))
266
+ .flatMap(typ => allVars(typ.name))
267
+ ),
268
+ assignExprs
49
269
)
50
270
}
51
271
52
- forAll(genFull) { parsedFile =>
53
- ExecTests .valgrindCheck(
54
- parsedFile,
55
- None ,
56
- None ,
57
- save = Some (" blech-oiwjsd.c" ),
58
- settings = Settings (includeMemcheck = true )
59
- )
60
- }
272
+ forAll(genFull) { generated => fuzz(generated, " no-intermediate.c" ) }
61
273
}
62
274
63
275
property(" With intermediate checks" , Slow ) {
64
276
given PropertyCheckConfiguration =
65
- PropertyCheckConfiguration (minSize = 5 , sizeRange = 60 )
277
+ PropertyCheckConfiguration (minSize = 10 , sizeRange = 60 )
66
278
given Shrink [GeneratedProgram ] = GenUtil .shrinkGenerated
67
279
280
+ val checkRate = 0.1
281
+
68
282
// TODO maybe randomness isn't needed here, just insert one check every few statements or something
69
283
def insertValgrindChecks (stmts : List [GenStmt ]): Gen [List [GenStmt ]] = {
70
284
GenUtil .sequence(stmts.map { stmt =>
71
- Gen .prob(0.1 ).map { insert =>
285
+ Gen .prob(checkRate ).map { insert =>
72
286
if (insert) List (stmt, GenStmt .ValgrindCheck ) else List (stmt)
73
287
}
74
288
}).map(_.flatten)
@@ -84,8 +298,7 @@ class FuzzTests
84
298
assignExprsOrdered <- GenUtil
85
299
.genAssignments(allTypes, allVars.view.mapValues(_.keySet).toMap)
86
300
seed <- Gen .long
87
- rand = Random (seed)
88
- assignExprs = Random .shuffle(assignExprsOrdered)
301
+ assignExprs = Random (seed).shuffle(assignExprsOrdered)
89
302
withChecks <- insertValgrindChecks(assignExprs)
90
303
} yield {
91
304
GeneratedProgram (
@@ -99,24 +312,6 @@ class FuzzTests
99
312
)
100
313
}
101
314
102
- forAll(genFull) {
103
- generated =>
104
- ExecTests .valgrindCheck(
105
- generated.asAst,
106
- None ,
107
- None ,
108
- save = Some (" blech-1234sd.c" ),
109
- settings = Settings (includeMemcheck = true ),
110
- processC = c => {
111
- // TODO make lexical lifetimes or whatever they're called a setting in
112
- // the compiler instead of this buffoonery
113
- // Remove all $decr_TX calls for the variables at the end (but not $decr_OptTX calls)
114
- // because we're calling $decr_TX ourselves above
115
- val (beforeMain, afterMain) = c.splitAt(c.indexOf(" int main" ))
116
- beforeMain +
117
- afterMain.replaceAll(""" \$decr_T\d+\(vT\d+_\d+\);\n""" , " " )
118
- }
119
- )
120
- }
315
+ forAll(genFull) { generated => fuzz(generated, " with-intermediate.c" ) }
121
316
}
122
317
}
0 commit comments