Add function to force an nvlist into the error state

Add an nvlist_set_error() function that can be used to force an
nvlist into the error state.  This is useful both for writing
tests and for writing APIs that use nvlists internally.

Differential Revision:		https://reviews.freebsd.org/D1878
Reviewed by:			pjd, jfv
MFC After:			1 month
Sponsored by:			Sandvine Inc.
This commit is contained in:
Ryan Stone 2015-03-01 00:22:23 +00:00
parent 3cd4533107
commit a87e516267
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=279434
5 changed files with 65 additions and 1 deletions

View File

@ -22,6 +22,7 @@ MLINKS+=nv.3 libnv.3 \
MLINKS+=nv.3 nvlist_create.3 \
nv.3 nvlist_destroy.3 \
nv.3 nvlist_error.3 \
nv.3 nvlist_set_error.3 \
nv.3 nvlist_empty.3 \
nv.3 nvlist_clone.3 \
nv.3 nvlist_dump.3 \

View File

@ -35,6 +35,7 @@
.Nm nvlist_create ,
.Nm nvlist_destroy ,
.Nm nvlist_error ,
.Nm nvlist_set_error ,
.Nm nvlist_empty ,
.Nm nvlist_exists ,
.Nm nvlist_free ,
@ -63,6 +64,8 @@
.Fn nvlist_destroy "nvlist_t *nvl"
.Ft int
.Fn nvlist_error "const nvlist_t *nvl"
.Ft void
.Fn nvlist_set_error "nvlist_t *nvl, int error"
.Ft bool
.Fn nvlist_empty "const nvlist_t *nvl"
.\"
@ -248,8 +251,17 @@ the
error will be returned.
.Pp
The
.Fn nvlist_set_error
function sets an nvlist to be in the error state.
Subsequent calls to
.Fn nvlist_error
will return the given error value.
This function cannot be used to clear the error state from an nvlist.
This function does nothing if the nvlist is already in the error state.
.Pp
The
.Fn nvlist_empty
functions returns
function returns
.Dv true
if the given nvlist is empty and
.Dv false

View File

@ -69,6 +69,7 @@ nvlist_t *nvlist_create(int flags);
void nvlist_destroy(nvlist_t *nvl);
int nvlist_error(const nvlist_t *nvl);
bool nvlist_empty(const nvlist_t *nvl);
void nvlist_set_error(nvlist_t *nvl, int error);
nvlist_t *nvlist_clone(const nvlist_t *nvl);

View File

@ -137,6 +137,20 @@ nvlist_destroy(nvlist_t *nvl)
errno = serrno;
}
void
nvlist_set_error(nvlist_t *nvl, int error)
{
PJDLOG_ASSERT(error != 0);
/*
* Check for error != 0 so that we don't do the wrong thing if somebody
* tries to abuse this API when asserts are disabled.
*/
if (nvl != NULL && error != 0 && nvl->nvl_error == 0)
nvl->nvl_error = error;
}
int
nvlist_error(const nvlist_t *nvl)
{

View File

@ -409,6 +409,22 @@ ATF_TEST_CASE_BODY(nvlist_clone__nested_nvlist)
nvlist_destroy(nvl);
}
ATF_TEST_CASE_WITHOUT_HEAD(nvlist_clone__error_nvlist);
ATF_TEST_CASE_BODY(nvlist_clone__error_nvlist)
{
nvlist_t *nvl, *clone;
nvl = nvlist_create(0);
ATF_REQUIRE(nvl != NULL);
nvlist_set_error(nvl, ENOMEM);
clone = nvlist_clone(nvl);
ATF_REQUIRE(clone == NULL);
nvlist_destroy(nvl);
}
ATF_TEST_CASE_WITHOUT_HEAD(nvlist_pack__empty_nvlist);
ATF_TEST_CASE_BODY(nvlist_pack__empty_nvlist)
{
@ -550,6 +566,24 @@ ATF_TEST_CASE_BODY(nvlist_pack__multiple_values)
free(packed);
}
ATF_TEST_CASE_WITHOUT_HEAD(nvlist_pack__error_nvlist);
ATF_TEST_CASE_BODY(nvlist_pack__error_nvlist)
{
nvlist_t *nvl;
void *packed;
size_t size;
nvl = nvlist_create(0);
ATF_REQUIRE(nvl != NULL);
nvlist_set_error(nvl, ENOMEM);
packed = nvlist_pack(nvl, &size);
ATF_REQUIRE(packed == NULL);
nvlist_destroy(nvl);
}
ATF_TEST_CASE_WITHOUT_HEAD(nvlist_unpack__duplicate_key);
ATF_TEST_CASE_BODY(nvlist_unpack__duplicate_key)
{
@ -1148,9 +1182,11 @@ ATF_INIT_TEST_CASES(tp)
ATF_ADD_TEST_CASE(tp, nvlist_clone__empty_nvlist);
ATF_ADD_TEST_CASE(tp, nvlist_clone__nonempty_nvlist);
ATF_ADD_TEST_CASE(tp, nvlist_clone__nested_nvlist);
ATF_ADD_TEST_CASE(tp, nvlist_clone__error_nvlist);
ATF_ADD_TEST_CASE(tp, nvlist_pack__empty_nvlist);
ATF_ADD_TEST_CASE(tp, nvlist_pack__multiple_values);
ATF_ADD_TEST_CASE(tp, nvlist_pack__error_nvlist);
ATF_ADD_TEST_CASE(tp, nvlist_unpack__duplicate_key);
ATF_ADD_TEST_CASE(tp, nvlist_move_string__single_insert);