Mercurial > hg > Members > kono > jpf-core
view src/tests/gov/nasa/jpf/test/vm/threads/ThreadStopTest.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 source
/* * 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.annotation.NeverBreak; import gov.nasa.jpf.util.test.TestJPF; import gov.nasa.jpf.vm.Verify; import org.junit.Test; /** * regression test for Thread.stop() */ @SuppressWarnings("deprecation") public class ThreadStopTest extends TestJPF { @Test public void testStopNewThread(){ if (!isJPFRun()){ Verify.resetCounter(0); } if (verifyNoPropertyViolation()){ Thread t = new Thread(){ @Override public void run(){ Verify.println("# t running, that's bad"); fail("t should never run"); } }; t.stop(); Verify.println("# now starting the stopped thread"); t.start(); Thread.yield(); assertFalse( "t not terminated yet", t.isAlive()); Verify.println("# main got past start of stopped thread"); Verify.incrementCounter(0); } else { assertTrue( "main did not get past starting stopped thread", Verify.getCounter(0) > 0); } } @Test public void testStopNewSyncThread(){ if (!isJPFRun()){ Verify.resetCounter(0); } if (verifyNoPropertyViolation()){ Thread t = new Thread(){ @Override public synchronized void run(){ Verify.println("# t running, that's bad"); fail("t should never run"); } }; t.stop(); synchronized (t){ Verify.println("# now starting the stopped thread"); t.start(); // this should terminate the thread Verify.println("# main got past start of stopped sync thread"); } Verify.println("# main released lock for stopped sync thread"); Thread.yield(); assertFalse( "t not terminated yet", t.isAlive()); Verify.incrementCounter(0); } else { assertTrue( "main did not get past starting stopped thread", Verify.getCounter(0) > 0); } } @Test public void testStopSelf(){ if (!isJPFRun()){ Verify.resetCounter(0); Verify.resetCounter(1); } if (verifyNoPropertyViolation()){ Thread t = new Thread(){ @Override public synchronized void run(){ Verify.incrementCounter(1); Verify.println("# t running"); foo(); fail("t should not have gotten past self stop"); } void foo() { stop(); } }; Verify.println("# main now starting the thread"); t.start(); try { Verify.println("# main now joining the thread.."); t.join(); Verify.println("# main joined thread"); assertFalse( "t not terminated yet", t.isAlive()); Verify.incrementCounter(0); } catch (InterruptedException ix){ assert false : "main should not get an InterruptedException while joining"; } } else { assertTrue( "t did not run", Verify.getCounter(1) > 0); assertTrue( "main did not get past joining stopped thread", Verify.getCounter(0) > 0); } } // some sync helpers @NeverBreak static boolean isRunning; @Test public void testStopRunning () { if (!isJPFRun()) { Verify.resetCounter(0); Verify.resetCounter(1); } if (verifyNoPropertyViolation()) { isRunning = false; Thread t = new Thread() { @Override public synchronized void run () { isRunning = true; Verify.incrementCounter(1); Verify.println("# t running"); while (true) { // while(true) will cause no return insn ! // keep it alive Thread.yield(); } } }; Verify.println("# main now starting t"); t.start(); while (!isRunning) { Thread.yield(); } Verify.println("# main now stopping t"); t.stop(); try { Verify.println("# main now joining the stopped thread.."); t.join(); Verify.println("# main joined thread"); assertFalse("t not terminated yet", t.isAlive()); Verify.incrementCounter(0); } catch (InterruptedException ix) { assert false : "main should not get an InterruptedException while joining"; } } else { assertTrue("t did not run", Verify.getCounter(1) > 0); assertTrue("main did not get past join", Verify.getCounter(0) > 0); } } @NeverBreak static Object lock = new Object(); @Test public void testStopBlocked () { if (!isJPFRun()) { Verify.resetCounter(0); Verify.resetCounter(1); } if (verifyNoPropertyViolation()) { isRunning = false; Thread t = new Thread() { @Override public synchronized void run () { isRunning = true; Verify.incrementCounter(1); Verify.println("# t running, now blocking on lock.."); synchronized (lock) { fail("t should never get here"); } } }; synchronized (lock) { Verify.println("# main now starting t"); t.start(); while (!isRunning) { Thread.yield(); } assertTrue("t not blocked", t.getState() == Thread.State.BLOCKED); Verify.println("# main now stopping t"); t.stop(); assertTrue("t dead despite main not giving up lock", t.isAlive()); Verify.println("# main now releasing lock"); } try { Verify.println("# main now joining the stopped thread.."); t.join(); Verify.println("# main joined thread"); assertFalse("t not terminated yet", t.isAlive()); Verify.incrementCounter(0); } catch (InterruptedException ix) { assert false : "main should not get an InterruptedException while joining"; } } else { assertTrue("t did not run", Verify.getCounter(1) > 0); assertTrue("main did not get past join", Verify.getCounter(0) > 0); } } @Test public void testStopWaiting(){ if (!isJPFRun()){ Verify.resetCounter(0); Verify.resetCounter(1); } if (verifyNoPropertyViolation()){ isRunning = false; Thread t = new Thread(){ @Override public synchronized void run(){ isRunning = true; Verify.incrementCounter(1); Verify.println("# t running, now waiting on lock"); synchronized(lock){ try { lock.wait(); } catch (InterruptedException ix){ fail("should not get interrupted"); } } } }; Verify.println("# main now starting t"); t.start(); while (t.getState() != Thread.State.WAITING) { Thread.yield(); } Verify.println("# main now stopping t"); t.stop(); Thread.yield(); assertTrue("t dead despite main not notifying", t.isAlive()); Verify.println("# main now notifying"); synchronized (lock) { lock.notifyAll(); } try { Verify.println("# main now joining the stopped thread.."); t.join(); Verify.println("# main joined thread"); assertFalse( "t not terminated yet", t.isAlive()); Verify.incrementCounter(0); } catch (InterruptedException ix){ assert false : "main should not get an InterruptedException while joining"; } } else { assertTrue( "t did not run", Verify.getCounter(1) > 0); assertTrue( "main did not get past join", Verify.getCounter(0) > 0); } } static boolean wasHandled; @Test public void testStopHandler() { if (!isJPFRun()){ Verify.resetCounter(0); Verify.resetCounter(1); } if (verifyNoPropertyViolation()){ isRunning = false; wasHandled = false; Thread t = new Thread(){ @Override public synchronized void run(){ isRunning = true; Verify.incrementCounter(1); Verify.println("# t running, now waiting on lock"); try { synchronized (lock) { try { lock.wait(); } catch (InterruptedException ix) { fail("should not get interrupted"); } } } catch (ThreadDeath td){ // usually not a good style, but can happen for exit processing Verify.println("# t caught ThreadDeath"); wasHandled = true; throw td; // rethrow to continue with kill } } }; Verify.println("# main now starting t"); t.start(); while (t.getState() != Thread.State.WAITING) { Thread.yield(); } Verify.println("# main now stopping t"); t.stop(); Thread.yield(); assertTrue("t dead despite main not notifying", t.isAlive()); Verify.println("# main now notifying"); synchronized (lock) { lock.notifyAll(); } try { Verify.println("# main now joining the stopped thread.."); t.join(); Verify.println("# main joined thread"); assertFalse( "t not terminated yet", t.isAlive()); assertTrue("t did not handle ThreadDeath", wasHandled); Verify.incrementCounter(0); } catch (InterruptedException ix){ assert false : "main should not get an InterruptedException while joining"; } } else { assertTrue( "t did not run", Verify.getCounter(1) > 0); assertTrue( "main did not get past join", Verify.getCounter(0) > 0); } } @Test public void testStopTerminated(){ if (!isJPFRun()){ Verify.resetCounter(0); Verify.resetCounter(1); } if (verifyNoPropertyViolation()){ Thread t = new Thread(){ @Override public void run(){ Verify.incrementCounter(1); Verify.println("# t running"); } }; Verify.println("# main now starting t"); t.start(); while (t.isAlive()){ Thread.yield(); } assertFalse("t is a zombie", t.isAlive()); Verify.println("# main now stopping dead t"); t.stop(); Verify.println("# main survived stopping t"); assertFalse("t is a zombie", t.isAlive()); Verify.incrementCounter(0); } else { assertTrue( "t did not run", Verify.getCounter(1) > 0); assertTrue( "main did not get past join", Verify.getCounter(0) > 0); } } static Thread waitee; @Test public void testStopJoin() { // join() is a lockfree wait, which makes it interesting if (!isJPFRun()){ Verify.resetCounter(0); Verify.resetCounter(1); Verify.resetCounter(2); } if (verifyNoPropertyViolation()){ waitee = new Thread(){ @Override public void run(){ Verify.incrementCounter(2); Verify.println("# waitee running"); synchronized(lock){ try { Verify.println("# waitee now waiting for main to signal.."); lock.wait(); Verify.println("# waitee terminating"); } catch (InterruptedException ix) { fail("waitee should not get interrupted"); } } } }; waitee.start(); while (waitee.getState() != Thread.State.WAITING){ Thread.yield(); } Thread t = new Thread(){ @Override public synchronized void run(){ Verify.incrementCounter(1); try { Verify.println("# t now joining waitee.."); waitee.join(); fail("t should never get here"); } catch (InterruptedException ix){ fail("t should not get interrupted"); } } }; Verify.println("# main now starting t"); t.start(); while (t.getState() != Thread.State.WAITING){ Thread.yield(); } assertTrue("waitee is a zombie", waitee.isAlive()); assertTrue("t is a zombie", t.isAlive()); Verify.println("# main now stopping t"); t.stop(); assertTrue("t should not have terminated since waitee not notified yet", t.isAlive()); Verify.println("# main now notifying waitee"); synchronized(lock){ lock.notifyAll(); } try { Verify.println("# main now joining waitee"); waitee.join(); } catch (InterruptedException ix){ fail("main should not get interupted joining waitee"); } assertFalse("waitee is a zombie", waitee.isAlive()); try { Verify.println("# main now joining t"); t.join(); } catch (InterruptedException ix){ fail("main should not get interupted joining t"); } assertFalse("t is a zombie", t.isAlive()); Verify.incrementCounter(0); } else { assertTrue( "waitee did not run", Verify.getCounter(2) > 0); assertTrue( "t did not run", Verify.getCounter(1) > 0); assertTrue( "main did not get past t join", Verify.getCounter(0) > 0); } } // and a lot more.. (e.g. stopping interrupted or timedout threads) }