And the automerge property.
[asterisk/asterisk.git] / tests / test_heap.c
index c5d3f5f..de48f0a 100644 (file)
  * \author Russell Bryant <russell@digium.com>
  */
 
+/*** MODULEINFO
+       <depend>TEST_FRAMEWORK</depend>
+ ***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/module.h"
-#include "asterisk/cli.h"
 #include "asterisk/utils.h"
 #include "asterisk/heap.h"
+#include "asterisk/test.h"
 
 struct node {
        long val;
@@ -51,24 +55,30 @@ static int node_cmp(void *_n1, void *_n2)
        }
 }
 
-static int test1(int fd)
+AST_TEST_DEFINE(heap_test_1)
 {
        struct ast_heap *h;
        struct node *obj;
        struct node nodes[3] = {
-               { 1, },
-               { 2, },
-               { 3, },
+               { 1, } ,
+               { 2, } ,
+               { 3, } ,
        };
 
-       if (!(h = ast_heap_create(8, node_cmp, offsetof(struct node, index)))) {
-               return -1;
+       switch (cmd) {
+       case TEST_INIT:
+               info->name = "heap_test_1";
+               info->category = "main/heap/";
+               info->summary = "push and pop elements";
+               info->description = "Push a few elements onto a heap and make sure that they come back off in the right order.";
+               return AST_TEST_NOT_RUN;
+       case TEST_EXECUTE:
+               break;
        }
 
-       /* Pushing 1 2 3, and then popping 3 elements */
-
-       ast_cli(fd, "Test #1 - Push a few elements onto a heap and make sure that they "
-                       "come back off in the right order.\n");
+       if (!(h = ast_heap_create(8, node_cmp, offsetof(struct node, index)))) {
+               return AST_TEST_FAIL;
+       }
 
        ast_heap_push(h, &nodes[0]);
 
@@ -78,52 +88,66 @@ static int test1(int fd)
 
        obj = ast_heap_pop(h);
        if (obj->val != 3) {
-               return -2;
+               ast_test_status_update(test, "expected 3, got %ld\n", obj->val);
+               return AST_TEST_FAIL;
        }
 
        obj = ast_heap_pop(h);
        if (obj->val != 2) {
-               return -3;
+               ast_test_status_update(test, "expected 2, got %ld\n", obj->val);
+               return AST_TEST_FAIL;
        }
 
        obj = ast_heap_pop(h);
        if (obj->val != 1) {
-               return -4;
+               ast_test_status_update(test, "expected 1, got %ld\n", obj->val);
+               return AST_TEST_FAIL;
        }
 
        obj = ast_heap_pop(h);
        if (obj) {
-               return -5;
+               ast_test_status_update(test, "got unexpected object\n");
+               return AST_TEST_FAIL;
        }
 
        h = ast_heap_destroy(h);
 
-       ast_cli(fd, "Test #1 successful.\n");
-
-       return 0;
+       return AST_TEST_PASS;
 }
 
