From 7d6b42c51111d450097af396af16a052e52a4442 Mon Sep 17 00:00:00 2001
From: Jan Breuer <jan.breuer@jaybee.cz>
Date: 周日, 24 4月 2016 21:15:39 +0800
Subject: [PATCH] Fix order of deallocations, add heap unit test

---
 libscpi/test/test_scpi_utils.c |   58 +++++++++++++++++++++++++++++
 libscpi/src/error.c            |   20 ++-------
 2 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/libscpi/src/error.c b/libscpi/src/error.c
index e07ced3..0caa917 100644
--- a/libscpi/src/error.c
+++ b/libscpi/src/error.c
@@ -127,12 +127,13 @@
     return result;
 }
 
-static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err, char * info) {
+static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err, char * info, size_t info_len) {
     scpi_error_t error_value;
-    SCPI_ERROR_SETVAL(&error_value, err, info);
+    SCPI_ERROR_SETVAL(&error_value, err, SCPIDEFINE_strndup(&context->error_info_heap, info, info_len));
     if (!fifo_add(&context->error_queue, &error_value)) {
+        SCPIDEFINE_free(&context->error_info_heap, error_value.device_dependent_info, true);
         fifo_remove_last(&context->error_queue, &error_value);
-        SCPIDEFINE_free(&context->error_info_heap, error_value.device_dependent_info, false);
+        SCPIDEFINE_free(&context->error_info_heap, error_value.device_dependent_info, true);
         SCPI_ERROR_SETVAL(&error_value, SCPI_ERROR_QUEUE_OVERFLOW, NULL);
         fifo_add(&context->error_queue, &error_value);
         return FALSE;
@@ -167,15 +168,7 @@
  */
 void SCPI_ErrorPushEx(scpi_t * context, int16_t err, char * info, size_t info_len) {
     int i;
-    char * info_ptr = NULL;
-
-#if USE_DEVICE_DEPENDENT_ERROR_INFORMATION
-    if (info) {
-        info_ptr = SCPIDEFINE_strndup(&context->error_info_heap, info, info_len);
-    }
-#endif
-
-    scpi_bool_t queue_overflow = !SCPI_ErrorAddInternal(context, err, info_ptr);
+    scpi_bool_t queue_overflow = !SCPI_ErrorAddInternal(context, err, info, info_len);
 
     for (i = 0; i < ERROR_DEFS_N; i++) {
         if ((err <= errs[i].from) && (err >= errs[i].to)) {
@@ -186,9 +179,6 @@
     SCPI_ErrorEmit(context, err);
     if (queue_overflow) {
         SCPI_ErrorEmit(context, SCPI_ERROR_QUEUE_OVERFLOW);
-#if USE_DEVICE_DEPENDENT_ERROR_INFORMATION
-        SCPIDEFINE_free(&context->error_info_heap, info_ptr, true);
-#endif
     }
 
     if (context) {
diff --git a/libscpi/test/test_scpi_utils.c b/libscpi/test/test_scpi_utils.c
index 98a7305..83d7fb0 100644
--- a/libscpi/test/test_scpi_utils.c
+++ b/libscpi/test/test_scpi_utils.c
@@ -744,6 +744,61 @@
     TEST_SWAP(64, 0x123456789ABCDEF0ull, 0xF0DEBC9A78563412ull);
 }
 
+#if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE
+
+static void test_heap(void) {
+
+#define ERROR_INFO_HEAP_LENGTH  16
+    scpi_error_info_heap_t heap;
+    char error_info_heap[ERROR_INFO_HEAP_LENGTH];
+
+    scpiheap_init(&heap, error_info_heap, ERROR_INFO_HEAP_LENGTH);
+    CU_ASSERT_EQUAL(heap.size, ERROR_INFO_HEAP_LENGTH);
+    CU_ASSERT_EQUAL(heap.data, error_info_heap);
+    CU_ASSERT_EQUAL(heap.count, heap.size);
+
+    char * ptr1 = scpiheap_strndup(&heap, "abcd", 4);
+    CU_ASSERT_STRING_EQUAL(ptr1, "abcd");
+
+    char * ptr2 = scpiheap_strndup(&heap, "xyz", 3);
+    CU_ASSERT_STRING_EQUAL(ptr2, "xyz");
+
+    char * ptr3 = scpiheap_strndup(&heap, "ghijklmnop", 10);
+    CU_ASSERT_EQUAL(ptr3, NULL);
+
+    scpiheap_free(&heap, ptr1, false);
+
+    char * ptr4 = scpiheap_strndup(&heap, "ghijklmnop", 10);
+    CU_ASSERT_NOT_EQUAL(ptr4, NULL);
+
+    const char * ptr5;
+    size_t len1, len2;
+    CU_ASSERT_EQUAL(scpiheap_get_parts(&heap, ptr4, &len1, &ptr5, &len2), TRUE);
+    CU_ASSERT_EQUAL(len1, 7);
+    CU_ASSERT_EQUAL(len2, 3);
+    CU_ASSERT_STRING_EQUAL(ptr5, "nop");
+    CU_ASSERT_EQUAL(memcmp(ptr4, "ghijklm", len1), 0);
+
+    scpiheap_free(&heap, ptr2, false);
+
+    char * ptr6 = scpiheap_strndup(&heap, "abcd", 4);
+    CU_ASSERT_STRING_EQUAL(ptr6, "abcd");
+
+    scpiheap_free(&heap, ptr6, true);
+
+    char * ptr7 = scpiheap_strndup(&heap, "123456789", 9);
+    CU_ASSERT_EQUAL(ptr7, NULL);
+
+    char * ptr8 = scpiheap_strndup(&heap, "123456789", 4);
+    CU_ASSERT_STRING_EQUAL(ptr8, "1234");
+
+    scpiheap_free(&heap, ptr4, false);
+    scpiheap_free(&heap, ptr8, false);
+    CU_ASSERT_EQUAL(heap.count, heap.size);
+
+}
+#endif
+
 int main() {
     unsigned int result;
     CU_pSuite pSuite = NULL;
@@ -780,6 +835,9 @@
             || (NULL == CU_add_test(pSuite, "matchCommand", test_matchCommand))
             || (NULL == CU_add_test(pSuite, "composeCompoundCommand", test_composeCompoundCommand))
             || (NULL == CU_add_test(pSuite, "swap", test_swap))
+#if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE
+            || (NULL == CU_add_test(pSuite, "heap", test_heap))
+#endif
             ) {
         CU_cleanup_registry();
         return CU_get_error();

--
Gitblit v1.9.1