comparison src/tests/gov/nasa/jpf/test/vm/threads/JoinTest.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
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
19 package gov.nasa.jpf.test.vm.threads;
20
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 * regression test for various Thread.join scenarios
29 */
30 public class JoinTest extends TestJPF {
31
32 static final String[] JPF_ARGS = { "+cg.threads.break_start=true",
33 "+cg.threads.break_yield=true",
34 "+vm.tree_output=false",
35 "+vm.path_output=true"};
36
37 @Test public void testSimpleJoin(){
38 if (verifyNoPropertyViolation(JPF_ARGS)) {
39 Runnable r = new Runnable() {
40 @Override
41 public void run() {
42 System.out.println("thread-0 run");
43 }
44 };
45
46 Thread t = new Thread(r);
47 t.start();
48
49 try {
50 t.join();
51 assert !t.isAlive();
52 System.out.println("main returned from join");
53 } catch (InterruptedException x) {
54 fail("join() did throw InterruptedException");
55 }
56 }
57 }
58
59 @Test public void testNoRunnableSimpleJoin() {
60 if (verifyNoPropertyViolation(JPF_ARGS)) {
61 Thread t = new Thread() {
62 @Override
63 public synchronized void run() {
64 System.out.println("thread-0 run");
65 }
66 };
67
68 t.start();
69
70 try {
71 t.join();
72 assert !t.isAlive();
73 System.out.println("main returned from join");
74 } catch (InterruptedException x) {
75 fail("join() did throw InterruptedException");
76 }
77 }
78 }
79
80 static class SomeThread extends Thread {
81 Object o;
82
83 @Override
84 public void run() {
85 synchronized (this){
86 // this causes a transition break - write on a shared object while
87 // we still hold the lock
88 o = new Object();
89 }
90 System.out.println("thread-0 done");
91 }
92 }
93
94 @Test public void testBlockedJoin() {
95 if (verifyNoPropertyViolation("+cg.threads.break_start=true",
96 "+vm.storage.class=null")) {
97 Thread t = new SomeThread();
98
99 t.start();
100 System.out.println("main started thread-0");
101
102 try {
103 t.join();
104 assert !t.isAlive();
105 System.out.println("main returned from join");
106 } catch (InterruptedException x) {
107 fail("join() did throw InterruptedException");
108 }
109 }
110 }
111
112 @Test public void testJoinHoldingLock(){
113 if (verifyNoPropertyViolation(JPF_ARGS)) {
114 Runnable r = new Runnable() {
115 @Override
116 public void run() {
117 System.out.println("thread-0 run");
118 }
119 };
120
121 Thread t = new Thread(r);
122 t.start();
123
124 try {
125 synchronized(t){
126 t.join();
127 }
128 System.out.println("main returned from join");
129 } catch (InterruptedException x) {
130 fail("join() did throw InterruptedException");
131 }
132 }
133 }
134
135
136 @Test public void testNotAliveJoin(){
137 if (verifyNoPropertyViolation(JPF_ARGS)) {
138 Runnable r = new Runnable() {
139 @Override
140 public void run() {
141 System.out.println("thread-0 run");
142 }
143 };
144
145 Thread t = new Thread(r);
146 t.start();
147
148 // poor man's join
149 while (t.isAlive()){
150 Thread.yield();
151 }
152
153 try {
154 t.join();
155 System.out.println("main returned from join");
156 } catch (InterruptedException x) {
157 fail("join() did throw InterruptedException");
158 }
159 }
160 }
161
162 @Test public void testPreJoinInterrupt() {
163 if (verifyNoPropertyViolation(JPF_ARGS)) {
164 Runnable r = new Runnable() {
165 @Override
166 public void run() {
167 System.out.println("thread-0 run");
168 }
169 };
170
171 Thread.currentThread().interrupt();
172
173 Thread t = new Thread(r);
174 t.start();
175
176 try {
177 t.join();
178 fail("join() didn't throw InterruptedException");
179 } catch (InterruptedException x) {
180 System.out.println("caught InterruptedException");
181 }
182 }
183 }
184
185 @Test public void testInterruptedJoin() {
186 if (verifyNoPropertyViolation(JPF_ARGS)) {
187 final Thread mainThread = Thread.currentThread();
188
189 Runnable r = new Runnable() {
190 @Override
191 public void run() {
192 System.out.println("thread-0 interrupting main");
193 mainThread.interrupt();
194 }
195 };
196
197 Thread t = new Thread(r);
198 t.start();
199
200 try {
201 t.join();
202 fail("join() didn't throw InterruptedException");
203 } catch (InterruptedException x) {
204 System.out.println("caught InterruptedException");
205 }
206 }
207 }
208
209 @Test public void testJoinLoop() {
210 if (verifyDeadlock(JPF_ARGS)) {
211 try {
212 Thread.currentThread().join();
213 fail("main can't get here if waiting for itself");
214 } catch (InterruptedException ex) {
215 fail("thread cannot be interrupted");
216 }
217 }
218 }
219
220 @Test public void testMultipleJoins() {
221 if (verifyNoPropertyViolation(JPF_ARGS)) {
222 try {
223 final Thread t1 = new Thread() {
224 @Override
225 public void run() {
226 Thread.yield();
227 }
228 };
229 Thread t2 = new Thread() {
230 @Override
231 public void run() {
232 try {
233 t1.join();
234 } catch (InterruptedException e) {
235 fail("unexpected interrupt");
236 }
237 }
238 };
239
240 t1.start();
241 t2.start();
242 t1.join();
243 t2.join();
244
245 assert (!t1.isAlive() && !t2.isAlive());
246 } catch (Exception ex) {
247 fail("unexpected exception: " + ex);
248 }
249 }
250 }
251
252 @Test public void testJoinBeforeStart() {
253 if (verifyNoPropertyViolation(JPF_ARGS)) {
254 try {
255 Thread t = new Thread();
256 t.join();
257 System.out.println("join on not-yet-started thread has no effect");
258 } catch (Exception ex) {
259 fail(ex.getMessage());
260 }
261 }
262 }
263
264
265 @Test public void testJoinAfterNotify() {
266 if (verifyNoPropertyViolation(JPF_ARGS)) {
267 try {
268 final Thread t = new Thread() {
269 @Override
270 public void run() {
271 synchronized(this){
272 System.out.println("thread-0 notifying");
273 notifyAll(); // this should not get us out of the join()
274 }
275 System.out.println("thread-0 terminating");
276 }
277 };
278
279 t.start();
280 System.out.println("main joining..");
281 t.join();
282 System.out.println("main joined");
283
284 Verify.printPathOutput("main termination");
285 assert !t.isAlive();
286
287 } catch (Exception ex) {
288 fail("unexpected exception: " + ex);
289 }
290 }
291 }
292
293 @Test public void testJoinNotifyDeadlock() {
294 if (verifyDeadlock(JPF_ARGS)) {
295 try {
296 final Thread t = new Thread() {
297 @Override
298 public void run() {
299 synchronized(this){
300 System.out.println("thread-0 notifying");
301 notifyAll();
302
303 try {
304 System.out.println("thread-0 waiting");
305 wait();
306 } catch (InterruptedException ix){
307 System.out.println("unexpected interrupt");
308 }
309 }
310 System.out.println("thread-0 terminating");
311 }
312 };
313
314 t.start();
315 System.out.println("main joining..");
316 t.join();
317 System.out.println("main joined");
318
319 synchronized (t){
320 System.out.println("main notifying");
321 t.notify();
322 }
323
324 Verify.printPathOutput("main termination");
325 assert !t.isAlive();
326
327 } catch (Exception ex) {
328 fail("unexpected exception: " + ex);
329 }
330 }
331 }
332
333
334 @Test public void testRedundantJoin() {
335 if (verifyNoPropertyViolation(JPF_ARGS)) {
336 try {
337 Thread t = new Thread();
338
339 t.start();
340 t.join();
341 System.out.println("main returned from first join()");
342 t.join();
343 System.out.println("main returned from second join()");
344
345 assert (!t.isAlive());
346 } catch (Exception ex) {
347 fail(ex.getMessage());
348 }
349 }
350 }
351
352 @Test public void testJoinThreadSet(){
353 if (verifyNoPropertyViolation(JPF_ARGS)) {
354 final Thread[] worker = new Thread[3];
355 worker[0] = new Thread(new Runnable() {
356 @Override
357 public void run() {
358 System.out.println("worker[0] finished");
359 }
360 });
361 worker[1] = new Thread(new Runnable() {
362 @Override
363 public void run() {
364 System.out.println("worker[1] finished");
365 }
366 });
367 worker[2] = new Thread(new Runnable() {
368 @Override
369 public void run() {
370 System.out.println("worker[2] finished");
371 }
372 });
373
374 int nJoin = 0;
375 for (int i = 0; i < worker.length; i++) {
376 worker[i].start();
377 nJoin++;
378 }
379
380 while (nJoin > 0) {
381 for (int i = 0; i < worker.length; i++) {
382 if (worker[i] != null) {
383 try {
384 worker[i].join();
385 } catch (InterruptedException x) {
386 fail("unexpected interrupt");
387 }
388 nJoin--;
389 worker[i] = null;
390 System.out.println("main joined worker[" + i + "]");
391 }
392 }
393 }
394 }
395 }
396
397
398 @Test public void testRecursiveJoinThreadGroup() {
399 if (!isJPFRun()){
400 Verify.resetCounter(0);
401 Verify.resetCounter(1);
402 Verify.resetCounter(2);
403 Verify.resetCounter(3);
404 }
405
406 if (verifyNoPropertyViolation(JPF_ARGS)) {
407
408 ThreadGroup workers = new ThreadGroup("workers");
409
410 Thread t = new Thread( workers, new Runnable(){
411 @Override
412 public void run() {
413 Thread t1 = new Thread( new Runnable(){
414 @Override
415 public void run() {
416 Thread t11 = new Thread(new Runnable() {
417 @Override
418 public void run() {
419 System.out.println("t11 run");
420 Verify.incrementCounter(0);
421 }
422 }, "t11");
423 t11.start();
424 System.out.println("t1 run");
425 Verify.incrementCounter(1);
426 }
427 }, "t1");
428 t1.start();
429
430 Thread t2 = new Thread( new Runnable(){
431 @Override
432 public void run() {
433 System.out.println("t2 run");
434 Verify.incrementCounter(2);
435 }
436 }, "t2");
437 t2.start();
438 System.out.println("t run");
439 Verify.incrementCounter(3);
440 }
441 }, "t");
442 t.start();
443
444 try {
445 Thread[] actives = new Thread[10]; // the length is just a guess here
446 int nActives = workers.enumerate(actives, true);
447 System.out.println("main joining " + nActives + " active threads");
448
449 while (nActives > 0){
450 assert nActives < actives.length; // it has to be strictly less to know we've got all
451 for (int i=0; i<nActives; i++){
452 System.out.println("main joining: " + actives[i].getName());
453 actives[i].join();
454 System.out.println("main joined: " + actives[i].getName());
455 }
456 nActives = workers.enumerate(actives, true);
457 System.out.println("..main now joining " + nActives + " active threads");
458 }
459 } catch (Throwable x){
460 fail("unexpected exception: " + x);
461 }
462
463 System.out.println("main done");
464 Verify.printPathOutput("end");
465 }
466
467 if (!isJPFRun()){
468 // not an ideal test since we don't know if the threads are still alive
469 assert Verify.getCounter(0) > 0;
470 assert Verify.getCounter(1) > 0;
471 assert Verify.getCounter(2) > 0;
472 assert Verify.getCounter(3) > 0;
473 }
474 }
475
476
477 @Test
478 public void testInterruptThreadWaitingToJoin() {
479 if (!isJPFRun()){
480 Verify.resetCounter(0);
481 }
482
483 if (verifyNoPropertyViolation(JPF_ARGS)) {
484 try {
485 class ChildThread extends Thread {
486 Thread toInterrupt;
487 public void setToInterrupt(Thread toInterrupt) {
488 this.toInterrupt = toInterrupt;
489 }
490 @Override
491 public void run() {
492 toInterrupt.interrupt();
493 }
494 }
495 final ChildThread child = new ChildThread();
496
497 class WaitingToJoinThread extends Thread {
498 @Override
499 public void run() {
500 try {
501 child.setToInterrupt(this);
502 child.start();
503 child.join();
504 } catch (InterruptedException ix) {
505 System.out.println("-- parent interrupted while child continues to run");
506 Verify.incrementCounter(0);
507 }
508 }
509 }
510
511 WaitingToJoinThread threadWaitingToJoin = new WaitingToJoinThread();
512
513 threadWaitingToJoin.start();
514 try {
515 threadWaitingToJoin.join();
516 } catch (InterruptedException ix) {
517 throw new RuntimeException("main thread was interrupted");
518 }
519 try {
520 child.join();
521 } catch (InterruptedException ix) {
522 throw new RuntimeException("main thread was interrupted");
523 }
524 } catch (Exception ex) {
525 throw new RuntimeException(ex.getMessage());
526 }
527 }
528
529 if (!isJPFRun()){
530 // at least one execution interrupts parent while child continues to run
531 assert Verify.getCounter(0) > 0;
532 }
533 }
534
535 @Test public void testTimeoutJoin () {
536 if (!isJPFRun()){
537 Verify.resetCounter(0);
538 Verify.resetCounter(1);
539 }
540
541 if (verifyNoPropertyViolation(JPF_ARGS)) {
542 Runnable r = new Runnable() {
543 @Override
544 public void run() {
545 System.out.println("thread-0 run");
546 Thread.yield();
547 }
548 };
549
550 Thread t = new Thread(r);
551 t.start();
552 //Thread.yield();
553
554 try {
555 System.out.println("main joining..");
556 t.join(42);
557 System.out.println("main joined, t state: " + t.getState());
558
559 // we should get here for both terminated and non-terminated thread
560 switch (t.getState()) {
561 case TERMINATED:
562 System.out.println("got terminated case");
563 Verify.incrementCounter(0);
564 break;
565 case RUNNABLE:
566 System.out.println("got timedout case");
567 Verify.incrementCounter(1);
568 break;
569 default:
570 fail("infeasible thread state: " + t.getState());
571 }
572
573 } catch (InterruptedException ix) {
574 fail("main thread was interrupted");
575 }
576 }
577
578 if (!isJPFRun()) {
579 assert Verify.getCounter(0) > 0;
580 assert Verify.getCounter(1) > 0;
581 }
582 }
583
584 @Test public void testZeroTimeoutJoin () {
585 if (!isJPFRun()){
586 Verify.resetCounter(0);
587 Verify.resetCounter(1);
588 }
589
590 if (verifyNoPropertyViolation(JPF_ARGS)) {
591 Runnable r = new Runnable() {
592 @Override
593 public void run() {
594 System.out.println("thread-0 run");
595 Thread.yield();
596 }
597 };
598
599 Thread t = new Thread(r);
600 t.start();
601 //Thread.yield();
602
603 try {
604 System.out.println("main joining..");
605 t.join(0);
606 System.out.println("main joined, t state: " + t.getState());
607
608 // we should get here for both terminated and non-terminated thread
609 switch (t.getState()) {
610 case TERMINATED:
611 Verify.incrementCounter(0);
612 break;
613 case RUNNABLE:
614 Verify.incrementCounter(1);
615 break;
616 default:
617 fail("infeasible thread state: " + t.getState());
618 }
619
620 } catch (InterruptedException ix) {
621 fail("main thread was interrupted");
622 }
623 }
624
625 if (!isJPFRun()) {
626 assert Verify.getCounter(0) > 0;
627 assert Verify.getCounter(1) == 0;
628 }
629 }
630
631 @Test public void testNegativeTimeoutJoin() {
632 if (verifyNoPropertyViolation(JPF_ARGS)) {
633 try {
634 Thread t = new Thread();
635 t.join(-1);
636 fail("should never get here");
637 } catch (InterruptedException ix) {
638 fail("unexpected InterruptedException");
639 } catch (IllegalArgumentException ax){
640 System.out.println("caught " + ax);
641 }
642 }
643 }
644
645 @Test public void testNestedLocksJoin() {
646 if (verifyNoPropertyViolation(JPF_ARGS)){
647 Thread t1 = new Thread() {
648 @Override
649 public synchronized void run() {
650 System.out.println("t1 notifying");
651 notifyAll();
652
653 try{
654 System.out.println("t1 waiting");
655 wait();
656 } catch (InterruptedException ix){
657 System.out.println("t1 unexpectedly interrupted");
658 }
659
660 System.out.println("t1 terminating");
661 }
662 };
663
664 Thread t2 = new Thread() {
665 @Override
666 public synchronized void run() {
667 System.out.println("t2 notifying");
668 notifyAll();
669
670 try{
671 System.out.println("t2 waiting");
672 wait();
673 } catch (InterruptedException ix){
674 System.out.println("t2 unexpectedly interrupted");
675 }
676
677 System.out.println("t2 terminating");
678 }
679 };
680
681 synchronized (t2){
682 try {
683 t2.start();
684
685 System.out.println("main waiting on t2");
686 t2.wait();
687
688 synchronized(t1){
689 t1.start();
690
691 System.out.println("main waiting on t1");
692 t1.wait();
693
694 System.out.println("main notifying t1");
695 t1.notify();
696 }
697
698 System.out.println("main joining t1");
699 t1.join();
700
701 System.out.println("main notifying t2");
702 t2.notify();
703
704 System.out.println("main joining t2");
705 t2.join();
706
707 } catch (InterruptedException ix){
708 System.out.println("main unexpectedly interrupted");
709 }
710 }
711
712 System.out.println("main terminating");
713 Verify.printPathOutput("main termination");
714 }
715 }
716 }