Mercurial > hg > Members > kono > jpf-core
diff src/tests/gov/nasa/jpf/test/vm/threads/SuspendResumeTest.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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tests/gov/nasa/jpf/test/vm/threads/SuspendResumeTest.java Fri Jan 23 10:14:01 2015 -0800 @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2014, United States Government, as represented by the + * Administrator of the National Aeronautics and Space Administration. + * All rights reserved. + * + * The Java Pathfinder core (jpf-core) platform is licensed under the + * Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package gov.nasa.jpf.test.vm.threads; + +import gov.nasa.jpf.util.test.TestJPF; + +import org.junit.Test; + +/** + * regression test for suspend/resume + */ +@SuppressWarnings("deprecation") +public class SuspendResumeTest extends TestJPF { + + static boolean isRunning; + static boolean pass = false; + + static class T1 extends Thread { + @Override + public void run(){ + System.out.println("t1 running"); + isRunning = true; + while (!pass){ + Thread.yield(); + } + System.out.println("t1 terminating"); + } + } + + @Test + public void testBasicSuspendDeadlock(){ + if (verifyDeadlock("+cg.threads.break_yield")) { + Thread t1 = new T1(); + t1.start(); + + while (!isRunning) { + Thread.yield(); + } + + t1.suspend(); + assertTrue(t1.getState() == Thread.State.RUNNABLE); + + pass = true; + + // without resuming, T1 should not be scheduled again, despite being in a RUNNABLE state + //t1.resume(); + } + } + + @Test + public void testBasicSuspendResume(){ + if (verifyNoPropertyViolation("+cg.threads.break_yield")) { + Thread t1 = new T1(); + t1.start(); + + while (!isRunning) { + Thread.yield(); + } + + System.out.println("main suspending t1"); + t1.suspend(); + assertTrue(t1.getState() == Thread.State.RUNNABLE); + + pass = true; + + System.out.println("main resuming t1"); + t1.resume(); + try { + System.out.println("main joining t1"); + t1.join(); + } catch (InterruptedException ix){ + fail("t1.join got interrupted"); + } + + System.out.println("main terminating after t1.join"); + } + } + + //--------------- + // this is the main reason to model suspend/resume, since suspension does + // *not* give up any held locks, and hence is very prone to creating deadlocks + + static class T2 extends Thread { + @Override + public synchronized void run(){ + System.out.println("t2 running with lock"); + isRunning = true; + while (!pass){ + Thread.yield(); + } + System.out.println("t2 terminating"); + } + } + + @Test + public void testLockholderSuspendDeadlock(){ + + if (verifyDeadlock("+cg.threads.break_yield")) { + Thread t2 = new T2(); + t2.start(); + + while (!isRunning) { + Thread.yield(); + } + + System.out.println("main suspending t2"); + t2.suspend(); + // now t2 should hold and never give up its lock + + synchronized (t2){ + fail("main should never get here"); + } + } + } + + //------------ + + static class T3 extends Thread { + @Override + public synchronized void run(){ + System.out.println("t3 running"); + isRunning = true; + try { + wait(); + } catch (InterruptedException ix){ + fail("t3 got interrupted"); + } + System.out.println("t3 terminating"); + } + } + + @Test + public void testWaitingSuspendNotifyDeadlock(){ + if (verifyDeadlock("+cg.threads.break_yield")) { + Thread t3 = new T3(); + t3.start(); + + while (!isRunning) { + Thread.yield(); + } + + synchronized (t3){ + assertTrue( t3.getState() == Thread.State.WAITING); + + System.out.println("main suspending t3"); + t3.suspend(); + + System.out.println("main notifying t3"); + t3.notify(); + // t3 should be still suspended, despite being notified + } + } + } + + @Test + public void testWaitingSuspendNotifyResume(){ + if (verifyNoPropertyViolation("+cg.threads.break_yield")) { + Thread t3 = new T3(); + t3.start(); + + while (!isRunning) { + Thread.yield(); + } + + synchronized (t3){ + assertTrue( t3.getState() == Thread.State.WAITING); + + System.out.println("main suspending t3"); + t3.suspend(); + + System.out.println("main notifying t3"); + t3.notify(); + // t3 should be still suspended, despite being notified + + System.out.println("main resuming t3"); + t3.resume(); + try { + System.out.println("main joining t3"); + t3.join(); + } catch (InterruptedException ix) { + fail("t3.join got interrupted"); + } + + System.out.println("main terminating after t3.join"); + } + } + } + + + //---------------- + + static class T4 extends Thread { + @Override + public void run(){ + System.out.println("t4 running "); + isRunning = true; + while (!pass){ + Thread.yield(); + } + + System.out.println("t4 trying to obtain lock"); + synchronized (this){ + System.out.println("t4 obtained lock"); + } + System.out.println("t4 terminating"); + } + } + + @Test + public void testBlockSuspendUnblockDeadlock(){ + if (verifyDeadlock("+cg.threads.break_yield")) { + Thread t4 = new T4(); + t4.start(); + + while (!isRunning) { + Thread.yield(); + } + + synchronized (t4){ + pass = true; + + while (t4.getState() != Thread.State.BLOCKED){ + Thread.yield(); + } + + System.out.println("main suspending t4"); + t4.suspend(); + } + System.out.println("main released t4 lock"); + } + } + + + @Test + public void testBlockSuspendUnblockResume(){ + if (verifyNoPropertyViolation("+cg.threads.break_yield")) { + Thread t4 = new T4(); + t4.start(); + + while (!isRunning) { + Thread.yield(); + } + + synchronized (t4){ + pass = true; + + while (t4.getState() != Thread.State.BLOCKED){ + Thread.yield(); + } + + System.out.println("main suspending t4"); + t4.suspend(); + } + System.out.println("main released t4 lock"); + + System.out.println("main resuming t4"); + t4.resume(); + try { + System.out.println("main joining t4"); + t4.join(); + } catch (InterruptedException ix) { + fail("t4.join got interrupted"); + } + + System.out.println("main terminating after t4.join"); + } + } +}