Finished implementing list data type (except for dict items) - including

a reasonable set of automated unit/regression tests
This commit is contained in:
Glen Wiley 2013-07-22 15:16:40 -04:00
parent 0a6dfa46ae
commit 1ec3886604
6 changed files with 409 additions and 30 deletions

View File

@ -1,5 +1,5 @@
#
# common/Makefile. Generated from Makefile.in by configure.
# Makefile. Generated from Makefile.in by configure.
#
package = getdns

View File

@ -367,6 +367,7 @@ struct getdns_list_item {
};
/**
* get the length of the specified list (returned in *answer)
* @param list list of any of the supported data types
* @param answer number of valid items in the list
* @return GETDNS_RETURN_GOOD on success
@ -374,7 +375,7 @@ struct getdns_list_item {
*/
getdns_return_t getdns_list_get_length(struct getdns_list *list, size_t *answer);
/**
* return the enumerated data type of the indexed list item
* get the enumerated data type of the indexed list item
* @param list the list from which to fetch the data type
* @param index the item in the list from which to fetch the data type
* @param *answer assigned the value of the data type on success
@ -384,7 +385,9 @@ getdns_return_t getdns_list_get_length(struct getdns_list *list, size_t *answer)
getdns_return_t getdns_list_get_data_type(struct getdns_list *this_list, size_t index, getdns_data_type *answer);
getdns_return_t getdns_list_get_dict(struct getdns_list *this_list, size_t index, struct getdns_dict **answer);
/**
* retrieve the list value of the specified list item
* retrieve the list value of the specified list item, the caller must not free
* storage associated with the return value. When the list is destroyed any
* list data is also free()'d - keep this in mind when using this function.
* @param list the list from which to fetch the value
* @param index the item in the list from which to fetch the value
* @param **answer assigned a pointer to the list value of the indexed element
@ -393,6 +396,17 @@ getdns_return_t getdns_list_get_dict(struct getdns_list *this_list, size_t index
* @return GETDNS_RETURN_WRONG_TYPE_REQUESTED if the data type does not match the contents of the indexed item
*/
getdns_return_t getdns_list_get_list(struct getdns_list *this_list, size_t index, struct getdns_list **answer);
/**
* retrieve the binary data value of the specified list item, the caller must not
* free storage associated with the return value. When the list is destroyed any
* bindata data is also free()'d - keep this in mind when using this function.
* @param list the list from which to fetch the value
* @param index the item in the list from which to fetch the value
* @param **answer assigned a pointer to the list value of the indexed element
* @return GETDNS_RETURN_GOOD on success
* @return GETDNS_RETURN_NO_SUCH_LIST_ITEM if the index is out of range or the list is NULL
* @return GETDNS_RETURN_WRONG_TYPE_REQUESTED if the data type does not match the contents of the indexed item
*/
getdns_return_t getdns_list_get_bindata(struct getdns_list *this_list, size_t index, struct getdns_bindata **answer);
/**
* retrieve the integer value of the specified list item
@ -421,7 +435,11 @@ getdns_return_t getdns_dict_get_int(struct getdns_dict *this_dict, char *name, u
*/
struct getdns_list * getdns_list_create();
/**
* free memory allocated to the list
* free memory allocated to the list (also frees all children of the list)
* note that lists and bindata retrieved from the list via the getdns_list_get_*
* helper functions will be destroyed as well - if you fetched them previously
* you MUST copy those instances BEFORE you destroy the list else
* unpleasant things will happen at run-time
*/
void getdns_list_destroy(struct getdns_list *this_list);
/**
@ -434,6 +452,15 @@ void getdns_list_destroy(struct getdns_list *this_list);
*/
getdns_return_t getdns_list_add_item(struct getdns_list *list, size_t *index);
getdns_return_t getdns_list_set_dict(struct getdns_list *list, size_t index, struct getdns_dict *child_dict);
/**
* assign the child_list to an item in a parent list, the parent list copies
* the child list and will free the copy when the list is destroyed
* @param list list contiaining the item to which child_list is to be assigned
* @param index index of the item within list to which child_list is to be assigned
* @param *child_list list to assign to the item
* @return GETDNS_RETURN_GOOD on success
* @return GETDNS_RETURN_NO_SUCH_LIST_ITEM if index is out of range, or list is NULL
*/
getdns_return_t getdns_list_set_list(struct getdns_list *list, size_t index, struct getdns_list *child_list);
getdns_return_t getdns_list_set_bindata(struct getdns_list *list, size_t index, struct getdns_bindata *child_bindata);
/**

View File

@ -28,6 +28,7 @@
* THE SOFTWARE.
*/
#include <string.h>
#include <getdns_libevent.h>
#include "getdns_core_only.h"
@ -86,8 +87,24 @@ getdns_list_get_list(struct getdns_list *list, size_t index, struct getdns_list
return retval;
} /* getdns_list_get_list */
getdns_return_t getdns_list_get_bindata(struct getdns_list *this_list, size_t index, struct getdns_bindata **answer)
{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(answer); return GETDNS_RETURN_GOOD; }
/*---------------------------------------- getdns_list_get_bindata */
getdns_return_t getdns_list_get_bindata(struct getdns_list *list, size_t index, struct getdns_bindata **answer)
{
getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM;
if(list != NULL && index < list->numinuse)
{
if(list->items[index].dtype != t_bindata)
retval = GETDNS_RETURN_WRONG_TYPE_REQUESTED;
else
{
*answer = list->items[index].data.bindata;
retval = GETDNS_RETURN_GOOD;
}
}
return retval;
} /* getdns_list_get_bindata */
/*---------------------------------------- getdns_list_get_int */
getdns_return_t
@ -142,7 +159,71 @@ getdns_list_realloc(struct getdns_list *list)
}
return retval;
} /* getdns_list_alloc */
} /* getdns_list_realloc */
/*---------------------------------------- getdns_list_copy */
/**
* private function (API users should not be calling this), this uses library
* routines to make a copy of the list - would be faster to make the copy directly
* @param list pointer to list to copy
* @param newlist pointer to pointer to list to receive the copy (will be allocated)
* @return GETDNS_RETURN_GOOD on success
* @return GETDNS_RETURN_NO_SUCH_LIST_ITEM if list is invalid
* @return GETDNS_RETURN_GENERIC_ERROR if out of memory
*/
getdns_return_t
getdns_list_copy(struct getdns_list *srclist, struct getdns_list **dstlist)
{
int i;
size_t index;
getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM;
if(srclist != NULL && *dstlist != NULL)
{
*dstlist = getdns_list_create();
if(*dstlist != NULL)
{
retval = GETDNS_RETURN_GOOD;
for(i=0; i<srclist->numinuse; i++)
{
if(getdns_list_add_item(*dstlist, &index) == GETDNS_RETURN_GOOD)
{
(*dstlist)->items[index].inuse = true;
(*dstlist)->items[index].dtype = srclist->items[i].dtype;
if(srclist->items[i].dtype == t_int)
(*dstlist)->items[index].data.n = srclist->items[i].data.n;
else if(srclist->items[i].dtype == t_list)
retval = getdns_list_copy(srclist->items[index].data.list
, &((*dstlist)->items[i].data.list));
else if(srclist->items[i].dtype == t_bindata)
{
(*dstlist)->items[i].data.bindata = (struct getdns_bindata *)
malloc(sizeof(getdns_bindata));
(*dstlist)->items[i].data.bindata->size = srclist->items[i].data.bindata->size;
(*dstlist)->items[i].data.bindata->data = (uint8_t *)
malloc(srclist->items[i].data.bindata->size);
if((*dstlist)->items[i].data.bindata->data != NULL)
memcpy(srclist->items[i].data.bindata->data
, (*dstlist)->items[i].data.bindata->data
, srclist->items[i].data.bindata->size);
else
retval = GETDNS_RETURN_GENERIC_ERROR;
}
}
else
retval = GETDNS_RETURN_GENERIC_ERROR;
if(retval != GETDNS_RETURN_GOOD)
break;
}
}
else
retval = GETDNS_RETURN_GENERIC_ERROR;
}
return retval;
} /* getdns_list_copy */
/*---------------------------------------- getdns_list_create */
struct getdns_list *
@ -167,10 +248,28 @@ getdns_list_create()
void
getdns_list_destroy(struct getdns_list *list)
{
int i;
if(list != NULL)
{
if(list->items != NULL)
{
for(i=0; i<list->numinuse; i++)
{
if(list->items[i].dtype == t_list)
{
if(list->items[i].dtype == t_list)
getdns_list_destroy(list->items[i].data.list);
}
else if(list->items[i].dtype == t_bindata)
{
if(list->items[i].data.bindata->size > 0)
free(list->items[i].data.bindata->data);
free(list->items[i].data.bindata);
}
}
free(list->items);
}
free(list);
}
} /* getdns_list_destroy */
@ -200,13 +299,54 @@ getdns_list_add_item(struct getdns_list *list, size_t *index)
getdns_return_t getdns_list_set_dict(struct getdns_list *this_list, size_t index, struct getdns_dict *child_dict)
{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(child_dict); return GETDNS_RETURN_GOOD; }
getdns_return_t getdns_list_set_list(struct getdns_list *this_list, size_t index, struct getdns_list *child_list)
{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(child_list); return GETDNS_RETURN_GOOD; }
/*---------------------------------------- getdns_set_list */
getdns_return_t
getdns_list_set_list(struct getdns_list *list, size_t index, struct getdns_list *child_list)
{
getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM;
getdns_return_t getdns_list_set_bindata(struct getdns_list *this_list, size_t index, struct getdns_bindata *child_bindata)
{ UNUSED_PARAM(this_list); UNUSED_PARAM(index); UNUSED_PARAM(child_bindata); return GETDNS_RETURN_GOOD; }
if(list != NULL && child_list != NULL)
{
if(list->numinuse > index)
{
list->items[index].dtype = t_list;
retval = getdns_list_copy(child_list, &(list->items[index].data.list));
}
}
/*---------------------------------------- getdns_list_set */
return retval;
} /* getdns_set_list */
/*---------------------------------------- getdns_list_set_bindata */
getdns_return_t
getdns_list_set_bindata(struct getdns_list *list, size_t index, struct getdns_bindata *child_bindata)
{
getdns_return_t retval = GETDNS_RETURN_NO_SUCH_LIST_ITEM;
if(list != NULL && child_bindata != NULL)
{
if(list->numinuse > index)
{
list->items[index].dtype = t_bindata;
list->items[index].data.bindata = (struct getdns_bindata *)
malloc(sizeof(struct getdns_bindata));
if(list->items[index].data.bindata != NULL)
{
list->items[index].data.bindata->size = child_bindata->size;
list->items[index].data.bindata->data = (uint8_t *) malloc(child_bindata->size
* sizeof(uint8_t));
memcpy(list->items[index].data.bindata->data, child_bindata->data, child_bindata->size);
retval = GETDNS_RETURN_GOOD;
}
else
retval = GETDNS_RETURN_GENERIC_ERROR;
}
}
return retval;
} /* getdns_list_set_bindata */
/*---------------------------------------- getdns_list_set_int */
getdns_return_t
getdns_list_set_int(struct getdns_list *list, size_t index, uint32_t child_uint32)
{
@ -218,6 +358,7 @@ getdns_list_set_int(struct getdns_list *list, size_t index, uint32_t child_uint3
{
list->items[index].dtype = t_int;
list->items[index].data.n = child_uint32;
retval = GETDNS_RETURN_GOOD;
}
}

View File

@ -37,7 +37,7 @@ tests_list: tests_list.o ../common/libgetdns.so testmessages.o
# we want the library that was just built to be used in the tests
# NOT one that is installed on the system
tests_list.out : tests_list
DYLD_LIBRARY_PATH=../common; ./tests_list > tests_list.out
export DYLD_LIBRARY_PATH=../common; ./tests_list > tests_list.out
clean:
rm -f *.o *.out *.res $(PROGRAMS)

View File

@ -1,6 +1,8 @@
/**
* \file
* \brief unit tests for getdns_list helper routines
* unit tests for getdns_list helper routines, these should be used to
* perform regression tests, output must be unchanged from canonical output
* stored with the sources
*/
/* The MIT License (MIT)
* Copyright (c) 2013 Verisign, Inc.
@ -26,17 +28,173 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "testmessages.h"
#include "getdns_core_only.h"
#define TSTMSGBUF 80
/*---------------------------------------- tst_setget */
/*---------------------------------------- tst_bindatasetget */
/**
* test the routines that set and get values of items in the list
* test the list get and set routines
*/
void
tst_setget(void)
tst_bindatasetget(void)
{
char msg[TSTMSGBUF];
size_t index;
getdns_return_t retval;
struct getdns_list *list = NULL;
struct getdns_bindata *new_bindata = NULL;
struct getdns_bindata *ans_bindata = NULL;
tstmsg_case_begin("tst_bindatasetget");
list = getdns_list_create();
/* test get function against empty list and with bogus params */
tstmsg_case_msg("getdns_list_get_bindata() empty list");
retval = getdns_list_get_bindata(NULL, index, &ans_bindata);
sprintf(msg, "getdns_list_get_bindata(NULL, index, &ans_bindata),retval = %d"
, retval);
tstmsg_case_msg(msg);
retval = getdns_list_get_bindata(list, index, NULL);
sprintf(msg, "getdns_list_get_bindata(list, index, NULL),retval = %d", retval);
tstmsg_case_msg(msg);
tstmsg_case_msg("getdns_list_get_bindata(list, 0, &ans_bindata)");
retval = getdns_list_get_bindata(list, 0, &ans_bindata);
sprintf(msg, "getdns_list_get_bindata,retval = %d", retval);
tstmsg_case_msg(msg);
tstmsg_case_msg("getdns_list_get_bindata(list, 1, &ans_bindata)");
retval = getdns_list_get_bindata(list, 1, &ans_bindata);
sprintf(msg, "getdns_list_get_bindata,retval = %d", retval);
tstmsg_case_msg(msg);
/* test set function against empty list with bogus params */
tstmsg_case_msg("getdns_list_set_bindata() empty list");
retval = getdns_list_set_bindata(NULL, index, NULL);
sprintf(msg, "getdns_list_set_bindata(NULL, index, ans_bindata),retval = %d", retval);
tstmsg_case_msg(msg);
tstmsg_case_msg("getdns_list_set_bindata(list, 0, ans_bindata)");
retval = getdns_list_set_bindata(list, 0, NULL);
sprintf(msg, "getdns_list_set_bindata,retval = %d", retval);
tstmsg_case_msg(msg);
tstmsg_case_msg("getdns_list_set_bindata(list, 1, ans_bindata)");
retval = getdns_list_set_bindata(list, 1, NULL);
sprintf(msg, "getdns_list_set_bindata,retval = %d", retval);
tstmsg_case_msg(msg);
/* test set and get legitimate use case */
new_bindata = (struct getdns_bindata *) malloc(sizeof(struct getdns_bindata));
new_bindata->size = strlen("foobar") + 1;
new_bindata->data = (uint8_t *) strdup("foobar");
new_bindata->data[strlen("foobar")] = '\0';
getdns_list_add_item(list, &index);
getdns_list_set_bindata(list, index, new_bindata);
retval = getdns_list_get_bindata(list, index, &ans_bindata);
sprintf(msg, "getdns_list_set/get_bindata,retval = %d, bindata->data = %d,%s"
, retval, (int) ans_bindata->size, (char *) ans_bindata->data);
tstmsg_case_msg(msg);
getdns_list_destroy(list);
tstmsg_case_end();
return;
} /* tst_bindatasetget */
/*---------------------------------------- tst_listsetget */
/**
* test the list get and set routines
*/
void
tst_listsetget(void)
{
char msg[TSTMSGBUF];
size_t index;
getdns_return_t retval;
uint32_t ans_int;
struct getdns_list *list = NULL;
struct getdns_list *new_list = NULL;
struct getdns_list *ans_list = NULL;
tstmsg_case_begin("tst_listsetget");
list = getdns_list_create();
/* test get function against empty list and with bogus params */
tstmsg_case_msg("getdns_list_get_list() empty list");
retval = getdns_list_get_list(NULL, index, &ans_list);
sprintf(msg, "getdns_list_get_list(NULL, index, &ans_list),retval = %d", retval);
tstmsg_case_msg(msg);
retval = getdns_list_get_list(list, index, NULL);
sprintf(msg, "getdns_list_get_list(list, index, NULL),retval = %d", retval);
tstmsg_case_msg(msg);
tstmsg_case_msg("getdns_list_get_list(list, 0, &ans_list)");
retval = getdns_list_get_list(list, 0, &ans_list);
sprintf(msg, "getdns_list_get_list,retval = %d", retval);
tstmsg_case_msg(msg);
tstmsg_case_msg("getdns_list_get_list(list, 1, &ans_list)");
retval = getdns_list_get_list(list, 1, &ans_list);
sprintf(msg, "getdns_list_get_list,retval = %d", retval);
tstmsg_case_msg(msg);
/* test set function against empty list with bogus params */
tstmsg_case_msg("getdns_list_set_list() empty list");
retval = getdns_list_set_list(NULL, index, NULL);
sprintf(msg, "getdns_list_set_list(NULL, index, ans_list),retval = %d", retval);
tstmsg_case_msg(msg);
tstmsg_case_msg("getdns_list_set_list(list, 0, ans_list)");
retval = getdns_list_set_list(list, 0, NULL);
sprintf(msg, "getdns_list_set_list,retval = %d", retval);
tstmsg_case_msg(msg);
tstmsg_case_msg("getdns_list_set_list(list, 1, ans_list)");
retval = getdns_list_set_list(list, 1, NULL);
sprintf(msg, "getdns_list_set_list,retval = %d", retval);
tstmsg_case_msg(msg);
/* test set and get legitimate use case */
new_list = getdns_list_create();
getdns_list_add_item(new_list, &index);
getdns_list_set_int(new_list, index, 42);
getdns_list_add_item(list, &index);
getdns_list_set_list(list, index, new_list);
retval = getdns_list_get_list(list, index, &ans_list);
getdns_list_get_int(ans_list, 0, &ans_int);
sprintf(msg, "getdns_list_set/get_list,retval = %d, ans[0] = %d", retval, ans_int);
tstmsg_case_msg(msg);
getdns_list_destroy(list);
tstmsg_case_end();
return;
} /* tst_listsetget */
/*---------------------------------------- tst_intsetget */
/**
* test the int get and set routines
*/
void
tst_intsetget(void)
{
char msg[TSTMSGBUF];
size_t index;
@ -44,11 +202,11 @@ tst_setget(void)
getdns_return_t retval;
struct getdns_list *list = NULL;
tstmsg_case_begin("tst_setget");
tstmsg_case_begin("tst_intsetget");
list = getdns_list_create();
/* test get functions against empty list and with bogus params */
/* test int get function against empty list and with bogus params */
tstmsg_case_msg("getdns_list_get_int() empty list");
retval = getdns_list_get_int(NULL, index, &ans_int);
@ -66,15 +224,40 @@ tst_setget(void)
tstmsg_case_msg("getdns_list_get_int(list, 1, &ans_int)");
retval = getdns_list_get_int(list, 1, &ans_int);
sprintf(msg, "getdns_list_get_int,retval = %d", retval);
tstmsg_case_msg(msg);
/* test int set function against empty list with bogus params */
tstmsg_case_msg("getdns_list_set_int() empty list");
retval = getdns_list_set_int(NULL, index, ans_int);
sprintf(msg, "getdns_list_set_int(NULL, index, ans_int),retval = %d", retval);
tstmsg_case_msg(msg);
tstmsg_case_msg("getdns_list_set_int(list, 0, ans_int)");
retval = getdns_list_set_int(list, 0, ans_int);
sprintf(msg, "getdns_list_set_int,retval = %d", retval);
tstmsg_case_msg(msg);
tstmsg_case_msg("getdns_list_set_int(list, 1, ans_int)");
retval = getdns_list_set_int(list, 1, ans_int);
sprintf(msg, "getdns_list_set_int,retval = %d", retval);
tstmsg_case_msg(msg);
/* test set and get legitimate use case */
getdns_list_add_item(list, &index);
getdns_list_set_int(list, index, 42);
retval = getdns_list_get_int(list, index, &ans_int);
sprintf(msg, "getdns_list_set/get_int,retval = %d, ans = %d", retval, ans_int);
tstmsg_case_msg(msg);
getdns_list_destroy(list);
tstmsg_case_end();
return;
} /* tst_setget */
} /* tst_intsetget */
/*---------------------------------------- tst_create */
/**
@ -153,6 +336,7 @@ tst_create(void)
return;
} /* tst_create */
/*---------------------------------------- main */
/**
* runs unit tests against list management routines
*/
@ -163,7 +347,11 @@ main(int argc, char *argv[])
tst_create();
tst_setget();
tst_intsetget();
tst_listsetget();
tst_bindatasetget();
tstmsg_prog_end();

