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 }