]> git.mdlowis.com Git - projs/libcds.git/commitdiff
Implemented heap-based exceptions and added tests to increase coverage
authorMichael D. Lowis <mike@mdlowis.com>
Wed, 3 Sep 2014 02:43:33 +0000 (22:43 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Wed, 3 Sep 2014 02:43:33 +0000 (22:43 -0400)
Rakefile
source/exn/exn.c
source/exn/exn.h
source/mem/mem.c
source/rbt/rbt.c
tests/main.c
tests/test_buf.c
tests/test_exn.c
tests/test_mem.c [new file with mode: 0644]

index 5c88c39d7a1d1000abc4c5aeda49d462d4df8141..8f1cd2d3ddc1f615a62e71b7246c24689593a651 100644 (file)
--- a/Rakefile
+++ b/Rakefile
@@ -69,3 +69,6 @@ end
 desc "Clean all generated files and directories"
 task(:clean) { Rscons.clean }
 
+desc "Clobber all generated files and directories"
+task(:clobber) { FileUtils.rm_rf('build') }
+
index 95113dbcc707eb73af8c18d780402f6d6a99fbed..6507d0a89a59907ebe5be5761571f8ac206ed8ae 100755 (executable)
@@ -7,10 +7,20 @@
 #include "exn.h"
 #include <stdio.h>
 
-#ifndef EXN_MAX_NUM_HANDLERS
-#define EXN_MAX_NUM_HANDLERS (8)
+#ifdef TESTING
+extern void test_exit(int);
+#define exit(status) test_exit(status)
 #endif
 
+//#ifndef EXN_MAX_NUM_HANDLERS
+//#define EXN_MAX_NUM_HANDLERS (8)
+//#endif
+
+typedef struct exn_stack_t {
+    struct exn_stack_t* p_next;
+    exn_handler_t handler;
+} exn_stack_t;
+
 DEFINE_EXCEPTION(RuntimeException,            NULL);
 DEFINE_EXCEPTION(NullPointerException,        &RuntimeException);
 DEFINE_EXCEPTION(AssertionException,          &RuntimeException);
@@ -21,8 +31,7 @@ DEFINE_EXCEPTION(SegmentationException,       &RuntimeException);
 
 static bool Exn_Handled = true;
 static const exn_t* Exn_Current = NULL;
-static int Exn_Num_Handlers = 0;
-static exn_handler_t Exn_Handlers[EXN_MAX_NUM_HANDLERS];
+static exn_stack_t* Exn_Handlers = NULL;
 
 static void exn_uncaught(const exn_t* p_exn) {
     (void)p_exn;
@@ -30,11 +39,17 @@ static void exn_uncaught(const exn_t* p_exn) {
     exit(1);
 }
 
+static void exn_pop(void) {
+    exn_stack_t* p_prev = Exn_Handlers;
+    Exn_Handlers = p_prev->p_next;
+    free(p_prev);
+}
+
 void exn_prep(void) {
-    if((Exn_Num_Handlers+1) > EXN_MAX_NUM_HANDLERS)
-        exn_throw(&RuntimeException);
-    Exn_Handlers[Exn_Num_Handlers].state  = EXN_BEGIN;
-    Exn_Num_Handlers++;
+    exn_stack_t* p_prev = Exn_Handlers;
+    Exn_Handlers = (exn_stack_t*)malloc(sizeof(exn_stack_t));
+    Exn_Handlers->p_next = p_prev;
+    Exn_Handlers->handler.state = EXN_BEGIN;
     Exn_Handled = true;
 }
 
@@ -61,7 +76,7 @@ bool exn_process(void) {
             break;
 
         case EXN_DONE:
-            Exn_Num_Handlers--;
+            exn_pop();
             ret = false;
             break;
 
@@ -74,7 +89,7 @@ bool exn_process(void) {
 }
 
 void exn_throw(const exn_t* p_type) {
-    if (Exn_Num_Handlers == 0) {
+    if (Exn_Handlers == NULL) {
         exn_uncaught(Exn_Current);
     } else {
         Exn_Current = p_type;
@@ -84,7 +99,9 @@ void exn_throw(const exn_t* p_type) {
 }
 
 void exn_rethrow(void) {
-    Exn_Num_Handlers--;
+    printf("rethrowing 1 %p\n", Exn_Handlers);
+    exn_pop();
+    printf("rethrowing 2 %p\n", Exn_Handlers);
     exn_throw(Exn_Current);
 }
 
@@ -106,7 +123,7 @@ const exn_t* exn_current(void) {
 }
 
 exn_handler_t* exn_handler(void) {
-    return &(Exn_Handlers[Exn_Num_Handlers-1]);
+    return (NULL != Exn_Handlers) ? &(Exn_Handlers->handler) : NULL;
 }
 
 void exn_assert(bool expr) {
index 3c7febbc891c2e7aa3e5c5ba58dcea5f42028ca8..0ae6a19394ca64e3a1f0258e80e29b8e520050f8 100755 (executable)
@@ -31,6 +31,8 @@ typedef struct {
     exn_state_t state;
 } exn_handler_t;
 
+//typedef void (*)(const exn_t* p_exn);
+
 #define DECLARE_EXCEPTION(exname) \
     extern const exn_t exname
 
index f95dfa39c1b07d1595ea7c19c81a37cd6b48e25b..a0d8731bb0b38c332f562cdf297891bf4f38c4ae 100644 (file)
@@ -36,7 +36,10 @@ block_t* Live_Blocks = NULL;
 size_t Num_Allocations = 0;
 #endif
 
-static void summarize_leaks(void) {
+#ifndef TESTING
+static
+#endif
+void summarize_leaks(void) {
     #if (LEAK_DETECT_LEVEL == 2)
     bool leak_detected = false;
     block_t* p_curr = Live_Blocks;
index b17f3ac59ab6150aecf544a5b77c4c74b4c75ca5..1cc3dbd0ec32895584418cc4e6ae6822d56b81df 100644 (file)
@@ -69,9 +69,9 @@ static rbt_node_t* rbt_lookup_node(rbt_t* tree, rbt_node_t* node, void* value){
     rbt_node_t* ret = NULL;
     if(node){
         int c = tree->comp(value, node->contents);
-        if(c == 0) ret = node;
+        if (c < 0) ret = rbt_lookup_node(tree, node->left, value);
         else if(c > 0) ret = rbt_lookup_node(tree, node->right, value);
-        else if(c < 0) ret = rbt_lookup_node(tree, node->left, value);
+        else ret = node;
     }
     return ret;
 }
index cac9be5956e11a2e55ef027b5eea577b16ce23c2..50ed8ae003bef1ef935f206aa1c5e977c64c3d53 100644 (file)
@@ -10,5 +10,6 @@ int main(int argc, char** argv)
     RUN_TEST_SUITE(String);
     RUN_TEST_SUITE(RBT);
     RUN_TEST_SUITE(Exn);
+    RUN_TEST_SUITE(Mem);
     return PRINT_TEST_RESULTS();
 }
index 0dab2716c8d42a7a1edd44927ad1121cbe9170eb..9bf736a3a3d4f8f2d28a01c4476f166921991367 100644 (file)
@@ -83,7 +83,7 @@ TEST_SUITE(Buffer) {
     {
         buf_t* buf = buf_new(3);
         buf_write( buf, mem_box(0x1234) );
-        buf_write( buf, mem_box(0x1235) );
+        buf_write( buf, NULL );
         buf_write( buf, mem_box(0x1236) );
         buf_clear( buf );
         CHECK( buf->reads == 0 );
index fba5d48e7b745d9a70689e67cdc6d77c298b52b3..ea3304bba4b68a80a0fc2134427257fd602d1064 100644 (file)
@@ -5,7 +5,16 @@
 // File To Test
 #include "exn.h"
 
-static void test_setup(void) { }
+static int Exit_Status = 0;
+void test_exit(int status) {
+    Exit_Status = status;
+    if (NULL != exn_handler())
+        exn_handler()->state = EXN_DONE;
+}
+
+static void test_setup(void) {
+    Exit_Status = 0;
+}
 
 //-----------------------------------------------------------------------------
 // Begin Unit Tests
@@ -114,4 +123,22 @@ TEST_SUITE(Exn) {
         catch(AssertionException) { counter--; }
         CHECK(counter == -1);
     }
+
+    //-------------------------------------------------------------------------
+    // Test extraordinary conditions
+    //-------------------------------------------------------------------------
+    TEST(Verify_an_uncaught_exception_terminates_the_program)
+    {
+        throw(AssertionException);
+        CHECK( Exit_Status == 1 );
+    }
+
+    TEST(Verify_an_invalid_exception_state_terminates_the_program)
+    {
+        try {
+            exn_handler()->state = EXN_DONE+1;
+            exn_process();
+        }
+        CHECK( Exit_Status == 1 );
+    }
 }
diff --git a/tests/test_mem.c b/tests/test_mem.c
new file mode 100644 (file)
index 0000000..9bc92e6
--- /dev/null
@@ -0,0 +1,20 @@
+// Unit Test Framework Includes
+#include "test.h"
+
+// File To Test
+#include "mem.h"
+
+static void test_setup(void) { }
+
+//-----------------------------------------------------------------------------
+// Begin Unit Tests
+//-----------------------------------------------------------------------------
+TEST_SUITE(Mem) {
+    TEST(Verify_mem_can_summarize_leaks)
+    {
+        void* p_obj = mem_allocate(sizeof(4),NULL);
+        extern void summarize_leaks(void);
+        summarize_leaks();
+        mem_release( p_obj );
+    }
+}