Initial import
[jpf-core.git] / src / tests / gov / nasa / jpf / test / vm / threads / ThreadTest.java
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.test.vm.threads;
19
20 import gov.nasa.jpf.annotation.FilterField;
21 import gov.nasa.jpf.util.test.TestJPF;
22 import gov.nasa.jpf.vm.Verify;
23
24 import org.junit.Test;
25
26
27 /**
28  * threading test
29  */
30 public class ThreadTest extends TestJPF {
31   static String didRunThread = null;
32
33   @Test public void testDaemon () {
34     if (verifyNoPropertyViolation()) {
35       Runnable r = new Runnable() {
36
37         @Override
38                 public void run() {
39           Thread t = Thread.currentThread();
40
41           if (!t.isDaemon()) {
42             throw new RuntimeException("isDaemon failed");
43           }
44
45           didRunThread = t.getName();
46         }
47       };
48
49       didRunThread = null;
50
51       Thread t = new Thread(r);
52       t.setDaemon(true);
53       t.start();
54
55       try {
56         t.join();
57       } catch (InterruptedException ix) {
58         throw new RuntimeException("thread was interrupted");
59       }
60
61       String tname = Thread.currentThread().getName();
62       if ((didRunThread == null) || (didRunThread.equals(tname))) {
63         throw new RuntimeException("thread did not execute: " + didRunThread);
64       }
65     }
66   }
67
68   @Test public void testDaemonTermination () {
69     if (verifyNoPropertyViolation("+cg.threads.break_start=true",
70                                   "+cg.threads.break_yield=true")) {
71       final Thread mainThread = Thread.currentThread();
72
73       Runnable r = new Runnable() {
74
75         @FilterField  // without this, we have a perfectly open state space and never finish in JPF
76         int n = 0;
77
78         @Override
79                 public void run() {
80           while (true) { // loop forever or until main finishes
81             n++;
82
83             // NOTE: this does not necessarily hold outside of JPF, since the daemon might still run for a few cycles
84             assert (n < 100) || mainThread.isAlive() : "main terminated but daemon still running";
85             System.out.println("  daemon running in round: " + n);
86
87             Thread.yield();
88           }
89         }
90       };
91
92       Thread t = new Thread(r);
93       t.setDaemon(true);
94       t.start();
95
96       Thread.yield();
97       // finishing this thread should also (eventually) terminate the daemon
98       System.out.println("main terminating");
99     }
100   }
101   
102   @Test public void testMain () {
103     if (verifyNoPropertyViolation()) {
104       Thread t = Thread.currentThread();
105       String refName = "main";
106
107       String name = t.getName();
108
109       if (!name.equals(refName)) {
110         throw new RuntimeException("wrong main thread name, is: " + name +
111                 ", expected: " + refName);
112       }
113
114       refName = "my-main-thread";
115       t.setName(refName);
116       name = t.getName();
117
118       if (!name.equals(refName)) {
119         throw new RuntimeException("Thread.setName() failed, is: " + name +
120                 ", expected: " + refName);
121       }
122
123       int refPrio = Thread.NORM_PRIORITY;
124       int prio = t.getPriority();
125
126       if (prio != refPrio) {
127         throw new RuntimeException("main thread has no NORM_PRIORITY: " + prio);
128       }
129
130       refPrio++;
131       t.setPriority(refPrio);
132       prio = t.getPriority();
133
134       if (prio != refPrio) {
135         throw new RuntimeException("main thread setPriority failed: " + prio);
136       }
137
138       if (t.isDaemon()) {
139         throw new RuntimeException("main thread is daemon");
140       }
141     }
142   }
143
144   @Test public void testName () {
145     if (verifyNoPropertyViolation()) {
146       Runnable r = new Runnable() {
147
148         @Override
149                 public void run() {
150           Thread t = Thread.currentThread();
151           String name = t.getName();
152
153           if (!name.equals("my-thread")) {
154             throw new RuntimeException("wrong Thread name: " + name);
155           }
156
157           didRunThread = name;
158         }
159       };
160
161       didRunThread = null;
162
163       Thread t = new Thread(r, "my-thread");
164
165
166       //Thread t = new Thread(r);
167       t.start();
168
169       try {
170         t.join();
171       } catch (InterruptedException ix) {
172         throw new RuntimeException("thread was interrupted");
173       }
174
175       String tname = Thread.currentThread().getName();
176       if ((didRunThread == null) || (didRunThread.equals(tname))) {
177         throw new RuntimeException("thread did not execute: " + didRunThread);
178       }
179     }
180   }
181
182   public void testSingleYield () {
183     Thread.yield();
184   }
185   
186   @Test public void testYield () {
187     if (verifyNoPropertyViolation("+cg.threads.break_start=true",
188                                   "+cg.threads.break_yield=true")) {
189       Runnable r = new Runnable() {
190
191         @Override
192                 public void run() {
193           Thread t = Thread.currentThread();
194
195           while (!didRunThread.equals("blah")) {
196             Thread.yield();
197           }
198
199           didRunThread = t.getName();
200         }
201       };
202
203       didRunThread = "blah";
204
205       Thread t = new Thread(r);
206       t.start();
207
208       while (didRunThread.equals("blah")) {
209         Thread.yield();
210       }
211
212       String tname = Thread.currentThread().getName();
213       if ((didRunThread == null) || (didRunThread.equals(tname))) {
214         throw new RuntimeException("thread did not execute: " + didRunThread);
215       }
216     }
217   }
218   
219   
220   @Test public void testPriority () {
221     if (verifyNoPropertyViolation()) {
222       Runnable r = new Runnable() {
223
224         @Override
225                 public void run() {
226           Thread t = Thread.currentThread();
227           int prio = t.getPriority();
228
229           if (prio != (Thread.MIN_PRIORITY + 2)) {
230             throw new RuntimeException("wrong Thread priority: " + prio);
231           }
232
233           didRunThread = t.getName();
234         }
235       };
236
237       didRunThread = null;
238
239       Thread t = new Thread(r);
240       t.setPriority(Thread.MIN_PRIORITY + 2);
241       t.start();
242
243       try {
244         t.join();
245       } catch (InterruptedException ix) {
246         throw new RuntimeException("thread was interrupted");
247       }
248
249       String tname = Thread.currentThread().getName();
250       if ((didRunThread == null) || (didRunThread.equals(tname))) {
251         throw new RuntimeException("thread did not execute: " + didRunThread);
252       }
253     }
254   }
255   
256   @Test public void testJoin () {
257     if (verifyNoPropertyViolation()) {
258       Runnable r = new Runnable() {
259
260         @Override
261                 public synchronized void run() {
262           didRunThread = Thread.currentThread().getName();
263         }
264       };
265
266       Thread t = new Thread(r);
267
268       synchronized (r) {
269         t.start();
270         Thread.yield();
271         if (didRunThread != null) {
272           throw new RuntimeException("sync thread did execute before lock release");
273         }
274       }
275
276       try {
277         t.join();
278       } catch (InterruptedException ix) {
279         throw new RuntimeException("main thread was interrupted");
280       }
281
282       if (didRunThread == null) {
283         throw new RuntimeException("sync thread did not run after lock release");
284       }
285     }
286   }
287
288   @Test public void testTimeoutJoin () {
289     if (!isJPFRun()){
290       Verify.resetCounter(0);
291       Verify.resetCounter(1);
292     }
293
294     if (verifyNoPropertyViolation()) {
295       Runnable r = new Runnable() {
296
297         @Override
298                 public void run() {
299           synchronized(this){
300             System.out.println("[t] started");
301           }
302           didRunThread = Thread.currentThread().getName(); // this causes a CG
303           System.out.println("[t] finished");
304         }
305       };
306
307       Thread t = new Thread(r);
308
309       synchronized (r) {
310         t.start();
311         Thread.yield();
312         if (didRunThread != null) {
313           throw new RuntimeException("sync thread did execute before lock release");
314         }
315       }
316
317       try {
318         System.out.println("[main] joining..");
319         t.join(42);
320         System.out.println("[main] joined, t state: " + t.getState());
321
322         // we should get here for both terminated and non-terminated t
323         switch (t.getState()) {
324           case TERMINATED:
325             if (didRunThread != null){
326               Verify.incrementCounter(0);
327             }
328             break;
329           case RUNNABLE:
330             Verify.incrementCounter(1);
331             break;
332           default:
333             throw new RuntimeException("infeasible thread state: " + t.getState());
334         }
335
336       } catch (InterruptedException ix) {
337         throw new RuntimeException("main thread was interrupted");
338       }
339     }
340
341     if (!isJPFRun()){
342       assert Verify.getCounter(0) > 0;
343       assert Verify.getCounter(1) > 0;
344     }
345   }
346
347
348   @Test public void testInterrupt() {
349     if (verifyNoPropertyViolation()) {
350
351       Runnable r = new Runnable() {
352
353         @Override
354                 public synchronized void run() {
355           try {
356             didRunThread = Thread.currentThread().getName();
357             System.out.println("-- t waiting");
358             wait();
359           } catch (InterruptedException x) {
360             System.out.println("-- t interrupted");
361             didRunThread = null;
362           }
363           System.out.println("-- t terminated");
364         }
365       };
366
367       Thread t = new Thread(r);
368       t.start();
369
370       while (didRunThread == null) {
371         Thread.yield();
372       }
373
374       synchronized (r) {
375         System.out.println("-- main thread interrupting...");
376         t.interrupt();
377       }
378
379       try {
380         t.join();
381       } catch (InterruptedException ix) {
382         throw new RuntimeException("main thread was interrupted");
383       }
384
385       if (didRunThread != null) {
386         throw new RuntimeException("t did not get interrupted");
387       }
388
389       System.out.println("-- main thread terminated");
390     }
391   }
392   
393   
394   @Test public void testSimpleThreadGroup () {
395     if (verifyNoPropertyViolation()) {
396
397       System.out.println("-- main thread started");
398
399       Thread mainThread = Thread.currentThread();
400       final ThreadGroup sysGroup = mainThread.getThreadGroup();
401
402
403       assert sysGroup != null && sysGroup.getName().equals("main");
404
405       int active = sysGroup.activeCount();
406       assert active == 1;
407       Thread[] list = new Thread[active];
408
409       int n = sysGroup.enumerate(list);
410       assert (n == active);
411       assert list[0] == mainThread;
412
413
414       Runnable r = new Runnable() {
415
416         @Override
417                 public void run() {
418           System.out.println("-- t started");
419           didRunThread = Thread.currentThread().getName();
420
421           Thread t = Thread.currentThread();
422           ThreadGroup group = t.getThreadGroup();
423
424           assert group != null && group == sysGroup;
425
426           int active = group.activeCount();
427           assert active == 2;
428           Thread[] list = new Thread[active];
429
430           int n = group.enumerate(list);
431           assert (n == active);
432
433           assert list[1] == t;
434           System.out.println("-- t terminated");
435         }
436       };
437
438       Thread t = new Thread(r);
439       t.start();
440
441       try {
442         t.join();
443       } catch (InterruptedException ix) {
444         throw new RuntimeException("main thread was interrupted");
445       }
446
447       if (didRunThread == null) {
448         throw new RuntimeException("t did not run");
449       }
450
451       System.out.println("-- main thread terminated");
452     }
453   }
454 }