View File

@ -11,13 +11,36 @@ TESTCASE tests_list:tst_create BEGIN
tests_list:tst_create: NUll, NULL, retval = 304
tests_list:tst_create: list, NULL, retval = 304
TESTCASE tests_list:tst_create END
TESTCASE tests_list:tst_setget BEGIN
tests_list:tst_setget: getdns_list_get_int() empty list
tests_list:tst_setget: getdns_list_get_int(NULL, index, &ans_int),retval = 304
tests_list:tst_setget: getdns_list_get_int(list, index, NULL),retval = 304
tests_list:tst_setget: getdns_list_get_int(list, 0, &ans_int)
tests_list:tst_setget: getdns_list_get_int,retval = 304
tests_list:tst_setget: getdns_list_get_int(list, 1, &ans_int)
tests_list:tst_setget: getdns_list_set_int,retval = 304
TESTCASE tests_list:tst_setget END
TESTCASE tests_list:tst_intsetget BEGIN
tests_list:tst_intsetget: getdns_list_get_int() empty list
tests_list:tst_intsetget: getdns_list_get_int(NULL, index, &ans_int),retval = 304
tests_list:tst_intsetget: getdns_list_get_int(list, index, NULL),retval = 304
tests_list:tst_intsetget: getdns_list_get_int(list, 0, &ans_int)
tests_list:tst_intsetget: getdns_list_get_int,retval = 304
tests_list:tst_intsetget: getdns_list_get_int(list, 1, &ans_int)
tests_list:tst_intsetget: getdns_list_get_int,retval = 304
tests_list:tst_intsetget: getdns_list_set_int() empty list
tests_list:tst_intsetget: getdns_list_set_int(NULL, index, ans_int),retval = 304
tests_list:tst_intsetget: getdns_list_set_int(list, 0, ans_int)
tests_list:tst_intsetget: getdns_list_set_int,retval = 304
tests_list:tst_intsetget: getdns_list_set_int(list, 1, ans_int)
tests_list:tst_intsetget: getdns_list_set_int,retval = 304
tests_list:tst_intsetget: getdns_list_set/get_int,retval = 0, ans = 42
TESTCASE tests_list:tst_intsetget END
TESTCASE tests_list:tst_listsetget BEGIN
tests_list:tst_listsetget: getdns_list_get_list() empty list
tests_list:tst_listsetget: getdns_list_get_list(NULL, index, &ans_list),retval = 304
tests_list:tst_listsetget: getdns_list_get_list(list, index, NULL),retval = 304
tests_list:tst_listsetget: getdns_list_get_list(list, 0, &ans_list)
tests_list:tst_listsetget: getdns_list_get_list,retval = 304
tests_list:tst_listsetget: getdns_list_get_int(list, 1, &ans_list)
tests_list:tst_listsetget: getdns_list_get_list,retval = 304
tests_list:tst_listsetget: getdns_list_set_list() empty list
tests_list:tst_listsetget: getdns_list_set_list(NULL, index, ans_list),retval = 304
tests_list:tst_listsetget: getdns_list_set_list(list, 0, ans_list)
tests_list:tst_listsetget: getdns_list_set_list,retval = 304
tests_list:tst_listsetget: getdns_list_set_list(list, 1, ans_list)
tests_list:tst_listsetget: getdns_list_set_list,retval = 304
tests_list:tst_listsetget: getdns_list_set/get_list,retval = 0, ans[0] = 42
TESTCASE tests_list:tst_listsetget END
TESTPROG tests_list END