bringing back in some tests
authorFred Hamster <fred@gruntose.com>
Thu, 5 Feb 2026 02:43:53 +0000 (21:43 -0500)
committerFred Hamster <fred@gruntose.com>
Thu, 5 Feb 2026 02:43:53 +0000 (21:43 -0500)
these have been pending for a while.  not at all ready yet though.

nucleus/library/tests_application/aa-readme.txt [new file with mode: 0644]
nucleus/library/tests_application/makefile [new file with mode: 0644]
nucleus/library/tests_application/test_break_signal.cpp [new file with mode: 0644]
nucleus/library/tests_application/test_command_line.cpp [new file with mode: 0644]
nucleus/library/tests_application/test_dirtree_fcopy.cpp [new file with mode: 0644]
nucleus/library/tests_application/test_ini_configurator.cpp [new file with mode: 0644]
nucleus/library/tests_application/test_ini_parser.cpp [new file with mode: 0644]
nucleus/library/tests_application/test_path_configuration.cpp [new file with mode: 0644]
nucleus/library/tests_application/test_registry_configurator.cpp [new file with mode: 0644]
nucleus/library/tests_application/test_system_values.cpp [new file with mode: 0644]
nucleus/library/tests_application/test_timer_driver.cpp [new file with mode: 0644]

