## thread-scheduler-inter-hostthreads-unit-test.pkg
#
# Unit/regression test functionality for interactions between
# the primary-hostthread threadkit stuff implemented in
#
#
src/lib/src/lib/thread-kit/src/core-thread-kit/microthread-preemptive-scheduler.pkg#
# and the secondary-hostthread threadkit stuff implemented in
#
#
src/lib/std/src/hostthread/io-wait-hostthread.pkg#
src/lib/std/src/hostthread/io-bound-task-hostthreads.pkg#
src/lib/std/src/hostthread/cpu-bound-task-hostthreads.pkg# Compiled by:
#
src/lib/test/unit-tests.lib# Run by:
#
src/lib/test/all-unit-tests.pkg#DO set_control "compiler::trap_int_overflow" "TRUE";
stipulate
include package threadkit; # threadkit is from
src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg #
package cpu = cpu_bound_task_hostthreads; # cpu_bound_task_hostthreads is from
src/lib/std/src/hostthread/cpu-bound-task-hostthreads.pkg package io = io_bound_task_hostthreads; # io_bound_task_hostthreads is from
src/lib/std/src/hostthread/io-bound-task-hostthreads.pkg# package hth = hostthread; # hostthread is from
src/lib/std/src/hostthread.pkg package mps = microthread_preemptive_scheduler; # microthread_preemptive_scheduler is from
src/lib/src/lib/thread-kit/src/core-thread-kit/microthread-preemptive-scheduler.pkg #
sleep = makelib::scripting_globals::sleep;
herein
package thread_scheduler_inter_hostthreads_unit_test {
#
include package unit_test; # unit_test is from
src/lib/src/unit-test.pkg
name = "src/lib/std/src/hostthread/thread-scheduler-inter-hostthreads-unit-test.pkg";
zero = REF 0;
k64 = REF (256 * 256);
fun verify_basic__echo__operation ()
=
{
echoed_text = REF "";
#
mps::echo { what => "foo", reply => (\\ what = (echoed_text := what)) };
#
sleep 0.1;
#
assert( *echoed_text == "foo" );
};
fun verify_basic__do__operation ()
=
{
result1 = REF 0;
result2 = REF 0;
#
mps::do (\\ () = result1 := 1);
mps::do (\\ () = result2 := 2);
#
sleep 0.1;
#
assert( *result1 == 1 );
assert( *result2 == 2 );
};
fun verify_do_to_maildrop ()
=
{
# The above test sets a refcell and uses a timeout
# to wait for completion -- very primitive. Here
# we use a maildrop to sychronize -- much more realistic:
drop = make_empty_maildrop (): Maildrop(Int);
worked = REF TRUE;
mps::do (\\ () = {
put_in_maildrop (drop, 17)
except
MAY_NOT_FILL_ALREADY_FULL_MAILDROP
=
worked := FALSE;
}
);
assert (take_from_maildrop drop == 17);
assert *worked;
};
fun verify_do_to_mailqueue ()
=
{
# Same as above, but using a mailqueue instead of a maildrop:
q = make_mailqueue (get_current_microthread()): Mailqueue(Int);
mps::do (\\ () = put_in_mailqueue (q, 13));
assert (take_from_mailqueue q == 13);
};
fun verify_do_via_cpu_bound_hostthread ()
=
{
# First nontrivial test: Submit a job to
# cpu server with reply via thread scheduler
# inter-hostthread interface:
q = make_mailqueue (get_current_microthread()): Mailqueue(Int); # Mailqueue for reply.
cpu::do {. # This block of code will be executed on one of the cpu-bound-task hostthreads.
mps::do {. # This block of code will be executed back on the thread-scheduler hostthread.
put_in_mailqueue (q, 19);
};
};
result = take_from_mailqueue q;
assert (result == 19);
};
fun verify_do_via_io_bound_hostthread ()
=
{
q = make_mailqueue (get_current_microthread()): Mailqueue(Int);
io::do {.
mps::do {.
put_in_mailqueue (q, 23);
};
};
result = take_from_mailqueue q;
assert (result == 23);
};
fun verify_divide_by_zero_in_cpu_bound_hostthread ()
=
{
##############################################################
# First, check that it works locally: :-)
#
foo = 12 / *zero # The '*zero' bit is just to guard against compiler optimizers.
except
DIVIDE_BY_ZERO = 13;
assert( foo == 13 );
##############################################################
# Now do the same thing in a CPU server to verify that
# exceptions get processed properly in secondary hostthreads:
q = make_mailqueue (get_current_microthread()): Mailqueue(Int);
cpu::do {.
foo = 12 / *zero # *zero just to guard against compiler optimizers.
except
DIVIDE_BY_ZERO = 13;
mps::do {.
put_in_mailqueue (q, foo);
};
};
result = take_from_mailqueue q;
assert (result == 13);
};
fun verify_int_overflow_in_cpu_bound_hostthread ()
=
{
##############################################################
# First, check that it works locally:
#
foo = *k64 * *k64 # The '*k64' bit is just to guard against compiler optimizers.
except
OVERFLOW = 23;
assert( foo == 23 );
##############################################################
# Now do the same thing in a CPU server to verify that
# exceptions get processed properly in secondary hostthreads:
q = make_mailqueue (get_current_microthread()): Mailqueue(Int);
cpu::do {.
foo = *k64 * *k64 # *k64 just to guard against compiler optimizers.
except
OVERFLOW = 23;
mps::do {.
put_in_mailqueue (q, foo);
};
};
result = take_from_mailqueue q;
assert (result == 23);
};
fun verify_bounds_check_in_cpu_bound_hostthread ()
=
{
# Currently, at least, bounds-checking doesn't involve any
# signals sorts of stuff, so this one isn't much of a test
# of hostthread signals support. But it doesn't hurt to have
# have it around... -- CrT 2012-10-09
##############################################################
# First, check that it works locally:
#
foo = vector::from_list [ 0, 1, 2 ];
bar = vector::get (foo, 3) except INDEX_OUT_OF_BOUNDS = 29;
assert( bar == 29 );
##############################################################
# Now do the same thing in a CPU server to verify that
# exceptions get processed properly in secondary hostthreads:
q = make_mailqueue (get_current_microthread()): Mailqueue(Int);
cpu::do {.
bar = vector::get (foo, 3)
except
INDEX_OUT_OF_BOUNDS = 29;
mps::do {.
put_in_mailqueue (q, bar);
};
};
result = take_from_mailqueue q;
assert (result == 29);
};
fun run ()
=
{ printf "\nDoing %s:\n" name;
#
verify_basic__echo__operation ();
verify_basic__do__operation ();
verify_do_to_maildrop ();
verify_do_to_mailqueue ();
verify_do_via_cpu_bound_hostthread ();
verify_do_via_io_bound_hostthread ();
verify_divide_by_zero_in_cpu_bound_hostthread ();
verify_int_overflow_in_cpu_bound_hostthread ();
verify_bounds_check_in_cpu_bound_hostthread ();
#
summarize_unit_tests name;
};
};
end;