//
// Copyright (C) 2006 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 org.junit.Test;
import gov.nasa.jpf.util.test.TestJPF;
/**
* signal test (wait/notify)
*/
public class WaitTest extends TestJPF
{
int counter;
boolean cond;
boolean done;
@Test public void testVerySimpleWait () {
if (verifyNoPropertyViolation()) {
System.out.println("running testVerySimpleWait()");
synchronized (this) {
try {
System.out.println("waiting");
wait(100L);
System.out.println("timed out");
} catch (InterruptedException ix) {
throw new RuntimeException("got interrupted");
}
}
}
}
@Test public void testSimpleWait () {
if (verifyNoPropertyViolation()) {
System.out.println("running testSimpleWait()");
Runnable notifier = new Runnable() {
public void run() {
synchronized (WaitTest.this) {
System.out.println("notifying");
cond = true;
WaitTest.this.notify();
}
}
};
Thread t = new Thread(notifier);
cond = false;
synchronized (this) {
t.start();
try {
System.out.println("waiting");
wait();
System.out.println("notified");
if (!cond) {
throw new RuntimeException("'cond' not set, premature wait return");
}
} catch (InterruptedException ix) {
throw new RuntimeException("got interrupted");
}
}
}
}
@Test public void testSyncRunWait () {
if (verifyNoPropertyViolation()) {
System.out.println("running testSyncRunWait()");
Runnable waiter = new Runnable() {
public synchronized void run() {
System.out.println("thread-0 running");
try {
wait(); // needs to be first insn
System.out.println("thread-0 notified");
} catch (InterruptedException ix) {
throw new RuntimeException("thread-0 got interrupted");
}
}
};
Thread t = new Thread(waiter);
t.setDaemon(true); // to make sure we don't get a deadlock
t.start();
synchronized (waiter) {
System.out.println("main notifying");
waiter.notify();
}
}
}
@SuppressWarnings("unused")
@Test public void testTimeoutWait () {
if (verifyNoPropertyViolation()) {
System.out.println("running testTimeoutWait()");
Runnable notifier = new Runnable() {
public void run() {
synchronized (WaitTest.this) {
System.out.println("notifying");
cond = true;
WaitTest.this.notify();
}
}
};
Thread t = new Thread(notifier);
cond = false;
synchronized (this) {
if (false) {
t.start();
}
try {
System.out.println("waiting");
wait(1);
if (cond) {
System.out.println("got notified");
} else {
System.out.println("wait timed out");
}
} catch (InterruptedException ix) {
throw new RuntimeException("got interrupted");
}
}
}
}
@Test public void testLoopedWait () {
if (verifyNoPropertyViolation()) {
System.out.println("running testLoopedWait()");
Runnable notifier = new Runnable() {
public void run() {
while (!done) {
synchronized (WaitTest.this) {
System.out.println("notifying");
cond = true;
WaitTest.this.notify();
}
}
}
};
Thread t = new Thread(notifier);
cond = false;
done = false;
t.start();
synchronized (this) {
for (int i = 0; i < 2; i++) {
try {
System.out.println("waiting "); //System.out.println(i);
wait();
System.out.println("notified "); //System.out.println(i);
if (!cond) {
throw new RuntimeException("'cond' not set, premature wait return");
}
cond = false;
} catch (InterruptedException ix) {
throw new RuntimeException("got interrupted");
}
}
done = true;
}
}
}
@Test public void testInterruptedWait () {
if (verifyNoPropertyViolation()) {
System.out.println("running testInterruptedWait()");
final Thread current = Thread.currentThread();
Runnable notifier = new Runnable() {
public void run() {
synchronized (WaitTest.this) {
System.out.println("interrupting");
cond = true;
current.interrupt();
}
}
};
Thread t = new Thread(notifier);
cond = false;
synchronized (this) {
t.start();
try {
System.out.println("waiting");
wait();
System.out.println("notified");
throw new RuntimeException("notified, not interrupted");
} catch (InterruptedException ix) {
if (!cond) {
throw new RuntimeException("'cond' not set, premature wait return");
}
}
}
}
}
class Waiter implements Runnable {
String name;
boolean waiting;
boolean done1;
Waiter (String name) {
this.name = name;
waiting = false;
done1 = false;
}
public void run () {
synchronized (WaitTest.this) {
try {
System.out.print(name); System.out.println(" waiting");
waiting = true;
WaitTest.this.wait();
System.out.print(name); System.out.println(" notified");
done1 = true;
} catch (InterruptedException ix) {
throw new RuntimeException("waiter was interrupted");
}
}
}
}
/**
* that's a misnomer, since this one executes almost all of signal handling (except of mixed
* wait/timeout-wait and timeout joins) it should be called 'testAlmostAll'
*
*/
@Test public void testNotifyAll () {
if (verifyNoPropertyViolation()) {
System.out.println("running testNotifyAll()");
Waiter waiter1 = new Waiter("waiter1");
Thread t1 = new Thread(waiter1);
t1.start();
while (!waiter1.waiting) {
Thread.yield();
}
Waiter waiter2 = new Waiter("waiter2");
Thread t2 = new Thread(waiter2);
t2.start();
while (!waiter2.waiting) {
Thread.yield();
}
synchronized (this) {
System.out.println("main notifying all waiters..");
notifyAll();
System.out.println("..done");
}
try {
t1.join();
} catch (InterruptedException ix) {
throw new RuntimeException("main interrupted while waiting for thread1 to finish");
}
try {
t2.join();
} catch (InterruptedException ix) {
throw new RuntimeException("main interrupted while waiting for thread2 to finish");
}
synchronized (this) {
if (!waiter1.done1) {
throw new RuntimeException("waiter1 was not done");
}
if (!waiter2.done1) {
throw new RuntimeException("waiter2 was not done");
}
}
}
}
}