Mercurial > hg > Members > kono > jpf-core
comparison src/main/gov/nasa/jpf/vm/Verify.java @ 0:61d41facf527
initial v8 import (history reset)
author | Peter Mehlitz <Peter.C.Mehlitz@nasa.gov> |
---|---|
date | Fri, 23 Jan 2015 10:14:01 -0800 |
parents | |
children | f6886b2bda4a |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:61d41facf527 |
---|---|
1 /* | |
2 * Copyright (C) 2014, United States Government, as represented by the | |
3 * Administrator of the National Aeronautics and Space Administration. | |
4 * All rights reserved. | |
5 * | |
6 * The Java Pathfinder core (jpf-core) platform is licensed under the | |
7 * Apache License, Version 2.0 (the "License"); you may not use this file except | |
8 * in compliance with the License. You may obtain a copy of the License at | |
9 * | |
10 * http://www.apache.org/licenses/LICENSE-2.0. | |
11 * | |
12 * Unless required by applicable law or agreed to in writing, software | |
13 * distributed under the License is distributed on an "AS IS" BASIS, | |
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
15 * See the License for the specific language governing permissions and | |
16 * limitations under the License. | |
17 */ | |
18 package gov.nasa.jpf.vm; | |
19 | |
20 import java.io.FileInputStream; | |
21 import java.io.FileOutputStream; | |
22 import java.io.ObjectInputStream; | |
23 import java.io.ObjectOutputStream; | |
24 import java.util.BitSet; | |
25 import java.util.Random; | |
26 | |
27 | |
28 /** | |
29 * Verify is the programmatic interface of JPF that can be used from inside of | |
30 * applications. In order to enable programs to run outside of the JPF | |
31 * environment, we provide (mostly empty) bodies for the methods that are | |
32 * otherwise intercepted by the native peer class | |
33 */ | |
34 public class Verify { | |
35 static final int MAX_COUNTERS = 10; | |
36 static int[] counter; // only here so that we don't pull in all JPF classes at RT | |
37 | |
38 private static Random random; | |
39 | |
40 /* | |
41 * only set if this was used from within a JPF context. This is mainly to | |
42 * enable encapsulation of JPF specific types so that they only get | |
43 * pulled in on demand, and we otherwise can still use the same Verify class | |
44 * for JPF-external execution. We use a class object to make sure it doesn't | |
45 * get recycled once JPF is terminated. | |
46 */ | |
47 static Class<?> peer; | |
48 | |
49 private static Random getRandom() { | |
50 if (random == null) { | |
51 random = new Random(42); | |
52 } | |
53 return random; | |
54 } | |
55 | |
56 /* | |
57 * register the peer class, which is only done from within a JPF execution | |
58 * context. Be aware of that this migh actually load the real Verify class. | |
59 * The sequence usually is | |
60 * JPF(Verify) -> VM(JPF_gov_nasa_jpf_vm_Verify) -> VM(Verify) | |
61 */ | |
62 public static void setPeerClass (Class<?> cls) { | |
63 peer = cls; | |
64 } | |
65 | |
66 // note this is NOT marked native because we might also call it from host VM code | |
67 // (beware that Verify is a different class there!). When executed by JPF, | |
68 // this is an MJI method | |
69 public static int getCounter (int id) { | |
70 if (peer != null) { | |
71 // this is executed if we are in a JPF context | |
72 return JPF_gov_nasa_jpf_vm_Verify.getCounter__I__I(null, 0, id); | |
73 } else { | |
74 if (counter == null) { | |
75 counter = new int[id >= MAX_COUNTERS ? (id+1) : MAX_COUNTERS]; | |
76 } | |
77 if ((id < 0) || (id >= counter.length)) { | |
78 return 0; | |
79 } | |
80 | |
81 return counter[id]; | |
82 } | |
83 } | |
84 | |
85 public static void resetCounter (int id) { | |
86 if (peer != null){ | |
87 JPF_gov_nasa_jpf_vm_Verify.resetCounter__I__V(null, 0, id); | |
88 } else { | |
89 if ((counter != null) && (id >= 0) && (id < counter.length)) { | |
90 counter[id] = 0; | |
91 } | |
92 } | |
93 } | |
94 | |
95 public static void setCounter (int id, int val) { | |
96 if (peer != null){ | |
97 JPF_gov_nasa_jpf_vm_Verify.setCounter__II__V(null, 0, id, val); | |
98 } else { | |
99 if ((counter != null) && (id >= 0) && (id < counter.length)) { | |
100 counter[id] = val; | |
101 } | |
102 } | |
103 } | |
104 | |
105 | |
106 public static int incrementCounter (int id) { | |
107 if (peer != null){ | |
108 return JPF_gov_nasa_jpf_vm_Verify.incrementCounter__I__I(null, 0, id); | |
109 } else { | |
110 if (counter == null) { | |
111 counter = new int[(id >= MAX_COUNTERS) ? id+1 : MAX_COUNTERS]; | |
112 } else if (id >= counter.length) { | |
113 int[] newCounter = new int[id+1]; | |
114 System.arraycopy(counter, 0, newCounter, 0, counter.length); | |
115 counter = newCounter; | |
116 } | |
117 | |
118 if ((id >= 0) && (id < counter.length)) { | |
119 return ++counter[id]; | |
120 } | |
121 | |
122 return 0; | |
123 } | |
124 } | |
125 | |
126 public static final int NO_VALUE = -1; | |
127 | |
128 public static void putValue (String key, int value) { | |
129 throw new UnsupportedOperationException("putValue requires JPF execution"); | |
130 } | |
131 | |
132 public static int getValue (String key) { | |
133 throw new UnsupportedOperationException("getValue requires JPF execution"); | |
134 } | |
135 | |
136 // same mechanism and purpose as the counters, but with BitSets, which is | |
137 // more convenient if we have a lot of different events to check | |
138 | |
139 static BitSet[] bitSets; | |
140 | |
141 private static void checkBitSetId(int id) { | |
142 if (bitSets == null) { | |
143 bitSets = new BitSet[id + 1]; | |
144 } else if (id >= bitSets.length) { | |
145 BitSet[] newBitSets = new BitSet[id + 1]; | |
146 System.arraycopy(bitSets, 0, newBitSets, 0, bitSets.length); | |
147 bitSets = newBitSets; | |
148 } | |
149 | |
150 if (bitSets[id] == null) { | |
151 bitSets[id] = new BitSet(); | |
152 } | |
153 } | |
154 | |
155 | |
156 public static void setBitInBitSet(int id, int bit, boolean value) { | |
157 if (peer != null){ | |
158 // this is executed if we did run JPF | |
159 JPF_gov_nasa_jpf_vm_Verify.setBitInBitSet__IIZ__V(null, 0, id, bit, value); | |
160 } else { | |
161 // this is executed if we run this without previously executing JPF | |
162 checkBitSetId(id); | |
163 bitSets[id].set(bit, value); | |
164 } | |
165 } | |
166 | |
167 public static boolean getBitInBitSet(int id, int bit) { | |
168 if (peer != null){ | |
169 // this is executed if we did run JPF | |
170 return JPF_gov_nasa_jpf_vm_Verify.getBitInBitSet__II__Z(null, 0, id, bit); | |
171 | |
172 } else { | |
173 // this is executed if we run this without previously executing JPF | |
174 checkBitSetId(id); | |
175 return bitSets[id].get(bit); | |
176 } | |
177 } | |
178 | |
179 /** | |
180 * Adds a comment to the error trace, which will be printed and saved. | |
181 */ | |
182 public static void addComment (String s) {} | |
183 | |
184 /** | |
185 * Backwards compatibility START | |
186 * @deprecated use "assert cond : msg" | |
187 */ | |
188 @Deprecated | |
189 public static void assertTrue (String s, boolean cond) { | |
190 if (!cond) { | |
191 System.out.println(s); | |
192 assertTrue(cond); | |
193 } | |
194 } | |
195 | |
196 /** | |
197 * Checks that the condition is true. | |
198 * @deprecated use 'assert' directly | |
199 */ | |
200 @Deprecated | |
201 public static void assertTrue (boolean cond) { | |
202 if (!cond) { | |
203 throw new AssertionError("Verify.assertTrue failed"); | |
204 } | |
205 } | |
206 | |
207 public static void atLabel (String label) {} | |
208 | |
209 public static void atLabel (int label) {} | |
210 | |
211 /** | |
212 * Marks the beginning of an atomic block. | |
213 * THIS IS EVIL, DON'T USE IT FOR OPTIMIZATION - THAT'S WHAT POR IS FOR! | |
214 * (it's mostly here to support model classes that need to execute atomic) | |
215 */ | |
216 public static void beginAtomic () {} | |
217 | |
218 /** | |
219 * Marks the end of an atomic block. | |
220 * EVIL - see beginAtomic() | |
221 */ | |
222 public static void endAtomic () {} | |
223 | |
224 public static void boring (boolean cond) {} | |
225 | |
226 public static void busyWait (long duration) { | |
227 // this gets only executed outside of JPF | |
228 while (duration > 0) { | |
229 duration--; | |
230 } | |
231 } | |
232 | |
233 public static boolean isCalledFromClass (String refClsName) { | |
234 Throwable t = new Throwable(); | |
235 StackTraceElement[] st = t.getStackTrace(); | |
236 | |
237 if (st.length < 3) { | |
238 // main() or run() | |
239 return false; | |
240 } | |
241 | |
242 try { | |
243 Class<?> refClazz = Class.forName(refClsName); | |
244 Class<?> callClazz = Class.forName(st[2].getClassName()); | |
245 | |
246 return (refClazz.isAssignableFrom(callClazz)); | |
247 | |
248 } catch (ClassNotFoundException cfnx) { | |
249 return false; | |
250 } | |
251 } | |
252 | |
253 public static void ignoreIf (boolean cond) {} | |
254 | |
255 public static void instrumentPoint (String label) {} | |
256 | |
257 public static void instrumentPointDeep (String label) {} | |
258 | |
259 public static void instrumentPointDeepRecur (String label, int depth) {} | |
260 | |
261 public static void interesting (boolean cond) {} | |
262 | |
263 public static void breakTransition (String reason) {} | |
264 | |
265 /** | |
266 * simple debugging aids to imperatively print the current path output of the SUT | |
267 * (to be used with vm.path_output) | |
268 */ | |
269 public static void printPathOutput(String msg) {} | |
270 public static void printPathOutput(boolean cond, String msg) {} | |
271 | |
272 public static void threadPrint (String s) { | |
273 System.out.print( Thread.currentThread().getName()); | |
274 System.out.print(": "); | |
275 System.out.print(s); | |
276 } | |
277 | |
278 public static void threadPrintln (String s) { | |
279 threadPrint(s); | |
280 System.out.println(); | |
281 } | |
282 | |
283 public static void print (String s) { | |
284 System.out.print(s); | |
285 } | |
286 | |
287 public static void println (String s) { | |
288 System.out.println(s); | |
289 } | |
290 | |
291 public static void print (String s, int i) { | |
292 System.out.print(s + " : " + i); | |
293 } | |
294 | |
295 public static void print (String s, boolean b) { | |
296 System.out.print(s + " : " + b); | |
297 } | |
298 | |
299 public static void println() { | |
300 System.out.println(); | |
301 } | |
302 | |
303 /** | |
304 * this is to avoid StringBuilders | |
305 */ | |
306 public static void print (String... args){ | |
307 for (String s : args){ | |
308 System.out.print(s); | |
309 } | |
310 } | |
311 | |
312 /** | |
313 * note - these are mostly for debugging purposes (to see if attributes get | |
314 * propagated correctly, w/o having to write a listener), since attributes are | |
315 * supposed to be created at the native side, and hence can't be accessed from | |
316 * the application | |
317 */ | |
318 | |
319 //--- use these if you know there are single attributes | |
320 public static void setFieldAttribute (Object o, String fieldName, int val) {} | |
321 public static int getFieldAttribute (Object o, String fieldName) { return 0; } | |
322 | |
323 //--- use these for multiple attributes | |
324 public static void addFieldAttribute (Object o, String fieldName, int val) {} | |
325 public static int[] getFieldAttributes (Object o, String fieldName) { return new int[0]; } | |
326 | |
327 public static void setLocalAttribute (String varName, int val) {} | |
328 public static int getLocalAttribute (String varName) { return 0; } | |
329 | |
330 public static void addLocalAttribute (String varName, int val) {} | |
331 public static int[] getLocalAttributes (String varName) { return new int[0]; } | |
332 | |
333 public static void setElementAttribute (Object arr, int idx, int val){} | |
334 public static int getElementAttribute (Object arr, int idx) { return 0; } | |
335 | |
336 public static void addElementAttribute (Object arr, int idx, int val){} | |
337 public static int[] getElementAttributes (Object arr, int idx) { return new int[0]; } | |
338 | |
339 public static void setObjectAttribute (Object o, int val) {} | |
340 public static int getObjectAttribute (Object o) { return 0; } | |
341 | |
342 public static void addObjectAttribute (Object o, int val) {} | |
343 public static int[] getObjectAttributes (Object o) { return new int[0]; } | |
344 | |
345 | |
346 /** | |
347 * this is the new boolean choice generator. Since there's no real | |
348 * heuristic involved with boolean values, we skip the id (it's a | |
349 * hardwired "boolean") | |
350 */ | |
351 public static boolean getBoolean () { | |
352 // just executed when not running inside JPF, native otherwise | |
353 return ((System.currentTimeMillis() & 1) != 0); | |
354 } | |
355 | |
356 /** | |
357 * new boolean choice generator that also tells jpf which value to | |
358 * use first by default in a search. | |
359 */ | |
360 public static boolean getBoolean (boolean falseFirst) { | |
361 // this is only executed when not running JPF | |
362 return getBoolean(); | |
363 } | |
364 | |
365 | |
366 /** | |
367 * Returns int nondeterministically between (and including) min and max. | |
368 */ | |
369 public static int getInt (int min, int max) { | |
370 // this is only executed when not running JPF, native otherwise | |
371 return getRandom().nextInt((max-min+1)) + min; | |
372 } | |
373 | |
374 public static int getIntFromList (int... values){ | |
375 if (values != null && values.length > 0) { | |
376 int i = getRandom().nextInt(values.length); | |
377 return values[i]; | |
378 } else { | |
379 return getRandom().nextInt(); | |
380 } | |
381 } | |
382 | |
383 public static Object getObject (String key) { | |
384 return "?"; | |
385 } | |
386 | |
387 /** | |
388 * this is the API for int value choice generators. 'id' is used to identify | |
389 * both the corresponding ChoiceGenerator subclass, and the application specific | |
390 * ctor parameters from the normal JPF configuration mechanism | |
391 */ | |
392 public static int getInt (String key){ | |
393 // this is only executed when not running JPF, native otherwise | |
394 return getRandom().nextInt(); | |
395 } | |
396 | |
397 /** | |
398 * this is the API for double value choice generators. 'id' is used to identify | |
399 * both the corresponding ChoiceGenerator subclass, and the application specific | |
400 * ctor parameters from the normal JPF configuration mechanism | |
401 */ | |
402 public static double getDouble (String key){ | |
403 // this is only executed when not running JPF, native otherwise | |
404 return getRandom().nextDouble(); | |
405 } | |
406 | |
407 public static double getDoubleFromList (double... values){ | |
408 if (values != null && values.length > 0) { | |
409 int i = getRandom().nextInt(values.length); | |
410 return values[i]; | |
411 } else { | |
412 return getRandom().nextDouble(); | |
413 } | |
414 } | |
415 | |
416 public static long getLongFromList (long...values){ | |
417 if (values != null && values.length > 0) { | |
418 int i = getRandom().nextInt(values.length); | |
419 return values[i]; | |
420 } else { | |
421 return getRandom().nextLong(); | |
422 } | |
423 } | |
424 | |
425 public static float getFloatFromList (float...values){ | |
426 if (values != null && values.length > 0) { | |
427 int i = getRandom().nextInt(values.length); | |
428 return values[i]; | |
429 } else { | |
430 return getRandom().nextFloat(); | |
431 } | |
432 } | |
433 | |
434 | |
435 /** | |
436 * Returns a random number between 0 and max inclusive. | |
437 */ | |
438 public static int random (int max) { | |
439 // this is only executed when not running JPF | |
440 return getRandom().nextInt(max + 1); | |
441 } | |
442 | |
443 /** | |
444 * Returns a random boolean value, true or false. Note this gets | |
445 * handled by the native peer, and is just here to enable running | |
446 * instrumented applications w/o JPF | |
447 */ | |
448 public static boolean randomBool () { | |
449 // this is only executed when not running JPF | |
450 return getRandom().nextBoolean(); | |
451 } | |
452 | |
453 public static long currentTimeMillis () { | |
454 return System.currentTimeMillis(); | |
455 } | |
456 | |
457 // Backwards compatibility START | |
458 public static Object randomObject (String type) { | |
459 return null; | |
460 } | |
461 | |
462 public static boolean isRunningInJPF() { | |
463 return false; | |
464 } | |
465 | |
466 /** | |
467 * USE CAREFULLY - returns true if the virtual machine this code is | |
468 * running under is doing state matching. This can be used as a hint | |
469 * as to whether data structures (that are known to be correct!) | |
470 * should be configured to use a canonical representation. For example, | |
471 * <pre><code> | |
472 * Vector v = new Vector(); | |
473 * v.add(obj1); | |
474 * if (Verify.getBoolean()) { | |
475 * v.addAll(eleventyBillionObjectCollection); | |
476 * v.setSize(1); | |
477 * } | |
478 * // compare states here | |
479 * </code></pre> | |
480 * To the programmer, the states are (almost certainly) the same. To | |
481 * the VM, they could be different (capacity inside the Vector). For | |
482 * the sake of speed, Vector does not store things canonically, but this | |
483 * can cause (probably mild) state explosion if matching states. If | |
484 * you know whether states are being matched, you can choose the right | |
485 * structure--as long as those structures aren't what you're looking for | |
486 * bugs in! | |
487 */ | |
488 public static boolean vmIsMatchingStates() { | |
489 return false; | |
490 } | |
491 | |
492 public static void storeTrace (String fileName, String comment) { | |
493 // intercepted in NativePeer | |
494 } | |
495 | |
496 public static void storeTraceIf (boolean cond, String fileName, String comment) { | |
497 if (cond) { | |
498 storeTrace(fileName, comment); | |
499 } | |
500 } | |
501 | |
502 public static void storeTraceAndTerminate (String fileName, String comment) { | |
503 storeTrace(fileName, comment); | |
504 terminateSearch(); | |
505 } | |
506 | |
507 public static void storeTraceAndTerminateIf (boolean cond, String fileName, String comment) { | |
508 if (cond) { | |
509 storeTrace(fileName, comment); | |
510 terminateSearch(); | |
511 } | |
512 } | |
513 | |
514 public static boolean isTraceReplay () { | |
515 return false; // native | |
516 } | |
517 | |
518 public static boolean isShared (Object o){ | |
519 return false; // native | |
520 } | |
521 | |
522 public static void setShared (Object o, boolean isShared) { | |
523 // native | |
524 } | |
525 | |
526 public static void freezeSharedness (Object o, boolean freeze) { | |
527 // native | |
528 } | |
529 | |
530 public static void terminateSearch () { | |
531 // native | |
532 } | |
533 | |
534 public static void setProperties (String... p) { | |
535 // native | |
536 } | |
537 | |
538 public static String getProperty (String key) { | |
539 // native | |
540 return null; | |
541 } | |
542 | |
543 public static <T> T createFromJSON(Class<T> clazz, String json){ | |
544 return null; | |
545 } | |
546 | |
547 public static void writeObjectToFile(Object object, String fileName) { | |
548 try { | |
549 FileOutputStream fso = new FileOutputStream(fileName); | |
550 ObjectOutputStream oos = new ObjectOutputStream(fso); | |
551 oos.writeObject(object); | |
552 oos.flush(); | |
553 oos.close(); | |
554 | |
555 } catch (Exception ex) { | |
556 throw new RuntimeException(ex); | |
557 } | |
558 | |
559 } | |
560 | |
561 public static <T> T readObjectFromFile(Class<T> clazz, String fileName) { | |
562 try | |
563 { | |
564 FileInputStream fis = new FileInputStream(fileName); | |
565 ObjectInputStream ois = new ObjectInputStream(fis); | |
566 | |
567 Object read = ois.readObject(); | |
568 | |
569 return (T) read; | |
570 | |
571 } | |
572 catch (Exception ex) { | |
573 throw new RuntimeException(ex); | |
574 } | |
575 | |
576 } | |
577 | |
578 | |
579 //--- model logging support | |
580 | |
581 /* | |
582 * we add these here so that we don't need to pull in any java.util.logging classes | |
583 * Note - these need to be kept in sync with our native peer | |
584 */ | |
585 public static final int SEVERE = 1; | |
586 public static final int WARNING = 2; | |
587 public static final int INFO = 3; | |
588 public static final int FINE = 4; | |
589 public static final int FINER = 5; | |
590 public static final int FINEST = 6; | |
591 | |
592 public static void log( String loggerId, int logLevel, String msg){ | |
593 System.err.println(msg); | |
594 } | |
595 | |
596 // to avoid construction of strings on the model side | |
597 public static void log( String loggerId, int logLevel, String msg, String arg){ | |
598 System.err.println(msg); | |
599 } | |
600 | |
601 public static void log( String loggerId, int logLevel, String format, Object... args){ | |
602 System.err.printf(format, args); | |
603 } | |
604 | |
605 | |
606 } |