-static int test2(int fd)
+AST_TEST_DEFINE(heap_test_2)
 {
        struct ast_heap *h = NULL;
-       static const unsigned int one_million = 1000000;
+       static const unsigned int total = 100000;
        struct node *nodes = NULL;
        struct node *node;
-       unsigned int i = one_million;
-       long last = LONG_MAX, cur;
-       int res = 0;
+       unsigned int i = total;
+       long last = LONG_MAX;
+       long cur;
+       enum ast_test_result_state res = AST_TEST_PASS;
 
-       ast_cli(fd, "Test #2 - Push a million random elements on to a heap, "
-                       "verify that the heap has been properly constructed, "
-                       "and then ensure that the elements are come back off in the proper order\n");
+       switch (cmd) {
+       case TEST_INIT:
+               info->name = "heap_test_2";
+               info->category = "main/heap/";
+               info->summary = "load test";
+               info->description =
+                               "Push one hundred thousand random elements on to a heap, "
+                               "verify that the heap has been properly constructed, "
+                               "and then ensure that the elements are come back off "
+                               "in the proper order.";
+               return AST_TEST_NOT_RUN;
+       case TEST_EXECUTE:
+               break;
+       }
 
-       if (!(nodes = ast_malloc(one_million * sizeof(*node)))) {
-               res = -1;
+       if (!(nodes = ast_malloc(total * sizeof(*node)))) {
+               res = AST_TEST_FAIL;
                goto return_cleanup;
        }
 
        if (!(h = ast_heap_create(20, node_cmp, offsetof(struct node, index)))) {
-               res = -2;
+               res = AST_TEST_FAIL;
                goto return_cleanup;
        }
 
@@ -133,7 +157,7 @@ static int test2(int fd)
        }
 
        if (ast_heap_verify(h)) {
-               res = -3;
+               res = AST_TEST_FAIL;
                goto return_cleanup;
        }
 
@@ -141,22 +165,20 @@ static int test2(int fd)
        while ((node = ast_heap_pop(h))) {
                cur = node->val;
                if (cur > last) {
-                       ast_cli(fd, "i: %u, cur: %ld, last: %ld\n", i, cur, last);
-                       res = -4;
+                       ast_test_status_update(test, "i: %u, cur: %ld, last: %ld\n", i, cur, last);
+                       res = AST_TEST_FAIL;
                        goto return_cleanup;
                }
                last = cur;
                i++;
        }
 
-       if (i != one_million) {
-               ast_cli(fd, "Stopped popping off after only getting %u nodes\n", i);
-               res = -5;
+       if (i != total) {
+               ast_test_status_update(test, "Stopped popping off after only getting %u nodes\n", i);
+               res = AST_TEST_FAIL;
                goto return_cleanup;
        }
 
-       ast_cli(fd, "Test #2 successful.\n");
-
 return_cleanup:
        if (h) {
                h = ast_heap_destroy(h);
@@ -168,51 +190,117 @@ return_cleanup:
        return res;
 }
 
-static char *handle_cli_heap_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+AST_TEST_DEFINE(heap_test_3)
 {
-       int res;
+       struct ast_heap *h = NULL;
+       struct node *nodes = NULL;
+       struct node *node;
+       static const unsigned int test_size = 100000;
+       unsigned int i = test_size;
+       long last = LONG_MAX, cur;
+       int random_index;
+       enum ast_test_result_state res = AST_TEST_PASS;
 
        switch (cmd) {
-       case CLI_INIT:
-               e->command = "heap test";
-               e->usage = ""
-                       "Usage: heap test\n"
-                       "";
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;
+       case TEST_INIT:
+               info->name = "heap_test_3";
+               info->category = "main/heap/";
+               info->summary = "random element removal test";
+               info->description =
+                       "Push a hundred thousand random elements on to a heap, "
+                       "verify that the heap has been properly constructed, "
+                       "randomly remove and re-add 10000 elements, and then "
+                       "ensure that the elements come back off in the proper order.";
+               return AST_TEST_NOT_RUN;
+       case TEST_EXECUTE:
+               break;
        }
 
-       if (a->argc != e->args) {
-               return CLI_SHOWUSAGE;
+       if (!(nodes = ast_malloc(test_size * sizeof(*node)))) {
+               ast_test_status_update(test, "memory allocation failure\n");
+               res = AST_TEST_FAIL;
+               goto return_cleanup;
        }
 
-       if ((res = test1(a->fd))) {
-               ast_cli(a->fd, "Test 1 failed! (%d)\n", res);
-               return CLI_FAILURE;
+       if (!(h = ast_heap_create(20, node_cmp, offsetof(struct node, index)))) {
+               ast_test_status_update(test, "Failed to allocate heap\n");
+               res = AST_TEST_FAIL;
+               goto return_cleanup;
        }
 
-       if ((res = test2(a->fd))) {
-               ast_cli(a->fd, "Test 2 failed! (%d)\n", res);
-               return CLI_FAILURE;
+       while (i--) {
+               nodes[i].val = ast_random();
+               ast_heap_push(h, &nodes[i]);
        }
 
-       return CLI_SUCCESS;
-}
+       if (ast_heap_verify(h)) {
+               ast_test_status_update(test, "Failed to verify heap after populating it\n");
+               res = AST_TEST_FAIL;
+               goto return_cleanup;
+       }
 
-static struct ast_cli_entry cli_heap[] = {
-       AST_CLI_DEFINE(handle_cli_heap_test, "Test the heap implementation"),
-};
+       i = test_size / 10;
+       while (i--) {
+               random_index = ast_random() % test_size;
+               node = ast_heap_remove(h, &nodes[random_index]);
+               if (nodes[random_index].val != node->val){
+                       ast_test_status_update(test, "Failed to remove what we expected to\n");
+                       res = AST_TEST_FAIL;
+                       goto return_cleanup;
+               }
+               ast_heap_push(h, &nodes[random_index]);
+       }
+
+       if (ast_heap_verify(h)) {
+               ast_test_status_update(test, "Failed to verify after removals\n");
+               res = AST_TEST_FAIL;
+               goto return_cleanup;
+       }
+
+       i = 0;
+       while ((node = ast_heap_pop(h))) {
+               cur = node->val;
+               if (cur > last) {
+                       ast_test_status_update(test, "i: %u, cur: %ld, last: %ld\n", i, cur, last);
+                       res = AST_TEST_FAIL;
+                       goto return_cleanup;
+               }
+               last = cur;
+               i++;
+       }
+
+       if (i != test_size) {
+               ast_test_status_update(test, "Stopped popping off after only getting %u nodes\n", i);
+               res = AST_TEST_FAIL;
+               goto return_cleanup;
+       }
+
+return_cleanup:
+       if (h) {
+               h = ast_heap_destroy(h);
+       }
+       if (nodes) {
+               ast_free(nodes);
+       }
+
+       return res;
+}
 
 static int unload_module(void)
 {
-       ast_cli_unregister_multiple(cli_heap, ARRAY_LEN(cli_heap));
+       AST_TEST_UNREGISTER(heap_test_1);
+       AST_TEST_UNREGISTER(heap_test_2);
+       AST_TEST_UNREGISTER(heap_test_3);
+
        return 0;
 }
 
 static int load_module(void)
 {
-       ast_cli_register_multiple(cli_heap, ARRAY_LEN(cli_heap));
+       AST_TEST_REGISTER(heap_test_1);
+       AST_TEST_REGISTER(heap_test_2);
+       AST_TEST_REGISTER(heap_test_3);
+
        return AST_MODULE_LOAD_SUCCESS;
 }