diff --git a/nucleus/library/tests_application/aa-readme.txt b/nucleus/library/tests_application/aa-readme.txt
new file mode 100644 (file)
index 0000000..1f44dd9
--- /dev/null
@@ -0,0 +1,4 @@
+
+this is in transit, being brought back from cold storage.
+
+
diff --git a/nucleus/library/tests_application/makefile b/nucleus/library/tests_application/makefile
new file mode 100644 (file)
index 0000000..f899f5d
--- /dev/null
@@ -0,0 +1,37 @@
+CONSOLE_MODE = t
+
+include cpp/variables.def
+
+PROJECT = tests_application
+TYPE = test
+TARGETS =    test_command_line.exe \
+#test_break_signal.exe test_byte_filer.exe 
+#  test_directory.exe test_directory_tree.exe test_dirtree_fcopy.exe test_filename.exe \
+#  test_huge_file.exe test_ini_configurator.exe test_ini_parser.exe test_logger.exe \
+#  test_path_configuration.exe test_registry_configurator.exe test_redirection.exe \
+#  test_rendezvous.exe test_system_values.exe test_timer_driver.exe
+#ifeq "$(findstring EMBEDDED_BUILD, $(DEFINITIONS))" ""
+#  TARGETS += test_shared_memory.exe 
+#endif
+##LOCAL_LIBS_USED = basis i_library 
+DEFINITIONS += USE_FEISTY_MEOW_DLLS
+LOCAL_LIBS_USED = unit_test application 
+#configuration filesystem loggers \
+#  mathematics nodes processes structures textual timely structures basis  \
+#loggers 
+
+#VCPP_USE_GUI=t
+#USE_HOOPLE_DLLS=t
+
+#RUN_TARGETS = $(ACTUAL_TARGETS)
+# run every test except test_rendezvous, which waits for a key.
+RUN_TARGETS =    test_command_line.exe \
+
+#test_break_signal.exe test_byte_filer.exe 
+#  test_directory.exe test_directory_tree.exe test_filename.exe \
+#  test_huge_file.exe test_ini_configurator.exe test_ini_parser.exe test_logger.exe \
+#  test_path_configuration.exe test_registry_configurator.exe \
+#  test_system_values.exe test_timer_driver.exe
+
+include cpp/rules.def
+
diff --git a/nucleus/library/tests_application/test_break_signal.cpp b/nucleus/library/tests_application/test_break_signal.cpp
new file mode 100644 (file)
index 0000000..e835b3c
--- /dev/null
@@ -0,0 +1,69 @@
+/*****************************************************************************\
+*                                                                             *
+*  Name   : test_break_signal                                                 *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 2004-$now By Author.  This program 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 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+#include <basis/function.h>
+#include <basis/guards.h>
+#include <basis/istring.h>
+#include <mechanisms/time_stamp.h>
+#include <opsystem/application_shell.h>
+#include <loggers/console_logger.h>
+#include <opsystem/filename.h>
+#include <data_struct/static_memory_gremlin.h>
+
+#include <signal.h>
+#include <stdio.h>
+
+#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
+
+static bool _leave_now = false;
+
+class test_break_signal : public application_shell
+{
+public:
+  test_break_signal() : application_shell(class_name()) {}
+  IMPLEMENT_CLASS_NAME("test_break_signal");
+  virtual int execute();
+};
+
+void handle_break(int formal(signal))
+{
+  #undef static_class_name
+  #define static_class_name() "test_break_signal"
+  FUNCDEF("handle_break");
+  LOG("we have hit the signal handler for break!");
+  _leave_now = true;
+  #undef static_class_name
+}
+
+int test_break_signal::execute()
+{
+  FUNCDEF("execute");
+  signal(SIGINT, handle_break);
+  LOG("starting loop--hit ctrl-C to exit or wait for timeout.");
+  time_stamp leave_time(20 * SECOND_ms);
+  while (!_leave_now && (time_stamp() < leave_time) ) {
+    portable::sleep_ms(20);
+  }
+
+  // we jump to here when catching the signal.
+  istring to_print("break_signal:: works for those functions tested.");
+  guards::alert_message(to_print.s());
+  fflush(NIL);
+  return 0;
+}
+
+HOOPLE_MAIN(test_break_signal, )
+
+#undef static_class_name
+
diff --git a/nucleus/library/tests_application/test_command_line.cpp b/nucleus/library/tests_application/test_command_line.cpp
new file mode 100644 (file)
index 0000000..42f2b1f
--- /dev/null
@@ -0,0 +1,125 @@
+/*****************************************************************************\
+*                                                                             *
+*  Name   : test_command_line                                                 *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*  Purpose:                                                                   *
+*                                                                             *
+*    Tests the command_line class by showing our parameters.                  *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 1992-$now By Author.  This program 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 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+#include <basis/function.h>
+#include <basis/guards.h>
+#include <basis/istring.h>
+#include <basis/portable.h>
+#include <basis/string_array.h>
+#include <opsystem/application_shell.h>
+#include <opsystem/command_line.h>
+#include <loggers/console_logger.h>
+#include <opsystem/filename.h>
+#include <data_struct/static_memory_gremlin.h>
+
+class test_command_line : public application_shell
+{
+public:
+  test_command_line() : application_shell(class_name()) {}
+  IMPLEMENT_CLASS_NAME("test_command_line");
+  int execute();
+};
+
+int test_command_line::execute()
+{
+  program_wide_logger().log("these are the commands we got passed...");
+  string_array cmds = command_line::get_command_line();
+  for (int i = 0; i < cmds.length(); i++) {
+    program_wide_logger().log(isprintf("%02d: cmd=%s", i, cmds[i].s()));
+  }
+
+  // test 1 is a simple probe on the actual arguments to this program.
+  {
+    command_line cl1(__argc, __argv);
+    filename prog(cl1.program_name());
+    log(istring("got a program name of: [") + prog.dirname() + istring("] ")
+        + prog.basename());
+    log("got parms of:");
+    for (int i = 0; i < cl1.entries(); i++) {
+      command_parameter got = cl1.get(i);
+      log(istring(istring::SPRINTF, "%d: type=%s text=%s", i,
+          (got.type()==command_parameter::VALUE)? "VALUE"
+              : (got.type()==command_parameter::CHAR_FLAG)? "CHAR_FLAG"
+              : (got.type()==command_parameter::STRING_FLAG)? "STRING_FLAG"
+              : "UNKNOWN",
+          got.text().s()));
+    }
+  }
+
+  // test 2 ensures that our new special flag ending support (standard unix
+  // flag of --) is performing.
+  {
+    istring cmd_line = "tossedout spumeco -g -q --fleem -r -- spugnats.txt crumbole.h";
+    command_line cl2(cmd_line);
+
+    command_parameter spumeco = cl2.get(0);
+//log(isprintf("parm 0: type=%d text=%s", spumeco.type(), spumeco.text().s()));
+    if (spumeco.type() != command_parameter::VALUE)
+      deadly_error(class_name(), "test 2", "spumeco is wrong type");
+    if (spumeco.text() != "spumeco")
+      deadly_error(class_name(), "test 2", "spumeco is erroneous");
+
+    command_parameter gflag = cl2.get(1);
+    if (gflag.type() != command_parameter::CHAR_FLAG)
+      deadly_error(class_name(), "test 2", "G flag had wrong type");
+    if (gflag.text() != "g")
+      deadly_error(class_name(), "test 2", "G flag had wrong value");
+
+    command_parameter qflag = cl2.get(2);
+    if (qflag.type() != command_parameter::CHAR_FLAG)
+      deadly_error(class_name(), "test 2", "Q flag had wrong type");
+    if (qflag.text() != "q")
+      deadly_error(class_name(), "test 2", "Q flag had wrong value");
+
+    command_parameter fleemflag = cl2.get(3);
+    if (fleemflag.type() != command_parameter::STRING_FLAG)
+      deadly_error(class_name(), "test 2", "fleem flag had wrong type");
+    if (fleemflag.text() != "fleem")
+      deadly_error(class_name(), "test 2", "fleem flag had wrong value");
+
+    command_parameter rflag = cl2.get(4);
+    if (rflag.type() != command_parameter::CHAR_FLAG)
+      deadly_error(class_name(), "test 2", "R flag had wrong type");
+    if (rflag.text() != "r")
+      deadly_error(class_name(), "test 2", "R flag had wrong value");
+
+    command_parameter spugval = cl2.get(5);
+    if (spugval.type() != command_parameter::VALUE)
+      deadly_error(class_name(), "test 2", "spugval had wrong type");
+    if (spugval.text() != "spugnats.txt")
+      deadly_error(class_name(), "test 2", "spugval had wrong value");
+
+    command_parameter crumval = cl2.get(6);
+    if (crumval.type() != command_parameter::VALUE)
+      deadly_error(class_name(), "test 2", "crumval had wrong type");
+    if (crumval.text() != "crumbole.h")
+      deadly_error(class_name(), "test 2", "crumval had wrong value");
+
+    command_parameter bogus = cl2.get(7);
+    if (bogus.type() != command_parameter::BOGUS_ITEM)
+      deadly_error(class_name(), "test 2", "bogus parameter had wrong type");
+  }
+
+//more tests!
+
+  guards::alert_message("command_line:: works for those functions tested.");
+  return 0;
+}
+
+HOOPLE_MAIN(test_command_line, )
+
diff --git a/nucleus/library/tests_application/test_dirtree_fcopy.cpp b/nucleus/library/tests_application/test_dirtree_fcopy.cpp
new file mode 100644 (file)
index 0000000..4e5e40a
--- /dev/null
@@ -0,0 +1,147 @@
+/*****************************************************************************\
+*                                                                             *
+*  Name   : test_fcopy_file_transfer                                          *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*  Purpose:                                                                   *
+*                                                                             *
+*    Tests the directory_tree object as a file copy prompter.                 *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 2005-$now By Author.  This program 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 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+#include <basis/function.h>
+#include <basis/guards.h>
+#include <opsystem/application_shell.h>
+#include <loggers/console_logger.h>
+#include <opsystem/directory.h>
+#include <opsystem/directory_tree.h>
+#include <opsystem/filename.h>
+#include <opsystem/filename_list.h>
+#include <opsystem/heavy_file_ops.h>
+#include <data_struct/static_memory_gremlin.h>
+#include <textual/string_manipulation.h>
+
+#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
+
+class test_fcopy : public application_shell
+{
+public:
+  test_fcopy() : application_shell(static_class_name()) {}
+  IMPLEMENT_CLASS_NAME("test_dirtree_fcopy");
+  int execute();
+};
+
+int test_fcopy::execute()
+{
+  FUNCDEF("execute");
+
+  if (__argc < 3)
+    non_continuable_error(class_name(), "command line", "this program needs two "
+          "parameters:\na directory for the source and one for the target.");
+
+  istring source_dir = __argv[1];
+  istring target_dir = __argv[2];
+
+  // read the source location.
+  log(istring("Scanning source tree at \"") + source_dir + "\"");
+  directory_tree source(source_dir, "*");
+  if (!source.good())
+    non_continuable_error(class_name(), "directory_tree construction",
+          "the source directory could not be read");
+
+  // read the stuff that exists at the target.
+  log(istring("Scanning target tree at \"") + target_dir + "\"");
+  directory_tree target(target_dir, "*");
+  if (!target.good())
+    non_continuable_error(class_name(), "directory_tree construction",
+        "the target directory could not be read");
+
+  LOG("calculating checksums for source.");
+  if (!source.calculate())
+    non_continuable_error(class_name(), "directory_tree calculation",
+        "the source tree could not be calculated");
+
+  LOG("calculating checksums for target.");
+  if (!target.calculate())
+    non_continuable_error(class_name(), "directory_tree calculation",
+        "the target tree could not be calculated");
+
+  istring source_start;
+  istring target_start;
+  if (__argc > 3)
+    source_start = __argv[3];
+  if (__argc > 4)
+    target_start = __argv[4];
+
+  LOG("comparing the two trees.");
+  filename_list diffs;
+  directory_tree::compare_trees(source, source_start, target, target_start,
+      diffs);
+//LOG("missing files:");
+//LOG(diffs.text_form());
+
+  byte_array packed_form;
+  diffs.pack(packed_form);
+  filename_list regen;
+  if (!regen.unpack(packed_form))
+    non_continuable_error(class_name(), "filename_list packing",
+        "could not unpack the list of differences");
+
+//LOG("after packing and restoring:");
+//LOG(regen.text_form());
+
+  if (regen.elements() != diffs.elements())
+    non_continuable_error(class_name(), "filename_list packing",
+        "there were a different number of elements in unpacked form");
+  for (int i = 0; i < diffs.elements(); i++) {
+    if (!regen.member(*diffs[i])) {
+      istring name = diffs[i]->raw();
+      non_continuable_error(class_name(), "filename_list packing",
+          istring("name from original set was missing in regenerated: ")
+              + name);
+    }
+  }
+
+  for (int i = 0; i < diffs.elements(); i++) {
+    file_info *curr = diffs[i];
+    filename source_file = source.path() + filename::default_separator()
+        + curr->raw();
+    filename target_file = target.path() + filename::default_separator()
+        + curr->secondary();
+//LOG(istring("cp source: ") + source_file.raw());
+//LOG(istring("-> target: ") + target_file.raw());
+    filename targ_dir = target_file.dirname();
+    if (!targ_dir.is_directory()) {
+      bool worked = directory::recursive_create(targ_dir);
+      if (!worked)
+        non_continuable_error(class_name(), "recursive mkdir",
+            istring("failed to create the target directory ") + targ_dir);
+    }
+
+    outcome ret = heavy_file_operations::copy_file(source_file, target_file);
+    if (ret != heavy_file_operations::OKAY)
+      non_continuable_error(class_name(), "copying file", istring("there was an error ")
+          + heavy_file_operations::outcome_name(ret)
+          + " when copying the file.");
+  }
+
+//do the copy by going across the entire set of files and making sure
+//they get copied to target.
+//
+//reread the target location.
+//
+//compare with source tree read before.
+
+  guards::alert_message("directory_tree file transfer:: works for those functions tested.");
+  return 0;
+}
+
+HOOPLE_MAIN(test_fcopy, )
+
diff --git a/nucleus/library/tests_application/test_ini_configurator.cpp b/nucleus/library/tests_application/test_ini_configurator.cpp
new file mode 100644 (file)
index 0000000..477fe91
--- /dev/null
@@ -0,0 +1,178 @@
+/*****************************************************************************\
+*                                                                             *
+*  Name   : test_ini_configurator                                             *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 1998-$now By Author.  This program 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 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+const int test_iterations = 10;
+
+//#define DEBUG_INI_CONFIGURATOR_TEST
+  // uncomment for debugging version.
+
+#include <basis/function.h>
+#include <basis/guards.h>
+#include <basis/istring.h>
+#include <geometric/rectangle.h>
+#include <geometric/screen_rectangle.h>
+#include <mathematics/float_plus.h>
+#include <loggers/console_logger.h>
+#include <opsystem/ini_config.h>
+#include <opsystem/path_configuration.h>
+#include <data_struct/static_memory_gremlin.h>
+#include <textual/byte_format.h>
+
+#ifdef DEBUG_INI_CONFIGURATOR_TEST
+  #include <stdio.h>
+#endif
+
+HOOPLE_STARTUP_CODE;
+
+using namespace geometric;
+
+typedef float_plus<double> frunkle;
+
+#define WHERE __WHERE__.s()
+
+const char *INI_SECTION = "t_ini_configurator";
+
+int main(int formal(argc), char *formal(argv)[])
+{
+  ini_configurator ini("t_ini_configurator.ini", ini_configurator::AUTO_STORE);
+
+console_logger out;
+out.log(istring("ini file resides in: ") + ini.name());
+
+out.log(istring("exe directory is currently: ") + path_configuration::application_directory());
+
+  for (int i = 0; i < test_iterations; i++) {  // outer loop bracket.
+    // beginning of test sets.
+    {
+      // first test set.
+      const char *TEST_NAME = "first test: rectangle";
+      // this tests whether rectangle storage works.
+      screen_rectangle default_rectangle(10, 289, 388, 191);
+      ini.delete_entry(INI_SECTION, "window_size");
+      screen_rectangle win_size;
+      istring tmp = ini.load(INI_SECTION, "window_size",
+          default_rectangle.text_form());
+      win_size.from_text(tmp);
+      if (win_size != default_rectangle)
+        deadly_error(INI_SECTION, TEST_NAME,
+              "rectangle not equal to default");
+      screen_rectangle new_size(23, 49, 129, 93);
+      ini.store(INI_SECTION, "window_size", new_size.text_form());
+      screen_rectangle current_size;
+      tmp = ini.load(INI_SECTION, "window_size",
+          default_rectangle.text_form());
+      current_size.from_text(tmp);
+      if (current_size != new_size)
+        deadly_error(INI_SECTION, TEST_NAME,
+              "rectangle not equal to second size stored");
+    }
+    {
+      // second test set.
+      const char *TEST_NAME = "second test: string";
+      istring junk("this is a junky string to be stored as bytes....");
+      byte_array to_store(junk.length() + 1, (byte *)junk.observe());
+      istring as_bytes;
+      byte_format::bytes_to_string(to_store, as_bytes);
+      ini.store("test_of_byte_store", "test1", as_bytes);
+      istring blort = "blort_fest!";
+      istring rettle = ini.load("test_of_byte_store", "test1", blort);
+      byte_array found_byte;
+      byte_format::string_to_bytes(rettle, found_byte);
+      istring found_junk((const char *)found_byte.observe());
+      if (rettle == blort)
+        deadly_error(INI_SECTION, TEST_NAME,
+           "ini_configurator load failed: default was used");
+      else if (found_junk != junk)
+        deadly_error(INI_SECTION, TEST_NAME,
+           "ini_configurator load failed: result differed from original");
+    }
+    {
+      // third test set.
+      const char *TEST_NAME = "third test: frunkle";
+      frunkle def_frunkle(3.14159265358);
+      istring def_text(istring::SPRINTF, "%f", def_frunkle.value());
+      ini.store(INI_SECTION, TEST_NAME, def_text);
+      istring found_string = ini.load(INI_SECTION, TEST_NAME, "9949494.3");
+      frunkle found_frunkle = found_string.convert(0.0);
+      if (found_frunkle == frunkle(9949494.3))
+        deadly_error(INI_SECTION, TEST_NAME, 
+           "ini_configurator load failed: default was used");
+      if (found_frunkle != def_frunkle)
+        deadly_error(INI_SECTION, TEST_NAME, 
+           "ini_configurator load failed: saved value differed");
+    }
+    {
+      // fourth test set.
+      const char *TEST_NAME = "fourth test: frunkle";
+      frunkle def_frunkle(1487335673.1415926535834985987);
+      istring def_text(istring::SPRINTF, "%f", def_frunkle.value());
+      ini.store("test", "frunkle_test", def_text);
+      istring found_string = ini.load("test", "frunkle_test", "9949494.3");
+      frunkle found_frunkle = found_string.convert(0.0);
+      if (found_frunkle == frunkle(9949494.3))
+        deadly_error(INI_SECTION, TEST_NAME,
+           "ini_configurator load failed: wrong default was used");
+      if (found_frunkle != def_frunkle)
+        deadly_error(INI_SECTION, TEST_NAME, 
+           "ini_configurator load failed: saved value differed");
+    }
+    {
+      // fifth test set.
+      const char *TEST_NAME = "fifth test: bytes";
+      istring urp("urp");
+      istring junk("this is a junky string to be stored as bytes....");
+      byte_array default_bytes(urp.length() + 1, (byte *)urp.observe());
+      istring defbytes_string;
+      byte_format::bytes_to_string(default_bytes, defbytes_string);
+      byte_array found;
+      istring tmp = ini.load("test_of_byte_store", "test1", defbytes_string);
+      byte_format::string_to_bytes(tmp, found);
+      istring string_found = (char *)found.observe();
+      if (string_found == urp)
+        deadly_error(INI_SECTION, TEST_NAME,
+            "ini_configurator load_bytes failed: default was used");
+      if (string_found.length() != junk.length())
+        deadly_error(INI_SECTION, TEST_NAME,
+            "ini_configurator load_bytes failed: array lengths differ");
+      if (string_found != junk)
+        deadly_error(INI_SECTION, TEST_NAME,
+            "ini_configurator load_bytes failed: arrays differ");
+    }
+    {
+      // sixth test set.
+      const char *TEST_NAME = "sixth test: blank string";
+      ini.delete_entry("test_of_blank_string", "test1");
+      istring blank("");
+      istring fund = ini.load("test_of_blank_string", "test1", blank);
+      if (fund != blank)
+        deadly_error(INI_SECTION, TEST_NAME, "ini_configurator load string "
+               "with blank default failed: didn't return blank");
+      ini.delete_entry("test_of_blank_string", "test1");
+      istring non_blank("blinkblankblunk");
+      fund = ini.load("test_of_blank_string", "test1", non_blank);
+      if (fund != non_blank)
+        deadly_error(INI_SECTION, TEST_NAME, "ini_configurator load string "
+               "with non-blank default failed: didn't return default");
+      fund = ini.load("test_of_blank_string", "test1", blank);
+      if (fund != non_blank)
+        deadly_error(INI_SECTION, TEST_NAME, "ini_configurator load string "
+               "with blank default failed: returned wrong string");
+    }
+  }
+
+  istring to_print("ini_configurator:: works for those functions tested.");
+  guards::alert_message(to_print.s());
+  return 0;
+}
+
diff --git a/nucleus/library/tests_application/test_ini_parser.cpp b/nucleus/library/tests_application/test_ini_parser.cpp
new file mode 100644 (file)
index 0000000..1caa22c
--- /dev/null
@@ -0,0 +1,112 @@
+/*****************************************************************************\
+*                                                                             *
+*  Name   : test_ini_parser                                                   *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 1991-$now By Author.  This program 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 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+#include <basis/function.h>
+#include <basis/guards.h>
+#include <basis/istring.h>
+#include <data_struct/string_table.h>
+#include <opsystem/application_shell.h>
+#include <opsystem/byte_filer.h>
+#include <loggers/console_logger.h>
+#include <opsystem/ini_parser.h>
+#include <data_struct/static_memory_gremlin.h>
+
+const istring INI_FILE_1 = "\
+[bork]\n\
+norple=1\n\
+train=12.5\n\
+singhy=9   \r\n\
+\n\
+[twerf]\r\n\
+noodles=fungus\n\
+dora=34\n\
+";
+
+//#define READ_FILE_TEST
+  // uncomment to read in a file and parse it.
+
+class test_ini_parser : public application_shell
+{
+public:
+  test_ini_parser() : application_shell(class_name()) {}
+  IMPLEMENT_CLASS_NAME("test_ini_parser");
+  virtual int execute();
+};
+
+int test_ini_parser::execute()
+{
+  program_wide_logger().eol(log_base::NO_ENDING);
+
+  ini_parser par(INI_FILE_1);
+
+//istring dump;
+//par.restate(dump);
+//log(istring("table has:\n") + dump);
+
+  string_table twerf;
+  if (!par.get_section("twerf", twerf))
+    deadly_error(class_name(), "get_section 1", "twerf section was not found");
+//log(istring("twerf section is: ") + twerf.text_form());
+  if (!twerf.find("noodles"))
+    deadly_error(class_name(), "get_section 1", "item #1 was not found");
+  if (*twerf.find("noodles") != "fungus")
+    deadly_error(class_name(), "get_section 1", "item #1 found is incorrect");
+  if (!twerf.find("dora"))
+    deadly_error(class_name(), "get_section 1", "item #2 was not found");
+  if (*twerf.find("dora") != "34")
+    deadly_error(class_name(), "get_section 1", "item #2 found is incorrect");
+
+  string_table bork;
+  if (!par.get_section("bork", bork))
+    deadly_error(class_name(), "get_section 2", "bork section was not found");
+  if (!bork.find("norple"))
+    deadly_error(class_name(), "get_section 2", "item #1 was not found");
+  if (*bork.find("norple") != "1")
+    deadly_error(class_name(), "get_section 2", "item #1 found is incorrect");
+  if (!bork.find("train"))
+    deadly_error(class_name(), "get_section 2", "item #2 was not found");
+  if (*bork.find("train") != "12.5")
+    deadly_error(class_name(), "get_section 2", "item #2 found is incorrect");
+  if (!bork.find("singhy"))
+    deadly_error(class_name(), "get_section 2", "item #3 was not found");
+  if (*bork.find("singhy") != "9")
+    deadly_error(class_name(), "get_section 2", "item #3 found is incorrect");
+
+  istring new_ini;
+  par.restate(new_ini);
+
+  program_wide_logger().eol(log_base::CRLF_AT_END);
+  log("");
+
+#ifdef READ_FILE_TEST
+  byte_filer input("c:/home/fungal.lld", "rb");
+  int len = input.length();
+  log(isprintf("fungal len is %d", len));
+  istring jojo;
+  input.read(jojo, len);
+  //log("whole file is:");
+  //log(jojo);
+
+  ini_parser klug(jojo);
+  istring dump2;
+  klug.restate(dump2);
+  log(dump2);
+#endif
+
+  guards::alert_message("ini_parser:: works for those functions tested.\n");
+  return 0;
+}
+
+HOOPLE_MAIN(test_ini_parser, )
+
diff --git a/nucleus/library/tests_application/test_path_configuration.cpp b/nucleus/library/tests_application/test_path_configuration.cpp
new file mode 100644 (file)
index 0000000..1382c05
--- /dev/null
@@ -0,0 +1,38 @@
+/*****************************************************************************\
+*                                                                             *
+*  Name   : test_path_configuration                                           *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 2002-$now By Author.  This program 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 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+#include <basis/guards.h>
+#include <basis/istring.h>
+#include <loggers/console_logger.h>
+#include <opsystem/path_configuration.h>
+#include <data_struct/static_memory_gremlin.h>
+
+HOOPLE_STARTUP_CODE;
+
+int main(int argc, char *argv[])
+{
+  console_logger out;
+
+  istring jammed;
+  for (int i = 0; i < argc; i++)
+    jammed += istring(argv[i]) + " ";
+  out.log(istring("command line=") + jammed);
+
+  istring app_dir = path_configuration::application_directory();
+  out.log(istring("app dir is: ") + app_dir);
+
+  guards::alert_message("path_configuration:: works for those functions tested.");
+  return 0;
+}
+
diff --git a/nucleus/library/tests_application/test_registry_configurator.cpp b/nucleus/library/tests_application/test_registry_configurator.cpp
new file mode 100644 (file)
index 0000000..45f2989
--- /dev/null
@@ -0,0 +1,233 @@
+/*****************************************************************************\
+*                                                                             *
+*  Name   : test_registry_configurator                                        *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 1998-$now By Author.  This program 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 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+const int test_iterations = 10;
+
+//#define DEBUG_REGISTRY_CONFIGURATOR_TEST
+  // uncomment for debugging version.
+
+#include <basis/function.h>
+#include <basis/guards.h>
+#include <basis/istring.h>
+#include <data_struct/string_table.h>
+#include <data_struct/static_memory_gremlin.h>
+#include <geometric/rectangle.h>
+#include <geometric/screen_rectangle.h>
+#include <loggers/console_logger.h>
+#include <mathematics/float_plus.h>
+#include <opsystem/path_configuration.h>
+#include <opsystem/registry_config.h>
+#include <textual/byte_format.h>
+
+#include <stdio.h>
+
+HOOPLE_STARTUP_CODE;
+
+using namespace geometric;
+
+typedef float_plus<double> frunkle;
+
+#define WHERE __WHERE__.s()
+
+const registry_configurator::registry_hives THE_HIVE
+    = registry_configurator::hkey_current_user;
+
+const istring REGISTRY_SECTION = "boobo/tahini/nunkshus";
+
+#define LOG(s) program_wide_logger().log(s)
+
+int main(int formal(argc), char *formal(argv)[])
+{
+#ifdef __WIN32__
+  // this test is only needed for win32 OSes.
+  registry_configurator ini(THE_HIVE, registry_configurator::AUTO_STORE);
+
+console_logger out;
+
+  for (int i = 0; i < test_iterations; i++) {  // outer loop bracket.
+    // beginning of test sets.
+
+    {
+      const char *TEST_NAME = "zeroth test: cleaning section";
+      ini.delete_section(REGISTRY_SECTION);
+      if (ini.section_exists(REGISTRY_SECTION))
+        deadly_error(REGISTRY_SECTION, TEST_NAME,
+            "section still exists after deleting!");
+    }
+
+    {
+      // first test set.
+      const char *TEST_NAME = "first test: rectangle";
+      // this tests whether rectangle storage works.
+      screen_rectangle default_rectangle(10, 289, 388, 191);
+      ini.delete_entry(REGISTRY_SECTION, "window_size");
+      screen_rectangle win_size;
+      istring tmp = ini.load(REGISTRY_SECTION, "window_size",
+          default_rectangle.text_form());
+      win_size.from_text(tmp);
+      if (win_size != default_rectangle)
+        deadly_error(REGISTRY_SECTION, TEST_NAME,
+            "rectangle not equal to default");
+      screen_rectangle new_size(23, 49, 129, 93);
+      ini.store(REGISTRY_SECTION, "window_size", new_size.text_form());
+      screen_rectangle current_size;
+      tmp = ini.load(REGISTRY_SECTION, "window_size",
+          default_rectangle.text_form());
+      current_size.from_text(tmp);
+      if (current_size != new_size)
+        deadly_error(REGISTRY_SECTION, TEST_NAME,
+              "rectangle not equal to second size stored");
+    }
+    {
+      // second test set.
+      const char *TEST_NAME = "second test: string";
+      istring junk("this is a junky string to be stored as bytes....");
+      byte_array to_store(junk.length() + 1, (byte *)junk.observe());
+      istring as_bytes;
+      byte_format::bytes_to_string(to_store, as_bytes);
+      ini.store(REGISTRY_SECTION + "/test_of_byte_store", "test1", as_bytes);
+      istring blort = "blort_fest!";
+      istring rettle = ini.load(REGISTRY_SECTION + "/test_of_byte_store",
+          "test1", blort);
+      byte_array found_byte;
+      byte_format::string_to_bytes(rettle, found_byte);
+      istring found_junk((const char *)found_byte.observe());
+      if (rettle == blort)
+        deadly_error(REGISTRY_SECTION, TEST_NAME,
+           "registry_configurator load failed: default was used");
+      else if (found_junk != junk)
+        deadly_error(REGISTRY_SECTION, TEST_NAME,
+           "registry_configurator load failed: result differed from original");
+    }
+    {
+      // third test set.
+      const char *TEST_NAME = "third test: frunkle";
+      frunkle def_frunkle(3.14159265358);
+      istring def_text(istring::SPRINTF, "%f", def_frunkle.value());
+      ini.store(REGISTRY_SECTION, TEST_NAME, def_text);
+      istring found_string = ini.load(REGISTRY_SECTION, TEST_NAME, "9949494.3");
+      frunkle found_frunkle = found_string.convert(0.0);
+      if (found_frunkle == frunkle(9949494.3))
+        deadly_error(REGISTRY_SECTION, TEST_NAME, 
+           "registry_configurator load failed: default was used");
+      if (found_frunkle != def_frunkle)
+        deadly_error(REGISTRY_SECTION, TEST_NAME, 
+           "registry_configurator load failed: saved value differed");
+    }
+    {
+      // fourth test set.
+      const char *TEST_NAME = "fourth test: frunkle";
+      frunkle def_frunkle(1487335673.1415926535834985987);
+      istring def_text(istring::SPRINTF, "%f", def_frunkle.value());
+      ini.store(REGISTRY_SECTION + "/test", "frunkle_test", def_text);
+      istring found_string = ini.load(REGISTRY_SECTION + "/test",
+          "frunkle_test", "9949494.3");
+      frunkle found_frunkle = found_string.convert(0.0);
+      if (found_frunkle == frunkle(9949494.3))
+        deadly_error(REGISTRY_SECTION, TEST_NAME,
+           "registry_configurator load failed: wrong default was used");
+      if (found_frunkle != def_frunkle)
+        deadly_error(REGISTRY_SECTION, TEST_NAME, 
+           "registry_configurator load failed: saved value differed");
+    }
+    {
+      // fifth test set.
+      const char *TEST_NAME = "fifth test: bytes";
+      istring urp("urp");
+      istring junk("this is a junky string to be stored as bytes....");
+      byte_array default_bytes(urp.length() + 1, (byte *)urp.observe());
+      istring defbytes_string;
+      byte_format::bytes_to_string(default_bytes, defbytes_string);
+      byte_array found;
+      istring tmp = ini.load(REGISTRY_SECTION + "/test_of_byte_store", "test1", defbytes_string);
+      byte_format::string_to_bytes(tmp, found);
+      istring string_found = (char *)found.observe();
+      if (string_found == urp)
+        deadly_error(REGISTRY_SECTION, TEST_NAME,
+            "registry_configurator load_bytes failed: default was used");
+      if (string_found.length() != junk.length())
+        deadly_error(REGISTRY_SECTION, TEST_NAME,
+            "registry_configurator load_bytes failed: array lengths differ");
+      if (string_found != junk)
+        deadly_error(REGISTRY_SECTION, TEST_NAME,
+            "registry_configurator load_bytes failed: arrays differ");
+    }
+    {
+      // sixth test set.
+      const char *TEST_NAME = "sixth test: blank string";
+      ini.delete_entry(REGISTRY_SECTION + "/test_of_blank_string", "test1");
+      istring blank("");
+      istring fund = ini.load(REGISTRY_SECTION + "/test_of_blank_string", "test1", blank);
+      if (fund != blank)
+        deadly_error(REGISTRY_SECTION, TEST_NAME, "registry_configurator load string "
+               "with blank default failed: didn't return blank");
+      ini.delete_entry(REGISTRY_SECTION + "/test_of_blank_string", "test1");
+      istring non_blank("blinkblankblunk");
+      fund = ini.load(REGISTRY_SECTION + "/test_of_blank_string", "test1", non_blank);
+      if (fund != non_blank)
+        deadly_error(REGISTRY_SECTION, TEST_NAME, "registry_configurator load string "
+               "with non-blank default failed: didn't return default");
+      fund = ini.load(REGISTRY_SECTION + "/test_of_blank_string", "test1", blank);
+      if (fund != non_blank)
+        deadly_error(REGISTRY_SECTION, TEST_NAME, "registry_configurator load string "
+               "with blank default failed: returned wrong string");
+    }
+    {
+      // 7th set, test get_section.
+      registry_configurator ini(registry_configurator::HKCU,
+          registry_configurator::AUTO_STORE);
+      const char *TEST_NAME = "seventh test: get_section";
+      string_table sect;
+      bool worked = ini.get_section("Environment", sect);
+      if (!worked)
+        deadly_error(REGISTRY_SECTION, TEST_NAME, "failed to get sample section (environment)");
+//to see if it worked...
+//      LOG(istring("got section:\n") + sect.text_form());
+    }
+    {
+      // 8th set, test put_section.
+      const char *TEST_NAME = "eighth test: put_section";
+      string_table sect;
+      sect.add("dooby", "mastiff");
+      sect.add("flammix", "pontiff");
+      sect.add("gruntlix", "sagawilla");
+      sect.add("toast", "megaspoony");
+      bool worked = ini.put_section(REGISTRY_SECTION + "\\turnips", sect);
+      if (!worked)
+        deadly_error(REGISTRY_SECTION, TEST_NAME, "failed to put sample section");
+      string_table sect8;
+      worked = ini.get_section(REGISTRY_SECTION + "\\turnips", sect8);
+      // since it should read in the order written, these should come back
+      // directly comparable.
+      if (sect != sect8)
+        deadly_error(REGISTRY_SECTION, TEST_NAME, "registry contents didn't compare as expected");
+      worked = ini.delete_section(REGISTRY_SECTION + "\\turnips");
+      if (!worked)
+        deadly_error(REGISTRY_SECTION, TEST_NAME, "failed to delete new section");
+      worked = ini.get_section(REGISTRY_SECTION + "\\turnips", sect8);
+      if (worked)
+        deadly_error(REGISTRY_SECTION, TEST_NAME, "new section could be read still!");
+    }
+  }
+
+  // clean up after the test.
+  ini.delete_section(REGISTRY_SECTION);
+
+#endif // win32.
+
+  istring to_print("registry_configurator:: works for those functions tested.");
+  guards::alert_message(to_print.s());
+  return 0;
+}
+
diff --git a/nucleus/library/tests_application/test_system_values.cpp b/nucleus/library/tests_application/test_system_values.cpp
new file mode 100644 (file)
index 0000000..3afd8ab
--- /dev/null
@@ -0,0 +1,65 @@
+/*****************************************************************************\
+*                                                                             *
+*  Name   : test_system_values                                                *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 2005-$now By Author.  This program 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 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+#include <basis/function.h>
+#include <basis/guards.h>
+#include <basis/istring.h>
+#include <basis/portable.h>
+#include <opsystem/application_shell.h>
+#include <loggers/console_logger.h>
+#include <data_struct/static_memory_gremlin.h>
+#include <opsystem/system_values.h>
+
+#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
+
+class test_system_values : public application_shell
+{
+public:
+  test_system_values()
+      : application_shell(class_name()),
+        events(system_values::EVENT_VALUES()),
+        filters(system_values::FILTER_VALUES()),
+        outcomes(system_values::OUTCOME_VALUES())
+  {}
+
+  IMPLEMENT_CLASS_NAME("test_system_values");
+  virtual int execute();
+
+private:
+  system_values events;
+  system_values filters;
+  system_values outcomes;
+};
+
+int test_system_values::execute()
+{
+  FUNCDEF("execute");
+
+  log("Outcome Values");
+  log("==============");
+  log(outcomes.text_form());
+
+  log("Filter Values");
+  log("=============");
+  log(filters.text_form());
+
+  log("Event Values");
+  log("============");
+  log(events.text_form());
+
+  return 0;
+}
+
+HOOPLE_MAIN(test_system_values, )
+
diff --git a/nucleus/library/tests_application/test_timer_driver.cpp b/nucleus/library/tests_application/test_timer_driver.cpp
new file mode 100644 (file)
index 0000000..ba7fff1
--- /dev/null
@@ -0,0 +1,189 @@
+/*****************************************************************************\
+*                                                                             *
+*  Name   : t_timer_driver                                                    *
+*  Author : Chris Koeritz                                                     *
+*                                                                             *
+*  Purpose:                                                                   *
+*                                                                             *
+*    Tests the timer driver class from the operating system library.          *
+*                                                                             *
+*******************************************************************************
+* Copyright (c) 2005-$now By Author.  This program 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 of   *
+* the License or (at your option) any later version.  This is online at:      *
+*     http://www.fsf.org/copyleft/gpl.html                                    *
+* Please send any updates to: fred@gruntose.com                               *
+\*****************************************************************************/
+
+#include <basis/chaos.h>
+#include <basis/function.h>
+#include <basis/guards.h>
+#include <basis/istring.h>
+#include <basis/log_base.h>
+#include <basis/set.h>
+#include <data_struct/unique_id.h>
+#include <mechanisms/ithread.h>
+#include <mechanisms/thread_cabinet.h>
+#include <mechanisms/time_stamp.h>
+#include <opsystem/application_shell.h>
+#include <opsystem/event_extensions.h>
+#include <loggers/file_logger.h>
+#include <data_struct/static_memory_gremlin.h>
+#include <opsystem/timer_driver.h>
+
+#define LOG(s) STAMPED_EMERGENCY_LOG(program_wide_logger(), s)
+
+const int TEST_DURATION = 3 * MINUTE_ms;
+
+const int MAX_THREADS = 120;
+
+////////////////////////////////////////////////////////////////////////////
+
+class timer_driver_tester : public application_shell
+{
+public:
+  timer_driver_tester()
+      : application_shell(static_class_name()), _in_progress(false) {}
+  IMPLEMENT_CLASS_NAME("timer_driver_tester");
+  virtual ~timer_driver_tester() {}
+
+  int execute();
+
+  thread_cabinet &threads() { return _threads; }
+
+  bool in_progress() const { return _in_progress; }
+    // returns true if activity is currently occurring on the main thread.
+    // we don't expect this activity to be interrupted by timer events.
+
+private:
+  bool _in_progress;
+    // simple flag to check when a timer hits.  if this is true, then a timer
+    // hit while we were doing actual functional operations, rather than
+    // just waiting in a sleep.
+  thread_cabinet _threads;  // storage for our time_stamp testing threads.
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+class timer_test_thread : public ithread
+{
+public:
+  timer_test_thread(application_shell &parent)
+      : ithread(parent.randomizer().inclusive(20, 480)), _parent(parent)
+  { start(NIL); }
+
+  IMPLEMENT_CLASS_NAME("timer_test_thread");
+  void perform_activity(void *) {
+    FUNCDEF("perform_activity");
+    if (time_stamp() < _started)
+      deadly_error(class_name(), func, "start time is before current time.");
+    if (time_stamp() < _last) 
+      deadly_error(class_name(), func, "last check is before current time.");
+    _last.reset();  // set the last time to right now.
+    time_stamp ted;
+    time_stamp jed;
+    if (ted > jed)
+      deadly_error(class_name(), func, "jed is less than test.");
+  }
+
+private:
+  application_shell &_parent;
+  time_stamp _started;
+  time_stamp _last;
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+class my_timer_handler : public timed_object
+{
+public:
+  my_timer_handler(timer_driver_tester &parent, int id) : _id(id), _parent(parent) {}
+  virtual ~my_timer_handler() {}
+  IMPLEMENT_CLASS_NAME("my_timer_handler");
+
+  virtual void handle_timer_callback() {
+    FUNCDEF("handle_timer_callback");
+    if (_parent.in_progress())
+      LOG("saw in progress flag set to true!  we interrupted real "
+          "ops, not just sleep!");
+    LOG(isprintf("timer%d hit.", _id));
+    timer_test_thread *new_thread = new timer_test_thread(_parent);
+    unique_int id = _parent.threads().add_thread(new_thread, false, NIL);
+      // the test thread auto-starts, so we don't let the cabinet start it.
+    if (!id)
+      deadly_error(class_name(), func, "failed to start a new thread.");
+
+    if (_parent.threads().threads() > MAX_THREADS) {
+      int gone_index = _parent.randomizer().inclusive(0, _parent.threads().threads() - 1);
+      unique_int gone_thread = _parent.threads().thread_ids()[gone_index];
+      _parent.threads().cancel_thread(gone_thread);
+      portable::sleep_ms(100);  // allow thread to start up.
+    }
+    _parent.threads().clean_debris();  // toss any dead threads.
+
+    LOG(isprintf("%d threads checking time_stamp.", _parent.threads().threads()));
+  }
+
+private:
+  int _id;
+  timer_driver_tester &_parent;
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+#define CREATE_TIMER(name, id, dur) \
+  my_timer_handler name(*this, id); \
+  program_wide_timer().set_timer(dur, &name); \
+  LOG(istring("timer ") + #name + " hitting every " \
+      + #dur + " ms")
+
+#define ZAP_TIMER(name) \
+  program_wide_timer().zap_timer(&name)
+
+int timer_driver_tester::execute()
+{
+  SET_DEFAULT_COMBO_LOGGER;
+
+  CREATE_TIMER(timer1, 1, 500);
+//  CREATE_TIMER(timer1, 1, 10);
+  CREATE_TIMER(timer2, 2, SECOND_ms);
+  CREATE_TIMER(timer3, 3, 3 * SECOND_ms);
+  CREATE_TIMER(timer4, 4, 8 * SECOND_ms);
+  CREATE_TIMER(timer5, 5, 12 * SECOND_ms);
+
+  LOG("pausing for a while...");
+  time_stamp when_done(TEST_DURATION);
+  while (time_stamp() < when_done) {
+    _in_progress = true;
+    // do some various calculations in here and see if we're interrupted
+    // during them.  it's one thing to be interrupted in the middle of a
+    // sleep, but it's much different to be interrupted in mid operation.
+    int scrob = 1;
+    for (int i = 1; i < 50; i++) {
+      scrob *= i;
+    }
+    _in_progress = false;    
+#ifdef __UNIX__
+    portable::sleep_ms(100);
+#else
+    bool okay = event_extensions::poll();
+    if (!okay) break;
+#endif
+  }
+
+  guards::alert_message("timer_driver:: works for all functions tested (if messages seem appropriate).");
+
+  ZAP_TIMER(timer1);
+  ZAP_TIMER(timer2);
+  ZAP_TIMER(timer3);
+  ZAP_TIMER(timer4);
+  ZAP_TIMER(timer5);
+
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+HOOPLE_MAIN(timer_driver_tester, )
+