small fixes for stack tracker
authorFred T. Hamster <fred@feistymeow.org>
Tue, 10 Feb 2026 15:19:44 +0000 (10:19 -0500)
committerFred T. Hamster <fred@feistymeow.org>
Tue, 10 Feb 2026 15:19:44 +0000 (10:19 -0500)
things seem really good; everything builds with this enabled now, and the test app for the tracker makes sense.
need to add a recursive test to the tracker tester, and also implement a multi-threaded test of it.
OR...  i could just add callstack tracking output in one of our current multi-threaded tests.  oooh, i like it!
re-use the macro for getting the trace, testing its validity, and printing it.

nucleus/library/application/callstack_tracker.h
nucleus/library/tests_application/test_callstack_tracker.cpp

index e6392e3f0decb3bbbffbf2d8a4ddbd8ccd32078a..19fb94cd1652e9916c9a59f31a2710b7b5b06569 100644 (file)
@@ -76,7 +76,7 @@ public:
     /*!< the user *must* free() the string returned. */
 
   int full_trace_size() const;
-    //!< this returns the number of bytes needed for the above full_trace().
+    //!< this returns an estimated number of bytes needed for the full_trace().
 
   int depth() const { return _depth; }
     //!< the current number of frames we know of.
index 9199e8318e89a5dc1293e08be5a0da1b5f92ce2a..ba725e288d8ba5189eb4325e2890cdb322f21135 100644 (file)
@@ -31,6 +31,8 @@
 #include <structures/string_array.h>
 #include <unit_test/unit_base.h>
 
+//#include <string.h>
+
 using namespace application;
 using namespace basis;
 using namespace filesystem;
@@ -40,6 +42,36 @@ using namespace unit_test;
 
 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
 
+//////////////
+
+/*
+  super helpful macro that shows the current stack trace and checks it for validity.
+  this shouldn't impact the trace, since it's all embedded inline from the macro.
+*/
+#define SHOW_TRACE_AND_CHECK_IT(message) { \
+  int trace_size = program_wide_stack_trace().full_trace_size(); \
+  char *stack_trace = program_wide_stack_trace().full_trace(); \
+  ASSERT_TRUE(trace_size >= strlen(stack_trace) + 1, "insufficient estimated stack trace size"); \
+  if (trace_size < strlen(stack_trace) + 1) { \
+    /* error condition here; we are supposed to get the actual size we would need to allocate! */ \
+    LOG(a_sprintf("failure in stack trace return: estimated size (%d) was less than actual (%d)", \
+        trace_size, strlen(stack_trace))); \
+    /* mandatory free step for newly allocated string. */ \
+    free(stack_trace); \
+    return 1; \
+  } \
+  ASSERT_TRUE(strlen(stack_trace) > 1, "empty stack trace"); \
+  if (strlen(stack_trace) < 2) { \
+    LOG("failure in stack trace return: the trace output string was empty!"); \
+    return 1; \
+  } \
+  LOG(astring("\n\n################\n\n") + message + "\n" + stack_trace); \
+  /* mandatory free step for newly allocated string. */ \
+  free(stack_trace); \
+}
+
+//////////////
+
 class test_callstack_tracker : virtual public unit_base, virtual public application_shell
 {
 public:
@@ -50,28 +82,66 @@ public:
   int run_filestack_middling();
   int run_filestack_complex();
   int execute();
+
+private:
+  int sub_call_1();
+  int sub_call_2();
+  int sub_call_3();
+  int sub_call_4();
 };
 
 int test_callstack_tracker::run_filestack_simple()
 {
+  FUNCDEF("run_filestack_simple")
   #ifdef ENABLE_CALLSTACK_TRACKING
-//just show this stack.
-//return an error if any problem.
+    // just shows this method's own stack.
+    SHOW_TRACE_AND_CHECK_IT("trace of simple stack:");
   #endif
   return 0;
 }
 
-int test_callstack_tracker::run_filestack_middling()
+int test_callstack_tracker::sub_call_1()
+{
+  FUNCDEF("sub_call_1")
+  return sub_call_2();
+}
+
+int test_callstack_tracker::sub_call_2()
+{
+  FUNCDEF("sub_call_2");
+  return sub_call_3();
+}
+
+int test_callstack_tracker::sub_call_3()
+{
+  FUNCDEF("sub_call_3")
+  return sub_call_4();
+}
+
+int test_callstack_tracker::sub_call_4()
 {
+  FUNCDEF("sub_call_4");
   #ifdef ENABLE_CALLSTACK_TRACKING
-//show a couple calls in.
-//return an error if any problem.
+    // just shows this method's own stack.
+    SHOW_TRACE_AND_CHECK_IT("trace of middling stack:");
   #endif
   return 0;
 }
 
+int test_callstack_tracker::run_filestack_middling()
+{
+  FUNCDEF("run_filestack_middling");
+  int retval = 0;
+  #ifdef ENABLE_CALLSTACK_TRACKING
+    // show a couple calls in using our sub_calls.
+    retval = sub_call_1();
+  #endif
+  return retval;
+}
+
 int test_callstack_tracker::run_filestack_complex()
 {
+  FUNCDEF("run_filestack_complex")
   #ifdef ENABLE_CALLSTACK_TRACKING
 //do something recursive and show an elaborate stack
 //return an error if any problem.
@@ -83,6 +153,7 @@ int test_callstack_tracker::execute()
 {
   FUNCDEF("execute");
 
+//hmmm: do we really want the test to fail out for any subtest failure?  maybe so?
   int ret = run_filestack_simple();
   if (ret) return ret;
   ret = run_filestack_middling();