Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1546)

Side by Side Diff: runtime/tests/vm/dart/random_walk_fuzzer.dart

Issue 801113003: Random-walk fuzzer for the Dart VM. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 // Random-walk fuzzer for the Dart VM.
6 //
7 // Start with all the classes and libraries and various interesting values.
8 // Repeatedly choose one as a receiver, construct a message it is likely to
9 // understand, send the message, and add the result.
10 //
11 // Intentionally not run on the build bots because through dart:io it could
12 // trash their setups.
13
14 library fuzzer;
15
16 import 'dart:io';
17 import 'dart:math';
18 import 'dart:mirrors';
19 import 'dart:typed_data';
20
21 var blacklist = [
22 'dart.io.exit',
23 'dart.io.exitCode',
24 'dart.io.sleep',
25 'dart.io.Process.killPid',
26 ];
27
28 final bool trace = false;
29
30 void main(List<String> args) {
31 int seed;
32 if (args.length == 1) {
33 seed = int.parse(args[0]);
34 } else {
35 // Dart's built-in random number generator doesn't provide access to the
36 // seed when it is choosen by the implementation. We need to be able to
37 // report this seed to make runs of the fuzzer reproducible, so we create
38 // the seed ourselves.
39
40 // When running on many machines in parallel, the current time alone
41 // is a poor choice of seed.
42 seed = 0;
43 try {
44 var f = new File("/dev/urandom").openSync();
45 seed = (seed << 8) | f.readByteSync();
46 seed = (seed << 8) | f.readByteSync();
47 seed = (seed << 8) | f.readByteSync();
48 seed = (seed << 8) | f.readByteSync();
49 f.close();
50 } catch(e) {
51 print("Failed to read from /dev/urandom: $e");
52 }
53
54 seed ^= new DateTime.now().millisecondsSinceEpoch;
55 seed &= 0xFFFFFFFF;
56 }
57 random = new Random(seed);
58
59 // Information needed to reproduce this run.
60 print("Dart VM fuzzer");
61 print("Executable: ${Platform.executable}");
62 print("Arguments: ${Platform.executableArguments}");
63 print("Version: ${Platform.version}");
64 print("Seed: ${seed}");
65 print("------------------------------------------");
66
67 setupInterestingValues();
68 setupClasses();
69
70 // Bound the number of steps in our random walk so that if any issue is found
71 // it can be reproduced without having to wait too long.
72 for (int i = 0; i < 100000; i++) {
73 fuzz(randomElementOf(candidateReceivers));
74 if (maybe(0.01)) garbageCollect();
75 }
76 }
77
78 Random random;
79
80 bool maybe(probability) => random.nextDouble() < probability;
81
82 randomElementOf(list) {
83 return list.length == 0 ? null : list[random.nextInt(list.length)];
84 }
85
86 class Candidate<T> {
87 Candidate origin;
88 String message;
89 T mirror;
90 trace() {
91 if (origin == null) {
92 print("");
93 } else {
94 origin.trace();
95 print(" $message");
96 }
97 print(mirror);
98 }
99 }
100
101 List<Candidate<ObjectMirror>> candidateReceivers =
102 new List<Candidate<ObjectMirror>>();
103 List<Candidate<InstanceMirror>> candidateArguments =
104 new List<Candidate<InstanceMirror>>();
105
106 void addInstance(var instance) {
107 addInstanceMirror(reflect(instance));
108 }
109
110 void addInstanceMirror(InstanceMirror mirror,
111 [Candidate origin, String message]) {
112 var c = new Candidate<InstanceMirror>();
113 c.mirror = mirror;
114 c.origin = origin;
115 c.message = message;
116
117 candidateReceivers.add(c);
118 candidateArguments.add(c);
119 }
120
121 void addObjectMirror(ObjectMirror mirror) {
122 var c = new Candidate<ObjectMirror>();
123 c.mirror = mirror;
124 c.origin = null;
125 c.message = null;
126
127 candidateReceivers.add(c);
128 }
129
130 void setupInterestingValues() {
131 addInstance(null);
132 addInstance(true);
133 addInstance(false);
134
135 addInstance([]);
136 addInstance(const []);
137 addInstance({});
138 addInstance(const {});
139
140 addInstance(() => null);
141
142 addInstance(-1);
143 addInstance(0);
144 addInstance(1);
145 addInstance(2);
146
147 addInstance(1 << 31);
148 addInstance(1 << 31 + 1);
149 addInstance(1 << 31 - 1);
150
151 addInstance(1 << 32);
152 addInstance(1 << 32 + 1);
153 addInstance(1 << 32 - 1);
154
155 addInstance(1 << 63);
156 addInstance(1 << 63 + 1);
157 addInstance(1 << 63 - 1);
158
159 addInstance(1 << 64);
160 addInstance(1 << 64 + 1);
161 addInstance(1 << 64 - 1);
162
163 addInstance(-1.0);
164 addInstance(0.0);
165 addInstance(1.0);
166 addInstance(2.0);
167 addInstance(double.NAN);
168 addInstance(double.INFINITY);
169 addInstance(double.NEGATIVE_INFINITY);
170 addInstance(double.MIN_POSITIVE);
171 addInstance(double.MAX_FINITE);
172
173 addInstance("foo"); // ASCII string
174 addInstance("blåbærgrød"); // Latin1 string
175 addInstance("Îñţérñåţîöñåļîžåţîờñ"); // Unicode string
176 addInstance("𝄞"); // Surrogate pairs
177 addInstance("𝄞"[0]); // Surrogate pairs
178 addInstance("𝄞"[1]); // Surrogate pairs
179 addInstance("\u{0}"); // Non-printing charater
180 addInstance("\u{1}"); // Non-printing charater
181 addInstance("f\u{0}oo"); // Internal NUL
182 addInstance("blåbæ\u{0}rgrød"); // Internal NUL
183 addInstance("Îñţérñåţîö\u{0}ñåļîžåţîờñ"); // Internal NUL
184 addInstance("\u{0}𝄞"); // Internal NUL
185
186 for (int len = 0; len < 8; len++) {
187 addInstance(fillInt(new Int8List(len)));
188 addInstance(fillInt(new Int16List(len)));
189 addInstance(fillInt(new Int32List(len)));
190 addInstance(fillInt(new Int64List(len)));
191 addInstance(fillInt(new Uint8List(len)));
192 addInstance(fillInt(new Uint16List(len)));
193 addInstance(fillInt(new Uint32List(len)));
194 addInstance(fillInt(new Uint64List(len)));
195 addInstance(fillFloat(new Float32List(len)));
196 addInstance(fillFloat(new Float64List(len)));
197 }
198
199 randomInstance(ignore) {
200 return randomElementOf(candidateArguments).mirror.reflectee;
201 }
202 for (int len = 0; len < 8; len++) {
203 addInstance(new List.generate(len, randomInstance));
204 }
205 }
206
207 void fillInt(TypedData d) {
208 for (var i = 0; i < d.length; i++) {
209 d[i] = random.nextInt(0xFFFFFFFF);
210 }
211 }
212
213 void fillFloat(TypedData d) {
214 for (var i = 0; i < d.length; i++) {
215 d[i] = random.nextDouble();
216 }
217 }
218
219 void setupClasses() {
220 currentMirrorSystem().libraries.values.forEach((lib) {
221 if (lib.simpleName == #fuzzer) return; // Don't recurse.
222 addObjectMirror(lib);
223 lib.declarations.values.forEach((decl) {
224 if (decl is ClassMirror) {
225 addObjectMirror(decl);
226 }
227 });
228 });
229 }
230
231 MethodMirror randomMethodOf(receiver) {
232 if (receiver is ClassMirror) {
233 return randomElementOf(receiver.declarations.values.where(
234 (d) => d is MethodMirror && d.isStatic).toList());
235 } else if (receiver is LibraryMirror) {
236 return randomElementOf(receiver.declarations.values.where(
237 (d) => d is MethodMirror).toList());
238 } else if (receiver is InstanceMirror) {
239 var methods = [];
240 var cls = receiver.type;
241 while (cls != reflectClass(Object)) {
242 cls.declarations.values.forEach((d) {
243 if (d is MethodMirror && !d.isStatic) methods.add(d);
244 });
245 cls = cls.superclass;
246 }
247 return randomElementOf(methods);
248 }
249 throw new Error("UNREACHABLE");
250 }
251
252 String prettyMessageName(receiver, method) {
253 var r = "?", m = "?";
254 if (receiver is InstanceMirror) {
255 r = MirrorSystem.getName(receiver.type.simpleName);
256 } else if (receiver is ClassMirror) {
257 r = MirrorSystem.getName(receiver.simpleName);
258 r = "$r class";
259 } else if (receiver is LibraryMirror) {
260 r = MirrorSystem.getName(receiver.simpleName);
261 r = "$r lib";
262 }
263 m = MirrorSystem.getName(method.simpleName);
264 return "$r>>#$m";
265 }
266
267 void fuzz(Candidate c) {
268 ObjectMirror receiver = c.mirror;
269 MethodMirror method = randomMethodOf(receiver);
270 if (method == null) return;
271 if (blacklist.contains(MirrorSystem.getName(method.qualifiedName))) return;
272
273 List positional = randomPositionalArgumentsFor(method);
274 Map named = randomNamedArgumentsFor(method);
275 InstanceMirror result;
276
277 String message = prettyMessageName(receiver, method);
278 if (trace) {
279 c.trace();
280 print(message);
281 }
282
283 if (method.isConstructor) {
284 try {
285 result = receiver.newInstance(method.simpleName, positional, named);
286 } catch(e) {}
287 } else if (method.isRegularMethod) {
288 try {
289 result = receiver.invoke(method.simpleName, positional, named);
290 } catch(e) {}
291 } else if (method.isGetter) {
292 try {
293 result = receiver.getField(method.simpleName);
294 } catch(e) {}
295 } else if (method.isSetter) {
296 try {
297 result = receiver.setField(method.simpleName, positional[0]);
298 } catch(e) {}
299 }
300
301 if (result != null) {
302 addInstanceMirror(result, c, message);
303 }
304 }
305
306 InstanceMirror randomArgumentWithBias(TypeMirror bias) {
307 if (maybe(0.75)) {
308 for (var candidate in candidateArguments) {
309 if (candidate.mirror.type.isAssignableTo(bias)) {
310 return candidate.mirror;
311 }
312 }
313 }
314 return randomElementOf(candidateArguments).mirror;
315 }
316
317 List randomPositionalArgumentsFor(MethodMirror method) {
318 var result = [];
319 for (int i = 0; i < method.parameters.length; i++) {
320 ParameterMirror p = method.parameters[i];
321 if (!p.isNamed && (!p.isOptional || maybe(0.5))) {
322 result.add(randomArgumentWithBias(p.type));
323 }
324 }
325 return result;
326 }
327
328 Map randomNamedArgumentsFor(MethodMirror method) {
329 var result = {};
330 for (int i = 0; i < method.parameters.length; i++) {
331 ParameterMirror p = method.parameters[i];
332 if (p.isNamed && maybe(0.5)) {
333 result[p.simpleName] = randomArgumentWithBias(p.type);
334 }
335 }
336
337 return result;
338 }
339
340 void garbageCollect() {
341 // Chain a bunch of moderately sized arrays, then let go of them. Using a
342 // moderate size avoids our allocations going directly to a large object
343 // page in old space.
344 var n;
345 for (int i = 0; i < 2048; i++) {
346 var m = new List(512);
347 m[0] = n;
348 n = m;
349 }
350 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698