]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add fr_heap_verify() and FR_HEAP_VERIFY() (#4274)
authorJames Jones <jejones3141@gmail.com>
Thu, 21 Oct 2021 14:07:49 +0000 (09:07 -0500)
committerGitHub <noreply@github.com>
Thu, 21 Oct 2021 14:07:49 +0000 (10:07 -0400)
FR_HEAP_VERIFY() invocations are added to fr_heap_test() to confirm
that the verify function works.

src/lib/util/heap.c
src/lib/util/heap.h
src/lib/util/heap_tests.c

index 2ddc847816aa2cf9e6dfb90d37894f3658b02e7a..a780de1ee85192baa2e57f738886f57379d1e986 100644 (file)
@@ -58,7 +58,7 @@ typedef struct fr_heap_s heap_t;
  */
 #define HEAP_PARENT(_x)        ((_x) >> 1)
 #define HEAP_LEFT(_x)  (2 * (_x))
-/* #define HEAP_RIGHT(_x) (2 * (_x) + 1 ) */
+#define HEAP_RIGHT(_x) (2 * (_x) + 1 )
 #define        HEAP_SWAP(_a, _b) { void *_tmp = _a; _a = _b; _b = _tmp; }
 
 static void fr_heap_bubble(heap_t *h, fr_heap_index_t child);
@@ -386,3 +386,46 @@ void *fr_heap_iter_next(fr_heap_t *hp, fr_heap_iter_t *iter)
 
        return h->p[*iter];
 }
+
+#ifndef TALLOC_GET_TYPE_ABORT_NOOP
+void fr_heap_verify(char const *file, int line, fr_heap_t *hp)
+{
+       heap_t  *h;
+
+       fr_fatal_assert_msg(hp, "CONSISTENCY CHECK FAILED %s[%i]: fr_heap_t pointer was NULL", file, line);
+       (void) talloc_get_type_abort(hp, fr_heap_t);
+
+       /*
+        *      Allocating the heap structure and the array holding the heap as described in data structure
+        *      texts together is a respectable savings, but it means adding a level of indirection so the
+        *      fr_heap_t * isn't realloc()ed out from under the user, hence the following (and the use of h
+        *      rather than hp to access anything in the heap structure).
+        */
+       h = *hp;
+       fr_fatal_assert_msg(h, "CONSISTENCY CHECK FAILED %s[%i]: heap_t pointer was NULL", file, line);
+       (void) talloc_get_type_abort(h, heap_t);
+
+       fr_fatal_assert_msg(h->num_elements <= h->size,
+                           "CONSISTENCY CHECK FAILED %s[%i]: num_elements exceeds size", file, line);
+
+       fr_fatal_assert_msg(h->p[0] == (void *)UINTPTR_MAX,
+                           "CONSISTENCY CHECK FAILED %s[%i]: zeroeth element special value overwritten", file, line);
+
+       for (unsigned int i = 1; i <= h->num_elements; i++) {
+               void    *data = h->p[i];
+
+               fr_fatal_assert_msg(data, "CONSISTENCY CHECK FAILED %s[%i]: node %u was NULL", file, line, i);
+               if (h->type) (void)_talloc_get_type_abort(data, h->type, __location__);
+               fr_fatal_assert_msg(index_get(h, data) == i,
+                                   "CONSISTENCY CHECK FAILED %s[%i]: node %u index != %u", file, line, i, i);
+       }
+       for (unsigned int i = 1; ; i++) {
+               if (HEAP_LEFT(i) > h->num_elements) break;
+               fr_fatal_assert_msg(h->cmp(h->p[i], h->p[HEAP_LEFT(i)]) <= 0,
+                                   "CONSISTENCY_CHECK_FAILED %s[%i]: node %u > left child", file, line, i);
+               if (HEAP_RIGHT(i) > h->num_elements) break;
+               fr_fatal_assert_msg(h->cmp(h->p[i], h->p[HEAP_RIGHT(i)]) <= 0,
+                                   "CONSISTENCY_CHECK_FAILED %s[%i]: node %u > right child", file, line, i);
+       }
+}
+#endif
index 6ae651ccc7bb91bf6bab4f3ed73dc6aa5dc28fa2..ce1256ddea06019523b68b6c1089163939768bf2 100644 (file)
@@ -122,6 +122,14 @@ void               *fr_heap_iter_next(fr_heap_t *hp, fr_heap_iter_t *iter) CC_HINT(nonnull);
        fr_heap_iter_t _iter; \
        for (_type *_data = fr_heap_iter_init(_heap, &_iter); _data; _data = fr_heap_iter_next(_heap, &_iter))
 
+#ifndef TALLOC_GET_TYPE_ABORT_NOOP
+void fr_heap_verify(char const *file, int line, fr_heap_t *hp);
+#  define FR_HEAP_VERIFY(_heap) fr_heap_verify(__FILE__, __LINE__, _heap)
+#elif !defined(NDEBUG)
+#  define FR_HEAP_VERIFY(_heap) fr_assert(_heap)
+#else
+#  define FR_HEAP_VERIFY(_heap)
+#endif
 
 #ifdef __cplusplus
 }
index 06d6d6db16239959213d3e8220cd8de47de28872..c7372e49a53a5ca3de8c2941bc91936c7335587a 100644 (file)
@@ -73,6 +73,7 @@ static void heap_test(int skip)
 
        TEST_CASE("insertions");
        for (i = 0; i < HEAP_TEST_SIZE; i++) {
+               FR_HEAP_VERIFY(hp);
                TEST_CHECK((ret = fr_heap_insert(hp, &array[i])) >= 0);
                TEST_MSG("insert failed, returned %i - %s", ret, fr_strerror());
 
@@ -87,6 +88,7 @@ static void heap_test(int skip)
                for (i = 0; i < HEAP_TEST_SIZE / skip; i++) {
                        entry = i * skip;
 
+                       FR_HEAP_VERIFY(hp);
                        TEST_CHECK(array[entry].heap != 0);
                        TEST_MSG("element %i removed out of order", entry);
 
@@ -105,6 +107,7 @@ static void heap_test(int skip)
        for (i = 0; i < left; i++) {
                heap_thing *t;
 
+               FR_HEAP_VERIFY(hp);
                TEST_CHECK((t = fr_heap_peek(hp)) != NULL);
                TEST_MSG("expected %i elements remaining in the heap", left - i);