// Tags: JDK1.0
// Copyright (C) 2004 Free Software Foundation, Inc.
// Written by Mark Wielaard (mark@klomp.org)
// This file is part of Mauve.
// Mauve is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
// Mauve is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Mauve; see the file COPYING. If not, write to
// the Free Software Foundation, 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.
package gnu.testlet.wonka.lang.Thread;
import gnu.testlet.Testlet;
import gnu.testlet.TestHarness;
public class sleep implements Testlet, Runnable
{
private TestHarness harness;
private Thread thread;
private boolean helper_started;
private boolean helper_done;
private final static long SLEEP_TIME = 5 * 1000; // 5 seconds
// Time the helper thread should sleep before interrupting the main
// thread Or zero for immediate interruption (won't use
// synchronization either in that case).
private long helper_sleep = 0;
// Helper method that runs from another thread.
// Sleeps a bit and then interrupts the main thread.
public void run()
{
try
{
if (helper_sleep == 0)
{
thread.interrupt();
helper_done = true;
return;
}
// Make sure main thread know we are about to sleep.
// (It should also go to sleep)
synchronized(this)
{
helper_started = true;
this.notify();
}
Thread.sleep(helper_sleep);
thread.interrupt();
// Main thread should still have the lock on this
synchronized(this)
{
helper_done = true;
}
}
catch (InterruptedException ie)
{
harness.debug("Interrupted in helper thread");
harness.check(false);
}
}
public void test (TestHarness h)
{
harness = h;
Thread helper = new Thread(this);
harness.checkPoint("Interrupted sleep");
// Get a lock on this to coordinate with the runner thread.
// We should not loose it while sleeping.
synchronized(this)
{
helper_done = false;
helper_sleep = SLEEP_TIME / 2;
thread = Thread.currentThread();
long past = System.currentTimeMillis();
helper.start();
// Wait for the helper to start (and sleep immediately).
try
{
while (!helper_started)
this.wait();
}
catch (InterruptedException ie)
{
harness.debug("Interrupted during helper start");
harness.check(false);
}
// Go to sleep.
// Helper thread sleeps less time and should interrupt us.
boolean interrupted_exception = false;
try
{
Thread.sleep(SLEEP_TIME);
}
catch (InterruptedException ie)
{
interrupted_exception = true;
}
harness.check(interrupted_exception);
// About half the time should have been spent sleeping.
long present = System.currentTimeMillis();
long diff = present - past;
//harness.debug("diff: " + diff);
harness.check(diff >= SLEEP_TIME / 2);
harness.check(diff < SLEEP_TIME);
// Even though we are interrupted,
// the thread interrupted flag should be cleared.
harness.check(!Thread.interrupted());
// We are still holding the lock so the helper_thread
// cannot be done yet.
harness.check(!helper_done);
}
// Now wait for the helper thead to finish
try
{
helper.join();
}
catch(InterruptedException ie)
{
harness.debug("Interruped during joining the helper thread");
harness.check(false);
}
harness.check(helper_done);
// Invalid argument checks.
harness.checkPoint("Invalid argument");
invalid(Long.MIN_VALUE);
invalid(-1);
invalid(Long.MIN_VALUE, Integer.MIN_VALUE);
invalid(Long.MIN_VALUE, -1);
invalid(Long.MIN_VALUE, 0);
invalid(Long.MIN_VALUE, 1);
invalid(Long.MIN_VALUE, 999999);
invalid(Long.MIN_VALUE, 1000000);
invalid(Long.MIN_VALUE, Integer.MAX_VALUE);
invalid(-1, Integer.MIN_VALUE);
invalid(-1, -1);
invalid(-1, 0);
invalid(-1, 1);
invalid(-1, 999999);
invalid(-1, 1000000);
invalid(-1, Integer.MAX_VALUE);
invalid(0, Integer.MIN_VALUE);
invalid(0, -1);
invalid(0, 1000000);
invalid(0, Integer.MAX_VALUE);
invalid(1, Integer.MIN_VALUE);
invalid(1, -1);
invalid(1, 1000000);
invalid(1, Integer.MAX_VALUE);
invalid(Long.MAX_VALUE, Integer.MIN_VALUE);
invalid(Long.MAX_VALUE, -1);
invalid(Long.MAX_VALUE, 1000000);
invalid(Long.MAX_VALUE, Integer.MAX_VALUE);
// (Large) valid argument checks
valid(Integer.MAX_VALUE);
valid(Long.MAX_VALUE);
valid(Integer.MAX_VALUE, 0);
valid(Long.MAX_VALUE, 0);
valid(Integer.MAX_VALUE, 1);
valid(Long.MAX_VALUE, 1);
valid(Integer.MAX_VALUE, 999999);
valid(Long.MAX_VALUE, 999999);
// (Near) zero argument checks.
harness.checkPoint("(Near) zero sleep");
long past = System.currentTimeMillis();
nearZero(0);
nearZero(1);
nearZero(0, 0);
nearZero(0, 1);
nearZero(0, 999999);
nearZero(1, 0);
nearZero(1, 1);
nearZero(1, 999999);
// The thread should have slept at least 5 miliseconds.
// But certainly not more than 500 miliseconds.
long present = System.currentTimeMillis();
long diff = present - past;
//harness.debug("diff: " + diff);
harness.check(diff > 5);
harness.check(diff < 500);
// A thread in interrupted state that goes to sleep gets
// InterruptedException.
harness.checkPoint("Interrupted state sleep");
past = System.currentTimeMillis();
interruptedSleep(0);
interruptedSleep(1);
interruptedSleep(5000);
interruptedSleep(0, 0);
interruptedSleep(1, 0);
interruptedSleep(0, 1);
interruptedSleep(1, 1);
interruptedSleep(5000, 0);
interruptedSleep(5000, 5000);
// The thread should not actually have slept (much) since it was always
// immediately waken up by the InterrupedException.
present = System.currentTimeMillis();
harness.check(present - past < 5000);
}
private void invalid(long milli)
{
boolean illegal_argument = false;
try
{
Thread.sleep(milli);
}
catch (IllegalArgumentException iae)
{
illegal_argument = true;
}
catch(InterruptedException ie)
{
harness.debug("InterruptedException in invalid(" + milli + ")");
harness.check(false);
}
harness.check(illegal_argument);
}
private void invalid(long milli, int nano)
{
boolean illegal_argument = false;
try
{
Thread.sleep(milli, nano);
}
catch (IllegalArgumentException iae)
{
illegal_argument = true;
}
catch(InterruptedException ie)
{
harness.debug("InterruptedException in invalid("
+ milli + ", " + nano + ")");
harness.check(false);
}
harness.check(illegal_argument);
}
private void valid(long milli)
{
harness.checkPoint("valid long:" + milli);
Thread helper = new Thread(this);
helper_started = false;
helper_done = false;
helper_sleep = 1000;
thread = Thread.currentThread();
// Wait for the helper to start (and sleep immediately).
helper.start();
synchronized(this)
{
try
{
while (!helper_started)
this.wait();
}
catch (InterruptedException ie)
{
harness.debug("Interrupted during helper start");
harness.check(false);
}
}
boolean interrupted_exception = false;
try
{
Thread.sleep(milli);
}
catch (InterruptedException ie)
{
interrupted_exception = true;
}
harness.check(interrupted_exception);
try
{
helper.join();
}
catch(InterruptedException ie)
{
harness.debug("Interruped during joining the helper thread");
harness.check(false);
}
harness.check(helper_done);
}
private void valid(long milli, int nano)
{
harness.checkPoint("valid long " + milli + " int " + nano);
Thread helper = new Thread(this);
helper_started = false;
helper_done = false;
helper_sleep = 1000;
thread = Thread.currentThread();
// Wait for the helper to start (and sleep immediately).
helper.start();
synchronized(this)
{
try
{
while (!helper_started)
this.wait();
}
catch (InterruptedException ie)
{
harness.debug("Interrupted during helper start");
harness.check(false);
}
}
boolean interrupted_exception = false;
try
{
Thread.sleep(milli, nano);
}
catch (InterruptedException ie)
{
interrupted_exception = true;
}
catch (Exception x)
{
harness.debug(x);
try
{
// wait for the interrupt from the helper
Thread.sleep(1000);
}
catch (InterruptedException _)
{
}
}
harness.check(interrupted_exception);
try
{
helper.join();
}
catch(InterruptedException ie)
{
harness.debug("Interrupted during joining the helper thread");
harness.check(false);
}
harness.check(helper_done);
}
private void nearZero(long milli)
{
try
{
Thread.sleep(milli);
harness.check(true);
}
catch(InterruptedException ie)
{
harness.debug("InterruptedException in nearZero(" + milli + ")");
harness.check(false);
}
}
private void nearZero(long milli, int nano)
{
try
{
Thread.sleep(milli, nano);
harness.check(true);
}
catch(InterruptedException ie)
{
harness.debug("InterruptedException in nearZero("
+ milli + ", " + nano + ")");
harness.check(false);
}
}
private void interruptedSleep(long milli)
{
boolean interrupted_exception = false;
Thread.currentThread().interrupt();
try
{
Thread.sleep(milli);
}
catch(InterruptedException ie)
{
interrupted_exception = true;
}
harness.check(interrupted_exception,"interrupted exception "+milli);
harness.check(!Thread.interrupted(),"Thread.interrupted "+milli);
}
private void interruptedSleep(long milli, int nano)
{
boolean interrupted_exception = false;
Thread.currentThread().interrupt();
try
{
Thread.sleep(milli, nano);
}
catch(InterruptedException ie)
{
interrupted_exception = true;
}
harness.check(interrupted_exception, "interrupted exception "+milli+" - "+nano);
harness.check(!Thread.interrupted(), "Thread.interrupted "+milli+" - "+nano);
}
}