Skip to content

Commit

Permalink
Refactored: task scheduler test
Browse files Browse the repository at this point in the history
  • Loading branch information
luontola committed Nov 27, 2008
1 parent e6c0cd0 commit 4e377dc
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 51 deletions.
Expand Up @@ -35,6 +35,7 @@
import jdave.*;
import jdave.junit4.JDaveRunner;
import net.orfjackal.dimdwarf.api.EntityInfo;
import net.orfjackal.dimdwarf.context.ThreadContext;
import net.orfjackal.dimdwarf.entities.*;
import net.orfjackal.dimdwarf.modules.*;
import net.orfjackal.dimdwarf.tasks.TaskExecutor;
Expand Down Expand Up @@ -109,19 +110,30 @@ public void run() {
return true;
}

// Utility methods which create their own task context
// Utility methods which should be executed outside a task context.
// They will create their own task context when necessary.

private boolean taskMayBeTakenRightNow() {
final TaskBootstrap bootstrap = takeNextTaskFrom(scheduler);
taskContext.execute(new Runnable() {
public void run() {
specify(_takeNextTaskFrom(scheduler).getTaskInsideTransaction(), should.not().equal(null));
specify(bootstrap.getTaskInsideTransaction(), should.not().equal(null));
}
});
return true;
}

