On Mon, Sep 11, 2023 at 06:38:28PM +0200, mwi...@suse.com wrote:
> From: Martin Wilck <mwi...@suse.com>
> 
> 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.
> 
Reviewed-by: Benjamin Marzinski <bmarz...@redhat.com>
> Signed-off-by: Martin Wilck <mwi...@suse.com>
> ---
>  tests/alias.c | 971 ++++++++++++++++++++++++++++++++------------------
>  1 file changed, 621 insertions(+), 350 deletions(-)
> 
> diff --git a/tests/alias.c b/tests/alias.c
> index f334f92..50a21ec 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, i;
> +     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,67 +1349,133 @@ 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"));
>  
> @@ -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,32 +1613,59 @@ 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_allocate_binding("MPATHz", "WWID0");
> @@ -1380,11 +1678,9 @@ static void gufa_old_empty(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"));
>  
>       alias = get_user_friendly_alias("WWID0", "x", "MPATHz", "MPATH", false);
> @@ -1394,19 +1690,15 @@ static void gufa_old_match(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");
> @@ -1415,21 +1707,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);
> @@ -1439,15 +1726,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");
> @@ -1459,13 +1744,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");
>  
> @@ -1477,12 +1758,8 @@ 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);
>       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"));
> @@ -1495,12 +1772,9 @@ 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);
>       expect_condlog(3, NOMATCH_STR("MPATHz"));
> -
> -     mock_bindings_file(bindings, 0);
>       expect_condlog(3, FOUND_STR("MPATHa", "WWID0"));
>       mock_used_alias("MPATHa", "WWID0");
>  
> @@ -1510,17 +1784,13 @@ 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_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);
> @@ -1531,26 +1801,28 @@ static void gufa_old_nomatch_nowwidmatch(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_match),
> -             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_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_match, 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),
>       };
>  
>       return cmocka_run_group_tests(tests, NULL, NULL);
> @@ -1566,7 +1838,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.42.0
--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel

Reply via email to