//
// Copyright (C) 2008 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.test.vm.threads;
import java.util.concurrent.locks.LockSupport;
import org.junit.Test;
import gov.nasa.jpf.util.test.TestJPF;
/**
* raw test for Thread.interrupt conformance
*/
public class InterruptTest extends TestJPF {
@Test public void testInterruptStatus () {
if (verifyNoPropertyViolation()) {
Thread t = Thread.currentThread();
assert !t.isInterrupted() : "initial interrupt status is set";
System.out.println("setting interrupt status");
t.interrupt();
assert t.isInterrupted() : "interrupt status not set";
System.out.println("query and clear interrupt status");
assert Thread.interrupted() : "interrupt status prematurely reset";
assert !Thread.interrupted() : "interrupt status wasn't reset";
}
}
@Test public void testWaitSyncInterrupt() {
if (verifyNoPropertyViolation()) {
Runnable r = new Runnable() {
public void run() {
// doesn't matter from where we interrupt (thread can interrupt itself)
Thread t = Thread.currentThread();
t.interrupt();
synchronized (this) {
// if we don't enter here, this should be reported as a deadlock
System.out.println("T waiting");
try {
wait(); // this should immediately throw, i.e. return
assert false : "wait() did not throw InterruptedException";
} catch (InterruptedException ix) {
ix.printStackTrace(); // should include Object.wait()
System.out.println("T interrupted, terminating");
assert !t.isInterrupted() : "throw didn't reset interrupt status";
return;
} catch (Throwable x) {
assert false : "wait did throw wrong exception: " + x;
return;
}
}
assert false : "should never get here";
}
};
Thread t1 = new Thread(r);
t1.interrupt(); // should have no effect - it's not runnable yet
assert !t1.isInterrupted() : "non-started thread has interrupt status set";
t1.start();
System.out.println("main terminated");
}
}
@Test public void testWaitAsyncInterrupt() {
if (verifyNoPropertyViolation()) {
Runnable r = new Runnable() {
public void run() {
synchronized (this) {
// if we don't enter here, this should be reported as a deadlock
try {
System.out.println("T waiting");
wait();
assert false : "wait() did not throw InterruptedException";
} catch (InterruptedException ix) {
ix.printStackTrace(); // should include Object.wait()
System.out.println("T interrupted, terminating");
assert !Thread.currentThread().isInterrupted() : "throw didn't reset interrupt status";
return;
} catch (Throwable x) {
assert false : "wait did throw wrong exception: " + x;
return;
}
}
assert false : "should never get here";
}
};
Thread t1 = new Thread(r);
t1.start();
// no matter if this is executed before or after t1 enters Object.wait()
// it should terminate it by throwing. In fact, JPF should explore both
// paths
System.out.println("main interrupting t1");
t1.interrupt();
System.out.println("main terminated");
}
}
boolean interrupted;
boolean waiting;
@Test public void testBlockedWaitAsyncInterrupt() {
if (verifyNoPropertyViolation()) {
interrupted = false;
waiting = false;
Runnable r = new Runnable() {
public void run() {
synchronized (this) {
// if we don't enter here, this should be reported as a deadlock
try {
System.out.println("T waiting");
waiting = true;
wait();
assert false : "wait() did not throw InterruptedException";
} catch (InterruptedException ix) {
ix.printStackTrace(); // should include Object.wait()
assert !Thread.currentThread().isInterrupted() : "throw didn't reset interrupt status";
System.out.println("T interrupted, terminating");
interrupted = true;
return;
} catch (Throwable x) {
assert false : "wait did throw wrong exception: " + x;
return;
}
}
assert false : "should never get here";
}
};
Thread t1 = new Thread(r);
t1.start();
while (!waiting) {
Thread.yield();
}
synchronized (r) {
System.out.println("main interrupting t1");
t1.interrupt();
// t1 can't run before we release the lock
Thread.yield(); // this shouldn't reschedule, t1 is blocked
assert !interrupted : "t1 prematurely scheduled w/o acquiring the lock";
System.out.println("main terminated, t1 runnable again");
}
}
}
@Test public void testPark() {
if (verifyNoPropertyViolation()) {
interrupted = false;
Thread t1 = new Thread(new Runnable() {
public void run() {
System.out.println("T parking..");
LockSupport.park();
interrupted = true;
System.out.println("T terminated");
}
});
t1.start();
System.out.println("main interrupting");
t1.interrupt();
try {
System.out.println("main joining t1..");
t1.join();
System.out.println("main joined t1");
} catch (InterruptedException e) {
assert false : "t1.join() interrupted in main";
}
assert interrupted : "LockSupport.park() didn't get interrupted";
System.out.println("main terminated");
}
}
}