From 88d041fbbf8007f9705a4a853725a727ab6979ec Mon Sep 17 00:00:00 2001 From: "Fred T. Hamster" Date: Wed, 18 Feb 2026 14:27:17 -0500 Subject: [PATCH] added tests for processes and one for timely time_stamp tester is kind of silly, but it's in there again. it needs to do some more verification. the safe_callback test is also totally minimal, and wouldn't catch many bugs. it needs to be threaded and much more active. state machine test is also in and compiling, but totally doesn't work. pared a file down to a list of *.h and *.cpp files, and every line is rejected for some reason. need to investigate, because if it's telling the truth, then state_machine got broken at some point. --- nucleus/library/makefile | 1 + .../input_data_state_machine.txt | 21 ++ nucleus/library/tests_processes/makefile | 15 ++ .../tests_processes/test_safe_callback.cpp | 80 +++++++ .../tests_processes/test_state_machine.cpp | 195 ++++++++++++++++++ nucleus/library/tests_timely/makefile | 2 +- .../library/tests_timely/test_time_stamp.cpp | 93 +++++++++ .../buildor/upgrade_hoople_to_feistymeow.sh | 1 + 8 files changed, 407 insertions(+), 1 deletion(-) create mode 100644 nucleus/library/tests_processes/input_data_state_machine.txt create mode 100644 nucleus/library/tests_processes/makefile create mode 100644 nucleus/library/tests_processes/test_safe_callback.cpp create mode 100644 nucleus/library/tests_processes/test_state_machine.cpp create mode 100644 nucleus/library/tests_timely/test_time_stamp.cpp diff --git a/nucleus/library/makefile b/nucleus/library/makefile index 5aa38477..6b6045fb 100644 --- a/nucleus/library/makefile +++ b/nucleus/library/makefile @@ -19,6 +19,7 @@ BUILD_BEFORE = algorithms \ tests_structures \ tests_filesystem \ tests_mathematics \ + tests_processes \ tests_nodes \ tests_textual \ tests_timely \ diff --git a/nucleus/library/tests_processes/input_data_state_machine.txt b/nucleus/library/tests_processes/input_data_state_machine.txt new file mode 100644 index 00000000..08608c5e --- /dev/null +++ b/nucleus/library/tests_processes/input_data_state_machine.txt @@ -0,0 +1,21 @@ +array.h +astring.cpp +astring.h +base_string.h +byte_array.h +common_outcomes.cpp +common_outcomes.h +contracts.h +definitions.h +enhance_cpp.h +environment.cpp +environment.h +functions.h +guards.cpp +guards.h +makefile +mutex.cpp +mutex.h +outcome.h +utf_conversion.cpp +utf_conversion.h diff --git a/nucleus/library/tests_processes/makefile b/nucleus/library/tests_processes/makefile new file mode 100644 index 00000000..f872ba24 --- /dev/null +++ b/nucleus/library/tests_processes/makefile @@ -0,0 +1,15 @@ +CONSOLE_MODE = t + +include cpp/variables.def + +PROJECT = test_processes +TYPE = test +SOURCE = +TARGETS = test_safe_callback.exe test_state_machine.exe +LOCAL_LIBS_USED = unit_test application configuration filesystem loggers \ + nodes processes structures textual timely structures basis +#filesystem mathematics +RUN_TARGETS = $(ACTUAL_TARGETS) + +include cpp/rules.def + diff --git a/nucleus/library/tests_processes/test_safe_callback.cpp b/nucleus/library/tests_processes/test_safe_callback.cpp new file mode 100644 index 00000000..5b8232ff --- /dev/null +++ b/nucleus/library/tests_processes/test_safe_callback.cpp @@ -0,0 +1,80 @@ +/*****************************************************************************\ +* * +* Name : test_safe_callback * +* Author : Chris Koeritz * +* * +* Purpose: * +* * +* Tests the safe callback object slightly. Mainly this is to ensure that * +* no memory leaks are being caused by the object and that minimal support is * +* provided by the object. * +* * +******************************************************************************* +* 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 * +\*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include + +using namespace application; +using namespace basis; +using namespace configuration; +//using namespace mathematics; +//using namespace filesystem; +using namespace loggers; +using namespace processes; +//using namespace structures; +//using namespace textual; +using namespace timely; +using namespace unit_test; + +#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), astring(s)) + +////////////// + +const astring LOGFILE_NAME = application_configuration::make_logfile_name + ("t_safe_callback.log"); + // where our debugging output goes by default. + +///#define LOG(to_print) log.log(timestamp(true) + astring(to_print)) + // our macro for logging with a timestamp. + +//hmmm: this tester doesn't really do very much at all. +// how about a more aggressive test, which has a bunch of threads using +// safe callback? + +class cb_tester : public safe_callback +{ +public: + cb_tester() : safe_callback() {} + ~cb_tester() { end_availability(); } + + virtual void real_callback(callback_data_block &) + { /* do nothing. */ } +}; + +//hmmm: move this to using a class based approach, based on unit_test and application_shell. + +int main(int formal(argc), char *formal(argv)[]) +{ +/// file_logger log(LOGFILE_NAME); + + cb_tester testing; + + critical_events::alert_message("safe_callback:: works for all functions tested."); + return 0; +} + diff --git a/nucleus/library/tests_processes/test_state_machine.cpp b/nucleus/library/tests_processes/test_state_machine.cpp new file mode 100644 index 00000000..27a60edb --- /dev/null +++ b/nucleus/library/tests_processes/test_state_machine.cpp @@ -0,0 +1,195 @@ +/*****************************************************************************\ +* * +* Name : test_state_machine * +* Author : Chris Koeritz * +* * +* Purpose: * +* * +* Sets up a simple state machine for a pattern matcher. * +* * +******************************************************************************* +* 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 * +\*****************************************************************************/ + +// This simple state machine recognizes all strings that are of the form +// *.[cho], which means any string with either .o, .c, or .h on the end. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace application; +using namespace basis; +using namespace configuration; +//using namespace mathematics; +using namespace filesystem; +using namespace loggers; +using namespace processes; +//using namespace structures; +//using namespace textual; +using namespace timely; +using namespace unit_test; + +#undef LOG +#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), astring(s)) + +////////////// + +enum recognizer_states { GET_ANY = 1, GOT_DOT, GOT_CHO, RECOGNIZED, REJECTED }; + +//#undef LOG +//#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s) + +class test_state_machine : public application_shell +{ +public: + test_state_machine(); + DEFINE_CLASS_NAME("test_state_machine"); + int execute(); + void setup_state_machine(transition_map &recog); + void print_instructions(); +}; + +astring state_text(recognizer_states to_show) +{ + switch (to_show) { + case GET_ANY: return "get_any"; + case GOT_DOT: return "got_dot"; + case GOT_CHO: return "got_cho"; + case RECOGNIZED: return "recognized"; + case REJECTED: return "rejected"; + default: return "unknown!"; + } +} + +#define TEST(action) \ + if (!action) \ + deadly_error(class_name(), "setup", a_sprintf("failed on %s", #action)) + +void test_state_machine::setup_state_machine(transition_map &recog) +{ + TEST(recog.add_state(GET_ANY)); + TEST(recog.add_state(GOT_DOT)); + TEST(recog.add_state(GOT_CHO)); + TEST(recog.add_state(RECOGNIZED)); + TEST(recog.add_state(REJECTED)); + + TEST(recog.set_start(GET_ANY)); + +// bogus for test! +//TEST(recog.add_range_transition(GET_ANY, 29378, 0, 0)); + + TEST(recog.add_range_transition(GET_ANY, REJECTED, 0, 0)); + TEST(recog.add_range_transition(GET_ANY, GET_ANY, 1, '.'-1)); + TEST(recog.add_range_transition(GET_ANY, GOT_DOT, '.', '.')); + TEST(recog.add_range_transition(GET_ANY, GET_ANY, '.'+1, 255)); + + // we wouldn't need so many cases if the update function made the + // jump out of GOT_DOT when an unsatisfactory pulse is seen? + TEST(recog.add_range_transition(GOT_DOT, REJECTED, '\0', '\0')); + TEST(recog.add_range_transition(GOT_DOT, GET_ANY, 1, '.'-1)); + TEST(recog.add_range_transition(GOT_DOT, GOT_DOT, '.', '.')); + TEST(recog.add_range_transition(GOT_DOT, GET_ANY, '.'+1, 'c'-1)); + TEST(recog.add_range_transition(GOT_DOT, GOT_CHO, 'c', 'c')); + TEST(recog.add_range_transition(GOT_DOT, GET_ANY, 'c'+1, 'h'-1)); + TEST(recog.add_range_transition(GOT_DOT, GOT_CHO, 'h', 'h')); + TEST(recog.add_range_transition(GOT_DOT, GET_ANY, 'h'+1, 'o'-1)); + TEST(recog.add_range_transition(GOT_DOT, GOT_CHO, 'o', 'o')); + TEST(recog.add_range_transition(GOT_DOT, GET_ANY, 'o'+1, 255)); +/// if update was doing it; TEST(recog.add_simple_transition(GOT_DOT, GET_ANY)); + + TEST(recog.add_range_transition(GOT_CHO, RECOGNIZED, '\0', '\0')); + TEST(recog.add_range_transition(GOT_CHO, GET_ANY, 1, '.'-1)); + TEST(recog.add_range_transition(GOT_CHO, GOT_DOT, '.', '.')); + TEST(recog.add_range_transition(GOT_CHO, GET_ANY, '.'+1, 255)); + + int hosed; + if (recog.validate(hosed) != transition_map::OKAY) + deadly_error(class_name(), "check_machine", + astring(astring::SPRINTF, "invalid state_machine due to state %d", hosed).s()); +} + +test_state_machine::test_state_machine() +: application_shell() +{} + +void test_state_machine::print_instructions() +{ + critical_events::alert_message("\ +This program demonstrates the state machine class by constructing a machine\n\ +that recognizes the regular expression *.[cho], which is all strings ending\n\ +in a period followed by c, h, or o. The first parameter is the name of a\n\ +file to load strings from.\n"); +} + +int test_state_machine::execute() +{ + FUNCDEF("execute"); + transition_map recog; + setup_state_machine(recog); + + if (application::_global_argc < 2) { + print_instructions(); + return 1; + } + astring filename = astring(application::_global_argv[1]); +/// int indy = filename.find(' '); + if (!filename) { + print_instructions(); + return 1; + } + ///filename.zap(indy, filename.end()); + + byte_filer fil(filename.s(), "r"); + +//LOG(astring("filename is ") + filename.raw()); + + while (!fil.eof()) { + state_machine m; + recog.reset(m); + + byte_array typed_string(901); +//need a getline function for byte filer... + fil.getline(typed_string, 900); + + int len = int(strlen((char *)typed_string.access())); + if (!len) continue; // skip blank lines... + + int position = 0; + while ( (m.current() != RECOGNIZED) && (m.current() != REJECTED) ) { + recog.pulse(m, typed_string[position++]); + } + + if (m.current() == RECOGNIZED) { + LOG((char *)typed_string.access()); + } else if (m.current() == REJECTED) { + LOG("rejected..."); + } else { + LOG("unknown final state!"); + } + } + return 0; +} + +////////////// + +HOOPLE_MAIN(test_state_machine, ) + diff --git a/nucleus/library/tests_timely/makefile b/nucleus/library/tests_timely/makefile index db6d5f65..178ac2b1 100644 --- a/nucleus/library/tests_timely/makefile +++ b/nucleus/library/tests_timely/makefile @@ -2,7 +2,7 @@ include cpp/variables.def PROJECT = tests_timely TYPE = test -TARGETS = test_earth_time.exe test_stopwatch.exe test_timer_driver.exe +TARGETS = test_earth_time.exe test_stopwatch.exe test_timer_driver.exe test_time_stamp.exe DEFINITIONS += USE_FEISTY_MEOW_DLLS LOCAL_LIBS_USED = unit_test application processes loggers configuration mathematics nodes \ structures textual timely filesystem structures basis diff --git a/nucleus/library/tests_timely/test_time_stamp.cpp b/nucleus/library/tests_timely/test_time_stamp.cpp new file mode 100644 index 00000000..66efe027 --- /dev/null +++ b/nucleus/library/tests_timely/test_time_stamp.cpp @@ -0,0 +1,93 @@ +/*****************************************************************************\ +* * +* Name : test_time_stamp * +* 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 * +\*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace application; +using namespace basis; +using namespace loggers; +using namespace structures; +using namespace textual; +using namespace timely; +using namespace unit_test; + +#undef LOG +#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s) + +////////////// + +//#define DEBUG_TIME_STAMP + +//const int RUN_DURATION = 5 * MINUTE_ms; +const int RUN_DURATION = 3 * SECOND_ms; + // how long the test will run. + +const int SLEEP_DURATION = 42; + // the period of sleep between checks on the time stamp. + +const int REPORT_INTERVAL = 500; // every half second. + // how often we show the current time stamp. + +////////////// + +class time_stamp_tester : virtual public unit_base, virtual public application_shell +{ +public: + time_stamp_tester() : application_shell() {} + + DEFINE_CLASS_NAME("time_stamp_tester"); + + int execute() { + time_stamp start; + log(a_sprintf("initial time stamp: %0.0f", start.value())); + + time_stamp curr; + time_stamp get_out(RUN_DURATION); + time_stamp report_time(REPORT_INTERVAL); + int iterations = RUN_DURATION / SLEEP_DURATION; + while (iterations-- > 0) { + if (time_stamp() < curr) + deadly_error(class_name(), "compare test", "failure; now is less " + "than earlier!"); + +//hmmm: how about some more verifications, like the sleep time we asked for is reflected (or nearly) in the time stamp difference? + + time_control::sleep_ms(SLEEP_DURATION); + curr = time_stamp(); + if (time_stamp() >= report_time) { + log(a_sprintf("current time stamp: %0.0f", time_stamp().value())); + report_time.reset(REPORT_INTERVAL); + } + } + + time_stamp end; + log(a_sprintf(" ending time stamp: %0.0f", end.value())); + + critical_events::alert_message("time_stamp:: works for those functions tested."); + return 0; + } +}; + +////////////// + +HOOPLE_MAIN(time_stamp_tester, ) + diff --git a/scripts/buildor/upgrade_hoople_to_feistymeow.sh b/scripts/buildor/upgrade_hoople_to_feistymeow.sh index 0ed1692a..12d31222 100644 --- a/scripts/buildor/upgrade_hoople_to_feistymeow.sh +++ b/scripts/buildor/upgrade_hoople_to_feistymeow.sh @@ -163,6 +163,7 @@ standards and usages." | sed -e 's/^#include *$/#include /g' \ | sed -e 's/^#include *$/#include /g' \ | sed -e 's/\([^A-Za-z0-9_]\)NIL\([^A-Za-z0-9_]\)/\1NULL_POINTER\2/g' \ + | sed -e 's/^#include *$/#include /g' \ | sed -e 's/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/[\/]*/\/\/\/\/\/\/\/\/\/\/\/\/\/\//g' \ >"$tempfile" -- 2.43.0