Newer
Older
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2009, Digium, Inc.
*
* Russell Bryant <russell@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Heap data structure test module
*
* \author Russell Bryant <russell@digium.com>
*/
<depend>TEST_FRAMEWORK</depend>
<support_level>core</support_level>
#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/utils.h"
#include "asterisk/heap.h"
struct node {
long val;
size_t index;
};
static int node_cmp(void *_n1, void *_n2)
{
struct node *n1 = _n1;
struct node *n2 = _n2;
if (n1->val < n2->val) {
return -1;
} else if (n1->val == n2->val) {
return 0;
} else {
return 1;
}
}
{
struct ast_heap *h;
struct node *obj;
struct node nodes[3] = {
switch (cmd) {
case TEST_INIT:
info->name = "heap_test_1";
Tilghman Lesher
committed
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;
if (!(h = ast_heap_create(8, node_cmp, offsetof(struct node, index)))) {
return AST_TEST_FAIL;
}
ast_heap_push(h, &nodes[0]);
ast_heap_push(h, &nodes[1]);
ast_heap_push(h, &nodes[2]);
obj = ast_heap_pop(h);
if (obj->val != 3) {
ast_test_status_update(test, "expected 3, got %ld\n", obj->val);
}
obj = ast_heap_pop(h);
if (obj->val != 2) {
ast_test_status_update(test, "expected 2, got %ld\n", obj->val);
}
obj = ast_heap_pop(h);
if (obj->val != 1) {
ast_test_status_update(test, "expected 1, got %ld\n", obj->val);
}
obj = ast_heap_pop(h);
if (obj) {
ast_test_status_update(test, "got unexpected object\n");
}
h = ast_heap_destroy(h);
{
struct ast_heap *h = NULL;
static const unsigned int total = 100000;
struct node *nodes = NULL;
struct node *node;
long last = LONG_MAX;
long cur;
enum ast_test_result_state res = AST_TEST_PASS;
switch (cmd) {
case TEST_INIT:
info->name = "heap_test_2";
Tilghman Lesher
committed
info->category = "/main/heap/";
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 "
David Vossel
committed
"in the proper order.";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
if (!(nodes = ast_malloc(total * sizeof(*node)))) {
goto return_cleanup;
}
if (!(h = ast_heap_create(20, node_cmp, offsetof(struct node, index)))) {
goto return_cleanup;
}
while (i--) {
nodes[i].val = ast_random();
ast_heap_push(h, &nodes[i]);
}
if (ast_heap_verify(h)) {
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);
goto return_cleanup;
}
last = cur;
i++;
}
if (i != total) {
ast_test_status_update(test, "Stopped popping off after only getting %u nodes\n", i);
goto return_cleanup;
}
return_cleanup:
if (h) {
h = ast_heap_destroy(h);
}
if (nodes) {
ast_free(nodes);
}
return res;
}
AST_TEST_DEFINE(heap_test_3)
{
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 TEST_INIT:
info->name = "heap_test_3";
Tilghman Lesher
committed
info->category = "/main/heap/";
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
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 (!(nodes = ast_malloc(test_size * sizeof(*node)))) {
ast_test_status_update(test, "memory allocation failure\n");
res = AST_TEST_FAIL;
goto return_cleanup;
}
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;
}
while (i--) {
nodes[i].val = ast_random();
ast_heap_push(h, &nodes[i]);
}
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;
}
i = test_size / 10;
while (i--) {
random_index = ast_random() % test_size;
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
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_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_TEST_REGISTER(heap_test_1);
AST_TEST_REGISTER(heap_test_2);
AST_TEST_REGISTER(heap_test_3);
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Heap test module");