public static TaskBootstrap takeNextTaskFrom(TaskSchedulerImpl scheduler) {
assert ThreadContext.getCurrentContext() == null;
try {
return scheduler.takeNextTask();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

private boolean thereAreNoExecutableTasksRightNow() {
_interruptTestThreadAfter(THREAD_SYNC_DELAY);
interruptTestThreadAfter(THREAD_SYNC_DELAY);
specify(new Block() {
public void run() throws Throwable {
TaskBootstrap bootstrap;
Expand All @@ -144,39 +156,14 @@ public void run() {
}

private boolean taskCanBeTakenExactlyAfterDelay(final int delay) {
taskContext.execute(new Runnable() {
public void run() {
clock.addTime(delay - 1);
_interruptTestThreadAfter(THREAD_SYNC_DELAY);
specify(_takeNextTaskIsInterrupted());
clock.addTime(1);
specify(_takeNextTaskFrom(scheduler).getTaskInsideTransaction(), should.not().equal(null));
}
});
clock.addTime(delay - 1);
specify(thereAreNoExecutableTasksRightNow());
clock.addTime(1);
specify(taskMayBeTakenRightNow());
return true;
}

private boolean cancelsSuccessfully(Future<?> f) {
specify(!f.isDone());
specify(!f.isCancelled());
boolean success = f.cancel(false);
specify(success);
specify(f.isDone());
specify(f.isCancelled());
return true;
}

// Utility methods which expect a task context (prefixed with "_")

public static TaskBootstrap _takeNextTaskFrom(TaskSchedulerImpl scheduler) {
try {
return scheduler.takeNextTask();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

private static void _interruptTestThreadAfter(final int delay) {
private static void interruptTestThreadAfter(final int delay) {
final Thread testThread = Thread.currentThread();
new Thread(new Runnable() {
public void run() {
Expand All @@ -190,15 +177,18 @@ public void run() {
}).start();
}

private boolean _takeNextTaskIsInterrupted() {
specify(new Block() {
public void run() throws Throwable {
scheduler.takeNextTask();
}
}, should.raise(InterruptedException.class));
private boolean _cancelsSuccessfully(Future<?> f) {
specify(!f.isDone());
specify(!f.isCancelled());
boolean success = f.cancel(false);
specify(success);
specify(f.isDone());
specify(f.isCancelled());
return true;
}

// Utility methods which expect a task context (prefixed with "_")

private void _saveFuture(Future<?> future) {
specify(future, should.not().equal(null));
bindings.get().update("future", new DummyEntity(future));
Expand Down Expand Up @@ -252,9 +242,10 @@ public void theTaskIsQueued() {
}

public void anExecutorMayTakeTheTask() {
final TaskBootstrap bootstrap = takeNextTaskFrom(scheduler);
taskContext.execute(new Runnable() {
public void run() {
specify(_takeNextTaskFrom(scheduler).getTaskInsideTransaction(), should.equal(task1));
specify(bootstrap.getTaskInsideTransaction(), should.equal(task1));
}
});
}
Expand All @@ -275,9 +266,10 @@ public void run() {
}
});
specify(scheduler.getQueuedTasks(), should.equal(1));
final TaskBootstrap bootstrap = takeNextTaskFrom(scheduler);
taskContext.execute(new Runnable() {
public void run() {
_takeNextTaskFrom(scheduler).getTaskInsideTransaction();
bootstrap.getTaskInsideTransaction();
}
});
}
Expand Down Expand Up @@ -354,10 +346,12 @@ public void run() {
}
});
clock.addTime(2000);
final TaskBootstrap bootstrap1 = takeNextTaskFrom(scheduler);
final TaskBootstrap bootstrap2 = takeNextTaskFrom(scheduler);
taskContext.execute(new Runnable() {
public void run() {
specify(_takeNextTaskFrom(scheduler).getTaskInsideTransaction(), should.equal(task2));
specify(_takeNextTaskFrom(scheduler).getTaskInsideTransaction(), should.equal(task1));
specify(bootstrap1.getTaskInsideTransaction(), should.equal(task2));
specify(bootstrap2.getTaskInsideTransaction(), should.equal(task1));
}
});
}
Expand Down Expand Up @@ -429,7 +423,7 @@ public void run() {
// Use each variation of scheduling when testing cancelling
ScheduledFuture<?> f = scheduler.schedule(task1, 1, TimeUnit.SECONDS);
specify(f.getDelay(TimeUnit.SECONDS), should.equal(1));
specify(cancelsSuccessfully(f));
specify(_cancelsSuccessfully(f));
}
});
}
Expand All @@ -456,7 +450,7 @@ public void run() {
public void run() {
ScheduledFuture<?> f = _loadFuture();
specify(f.getDelay(TimeUnit.MILLISECONDS), should.equal(900));
specify(cancelsSuccessfully(f));
specify(_cancelsSuccessfully(f));
}
});
}
Expand All @@ -479,12 +473,13 @@ public void run() {
}
});
clock.addTime(1000);
final TaskBootstrap bootstrap = takeNextTaskFrom(scheduler);
taskContext.execute(new Runnable() {
public void run() {
specify(_takeNextTaskFrom(scheduler).getTaskInsideTransaction(), should.equal(task1));
specify(bootstrap.getTaskInsideTransaction(), should.equal(task1));
ScheduledFuture<?> f = _loadFuture();
specify(f.getDelay(TimeUnit.MILLISECONDS), should.equal(2000));
specify(cancelsSuccessfully(f));
specify(_cancelsSuccessfully(f));
}
});
}
Expand Down
Expand Up @@ -37,7 +37,7 @@
import net.orfjackal.dimdwarf.api.EntityInfo;
import net.orfjackal.dimdwarf.entities.BindingStorage;
import net.orfjackal.dimdwarf.modules.*;
import static net.orfjackal.dimdwarf.scheduler.TaskSchedulerSpec._takeNextTaskFrom;
import static net.orfjackal.dimdwarf.scheduler.TaskSchedulerSpec.takeNextTaskFrom;
import net.orfjackal.dimdwarf.tasks.*;
import net.orfjackal.dimdwarf.tx.*;
import net.orfjackal.dimdwarf.util.*;
Expand Down Expand Up @@ -168,9 +168,10 @@ public void theTaskIsIsRescheduledIfTheTransactionRollsBack() {
specify(new Block() {
public void run() throws Throwable {

final TaskBootstrap bootstrap = takeNextTaskFrom(scheduler);
taskContext.execute(new Runnable() {
public void run() {
specify(_takeNextTaskFrom(scheduler).getTaskInsideTransaction(), should.equal(task1));
specify(bootstrap.getTaskInsideTransaction(), should.equal(task1));
tx.get().setRollbackOnly();
}
});
Expand All @@ -196,19 +197,21 @@ public void theNextExecutionIsNotScheduledIfTheTransactionRollsBack() {
specify(new Block() {
public void run() throws Throwable {

final TaskBootstrap bootstrap = takeNextTaskFrom(scheduler);
taskContext.execute(new Runnable() {
public void run() {
specify(_takeNextTaskFrom(scheduler).getTaskInsideTransaction(), should.equal(task1));
specify(bootstrap.getTaskInsideTransaction(), should.equal(task1));
tx.get().setRollbackOnly();
}
});
}
}, should.raise(TransactionException.class));
specify(scheduler.getQueuedTasks(), should.equal(1)); // the first task at T1000; can be taken right away

final TaskBootstrap bootstrap = takeNextTaskFrom(scheduler);
taskContext.execute(new Runnable() {
public void run() {
specify(_takeNextTaskFrom(scheduler).getTaskInsideTransaction(), should.equal(task1));
specify(bootstrap.getTaskInsideTransaction(), should.equal(task1));
}
});
specify(scheduler.getQueuedTasks(), should.equal(1)); // the next task at T1000+2000
Expand Down

0 comments on commit 4e377dc

Please sign in to comment.