Re: [PATCH 19/21] multipath-tools tests: fix alias tests

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Sep 01, 2023 at 08:02:32PM +0200, mwilck@xxxxxxxx wrote:
> From: Martin Wilck <mwilck@xxxxxxxx>
> 
> The different implementation of get_user_friendly_alias() and its helpers
> necessitates changes in the unit tests. It would be nice if it didn't, but the
> unit tests are too closely bound to the implementation to make this possible.
> 
> - The bindings table is held in memory in alphabetically sorted order, which
>   may change the result of looking for free alias IDs if the entries in the
>   bindings file were unordered initially. In particular, if only a small
>   number of bindings exists, "holes" in the file will be detected more easily.
>   But because the sort order of the aliases differs from simple alphabetic
>   sorting ("mpathz" precedes "mpathaa"), a bindings file that contains all
>   bindings from "a" to "aa" (or more) will appear unsorted.
>   As an extra check, some of the unit tests deliberately use a different
>   implementation of add_binding() that does not order the bindings
>   table.
> 
> - Broken lines in the bindings file never make it to the in-memory
>   representation. An alias that appeard "used" because it occurred in a broken
>   line will not appear used any more. Warnings about malformed lines will only
>   be printed while the bindings file is read, not from get_user_friendly_alias().
> 
> - The match_line argument of mock_bindings_file() is obsolete.
> 
> - lookup_binding() and rlookup_binding() have been removed from
>   libmultipath. They are now emulated in the unit test code.
> 
> - lookup_binding() didn't check for used alias in all cases previously, but it does now.
> 
> - prefix != NULL and check_if_taken == false is not supported any more
>   in lookup_binding().
> 
> - allocate_binding() uses a very different sequence of systems calls now, as
>   it's implemented using update_bindings_file(). In particular, it's now more
>   difficult to predict the content of the write() call that creates the
>   bindings file. See comments for __wrap_write().
> 
> - some unit tests for get_user_friendly_alias() had to call
>   mock_bindings_file() twice, because the old implementation would read the
>   file twice (first rlookup_binding() and then lookup_binding()). This is not
>   necessary any more.
> 
> - The unit tests need a teardown function to clear the bindings table in memory.
> 
> - Minor changes are necessary because of changed ordering of the log messages.
>   Previously, lookup_binding() combined check for an existing entry and the
>   search for a new ID. The new algorithm does this in two separate steps and
>   tests for used aliases in between, which causes a change in the order in which
>   log messages are emitted.
> 

I'm still not sure that gufa_old_empty_used, gufa_old_match_used, and
gufa_old_nomatch_nowwidmatch_used are valid tests.

-Ben

> Signed-off-by: Martin Wilck <mwilck@xxxxxxxx>
> ---
>  tests/alias.c | 1013 +++++++++++++++++++++++++++++++------------------
>  1 file changed, 638 insertions(+), 375 deletions(-)
> 
> diff --git a/tests/alias.c b/tests/alias.c
> index a1415c6..4ac6425 100644
> --- a/tests/alias.c
> +++ b/tests/alias.c
> @@ -3,10 +3,12 @@
>  #include <setjmp.h>
>  #include <stdio.h>
>  #include <cmocka.h>
> +#include "strbuf.h"
>  #include "util.h"
>  #include "alias.h"
>  #include "test-log.h"
>  #include <errno.h>
> +#include <string.h>
>  
>  #include "globals.c"
>  #include "../libmultipath/alias.c"
> @@ -20,18 +22,6 @@
>  #define MPATH_ID_INT_MAX_p1 "fxshrxx"
>  #endif
>  
> -void __wrap_rewind(FILE *stream)
> -{}
> -
> -char *__wrap_fgets(char *buf, int n, FILE *stream)
> -{
> -	char *val = mock_ptr_type(char *);
> -	if (!val)
> -		return NULL;
> -	strlcpy(buf, val, n);
> -	return buf;
> -}
> -
>  static int __set_errno(int err)
>  {
>  	if (err >= 0) {
> @@ -43,25 +33,46 @@ static int __set_errno(int err)
>  	}
>  }
>  
> -off_t __wrap_lseek(int fd, off_t offset, int whence)
> -{
> -	return __set_errno(mock_type(int));
> -
> -}
> -
> +/*
> + * allocate_binding -> write_bindings_file() writes the entire file, i.e. the
> + * header, any pre-existing bindings, and the new binding. The complete content
> + * depends on history and is different to predict here. Therefore we check only
> + * the newly added binding. Because add_binding() sorts entries, this new
> + * binding isn't necessarily the last one; receive it from will_return() and
> + * search for it with strstr().
> + * If the string to be written doesn't start with the bindings file
> + * header, it's a test of a partial write.
> + */
>  ssize_t __wrap_write(int fd, const void *buf, size_t count)
>  {
> +	const char *binding, *start;
> +
> +#if DEBUG_WRITE
> +	fprintf(stderr, "%s: %zx exp %zx\n===\n%s\n===\n", __func__, strlen(buf),
> +		count, (const char *)buf);
> +#endif
> +	if (!strncmp((const char *)buf, BINDINGS_FILE_HEADER,
> +		     sizeof(BINDINGS_FILE_HEADER) - 1))
> +		start = (const char *)buf + sizeof(BINDINGS_FILE_HEADER) - 1;
> +	else
> +		start = buf;
> +	binding = mock_ptr_type(char *);
> +	start = strstr(start, binding);
>  	check_expected(count);
> -	check_expected(buf);
> +	assert_ptr_not_equal(start, NULL);
>  	return __set_errno(mock_type(int));
>  }
>  
> -int __wrap_ftruncate(int fd, off_t length)
> +int __wrap_rename(const char *old, const char *new)
>  {
> -	check_expected(length);
>  	return __set_errno(mock_type(int));
>  }
>  
> +int __wrap_mkstemp(char *template)
> +{
> +	return 10;
> +}
> +
>  int __wrap_dm_map_present(const char * str)
>  {
>  	check_expected(str);
> @@ -84,32 +95,6 @@ int __wrap_dm_get_uuid(const char *name, char *uuid, int uuid_len)
>  #define TEST_FDNO 1234
>  #define TEST_FPTR ((FILE *) 0xaffe)
>  
> -int __wrap_open_file(const char *file, int *can_write, const char *header)
> -{
> -	int cw = mock_type(int);
> -
> -        *can_write = cw;
> -	return TEST_FDNO;
> -}
> -
> -FILE *__wrap_fdopen(int fd, const char *mode)
> -{
> -	assert_int_equal(fd, TEST_FDNO);
> -	return TEST_FPTR;
> -}
> -
> -int __wrap_fflush(FILE *f)
> -{
> -	assert_ptr_equal(f, TEST_FPTR);
> -	return 0;
> -}
> -
> -int __wrap_fclose(FILE *f)
> -{
> -	assert_ptr_equal(f, TEST_FPTR);
> -	return 0;
> -}
> -
>  /* strbuf wrapper for the old format_devname() */
>  static int __format_devname(char *name, int id, size_t len, const char *prefix)
>  {
> @@ -466,22 +451,85 @@ static void mock_self_alias(const char *alias, const char *wwid)
>  		expect_condlog(3, USED_STR(alias, wwid));		\
>  	} while(0)
>  
> -static void mock_bindings_file(const char *content, int match_line)
> +static int add_binding_unsorted(Bindings *bindings,
> +				const char *alias, const char *wwid)
>  {
> -	static char cnt[1024];
> -	char *token;
> +	struct binding *bdg = calloc(1, sizeof(*bdg));
> +
> +	if (!bdg)
> +		return -1;
> +	bdg->wwid = strdup(wwid);
> +	bdg->alias = strdup(alias);
> +	if (!bdg->wwid || !bdg->alias || !vector_alloc_slot(bindings)) {
> +		free(bdg->alias);
> +		free(bdg->wwid);
> +		free(bdg);
> +		return BINDING_ERROR;
> +	}
> +	vector_set_slot(bindings, bdg);
> +	return BINDING_ADDED;
> +}
> +
> +static void __mock_bindings_file(const char *content,
> +				 int (*add)(Bindings *, const char *, const char *))
> +{
> +	char *cnt __attribute__((cleanup(cleanup_charp))) = NULL;
> +	char *token, *savep = NULL;
>  	int i;
>  
> -	assert_in_range(strlcpy(cnt, content, sizeof(cnt)), 0, sizeof(cnt) - 1);
> +	cnt = strdup(content);
> +	assert_ptr_not_equal(cnt, NULL);
>  
> -	for (token = strtok(cnt, "\n"), i = 0;
> +	for (token = strtok_r(cnt, "\n", &savep), i = 0;
>  	     token && *token;
> -	     token = strtok(NULL, "\n"), i++) {
> -		will_return(__wrap_fgets, token);
> -		if (match_line == i)
> -			return;
> +	     token = strtok_r(NULL, "\n", &savep), i++) {
> +		char *alias, *wwid;
> +		int rc;
> +
> +		if (read_binding(token, i + 1, &alias, &wwid)
> +		    == READ_BINDING_SKIP)
> +			continue;
> +
> +		rc = add(&global_bindings, alias, wwid);
> +		assert_int_equal(rc, BINDING_ADDED);
>  	}
> -	will_return(__wrap_fgets, NULL);
> +}
> +
> +static void mock_bindings_file(const char *content) {
> +	return __mock_bindings_file(content, add_binding);
> +}
> +
> +static void mock_bindings_file_unsorted(const char *content) {
> +	return __mock_bindings_file(content, add_binding_unsorted);
> +}
> +
> +static int teardown_bindings(void **state)
> +{
> +	cleanup_bindings();
> +	return 0;
> +}
> +
> +static int lookup_binding(FILE *dummy, const char *wwid, char **alias,
> +			  const char *prefix, int check_if_taken)
> +{
> +	const struct binding *bdg;
> +	int id;
> +
> +	/*
> +	 * get_free_id() always checks if aliases are taken.
> +	 * Therefore if prefix is non-null, check_if_taken must be true.
> +	 */
> +	assert_true(!prefix || check_if_taken);
> +	*alias = NULL;
> +	bdg = get_binding_for_wwid(&global_bindings, wwid);
> +	if (bdg) {
> +		*alias = strdup(bdg->alias);
> +		return 0;
> +	} else if (!prefix && check_if_taken)
> +		return -1;
> +
> +	id = get_free_id(&global_bindings, prefix, wwid);
> +	return id;
>  }
>  
>  static void lb_empty(void **state)
> @@ -489,7 +537,7 @@ static void lb_empty(void **state)
>  	int rc;
>  	char *alias;
>  
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  	rc = lookup_binding(NULL, "WWID0", &alias, NULL, 0);
>  	assert_int_equal(rc, 1);
> @@ -501,7 +549,7 @@ static void lb_empty_unused(void **state)
>  	int rc;
>  	char *alias;
>  
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
>  	mock_unused_alias("MPATHa");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
> @@ -515,10 +563,10 @@ static void lb_empty_failed(void **state)
>  	int rc;
>  	char *alias;
>  
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  	mock_failed_alias("MPATHa", "WWID0");
>  	mock_unused_alias("MPATHb");
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 2);
>  	assert_ptr_equal(alias, NULL);
> @@ -530,10 +578,10 @@ static void lb_empty_1_used(void **state)
>  	int rc;
>  	char *alias;
>  
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  	mock_used_alias("MPATHa", "WWID0");
>  	mock_unused_alias("MPATHb");
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 2);
>  	assert_ptr_equal(alias, NULL);
> @@ -545,10 +593,10 @@ static void lb_empty_1_used_self(void **state)
>  	int rc;
>  	char *alias;
>  
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  	mock_used_alias("MPATHa", "WWID0");
>  	mock_self_alias("MPATHb", "WWID0");
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 2);
>  	assert_ptr_equal(alias, NULL);
> @@ -560,9 +608,9 @@ static void lb_match_a(void **state)
>  	int rc;
>  	char *alias;
>  
> -	mock_bindings_file("MPATHa WWID0\n", 0);
> +	mock_bindings_file("MPATHa WWID0\n");
>  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
> -	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 0);
> +	rc = lookup_binding(NULL, "WWID0", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 0);
>  	assert_ptr_not_equal(alias, NULL);
>  	assert_string_equal(alias, "MPATHa");
> @@ -574,9 +622,10 @@ static void lb_nomatch_a(void **state)
>  	int rc;
>  	char *alias;
>  
> -	mock_bindings_file("MPATHa WWID0\n", -1);
> +	mock_bindings_file("MPATHa WWID0\n");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
> -	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 0);
> +	mock_unused_alias("MPATHb");
> +	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 2);
>  	assert_ptr_equal(alias, NULL);
>  }
> @@ -586,8 +635,8 @@ static void lb_nomatch_a_bad_check(void **state)
>  	int rc;
>  	char *alias;
>  
> -	mock_bindings_file("MPATHa WWID0\n", -1);
> -	expect_condlog(0, NOMORE_STR);
> +	mock_bindings_file("MPATHa WWID0\n");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
>  	rc = lookup_binding(NULL, "WWID1", &alias, NULL, 1);
>  	assert_int_equal(rc, -1);
>  	assert_ptr_equal(alias, NULL);
> @@ -598,7 +647,7 @@ static void lb_nomatch_a_unused(void **state)
>  	int rc;
>  	char *alias;
>  
> -	mock_bindings_file("MPATHa WWID0\n", -1);
> +	mock_bindings_file("MPATHa WWID0\n");
>  	mock_unused_alias("MPATHb");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
>  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1);
> @@ -611,27 +660,27 @@ static void lb_nomatch_a_3_used_failed_self(void **state)
>  	int rc;
>  	char *alias;
>  
> -	mock_bindings_file("MPATHa WWID0\n", -1);
> +	mock_bindings_file("MPATHa WWID0\n");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
>  	mock_used_alias("MPATHb", "WWID1");
>  	mock_used_alias("MPATHc", "WWID1");
>  	mock_used_alias("MPATHd", "WWID1");
>  	mock_failed_alias("MPATHe", "WWID1");
>  	mock_self_alias("MPATHf", "WWID1");
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
>  	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 6);
>  	assert_ptr_equal(alias, NULL);
>  }
>  
> -static void do_lb_match_c(void **state, int check_if_taken)
> +static void do_lb_match_c(void **state)
>  {
>  	int rc;
>  	char *alias;
>  
>  	mock_bindings_file("MPATHa WWID0\n"
> -			   "MPATHc WWID1", 1);
> +			   "MPATHc WWID1");
>  	expect_condlog(3, FOUND_STR("MPATHc", "WWID1"));
> -	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", check_if_taken);
> +	rc = lookup_binding(NULL, "WWID1", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 0);
>  	assert_ptr_not_equal(alias, NULL);
>  	assert_string_equal(alias, "MPATHc");
> @@ -640,12 +689,12 @@ static void do_lb_match_c(void **state, int check_if_taken)
>  
>  static void lb_match_c(void **state)
>  {
> -	do_lb_match_c(state, 0);
> +	do_lb_match_c(state);
>  }
>  
>  static void lb_match_c_check(void **state)
>  {
> -	do_lb_match_c(state, 1);
> +	do_lb_match_c(state);
>  }
>  
>  static void lb_nomatch_a_c(void **state)
> @@ -654,9 +703,10 @@ static void lb_nomatch_a_c(void **state)
>  	char *alias;
>  
>  	mock_bindings_file("MPATHa WWID0\n"
> -			   "MPATHc WWID1", -1);
> +			   "MPATHc WWID1");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
> +	mock_unused_alias("MPATHb");
> +	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 2);
>  	assert_ptr_equal(alias, NULL);
>  }
> @@ -667,7 +717,7 @@ static void lb_nomatch_a_d_unused(void **state)
>  	char *alias;
>  
>  	mock_bindings_file("MPATHa WWID0\n"
> -			   "MPATHd WWID1", -1);
> +			   "MPATHd WWID1");
>  	mock_unused_alias("MPATHb");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
>  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> @@ -681,10 +731,10 @@ static void lb_nomatch_a_d_1_used(void **state)
>  	char *alias;
>  
>  	mock_bindings_file("MPATHa WWID0\n"
> -			   "MPATHd WWID1", -1);
> +			   "MPATHd WWID1");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
>  	mock_used_alias("MPATHb", "WWID2");
>  	mock_unused_alias("MPATHc");
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
>  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 3);
>  	assert_ptr_equal(alias, NULL);
> @@ -696,11 +746,11 @@ static void lb_nomatch_a_d_2_used(void **state)
>  	char *alias;
>  
>  	mock_bindings_file("MPATHa WWID0\n"
> -			   "MPATHd WWID1", -1);
> +			   "MPATHd WWID1");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
>  	mock_used_alias("MPATHb", "WWID2");
>  	mock_used_alias("MPATHc", "WWID2");
>  	mock_unused_alias("MPATHe");
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
>  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 5);
>  	assert_ptr_equal(alias, NULL);
> @@ -712,12 +762,12 @@ static void lb_nomatch_a_d_3_used(void **state)
>  	char *alias;
>  
>  	mock_bindings_file("MPATHa WWID0\n"
> -			   "MPATHd WWID1", -1);
> +			   "MPATHd WWID1");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
>  	mock_used_alias("MPATHb", "WWID2");
>  	mock_used_alias("MPATHc", "WWID2");
>  	mock_used_alias("MPATHe", "WWID2");
>  	mock_unused_alias("MPATHf");
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
>  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 6);
>  	assert_ptr_equal(alias, NULL);
> @@ -729,9 +779,10 @@ static void lb_nomatch_c_a(void **state)
>  	char *alias;
>  
>  	mock_bindings_file("MPATHc WWID1\n"
> -			   "MPATHa WWID0\n", -1);
> +			   "MPATHa WWID0\n");
> +	mock_unused_alias("MPATHb");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
> +	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 2);
>  	assert_ptr_equal(alias, NULL);
>  }
> @@ -743,7 +794,7 @@ static void lb_nomatch_d_a_unused(void **state)
>  
>  	mock_bindings_file("MPATHc WWID1\n"
>  			   "MPATHa WWID0\n"
> -			   "MPATHd WWID0\n", -1);
> +			   "MPATHd WWID0\n");
>  	mock_unused_alias("MPATHb");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
>  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> @@ -758,10 +809,10 @@ static void lb_nomatch_d_a_1_used(void **state)
>  
>  	mock_bindings_file("MPATHc WWID1\n"
>  			   "MPATHa WWID0\n"
> -			   "MPATHd WWID0\n", -1);
> +			   "MPATHd WWID0\n");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
>  	mock_used_alias("MPATHb", "WWID2");
>  	mock_unused_alias("MPATHe");
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
>  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 5);
>  	assert_ptr_equal(alias, NULL);
> @@ -774,9 +825,10 @@ static void lb_nomatch_a_b(void **state)
>  
>  	mock_bindings_file("MPATHa WWID0\n"
>  			   "MPATHz WWID26\n"
> -			   "MPATHb WWID1\n", -1);
> +			   "MPATHb WWID1\n");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
> +	mock_unused_alias("MPATHc");
> +	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 3);
>  	assert_ptr_equal(alias, NULL);
>  }
> @@ -786,13 +838,19 @@ static void lb_nomatch_a_b_bad(void **state)
>  	int rc;
>  	char *alias;
>  
> +	expect_condlog(1, "invalid line 3 in bindings file, missing WWID\n");
> +	/*
> +	 * The broken line will be ignored when constructing the bindings vector.
> +	 * Thus in lookup_binding() MPATHb is never encountered,
> +	 * and MPATHb appears usable.
> +	 */
>  	mock_bindings_file("MPATHa WWID0\n"
>  			   "MPATHz WWID26\n"
> -			   "MPATHb\n", -1);
> -	expect_condlog(3, "Ignoring malformed line 3 in bindings file\n");
> +			   "MPATHb\n");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
> -	assert_int_equal(rc, 3);
> +	mock_unused_alias("MPATHb");
> +	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> +	assert_int_equal(rc, 2);
>  	assert_ptr_equal(alias, NULL);
>  }
>  
> @@ -801,28 +859,140 @@ static void lb_nomatch_a_b_bad_self(void **state)
>  	int rc;
>  	char *alias;
>  
> +	expect_condlog(1, "invalid line 3 in bindings file, missing WWID\n");
>  	mock_bindings_file("MPATHa WWID0\n"
>  			   "MPATHz WWID26\n"
> -			   "MPATHb\n", -1);
> -	expect_condlog(3, "Ignoring malformed line 3 in bindings file\n");
> -	mock_self_alias("MPATHc", "WWID2");
> +			   "MPATHb\n");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> +	mock_self_alias("MPATHb", "WWID2");
> +	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> +	assert_int_equal(rc, 2);
> +	assert_ptr_equal(alias, NULL);
> +}
> +
> +static void lb_nomatch_b_z_a(void **state)
> +{
> +	int rc;
> +	char *alias;
> +
> +	/*
> +	 * add_bindings() sorts alphabetically. Therefore get_free_id()
> +	 * finds MPATHc as a free entry.
> +	 */
> +	mock_bindings_file("MPATHb WWID1\n"
> +			   "MPATHz WWID26\n"
> +			   "MPATHa WWID0\n");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> +	mock_unused_alias("MPATHc");
>  	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
>  	assert_int_equal(rc, 3);
>  	assert_ptr_equal(alias, NULL);
>  }
>  
> +static void lb_nomatch_b_aa_a(void **state)
> +{
> +	int rc;
> +	char *alias;
> +
> +	/*
> +	 * add_bindings() sorts alphabetically. ("a", "aa", b").
> +	 * The get_free_id() algorithm finds the "hole" after "b".
> +	 */
> +	mock_bindings_file("MPATHb WWID1\n"
> +			   "MPATHz WWID26\n"
> +			   "MPATHa WWID0\n");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> +	mock_unused_alias("MPATHc");
> +	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> +	assert_int_equal(rc, 3);
> +	assert_ptr_equal(alias, NULL);
> +}
> +
> +static void fill_bindings(struct strbuf *buf, int start, int end)
> +{
> +	int i;
> +
> +	for (i = start; i <= end; i++) {
> +		print_strbuf(buf,  "MPATH");
> +		format_devname(buf, i + 1);
> +		print_strbuf(buf,  " WWID%d\n", i);
> +	}
> +}
> +
> +static void lb_nomatch_b_a_aa(void **state)
> +{
> +	int rc;
> +	char *alias;
> +	STRBUF_ON_STACK(buf);
> +
> +	/*
> +	 * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...)
> +	 * lookup_binding finds MPATHac as next free entry.
> +	 */
> +	fill_bindings(&buf, 0, 26);
> +	mock_bindings_file(get_strbuf_str(&buf));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID28"));
> +	mock_unused_alias("MPATHab");
> +	rc = lookup_binding(NULL, "WWID28", &alias, "MPATH", 1);
> +	assert_int_equal(rc, 28);
> +	assert_ptr_equal(alias, NULL);
> +}
> +
> +static void lb_nomatch_b_a_aa_zz(void **state)
> +{
> +	int rc;
> +	char *alias;
> +	STRBUF_ON_STACK(buf);
> +
> +	/*
> +	 * add_bindings() sorts alphabetically. ("a", "aa", "ab", "b", "c", ...)
> +	 * lookup_binding finds MPATHaaa as next free entry, because MPATHaa is
> +	 * found before MPATHb, and MPATHzz was in the bindings, too.
> +	 */
> +	for (i = 0; i <= 26; i++) {
> +		print_strbuf(&buf,  "MPATH");
> +		format_devname(&buf, i + 1);
> +		print_strbuf(&buf,  " WWID%d\n", i);
> +	}
> +	print_strbuf(&buf, "MPATHzz WWID676\n");
> +	mock_bindings_file(get_strbuf_str(&buf));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID703"));
> +	mock_unused_alias("MPATHaaa");
> +	rc = lookup_binding(NULL, "WWID703", &alias, "MPATH", 1);
> +	assert_int_equal(rc, 703);
> +	assert_ptr_equal(alias, NULL);
> +}
> +
> +static void lb_nomatch_b_z_a_unsorted(void **state)
> +{
> +	int rc;
> +	char *alias;
> +
> +	/*
> +	 * With unsorted bindings (shouldn't happen normally), get_free_id()
> +	 * plays safe and returns MPATHaa as first free entry.
> +	 */
> +	mock_bindings_file_unsorted("MPATHb WWID1\n"
> +				    "MPATHz WWID26\n"
> +				    "MPATHa WWID0\n");
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> +	mock_unused_alias("MPATHaa");
> +	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> +	assert_int_equal(rc, 27);
> +	assert_ptr_equal(alias, NULL);
> +}
> +
>  static void lb_nomatch_b_a(void **state)
>  {
>  	int rc;
>  	char *alias;
>  
>  	mock_bindings_file("MPATHb WWID1\n"
> -			   "MPATHz WWID26\n"
> -			   "MPATHa WWID0\n", -1);
> +			   "MPATHa WWID0\n");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
> -	assert_int_equal(rc, 27);
> +	mock_unused_alias("MPATHc");
> +	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> +	assert_int_equal(rc, 3);
>  	assert_ptr_equal(alias, NULL);
>  }
>  
> @@ -830,55 +1000,59 @@ static void lb_nomatch_b_a_3_used(void **state)
>  {
>  	int rc;
>  	char *alias;
> +	STRBUF_ON_STACK(buf);
>  
> -	mock_bindings_file("MPATHb WWID1\n"
> -			   "MPATHz WWID26\n"
> -			   "MPATHa WWID0\n", -1);
> -	mock_used_alias("MPATHaa", "WWID2");
> -	mock_used_alias("MPATHab", "WWID2");
> -	mock_used_alias("MPATHac", "WWID2");
> -	mock_unused_alias("MPATHad");
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> -	assert_int_equal(rc, 30);
> +	fill_bindings(&buf, 0, 26);
> +	mock_bindings_file(get_strbuf_str(&buf));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID31"));
> +	mock_used_alias("MPATHab", "WWID31");
> +	mock_used_alias("MPATHac", "WWID31");
> +	mock_used_alias("MPATHad", "WWID31");
> +	mock_unused_alias("MPATHae");
> +	rc = lookup_binding(NULL, "WWID31", &alias, "MPATH", 1);
> +	assert_int_equal(rc, 31);
>  	assert_ptr_equal(alias, NULL);
>  }
>  
>  #ifdef MPATH_ID_INT_MAX
> -static void do_lb_nomatch_int_max(void **state, int check_if_taken)
> +/*
> + * The bindings will be sorted by alias, alphabetically, which is not
> + * the same as the "numeric" sort order for user-friendly aliases.
> + * get_free_id() selects the highest used ID + 1 if an unsorted entry
> + * is encountered in the bindings table and it's id is equal to the
> + * next "expected" id. This happens if all IDs from "a" to "aa" are
> + * in the table. If the INT_MAX entry is in the table, too, it will
> + * overflow.
> + */
> +static void lb_nomatch_int_max(void **state)
>  {
>  	int rc;
>  	char *alias;
> +	STRBUF_ON_STACK(buf);
>  
> -	mock_bindings_file("MPATHb WWID1\n"
> -			   "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n"
> -			   "MPATHa WWID0\n", -1);
> +	fill_bindings(&buf, 0, 26);
> +	print_strbuf(&buf, "MPATH%s WWIDMAX\n", MPATH_ID_INT_MAX);
> +	mock_bindings_file(get_strbuf_str(&buf));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE"));
>  	expect_condlog(0, NOMORE_STR);
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", check_if_taken);
> +	rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1);
>  	assert_int_equal(rc, -1);
>  	assert_ptr_equal(alias, NULL);
>  }
>  
> -static void lb_nomatch_int_max(void **state)
> -{
> -	do_lb_nomatch_int_max(state, 0);
> -}
> -
> -static void lb_nomatch_int_max_check(void **state)
> -{
> -	do_lb_nomatch_int_max(state, 1);
> -}
> -
>  static void lb_nomatch_int_max_used(void **state)
>  {
>  	int rc;
>  	char *alias;
> +	STRBUF_ON_STACK(buf);
>  
> -	mock_bindings_file("MPATHb WWID1\n"
> -			   "MPATH" MPATH_ID_INT_MAX " WWIDMAX\n", -1);
> -	mock_used_alias("MPATHa", "WWID2");
> +	fill_bindings(&buf, 1, 26);
> +	print_strbuf(&buf, "MPATH%s WWIDMAX\n", MPATH_ID_INT_MAX);
> +	mock_bindings_file(get_strbuf_str(&buf));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWIDNOMORE"));
> +	mock_used_alias("MPATHa", "WWIDNOMORE");
>  	expect_condlog(0, NOMORE_STR);
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> +	rc = lookup_binding(NULL, "WWIDNOMORE", &alias, "MPATH", 1);
>  	assert_int_equal(rc, -1);
>  	assert_ptr_equal(alias, NULL);
>  }
> @@ -887,12 +1061,14 @@ static void lb_nomatch_int_max_m1(void **state)
>  {
>  	int rc;
>  	char *alias;
> +	STRBUF_ON_STACK(buf);
>  
> -	mock_bindings_file("MPATHb WWID1\n"
> -			   "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"
> -			   "MPATHa WWID0\n", -1);
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 0);
> +	fill_bindings(&buf, 0, 26);
> +	print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1);
> +	mock_bindings_file(get_strbuf_str(&buf));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX"));
> +	mock_unused_alias("MPATH" MPATH_ID_INT_MAX);
> +	rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1);
>  	assert_int_equal(rc, INT_MAX);
>  	assert_ptr_equal(alias, NULL);
>  }
> @@ -901,13 +1077,15 @@ static void lb_nomatch_int_max_m1_used(void **state)
>  {
>  	int rc;
>  	char *alias;
> +	STRBUF_ON_STACK(buf);
>  
> -	mock_bindings_file("MPATHb WWID1\n"
> -			   "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n"
> -			   "MPATHa WWID0\n", -1);
> -	mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2");
> +	fill_bindings(&buf, 0, 26);
> +	print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1);
> +	mock_bindings_file(get_strbuf_str(&buf));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX"));
> +	mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX");
>  	expect_condlog(0, NOMORE_STR);
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> +	rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1);
>  	assert_int_equal(rc, -1);
>  	assert_ptr_equal(alias, NULL);
>  }
> @@ -916,13 +1094,15 @@ static void lb_nomatch_int_max_m1_1_used(void **state)
>  {
>  	int rc;
>  	char *alias;
> +	STRBUF_ON_STACK(buf);
>  
> -	mock_bindings_file("MPATHb WWID1\n"
> -			   "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1);
> -	mock_used_alias("MPATHa", "WWID2");
> +	fill_bindings(&buf, 1, 26);
> +	print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1);
> +	mock_bindings_file(get_strbuf_str(&buf));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX"));
> +	mock_used_alias("MPATHa", "WWIDMAX");
>  	mock_unused_alias("MPATH" MPATH_ID_INT_MAX);
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID2"));
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> +	rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1);
>  	assert_int_equal(rc, INT_MAX);
>  	assert_ptr_equal(alias, NULL);
>  }
> @@ -931,13 +1111,17 @@ static void lb_nomatch_int_max_m1_2_used(void **state)
>  {
>  	int rc;
>  	char *alias;
> +	STRBUF_ON_STACK(buf);
>  
> -	mock_bindings_file("MPATHb WWID1\n"
> -			   "MPATH" MPATH_ID_INT_MAX_m1 " WWIDMAX\n", -1);
> -	mock_used_alias("MPATHa", "WWID2");
> -	mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWID2");
> +	fill_bindings(&buf, 1, 26);
> +	print_strbuf(&buf, "MPATH%s WWIDMAXM1\n", MPATH_ID_INT_MAX_m1);
> +	mock_bindings_file(get_strbuf_str(&buf));
> +
> +	expect_condlog(3, NOMATCH_WWID_STR("WWIDMAX"));
> +	mock_used_alias("MPATHa", "WWIDMAX");
> +	mock_used_alias("MPATH" MPATH_ID_INT_MAX, "WWIDMAX");
>  	expect_condlog(0, NOMORE_STR);
> -	rc = lookup_binding(NULL, "WWID2", &alias, "MPATH", 1);
> +	rc = lookup_binding(NULL, "WWIDMAX", &alias, "MPATH", 1);
>  	assert_int_equal(rc, -1);
>  	assert_ptr_equal(alias, NULL);
>  }
> @@ -946,52 +1130,68 @@ static void lb_nomatch_int_max_m1_2_used(void **state)
>  static int test_lookup_binding(void)
>  {
>  	const struct CMUnitTest tests[] = {
> -		cmocka_unit_test(lb_empty),
> -		cmocka_unit_test(lb_empty_unused),
> -		cmocka_unit_test(lb_empty_failed),
> -		cmocka_unit_test(lb_empty_1_used),
> -		cmocka_unit_test(lb_empty_1_used_self),
> -		cmocka_unit_test(lb_match_a),
> -		cmocka_unit_test(lb_nomatch_a),
> -		cmocka_unit_test(lb_nomatch_a_bad_check),
> -		cmocka_unit_test(lb_nomatch_a_unused),
> -		cmocka_unit_test(lb_nomatch_a_3_used_failed_self),
> -		cmocka_unit_test(lb_match_c),
> -		cmocka_unit_test(lb_match_c_check),
> -		cmocka_unit_test(lb_nomatch_a_c),
> -		cmocka_unit_test(lb_nomatch_a_d_unused),
> -		cmocka_unit_test(lb_nomatch_a_d_1_used),
> -		cmocka_unit_test(lb_nomatch_a_d_2_used),
> -		cmocka_unit_test(lb_nomatch_a_d_3_used),
> -		cmocka_unit_test(lb_nomatch_c_a),
> -		cmocka_unit_test(lb_nomatch_d_a_unused),
> -		cmocka_unit_test(lb_nomatch_d_a_1_used),
> -		cmocka_unit_test(lb_nomatch_a_b),
> -		cmocka_unit_test(lb_nomatch_a_b_bad),
> -		cmocka_unit_test(lb_nomatch_a_b_bad_self),
> -		cmocka_unit_test(lb_nomatch_b_a),
> -		cmocka_unit_test(lb_nomatch_b_a_3_used),
> +		cmocka_unit_test_teardown(lb_empty, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_empty_unused, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_empty_failed, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_empty_1_used, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_empty_1_used_self, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_match_a, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_bad_check, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_unused, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_3_used_failed_self, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_match_c, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_match_c_check, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_c, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_d_unused, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_d_1_used, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_d_2_used, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_d_3_used, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_c_a, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_d_a_unused, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_d_a_1_used, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_b, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_b_bad, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_a_b_bad_self, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_b_z_a, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_b_aa_a, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_b_a_aa, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_b_a_aa_zz, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_b_z_a_unsorted, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_b_a, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_b_a_3_used, teardown_bindings),
>  #ifdef MPATH_ID_INT_MAX
> -		cmocka_unit_test(lb_nomatch_int_max),
> -		cmocka_unit_test(lb_nomatch_int_max_check),
> -		cmocka_unit_test(lb_nomatch_int_max_used),
> -		cmocka_unit_test(lb_nomatch_int_max_m1),
> -		cmocka_unit_test(lb_nomatch_int_max_m1_used),
> -		cmocka_unit_test(lb_nomatch_int_max_m1_1_used),
> -		cmocka_unit_test(lb_nomatch_int_max_m1_2_used),
> +		cmocka_unit_test_teardown(lb_nomatch_int_max, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_int_max_used, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_int_max_m1, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_int_max_m1_used, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_int_max_m1_1_used, teardown_bindings),
> +		cmocka_unit_test_teardown(lb_nomatch_int_max_m1_2_used, teardown_bindings),
>  #endif
>  	};
>  
>  	return cmocka_run_group_tests(tests, NULL, NULL);
>  }
>  
> +static int rlookup_binding(FILE *dummy, char *buf, const char *alias) {
> +
> +	const struct binding *bdg;
> +
> +	bdg = get_binding_for_alias(&global_bindings, alias);
> +	if (!bdg) {
> +		return -1;
> +	}
> +	strlcpy(buf, bdg->wwid, WWID_SIZE);
> +	return 0;
> +}
> +
>  static void rl_empty(void **state)
>  {
>  	int rc;
>  	char buf[WWID_SIZE];
>  
>  	buf[0] = '\0';
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
>  	expect_condlog(3, NOMATCH_STR("MPATHa"));
>  	rc = rlookup_binding(NULL, buf, "MPATHa");
>  	assert_int_equal(rc, -1);
> @@ -1004,7 +1204,7 @@ static void rl_match_a(void **state)
>  	char buf[WWID_SIZE];
>  
>  	buf[0] = '\0';
> -	mock_bindings_file("MPATHa WWID0\n", 0);
> +	mock_bindings_file("MPATHa WWID0\n");
>  	expect_condlog(3, FOUND_ALIAS_STR("MPATHa", "WWID0"));
>  	rc = rlookup_binding(NULL, buf, "MPATHa");
>  	assert_int_equal(rc, 0);
> @@ -1017,7 +1217,7 @@ static void rl_nomatch_a(void **state)
>  	char buf[WWID_SIZE];
>  
>  	buf[0] = '\0';
> -	mock_bindings_file("MPATHa WWID0\n", -1);
> +	mock_bindings_file("MPATHa WWID0\n");
>  	expect_condlog(3, NOMATCH_STR("MPATHb"));
>  	rc = rlookup_binding(NULL, buf, "MPATHb");
>  	assert_int_equal(rc, -1);
> @@ -1030,8 +1230,8 @@ static void rl_malformed_a(void **state)
>  	char buf[WWID_SIZE];
>  
>  	buf[0] = '\0';
> -	mock_bindings_file("MPATHa     \n", -1);
> -	expect_condlog(3, "Ignoring malformed line 1 in bindings file\n");
> +	expect_condlog(1, "invalid line 1 in bindings file, missing WWID\n");
> +	mock_bindings_file("MPATHa     \n");
>  	expect_condlog(3, NOMATCH_STR("MPATHa"));
>  	rc = rlookup_binding(NULL, buf, "MPATHa");
>  	assert_int_equal(rc, -1);
> @@ -1049,8 +1249,8 @@ static void rl_overlong_a(void **state)
>  	snprintf(line + sizeof(line) - 2, 2, "\n");
>  
>  	buf[0] = '\0';
> -	mock_bindings_file(line, -1);
>  	expect_condlog(3, "Ignoring too large wwid at 1 in bindings file\n");
> +	mock_bindings_file(line);
>  	expect_condlog(3, NOMATCH_STR("MPATHa"));
>  	rc = rlookup_binding(NULL, buf, "MPATHa");
>  	assert_int_equal(rc, -1);
> @@ -1065,7 +1265,7 @@ static void rl_match_b(void **state)
>  	buf[0] = '\0';
>  	mock_bindings_file("MPATHa WWID0\n"
>  			   "MPATHz WWID26\n"
> -			   "MPATHb WWID2\n", 2);
> +			   "MPATHb WWID2\n");
>  	expect_condlog(3, FOUND_ALIAS_STR("MPATHb", "WWID2"));
>  	rc = rlookup_binding(NULL, buf, "MPATHb");
>  	assert_int_equal(rc, 0);
> @@ -1075,31 +1275,41 @@ static void rl_match_b(void **state)
>  static int test_rlookup_binding(void)
>  {
>  	const struct CMUnitTest tests[] = {
> -		cmocka_unit_test(rl_empty),
> -		cmocka_unit_test(rl_match_a),
> -		cmocka_unit_test(rl_nomatch_a),
> -		cmocka_unit_test(rl_malformed_a),
> -		cmocka_unit_test(rl_overlong_a),
> -		cmocka_unit_test(rl_match_b),
> +		cmocka_unit_test_teardown(rl_empty, teardown_bindings),
> +		cmocka_unit_test_teardown(rl_match_a, teardown_bindings),
> +		cmocka_unit_test_teardown(rl_nomatch_a, teardown_bindings),
> +		cmocka_unit_test_teardown(rl_malformed_a, teardown_bindings),
> +		cmocka_unit_test_teardown(rl_overlong_a, teardown_bindings),
> +		cmocka_unit_test_teardown(rl_match_b, teardown_bindings),
>  	};
>  
>  	return cmocka_run_group_tests(tests, NULL, NULL);
>  }
>  
> +void check_bindings_size(int n)
> +{
> +	/* avoid -Waddress problem */
> +	Bindings *bindings = &global_bindings;
> +
> +	assert_int_equal(VECTOR_SIZE(bindings), n);
> +}
> +
>  static void al_a(void **state)
>  {
>  	static const char ln[] = "MPATHa WWIDa\n";
>  	char *alias;
>  
> -	will_return(__wrap_lseek, 0);
> -	expect_value(__wrap_write, count, strlen(ln));
> -	expect_string(__wrap_write, buf, ln);
> -	will_return(__wrap_write, strlen(ln));
> +	expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
> +	will_return(__wrap_write, ln);
> +	will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
> +	will_return(__wrap_rename, 0);
> +	expect_condlog(1, "updated bindings file foo");
>  	expect_condlog(3, NEW_STR("MPATHa", "WWIDa"));
>  
> -	alias = allocate_binding(0, "WWIDa", 1, "MPATH");
> +	alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
>  	assert_ptr_not_equal(alias, NULL);
>  	assert_string_equal(alias, "MPATHa");
> +	check_bindings_size(1);
>  	free(alias);
>  }
>  
> @@ -1108,15 +1318,17 @@ static void al_zz(void **state)
>  	static const char ln[] = "MPATHzz WWIDzz\n";
>  	char *alias;
>  
> -	will_return(__wrap_lseek, 0);
> -	expect_value(__wrap_write, count, strlen(ln));
> -	expect_string(__wrap_write, buf, ln);
> -	will_return(__wrap_write, strlen(ln));
> +	expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
> +	will_return(__wrap_write, ln);
> +	will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
> +	will_return(__wrap_rename, 0);
> +	expect_condlog(1, "updated bindings file foo");
>  	expect_condlog(3, NEW_STR("MPATHzz", "WWIDzz"));
>  
> -	alias = allocate_binding(0, "WWIDzz", 26*26 + 26, "MPATH");
> +	alias = allocate_binding("foo", "WWIDzz", 26*26 + 26, "MPATH");
>  	assert_ptr_not_equal(alias, NULL);
>  	assert_string_equal(alias, "MPATHzz");
> +	check_bindings_size(1);
>  	free(alias);
>  }
>  
> @@ -1127,6 +1339,7 @@ static void al_0(void **state)
>  	expect_condlog(0, "allocate_binding: cannot allocate new binding for id 0\n");
>  	alias = allocate_binding(0, "WWIDa", 0, "MPATH");
>  	assert_ptr_equal(alias, NULL);
> +	check_bindings_size(0);
>  }
>  
>  static void al_m2(void **state)
> @@ -1136,71 +1349,137 @@ static void al_m2(void **state)
>  	expect_condlog(0, "allocate_binding: cannot allocate new binding for id -2\n");
>  	alias = allocate_binding(0, "WWIDa", -2, "MPATH");
>  	assert_ptr_equal(alias, NULL);
> +	check_bindings_size(0);
>  }
>  
> -static void al_lseek_err(void **state)
> +static void al_write_partial(void **state)
>  {
> +	static const char ln[] = "MPATHa WWIDa\n";
>  	char *alias;
>  
> -	will_return(__wrap_lseek, -ENODEV);
> -	expect_condlog(0, "Cannot seek to end of bindings file : No such device\n");
> -	alias = allocate_binding(0, "WWIDa", 1, "MPATH");
> +	expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
> +	will_return(__wrap_write, ln);
> +	will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln) - 1);
> +	expect_value(__wrap_write, count, 1);
> +	will_return(__wrap_write, ln + sizeof(ln) - 2);
> +	will_return(__wrap_write, 1);
> +	will_return(__wrap_rename, 0);
> +	expect_condlog(1, "updated bindings file foo");
> +	expect_condlog(3, "Created new binding [MPATHa] for WWID [WWIDa]\n");
> +
> +	alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
> +	assert_ptr_not_equal(alias, NULL);
> +	assert_string_equal(alias, "MPATHa");
> +	check_bindings_size(1);
> +	free(alias);
> +}
> +
> +static void al_write_short(void **state)
> +{
> +	static const char ln[] = "MPATHa WWIDa\n";
> +	char *alias;
> +
> +	expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
> +	will_return(__wrap_write, ln);
> +	will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln) - 1);
> +	expect_value(__wrap_write, count, 1);
> +	will_return(__wrap_write, ln + sizeof(ln) - 2);
> +	will_return(__wrap_write, 0);
> +	expect_condlog(2, "write_bindings_file: short write");
> +	expect_condlog(1, "failed to write new bindings file");
> +	expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa");
> +
> +	alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
>  	assert_ptr_equal(alias, NULL);
> +	check_bindings_size(0);
>  }
>  
>  static void al_write_err(void **state)
>  {
>  	static const char ln[] = "MPATHa WWIDa\n";
> -	const int offset = 20;
>  	char *alias;
>  
> -	will_return(__wrap_lseek, offset);
> -	expect_value(__wrap_write, count, strlen(ln));
> -	expect_string(__wrap_write, buf, ln);
> -	will_return(__wrap_write, strlen(ln) - 1);
> -	expect_value(__wrap_ftruncate, length, offset);
> -	will_return(__wrap_ftruncate, 0);
> -	expect_condlog(0, "Cannot write binding to bindings file :");
> +	expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
> +	will_return(__wrap_write, ln);
> +	will_return(__wrap_write, -EPERM);
> +	expect_condlog(1, "failed to write new bindings file");
> +	expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa");
>  
> -	alias = allocate_binding(0, "WWIDa", 1, "MPATH");
> +	alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
>  	assert_ptr_equal(alias, NULL);
> +	check_bindings_size(0);
> +}
> +
> +static void al_rename_err(void **state)
> +{
> +	static const char ln[] = "MPATHa WWIDa\n";
> +	char *alias;
> +
> +	expect_value(__wrap_write, count, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
> +	will_return(__wrap_write, ln);
> +	will_return(__wrap_write, strlen(BINDINGS_FILE_HEADER) + strlen(ln));
> +	will_return(__wrap_rename, -EROFS);
> +
> +	expect_condlog(0, "update_bindings_file: rename: Read-only file system");
> +	expect_condlog(1, "allocate_binding: deleting binding MPATHa for WWIDa");
> +	alias = allocate_binding("foo", "WWIDa", 1, "MPATH");
> +	assert_ptr_equal(alias, NULL);
> +	check_bindings_size(0);
>  }
>  
>  static int test_allocate_binding(void)
>  {
>  	const struct CMUnitTest tests[] = {
> -		cmocka_unit_test(al_a),
> -		cmocka_unit_test(al_zz),
> -		cmocka_unit_test(al_0),
> -		cmocka_unit_test(al_m2),
> -		cmocka_unit_test(al_lseek_err),
> -		cmocka_unit_test(al_write_err),
> +		cmocka_unit_test_teardown(al_a, teardown_bindings),
> +		cmocka_unit_test_teardown(al_zz, teardown_bindings),
> +		cmocka_unit_test_teardown(al_0, teardown_bindings),
> +		cmocka_unit_test_teardown(al_m2, teardown_bindings),
> +		cmocka_unit_test_teardown(al_write_partial, teardown_bindings),
> +		cmocka_unit_test_teardown(al_write_short, teardown_bindings),
> +		cmocka_unit_test_teardown(al_write_err, teardown_bindings),
> +		cmocka_unit_test_teardown(al_rename_err, teardown_bindings),
>  	};
>  
>  	return cmocka_run_group_tests(tests, NULL, NULL);
>  }
>  
> -#define mock_allocate_binding(alias, wwid)				\
> +#define mock_allocate_binding_err_len(alias, wwid, len, err, msg)	\
>  	do {								\
>  		static const char ln[] = BINDING_STR(alias, wwid);	\
>  									\
> -		will_return(__wrap_lseek, 0);				\
> -		expect_value(__wrap_write, count, strlen(ln));		\
> -		expect_string(__wrap_write, buf, ln);			\
> -		will_return(__wrap_write, strlen(ln));			\
> -		expect_condlog(3, NEW_STR(alias, wwid));		\
> +		expect_value(__wrap_write, count,			\
> +			     strlen(BINDINGS_FILE_HEADER) + (len) + strlen(ln)); \
> +		will_return(__wrap_write, ln);				\
> +		will_return(__wrap_write,				\
> +			    strlen(BINDINGS_FILE_HEADER) + (len) + strlen(ln)); \
> +		will_return(__wrap_rename, err);			\
> +		if (err == 0) {						\
> +			expect_condlog(1, "updated bindings file x\n");	\
> +			expect_condlog(3, NEW_STR(alias, wwid));	\
> +		} else {						\
> +			expect_condlog(0, "update_bindings_file: rename: " msg "\n"); \
> +			expect_condlog(1, "allocate_binding: deleting binding "	\
> +				       alias " for " wwid "\n");	\
> +		}							\
>  	} while (0)
>  
> +#define mock_allocate_binding_err(alias, wwid, err, msg)	\
> +	mock_allocate_binding_err_len(alias, wwid, 0, err, msg)
> +
> +#define mock_allocate_binding(alias, wwid)			\
> +	mock_allocate_binding_err(alias, wwid, 0, "")
> +
> +#define mock_allocate_binding_len(alias, wwid, len)			\
> +	mock_allocate_binding_err_len(alias, wwid, len, 0, "")
> +
>  static void gufa_empty_new_rw(void **state) {
>  	char *alias;
>  
> -	will_return(__wrap_open_file, true);
> -
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
>  	mock_unused_alias("MPATHa");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
> -
>  	mock_allocate_binding("MPATHa", "WWID0");
> +
>  	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
>  	assert_string_equal(alias, "MPATHa");
>  	free(alias);
> @@ -1208,10 +1487,11 @@ static void gufa_empty_new_rw(void **state) {
>  
>  static void gufa_empty_new_ro_1(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, false);
> -	mock_bindings_file("", -1);
> +
> +	mock_bindings_file("");
>  	mock_unused_alias("MPATHa");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
> +	mock_allocate_binding_err("MPATHa", "WWID0", -EROFS, "Read-only file system");
>  
>  	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
>  	assert_ptr_equal(alias, NULL);
> @@ -1220,11 +1500,9 @@ static void gufa_empty_new_ro_1(void **state) {
>  static void gufa_empty_new_ro_2(void **state) {
>  	char *alias;
>  
> -	will_return(__wrap_open_file, true);
> -
> -	mock_bindings_file("", -1);
> -	mock_unused_alias("MPATHa");
> +	mock_bindings_file("");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
> +	mock_unused_alias("MPATHa");
>  
>  	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
>  	assert_ptr_equal(alias, NULL);
> @@ -1233,11 +1511,10 @@ static void gufa_empty_new_ro_2(void **state) {
>  static void gufa_match_a_unused(void **state) {
>  	char *alias;
>  
> -	will_return(__wrap_open_file, true);
> -
> -	mock_bindings_file("MPATHa WWID0", 0);
> +	mock_bindings_file("MPATHa WWID0");
>  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
>  	mock_unused_alias("MPATHa");
> +	expect_condlog(3, EXISTING_STR("MPATHa", "WWID0"));
>  
>  	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
>  	assert_string_equal(alias, "MPATHa");
> @@ -1247,11 +1524,10 @@ static void gufa_match_a_unused(void **state) {
>  static void gufa_match_a_self(void **state) {
>  	char *alias;
>  
> -	will_return(__wrap_open_file, true);
> -
> -	mock_bindings_file("MPATHa WWID0", 0);
> +	mock_bindings_file("MPATHa WWID0");
>  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
>  	mock_self_alias("MPATHa", "WWID0");
> +	expect_condlog(3, EXISTING_STR("MPATHa", "WWID0"));
>  
>  	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", true);
>  	assert_string_equal(alias, "MPATHa");
> @@ -1261,9 +1537,8 @@ static void gufa_match_a_self(void **state) {
>  static void gufa_match_a_used(void **state) {
>  	char *alias;
>  
> -	will_return(__wrap_open_file, true);
>  
> -	mock_bindings_file("MPATHa WWID0", 0);
> +	mock_bindings_file("MPATHa WWID0");
>  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
>  	mock_used_alias("MPATHa", "WWID0");
>  
> @@ -1273,15 +1548,14 @@ static void gufa_match_a_used(void **state) {
>  
>  static void gufa_nomatch_a_c(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
> +	static const char bindings[] = ("MPATHa WWID0\n"
> +					"MPATHc WWID2\n");
>  
> -	mock_bindings_file("MPATHa WWID0\n"
> -			   "MPATHc WWID2",
> -			   -1);
> +	mock_bindings_file(bindings);
>  	mock_unused_alias("MPATHb");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
>  
> -	mock_allocate_binding("MPATHb", "WWID1");
> +	mock_allocate_binding_len("MPATHb", "WWID1", strlen(bindings));
>  
>  	alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false);
>  	assert_string_equal(alias, "MPATHb");
> @@ -1290,15 +1564,14 @@ static void gufa_nomatch_a_c(void **state) {
>  
>  static void gufa_nomatch_c_a(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
> +	const char bindings[] = ("MPATHc WWID2\n"
> +				 "MPATHa WWID0\n");
>  
> -	mock_bindings_file("MPATHc WWID2\n"
> -			   "MPATHa WWID0",
> -			   -1);
> +	mock_bindings_file(bindings);
>  	mock_unused_alias("MPATHb");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID1"));
>  
> -	mock_allocate_binding("MPATHb", "WWID1");
> +	mock_allocate_binding_len("MPATHb", "WWID1", sizeof(bindings) - 1);
>  
>  	alias = get_user_friendly_alias("WWID1", "x", "", "MPATH", false);
>  	assert_string_equal(alias, "MPATHb");
> @@ -1307,15 +1580,14 @@ static void gufa_nomatch_c_a(void **state) {
>  
>  static void gufa_nomatch_c_b(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
> +	const char bindings[] = ("MPATHc WWID2\n"
> +				 "MPATHb WWID1\n");
>  
> -	mock_bindings_file("MPATHc WWID2\n"
> -			   "MPATHb WWID1\n",
> -			   -1);
> -	mock_unused_alias("MPATHa");
> +	mock_bindings_file(bindings);
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
> +	mock_unused_alias("MPATHa");
>  
> -	mock_allocate_binding("MPATHa", "WWID0");
> +	mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1);
>  
>  	alias = get_user_friendly_alias("WWID0", "x", "", "MPATH", false);
>  	assert_string_equal(alias, "MPATHa");
> @@ -1324,16 +1596,15 @@ static void gufa_nomatch_c_b(void **state) {
>  
>  static void gufa_nomatch_c_b_used(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
> +	const char bindings[] = ("MPATHc WWID2\n"
> +				 "MPATHb WWID1\n");
>  
> -	mock_bindings_file("MPATHc WWID2\n"
> -			   "MPATHb WWID1",
> -			   -1);
> -	mock_used_alias("MPATHa", "WWID4");
> +	mock_bindings_file(bindings);
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID4"));
> +	mock_used_alias("MPATHa", "WWID4");
>  	mock_unused_alias("MPATHd");
>  
> -	mock_allocate_binding("MPATHd", "WWID4");
> +	mock_allocate_binding_len("MPATHd", "WWID4", sizeof(bindings) - 1);
>  
>  	alias = get_user_friendly_alias("WWID4", "x", "", "MPATH", false);
>  	assert_string_equal(alias, "MPATHd");
> @@ -1342,34 +1613,60 @@ static void gufa_nomatch_c_b_used(void **state) {
>  
>  static void gufa_nomatch_b_f_a(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
> +	const char bindings[] = ("MPATHb WWID1\n"
> +				 "MPATHf WWID6\n"
> +				 "MPATHa WWID0\n");
>  
> -	mock_bindings_file("MPATHb WWID1\n"
> -			   "MPATHf WWID6\n"
> -			   "MPATHa WWID0\n",
> -			   -1);
> +	mock_bindings_file_unsorted(bindings);
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID7"));
>  	mock_unused_alias("MPATHg");
>  
> -	mock_allocate_binding("MPATHg", "WWID7");
> +	mock_allocate_binding_len("MPATHg", "WWID7", sizeof(bindings) - 1);
>  
>  	alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false);
>  	assert_string_equal(alias, "MPATHg");
>  	free(alias);
>  }
>  
> +static void gufa_nomatch_b_aa_a(void **state) {
> +	char *alias;
> +	STRBUF_ON_STACK(buf);
> +
> +	fill_bindings(&buf, 0, 26);
> +	mock_bindings_file(get_strbuf_str(&buf));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID28"));
> +	mock_unused_alias("MPATHab");
> +	mock_allocate_binding_len("MPATHab", "WWID28", get_strbuf_len(&buf));
> +
> +	alias = get_user_friendly_alias("WWID28", "x", "", "MPATH", false);
> +	assert_string_equal(alias, "MPATHab");
> +	free(alias);
> +}
> +
> +static void gufa_nomatch_b_f_a_sorted(void **state) {
> +	char *alias;
> +	const char bindings[] = ("MPATHb WWID1\n"
> +				 "MPATHf WWID6\n"
> +				 "MPATHa WWID0\n");
> +
> +	mock_bindings_file(bindings);
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID7"));
> +	mock_unused_alias("MPATHc");
> +
> +	mock_allocate_binding_len("MPATHc", "WWID7", sizeof(bindings) - 1);
> +
> +	alias = get_user_friendly_alias("WWID7", "x", "", "MPATH", false);
> +	assert_string_equal(alias, "MPATHc");
> +	free(alias);
> +}
> +
>  static void gufa_old_empty(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
>  
>  	/* rlookup_binding for ALIAS */
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
>  	expect_condlog(3, NOMATCH_STR("MPATHz"));
> -
> -	/* lookup_binding */
> -	mock_bindings_file("", -1);
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
> -
>  	mock_unused_alias("MPATHz");
>  
>  	mock_allocate_binding("MPATHz", "WWID0");
> @@ -1382,12 +1679,11 @@ static void gufa_old_empty(void **state) {
>  
>  static void gufa_old_empty_self(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
>  
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
>  	expect_condlog(3, NOMATCH_STR("MPATHz"));
>  
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  	mock_self_alias("MPATHz", "WWID0");
>  
> @@ -1401,15 +1697,14 @@ static void gufa_old_empty_self(void **state) {
>  
>  static void gufa_old_empty_used(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
>  
> -	mock_bindings_file("", -1);
> +	mock_bindings_file("");
>  	expect_condlog(3, NOMATCH_STR("MPATHz"));
>  
> -	mock_bindings_file("", -1);
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
> +	mock_bindings_file("");
>  	mock_used_alias("MPATHz", "WWID0");
>  	expect_condlog(0, ERR_STR("MPATHz", "WWID0"));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  
>  	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
>  	assert_ptr_equal(alias, NULL);
> @@ -1417,11 +1712,9 @@ static void gufa_old_empty_used(void **state) {
>  
>  static void gufa_old_match(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
>  
>  	mock_bindings_file("MPATHb WWID1\n"
> -			   "MPATHz WWID0",
> -			   1);
> +			   "MPATHz WWID0");
>  	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0"));
>  	mock_unused_alias("MPATHz");
>  
> @@ -1432,9 +1725,8 @@ static void gufa_old_match(void **state) {
>  
>  static void gufa_old_match_self(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
>  
> -	mock_bindings_file("MPATHz WWID0", 0);
> +	mock_bindings_file("MPATHz WWID0");
>  	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0"));
>  	mock_self_alias("MPATHz", "WWID0");
>  
> @@ -1445,9 +1737,8 @@ static void gufa_old_match_self(void **state) {
>  
>  static void gufa_old_match_used(void **state) {
>  	char *alias;
> -	will_return(__wrap_open_file, true);
>  
> -	mock_bindings_file("MPATHz WWID0", 0);
> +	mock_bindings_file("MPATHz WWID0");
>  	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID0"));
>  	mock_used_alias("MPATHz", "WWID0");
>  	expect_condlog(0, ERR_STR("MPATHz", "WWID0"));
> @@ -1458,19 +1749,15 @@ static void gufa_old_match_used(void **state) {
>  
>  static void gufa_old_match_other(void **state) {
>  	char *alias;
> -	static const char bindings[] = "MPATHz WWID9";
> +	static const char bindings[] = "MPATHz WWID9\n";
>  
> -	will_return(__wrap_open_file, true);
> -
> -	mock_bindings_file(bindings, 0);
> +	mock_bindings_file(bindings);
>  	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
>  	expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
> -
> -	mock_bindings_file(bindings, -1);
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  	mock_unused_alias("MPATHa");
>  
> -	mock_allocate_binding("MPATHa", "WWID0");
> +	mock_allocate_binding_len("MPATHa", "WWID0", sizeof(bindings) - 1);
>  
>  	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
>  	assert_string_equal(alias, "MPATHa");
> @@ -1479,21 +1766,16 @@ static void gufa_old_match_other(void **state) {
>  
>  static void gufa_old_match_other_used(void **state) {
>  	char *alias;
> -	static const char bindings[] = "MPATHz WWID9";
> +	static const char bindings[] = "MPATHz WWID9\n";
>  
> -	will_return(__wrap_open_file, true);
> -
> -	mock_bindings_file(bindings, 0);
> +	mock_bindings_file(bindings);
>  	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
>  	expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
> -
> -	mock_bindings_file(bindings, -1);
> -	mock_used_alias("MPATHa", "WWID0");
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
> +	mock_used_alias("MPATHa", "WWID0");
>  	mock_unused_alias("MPATHb");
>  
> -	mock_allocate_binding("MPATHb", "WWID0");
> -
> +	mock_allocate_binding_len("MPATHb", "WWID0", sizeof(bindings) - 1);
>  	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
>  	assert_string_equal(alias, "MPATHb");
>  	free(alias);
> @@ -1503,15 +1785,13 @@ static void gufa_old_match_other_wwidmatch(void **state) {
>  	char *alias;
>  	static const char bindings[] = ("MPATHz WWID9\n"
>  					"MPATHc WWID2");
> -	will_return(__wrap_open_file, true);
>  
> -	mock_bindings_file(bindings, 0);
> +	mock_bindings_file(bindings);
>  	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
>  	expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
> -
> -	mock_bindings_file(bindings, 1);
>  	expect_condlog(3, FOUND_STR("MPATHc", "WWID2"));
>  	mock_unused_alias("MPATHc");
> +	expect_condlog(3, EXISTING_STR("MPATHc", "WWID2"));
>  
>  	alias = get_user_friendly_alias("WWID2", "x", "MPATHz", "MPATH", false);
>  	assert_string_equal(alias, "MPATHc");
> @@ -1523,13 +1803,9 @@ static void gufa_old_match_other_wwidmatch_used(void **state) {
>  	static const char bindings[] = ("MPATHz WWID9\n"
>  					"MPATHc WWID2");
>  
> -	will_return(__wrap_open_file, true);
> -
> -	mock_bindings_file(bindings, 0);
> +	mock_bindings_file(bindings);
>  	expect_condlog(3, FOUND_ALIAS_STR("MPATHz", "WWID9"));
>  	expect_condlog(0, REUSE_STR("MPATHz", "WWID9"));
> -
> -	mock_bindings_file(bindings, 1);
>  	expect_condlog(3, FOUND_STR("MPATHc", "WWID2"));
>  	mock_used_alias("MPATHc", "WWID2");
>  
> @@ -1541,12 +1817,9 @@ static void gufa_old_nomatch_wwidmatch(void **state) {
>  	char *alias;
>  	static const char bindings[] = "MPATHa WWID0";
>  
> -	will_return(__wrap_open_file, true);
> -
> -	mock_bindings_file(bindings, -1);
> +	mock_bindings_file(bindings);
> +	mock_unused_alias("MPATHz");
>  	expect_condlog(3, NOMATCH_STR("MPATHz"));
> -
> -	mock_bindings_file(bindings, 0);
>  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
>  	mock_unused_alias("MPATHa");
>  	expect_condlog(3, EXISTING_STR("MPATHa", "WWID0"));
> @@ -1559,12 +1832,10 @@ static void gufa_old_nomatch_wwidmatch(void **state) {
>  static void gufa_old_nomatch_wwidmatch_used(void **state) {
>  	char *alias;
>  	static const char bindings[] = "MPATHa WWID0";
> -	will_return(__wrap_open_file, true);
>  
> -	mock_bindings_file(bindings, -1);
> +	mock_bindings_file(bindings);
> +	mock_unused_alias("MPATHz");
>  	expect_condlog(3, NOMATCH_STR("MPATHz"));
> -
> -	mock_bindings_file(bindings, 0);
>  	expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
>  	mock_used_alias("MPATHa", "WWID0");
>  
> @@ -1574,19 +1845,14 @@ static void gufa_old_nomatch_wwidmatch_used(void **state) {
>  
>  static void gufa_old_nomatch_nowwidmatch(void **state) {
>  	char *alias;
> -	static const char bindings[] = "MPATHb WWID1";
> +	static const char bindings[] = "MPATHb WWID1\n";
>  
> -	will_return(__wrap_open_file, true);
> -
> -	mock_bindings_file(bindings, -1);
> +	mock_bindings_file(bindings);
>  	expect_condlog(3, NOMATCH_STR("MPATHz"));
> -
> -	mock_bindings_file(bindings, -1);
>  	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
> -
>  	mock_unused_alias("MPATHz");
>  
> -	mock_allocate_binding("MPATHz", "WWID0");
> +	mock_allocate_binding_len("MPATHz", "WWID0", sizeof(bindings) - 1);
>  	expect_condlog(2, ALLOC_STR("MPATHz", "WWID0"));
>  
>  	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
> @@ -1598,16 +1864,12 @@ static void gufa_old_nomatch_nowwidmatch_used(void **state) {
>  	char *alias;
>  	static const char bindings[] = "MPATHb WWID1";
>  
> -	will_return(__wrap_open_file, true);
> -
> -	mock_bindings_file(bindings, -1);
> +	mock_bindings_file(bindings);
>  	expect_condlog(3, NOMATCH_STR("MPATHz"));
>  
> -	mock_bindings_file(bindings, -1);
> -	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
> -
>  	mock_used_alias("MPATHz", "WWID0");
>  	expect_condlog(0, ERR_STR("MPATHz", "WWID0"));
> +	expect_condlog(3, NOMATCH_WWID_STR("WWID0"));
>  
>  	alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
>  	assert_ptr_equal(alias, NULL);
> @@ -1616,31 +1878,33 @@ static void gufa_old_nomatch_nowwidmatch_used(void **state) {
>  static int test_get_user_friendly_alias()
>  {
>  	const struct CMUnitTest tests[] = {
> -		cmocka_unit_test(gufa_empty_new_rw),
> -		cmocka_unit_test(gufa_empty_new_ro_1),
> -		cmocka_unit_test(gufa_empty_new_ro_2),
> -		cmocka_unit_test(gufa_match_a_unused),
> -		cmocka_unit_test(gufa_match_a_self),
> -		cmocka_unit_test(gufa_match_a_used),
> -		cmocka_unit_test(gufa_nomatch_a_c),
> -		cmocka_unit_test(gufa_nomatch_c_a),
> -		cmocka_unit_test(gufa_nomatch_c_b),
> -		cmocka_unit_test(gufa_nomatch_c_b_used),
> -		cmocka_unit_test(gufa_nomatch_b_f_a),
> -		cmocka_unit_test(gufa_old_empty),
> -		cmocka_unit_test(gufa_old_empty_self),
> -		cmocka_unit_test(gufa_old_empty_used),
> -		cmocka_unit_test(gufa_old_match),
> -		cmocka_unit_test(gufa_old_match_self),
> -		cmocka_unit_test(gufa_old_match_used),
> -		cmocka_unit_test(gufa_old_match_other),
> -		cmocka_unit_test(gufa_old_match_other_used),
> -		cmocka_unit_test(gufa_old_match_other_wwidmatch),
> -		cmocka_unit_test(gufa_old_match_other_wwidmatch_used),
> -		cmocka_unit_test(gufa_old_nomatch_wwidmatch),
> -		cmocka_unit_test(gufa_old_nomatch_wwidmatch_used),
> -		cmocka_unit_test(gufa_old_nomatch_nowwidmatch),
> -		cmocka_unit_test(gufa_old_nomatch_nowwidmatch_used),
> +		cmocka_unit_test_teardown(gufa_empty_new_rw, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_empty_new_ro_1, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_empty_new_ro_2, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_match_a_unused, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_match_a_self, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_match_a_used, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_nomatch_a_c, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_nomatch_c_a, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_nomatch_c_b, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_nomatch_c_b_used, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_nomatch_b_f_a, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_nomatch_b_aa_a, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_nomatch_b_f_a_sorted, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_empty, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_empty_self, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_empty_used, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_match, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_match_self, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_match_used, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_match_other, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_match_other_used, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_match_other_wwidmatch, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_match_other_wwidmatch_used, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_nomatch_wwidmatch_used, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_nomatch_nowwidmatch, teardown_bindings),
> +		cmocka_unit_test_teardown(gufa_old_nomatch_nowwidmatch_used, teardown_bindings),
>  	};
>  
>  	return cmocka_run_group_tests(tests, NULL, NULL);
> @@ -1656,7 +1920,6 @@ int main(void)
>  	ret += test_lookup_binding();
>  	ret += test_rlookup_binding();
>  	ret += test_allocate_binding();
> -	ret += test_allocate_binding();
>  	ret += test_get_user_friendly_alias();
>  
>  	return ret;
> -- 
> 2.41.0
--
dm-devel mailing list
dm-devel@xxxxxxxxxx
https://listman.redhat.com/mailman/listinfo/dm-devel




[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux