PreviousUpNext

15.4.1097  src/lib/std/src/hostthread/thread-scheduler-inter-hostthreads-unit-test.pkg

## 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;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext