tests/hwtable: add test for broken hwentry filtering
[multipath-tools/.git] / tests / hwtable.c
1 /* Set BROKEN to 1 to treat broken behavior as success */
2 #define BROKEN 1
3 #define VERBOSITY 2
4
5 #include <stdbool.h>
6 #include <stdarg.h>
7 #include <stddef.h>
8 #include <setjmp.h>
9 #include <stdlib.h>
10 #include <cmocka.h>
11 #include <libudev.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <errno.h>
17 #include <limits.h>
18 #include <sys/sysmacros.h>
19 #include "structs.h"
20 #include "structs_vec.h"
21 #include "config.h"
22 #include "debug.h"
23 #include "defaults.h"
24 #include "pgpolicies.h"
25 #include "test-lib.h"
26 #include "print.h"
27
28 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
29 #define N_CONF_FILES 2
30
31 static const char tmplate[] = "/tmp/hwtable-XXXXXX";
32 /* pretend new dm, use minio_rq */
33 static const unsigned int dm_tgt_version[3] = { 1, 1, 1 };
34
35 struct key_value {
36         const char *key;
37         const char *value;
38 };
39
40 struct hwt_state {
41         char *tmpname;
42         char *dirname;
43         FILE *config_file;
44         FILE *conf_dir_file[N_CONF_FILES];
45         struct vectors *vecs;
46         void (*test)(const struct hwt_state *);
47         const char *test_name;
48 };
49
50 #define SET_TEST_FUNC(hwt, func) do {           \
51                 hwt->test = func;               \
52                 hwt->test_name = #func;         \
53         } while (0)
54
55 static struct config *_conf;
56 struct udev *udev;
57 int logsink;
58
59 struct config *get_multipath_config(void)
60 {
61         return _conf;
62 }
63
64 void put_multipath_config(void *arg)
65 {}
66
67 void make_config_file_path(char *buf, int buflen,
68                           const struct hwt_state *hwt, int i)
69 {
70         static const char fn_template[] = "%s/test-%02d.conf";
71
72         if (i == -1)
73                 /* main config file */
74                 snprintf(buf, buflen, fn_template, hwt->tmpname, 0);
75         else
76                 snprintf(buf, buflen, fn_template, hwt->dirname, i);
77 }
78
79 static void reset_vecs(struct vectors *vecs)
80 {
81         remove_maps(vecs);
82         free_pathvec(vecs->pathvec, FREE_PATHS);
83
84         vecs->pathvec = vector_alloc();
85         assert_ptr_not_equal(vecs->pathvec, NULL);
86         vecs->mpvec = vector_alloc();
87         assert_ptr_not_equal(vecs->mpvec, NULL);
88 }
89
90 static void free_hwt(struct hwt_state *hwt)
91 {
92         char buf[PATH_MAX];
93         int i;
94
95         if (hwt->config_file != NULL)
96                 fclose(hwt->config_file);
97         for (i = 0; i < N_CONF_FILES; i++) {
98                 if (hwt->conf_dir_file[i] != NULL)
99                         fclose(hwt->conf_dir_file[i]);
100         }
101
102         if (hwt->tmpname != NULL) {
103                 make_config_file_path(buf, sizeof(buf), hwt, -1);
104                 unlink(buf);
105                 rmdir(hwt->tmpname);
106                 free(hwt->tmpname);
107         }
108
109         if (hwt->dirname != NULL) {
110                 for (i = 0; i < N_CONF_FILES; i++) {
111                         make_config_file_path(buf, sizeof(buf), hwt, i);
112                         unlink(buf);
113                 }
114                 rmdir(hwt->dirname);
115                 free(hwt->dirname);
116         }
117
118         if (hwt->vecs != NULL) {
119                 if (hwt->vecs->mpvec != NULL)
120                         remove_maps(hwt->vecs);
121                 if (hwt->vecs->pathvec != NULL)
122                         free_pathvec(hwt->vecs->pathvec, FREE_PATHS);
123                 pthread_mutex_destroy(&hwt->vecs->lock.mutex);
124                 free(hwt->vecs);
125         }
126         free(hwt);
127 }
128
129 static int setup(void **state)
130 {
131         struct hwt_state *hwt;
132         char buf[PATH_MAX];
133         int i;
134
135         *state = NULL;
136         hwt = calloc(1, sizeof(*hwt));
137         if (hwt == NULL)
138                 return -1;
139
140         snprintf(buf, sizeof(buf), "%s", tmplate);
141         if (mkdtemp(buf) == NULL) {
142                 condlog(0, "mkdtemp: %s", strerror(errno));
143                 goto err;
144         }
145         hwt->tmpname = strdup(buf);
146
147         snprintf(buf, sizeof(buf), "%s", tmplate);
148         if (mkdtemp(buf) == NULL) {
149                 condlog(0, "mkdtemp (2): %s", strerror(errno));
150                 goto err;
151         }
152         hwt->dirname = strdup(buf);
153
154         make_config_file_path(buf, sizeof(buf), hwt, -1);
155         hwt->config_file = fopen(buf, "w+");
156         if (hwt->config_file == NULL)
157                 goto err;
158
159         for (i = 0; i < N_CONF_FILES; i++) {
160                 make_config_file_path(buf, sizeof(buf), hwt, i);
161                 hwt->conf_dir_file[i] = fopen(buf, "w+");
162                 if (hwt->conf_dir_file[i] == NULL)
163                         goto err;
164         }
165
166         hwt->vecs = calloc(1, sizeof(*hwt->vecs));
167         if (hwt->vecs == NULL)
168                 goto err;
169         pthread_mutex_init(&hwt->vecs->lock.mutex, NULL);
170         hwt->vecs->pathvec = vector_alloc();
171         hwt->vecs->mpvec = vector_alloc();
172         if (hwt->vecs->pathvec == NULL || hwt->vecs->mpvec == NULL)
173                 goto err;
174
175         *state = hwt;
176         return 0;
177
178 err:
179         free_hwt(hwt);
180         return -1;
181 }
182
183 static int teardown(void **state)
184 {
185         if (state == NULL || *state == NULL)
186                 return -1;
187
188         free_hwt(*state);
189         *state = NULL;
190
191         return 0;
192 }
193
194 /*
195  * Helpers for creating the config file(s)
196  */
197
198 static void reset_config(FILE *ff)
199 {
200         if (ff == NULL)
201                 return;
202         rewind(ff);
203         if (ftruncate(fileno(ff), 0) == -1)
204                 condlog(1, "ftruncate: %s", strerror(errno));
205 }
206
207 static void reset_configs(const struct hwt_state *hwt)
208 {
209         int i;
210
211         reset_config(hwt->config_file);
212         for (i = 0; i < N_CONF_FILES; i++)
213                 reset_config(hwt->conf_dir_file[i]);
214 }
215
216 static void write_key_values(FILE *ff, int nkv, const struct key_value *kv)
217 {
218         int i;
219
220         for (i = 0; i < nkv; i++) {
221                 if (strchr(kv[i].value, ' ') == NULL &&
222                     strchr(kv[i].value, '\"') == NULL)
223                         fprintf(ff, "\t%s %s\n", kv[i].key, kv[i].value);
224                 else
225                         fprintf(ff, "\t%s \"%s\"\n", kv[i].key, kv[i].value);
226         }
227 }
228
229 static void begin_section(FILE *ff, const char *section)
230 {
231         fprintf(ff, "%s {\n", section);
232 }
233
234 static void end_section(FILE *ff)
235 {
236         fprintf(ff, "}\n");
237 }
238
239 static void write_section(FILE *ff, const char *section,
240                           int nkv, const struct key_value *kv)
241 {
242         begin_section(ff, section);
243         write_key_values(ff, nkv, kv);
244         end_section(ff);
245 }
246
247 static void write_defaults(const struct hwt_state *hwt)
248 {
249         static const char bindings_name[] = "bindings";
250         static struct key_value defaults[] = {
251                 { "config_dir", NULL },
252                 { "bindings_file", NULL },
253                 { "detect_prio", "no" },
254                 { "detect_checker", "no" },
255         };
256         char buf[sizeof(tmplate) + sizeof(bindings_name)];
257
258         snprintf(buf, sizeof(buf), "%s/%s", hwt->tmpname, bindings_name);
259         defaults[0].value = hwt->dirname;
260         defaults[1].value = buf;
261         write_section(hwt->config_file, "defaults",
262                       ARRAY_SIZE(defaults), defaults);
263 }
264
265 static void begin_config(const struct hwt_state *hwt)
266 {
267         reset_configs(hwt);
268         write_defaults(hwt);
269 }
270
271 static void begin_section_all(const struct hwt_state *hwt, const char *section)
272 {
273         int i;
274
275         begin_section(hwt->config_file, section);
276         for (i = 0; i < N_CONF_FILES; i++)
277                 begin_section(hwt->conf_dir_file[i], section);
278 }
279
280 static void end_section_all(const struct hwt_state *hwt)
281 {
282         int i;
283
284         end_section(hwt->config_file);
285         for (i = 0; i < N_CONF_FILES; i++)
286                 end_section(hwt->conf_dir_file[i]);
287 }
288
289 static void finish_config(const struct hwt_state *hwt)
290 {
291         int i;
292
293         fflush(hwt->config_file);
294         for (i = 0; i < N_CONF_FILES; i++) {
295                 fflush(hwt->conf_dir_file[i]);
296         }
297 }
298
299 static void write_device(FILE *ff, int nkv, const struct key_value *kv)
300 {
301         write_section(ff, "device", nkv, kv);
302 }
303
304 /*
305  * Some macros to avoid boilerplace code
306  */
307
308 #define CHECK_STATE(state) ({ \
309         assert_ptr_not_equal(state, NULL); \
310         assert_ptr_not_equal(*(state), NULL);   \
311         *state; })
312
313 #define WRITE_EMPTY_CONF(hwt) do {                              \
314                 begin_config(hwt);                              \
315                 finish_config(hwt);                             \
316         } while (0)
317
318 #define WRITE_ONE_DEVICE(hwt, kv) do {                                  \
319                 begin_config(hwt);                                      \
320                 begin_section_all(hwt, "devices");                      \
321                 write_device(hwt->config_file, ARRAY_SIZE(kv), kv);     \
322                 end_section_all(hwt);                                   \
323                 finish_config(hwt);                                     \
324         } while (0)
325
326 #define WRITE_TWO_DEVICES(hwt, kv1, kv2) do {                           \
327                 begin_config(hwt);                                      \
328                 begin_section_all(hwt, "devices");                      \
329                 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);   \
330                 write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2);   \
331                 end_section_all(hwt);                                   \
332                 finish_config(hwt);                                     \
333         } while (0)
334
335 #define WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2) do {                     \
336                 begin_config(hwt);                                      \
337                 begin_section_all(hwt, "devices");                      \
338                 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);   \
339                 write_device(hwt->conf_dir_file[0],                     \
340                              ARRAY_SIZE(kv2), kv2);                     \
341                 end_section_all(hwt);                                   \
342                 finish_config(hwt);                                     \
343         } while (0)
344
345 #define LOAD_CONFIG(hwt) ({ \
346         char buf[PATH_MAX];        \
347         struct config *__cf;                                            \
348                                                                         \
349         make_config_file_path(buf, sizeof(buf), hwt, -1);               \
350         __cf = load_config(buf);                                        \
351         assert_ptr_not_equal(__cf, NULL);                               \
352         assert_ptr_not_equal(__cf->hwtable, NULL);                      \
353         __cf->verbosity = VERBOSITY;                                    \
354         memcpy(&__cf->version, dm_tgt_version, sizeof(__cf->version));  \
355         __cf; })
356
357 #define FREE_CONFIG(conf) do {                  \
358                 free_config(conf);              \
359                 conf = NULL;                    \
360         } while (0)
361
362 static void replace_config(const struct hwt_state *hwt,
363                            const char *conf_str)
364 {
365         FREE_CONFIG(_conf);
366         reset_configs(hwt);
367         fprintf(hwt->config_file, "%s", conf_str);
368         fflush(hwt->config_file);
369         _conf = LOAD_CONFIG(hwt);
370 }
371
372 #define TEST_PROP(prop, val) do {                               \
373                 if (val == NULL)                                \
374                         assert_ptr_equal(prop, NULL);           \
375                 else {                                          \
376                         assert_ptr_not_equal(prop, NULL);       \
377                         assert_string_equal(prop, val);         \
378                 }                                               \
379         } while (0)
380
381 #if BROKEN
382 #define TEST_PROP_BROKEN(name, prop, bad, good) do {                    \
383                 condlog(1, "%s: WARNING: Broken test for %s == \"%s\" on line %d, should be \"%s\"", \
384                         __func__, name, bad ? bad : "NULL",             \
385                         __LINE__, good ? good : "NULL");                        \
386                 TEST_PROP(prop, bad);                                   \
387         } while (0)
388 #else
389 #define TEST_PROP_BROKEN(name, prop, bad, good) TEST_PROP(prop, good)
390 #endif
391
392 /*
393  * Some predefined key/value pairs
394  */
395
396 static const char _wwid[] = "wwid";
397 static const char _vendor[] = "vendor";
398 static const char _product[] = "product";
399 static const char _prio[] = "prio";
400 static const char _checker[] = "path_checker";
401 static const char _getuid[] = "getuid_callout";
402 static const char _uid_attr[] = "uid_attribute";
403 static const char _bl_product[] = "product_blacklist";
404 static const char _minio[] = "rr_min_io_rq";
405 static const char _no_path_retry[] = "no_path_retry";
406
407 /* Device identifiers */
408 static const struct key_value vnd_foo = { _vendor, "foo" };
409 static const struct key_value prd_bar = { _product, "bar" };
410 static const struct key_value prd_bam = { _product, "bam" };
411 static const struct key_value prd_baq = { _product, "\"bar\"" };
412 static const struct key_value prd_baqq = { _product, "\"\"bar\"\"" };
413 static const struct key_value prd_barz = { _product, "barz" };
414 static const struct key_value vnd_boo = { _vendor, "boo" };
415 static const struct key_value prd_baz = { _product, "baz" };
416 static const struct key_value wwid_test = { _wwid, default_wwid };
417
418 /* Regular expresssions */
419 static const struct key_value vnd__oo = { _vendor, ".oo" };
420 static const struct key_value vnd_t_oo = { _vendor, "^.oo" };
421 static const struct key_value prd_ba_ = { _product, "ba." };
422 static const struct key_value prd_ba_s = { _product, "(bar|baz|ba\\.)$" };
423 /* Pathological cases, see below */
424 static const struct key_value prd_barx = { _product, "ba[[rxy]" };
425 static const struct key_value prd_bazy = { _product, "ba[zy]" };
426 static const struct key_value prd_bazy1 = { _product, "ba(z|y)" };
427
428 /* Properties */
429 static const struct key_value prio_emc = { _prio, "emc" };
430 static const struct key_value prio_hds = { _prio, "hds" };
431 static const struct key_value prio_rdac = { _prio, "rdac" };
432 static const struct key_value chk_hp = { _checker, "hp_sw" };
433 static const struct key_value gui_foo = { _getuid, "/tmp/foo" };
434 static const struct key_value uid_baz = { _uid_attr, "BAZ_ATTR" };
435 static const struct key_value bl_bar = { _bl_product, "bar" };
436 static const struct key_value bl_baz = { _bl_product, "baz" };
437 static const struct key_value bl_barx = { _bl_product, "ba[[rxy]" };
438 static const struct key_value bl_bazy = { _bl_product, "ba[zy]" };
439 static const struct key_value minio_99 = { _minio, "99" };
440 static const struct key_value npr_37 = { _no_path_retry, "37" };
441 static const struct key_value npr_queue = { _no_path_retry, "queue" };
442
443 /***** BEGIN TESTS SECTION *****/
444
445 /*
446  * Dump the configuration, subistitute the dumped configuration
447  * for the current one, and verify that the result is identical.
448  */
449 static void replicate_config(const struct hwt_state *hwt, bool local)
450 {
451         char *cfg1, *cfg2;
452         vector hwtable;
453         struct config *conf;
454
455         condlog(1, "--- %s: replicating %s configuration", __func__,
456                 local ? "local" : "full");
457
458         conf = get_multipath_config();
459         if (!local)
460                 /* "full" configuration */
461                 cfg1 = snprint_config(conf, NULL, NULL, NULL);
462         else {
463                 /* "local" configuration */
464                 hwtable = get_used_hwes(hwt->vecs->pathvec);
465                 cfg1 = snprint_config(conf, NULL, hwtable, hwt->vecs->mpvec);
466         }
467
468         assert_non_null(cfg1);
469         put_multipath_config(conf);
470
471         replace_config(hwt, cfg1);
472
473         /*
474          * The local configuration adds multipath entries, and may move device
475          * entries for local devices to the end of the list. Identical config
476          * strings therefore can't be expected in the "local" case.
477          * That doesn't matter. The important thing is that, with the reloaded
478          * configuration, the test case still passes.
479          */
480         if (local) {
481                 free(cfg1);
482                 return;
483         }
484
485         conf = get_multipath_config();
486         cfg2 = snprint_config(conf, NULL, NULL, NULL);
487         assert_non_null(cfg2);
488         put_multipath_config(conf);
489
490 // #define DBG_CONFIG 1
491 #ifdef DBG_CONFIG
492 #define DUMP_CFG_STR(x) do {                                            \
493                 FILE *tmp = fopen("/tmp/hwtable-" #x ".txt", "w");      \
494                 fprintf(tmp, "%s", x);                                  \
495                 fclose(tmp);                                            \
496         } while (0)
497
498         DUMP_CFG_STR(cfg1);
499         DUMP_CFG_STR(cfg2);
500 #endif
501
502         assert_int_equal(strlen(cfg2), strlen(cfg1));
503         assert_string_equal(cfg2, cfg1);
504         free(cfg1);
505         free(cfg2);
506 }
507
508 /*
509  * Run hwt->test three times; once with the constructed configuration,
510  * once after re-reading the full dumped configuration, and once with the
511  * dumped local configuration.
512  *
513  * Expected: test passes every time.
514  */
515 static void test_driver(void **state)
516 {
517         const struct hwt_state *hwt;
518
519         hwt = CHECK_STATE(state);
520         _conf = LOAD_CONFIG(hwt);
521         hwt->test(hwt);
522
523         replicate_config(hwt, false);
524         reset_vecs(hwt->vecs);
525         hwt->test(hwt);
526
527         replicate_config(hwt, true);
528         reset_vecs(hwt->vecs);
529         hwt->test(hwt);
530
531         reset_vecs(hwt->vecs);
532         FREE_CONFIG(_conf);
533 }
534
535 /*
536  * Sanity check for the test itself, because defaults may be changed
537  * in libmultipath.
538  *
539  * Our checking for match or non-match relies on the defaults being
540  * different from what our device sections contain.
541  */
542 static void test_sanity_globals(void **state)
543 {
544         assert_string_not_equal(prio_emc.value, DEFAULT_PRIO);
545         assert_string_not_equal(prio_hds.value, DEFAULT_PRIO);
546         assert_string_not_equal(chk_hp.value, DEFAULT_CHECKER);
547         assert_int_not_equal(MULTIBUS, DEFAULT_PGPOLICY);
548         assert_int_not_equal(NO_PATH_RETRY_QUEUE, DEFAULT_NO_PATH_RETRY);
549         assert_int_not_equal(atoi(minio_99.value), DEFAULT_MINIO_RQ);
550         assert_int_not_equal(atoi(npr_37.value), DEFAULT_NO_PATH_RETRY);
551 }
552
553 /*
554  * Regression test for internal hwtable. NVME is an example of two entries
555  * in the built-in hwtable, one if which matches a subset of the other.
556  */
557 static void test_internal_nvme(const struct hwt_state *hwt)
558 {
559         struct path *pp;
560         struct multipath *mp;
561
562         /*
563          * Generic NVMe: expect defaults for pgpolicy and no_path_retry
564          */
565         pp = mock_path("NVME", "NoName");
566         mp = mock_multipath(pp);
567         assert_ptr_not_equal(mp, NULL);
568         TEST_PROP(pp->checker.name, NONE);
569         TEST_PROP(pp->uid_attribute, "ID_WWN");
570         assert_int_equal(mp->pgpolicy, DEFAULT_PGPOLICY);
571         assert_int_equal(mp->no_path_retry, DEFAULT_NO_PATH_RETRY);
572         assert_int_equal(mp->retain_hwhandler, RETAIN_HWHANDLER_OFF);
573
574         /*
575          * NetApp NVMe: expect special values for pgpolicy and no_path_retry
576          */
577         pp = mock_path_wwid("NVME", "NetApp ONTAP Controller",
578                             default_wwid_1);
579         mp = mock_multipath(pp);
580         assert_ptr_not_equal(mp, NULL);
581         TEST_PROP(pp->checker.name, NONE);
582         TEST_PROP(pp->uid_attribute, "ID_WWN");
583         assert_int_equal(mp->pgpolicy, MULTIBUS);
584         assert_int_equal(mp->no_path_retry, NO_PATH_RETRY_QUEUE);
585         assert_int_equal(mp->retain_hwhandler, RETAIN_HWHANDLER_OFF);
586 }
587
588 static int setup_internal_nvme(void **state)
589 {
590         struct hwt_state *hwt = CHECK_STATE(state);
591
592         WRITE_EMPTY_CONF(hwt);
593         SET_TEST_FUNC(hwt, test_internal_nvme);
594
595         return 0;
596 }
597
598 /*
599  * Device section with a simple entry qith double quotes ('foo:"bar"')
600  */
601 static void test_quoted_hwe(const struct hwt_state *hwt)
602 {
603         struct path *pp;
604
605         /* foo:"bar" matches */
606         pp = mock_path(vnd_foo.value, prd_baq.value);
607         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
608
609         /* foo:bar doesn't match */
610         pp = mock_path(vnd_foo.value, prd_bar.value);
611         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
612 }
613
614 static int setup_quoted_hwe(void **state)
615 {
616         struct hwt_state *hwt = CHECK_STATE(state);
617         const struct key_value kv[] = { vnd_foo, prd_baqq, prio_emc };
618
619         WRITE_ONE_DEVICE(hwt, kv);
620         SET_TEST_FUNC(hwt, test_quoted_hwe);
621         return 0;
622 }
623
624 /*
625  * Device section with a single simple entry ("foo:bar")
626  */
627 static void test_string_hwe(const struct hwt_state *hwt)
628 {
629         struct path *pp;
630
631         /* foo:bar matches */
632         pp = mock_path(vnd_foo.value, prd_bar.value);
633         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
634
635         /* foo:baz doesn't match */
636         pp = mock_path(vnd_foo.value, prd_baz.value);
637         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
638
639         /* boo:bar doesn't match */
640         pp = mock_path(vnd_boo.value, prd_bar.value);
641         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
642 }
643
644 static int setup_string_hwe(void **state)
645 {
646         struct hwt_state *hwt = CHECK_STATE(state);
647         const struct key_value kv[] = { vnd_foo, prd_bar, prio_emc };
648
649         WRITE_ONE_DEVICE(hwt, kv);
650         SET_TEST_FUNC(hwt, test_string_hwe);
651         return 0;
652 }
653
654 /*
655  * Device section with a broken entry (no product)
656  * It should be ignored.
657  */
658 static void test_broken_hwe(const struct hwt_state *hwt)
659 {
660         struct path *pp;
661
662         /* foo:bar doesn't match, as hwentry is ignored */
663         pp = mock_path(vnd_foo.value, prd_bar.value);
664         TEST_PROP_BROKEN("prio", prio_name(&pp->prio), prio_emc.value,
665                          DEFAULT_PRIO);
666
667         /* boo:bar doesn't match */
668         pp = mock_path(vnd_boo.value, prd_bar.value);
669         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
670 }
671
672 static int setup_broken_hwe(void **state)
673 {
674         struct hwt_state *hwt = CHECK_STATE(state);
675         const struct key_value kv[] = { vnd_foo, prio_emc };
676
677         WRITE_ONE_DEVICE(hwt, kv);
678         SET_TEST_FUNC(hwt, test_broken_hwe);
679         return 0;
680 }
681
682 /*
683  * Like test_broken_hwe, but in config_dir file.
684  */
685 static int setup_broken_hwe_dir(void **state)
686 {
687         struct hwt_state *hwt = CHECK_STATE(state);
688         const struct key_value kv[] = { vnd_foo, prio_emc };
689
690         begin_config(hwt);
691         begin_section_all(hwt, "devices");
692         write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv), kv);
693         end_section_all(hwt);
694         finish_config(hwt);
695         hwt->test = test_broken_hwe;
696         hwt->test_name = "test_broken_hwe_dir";
697         return 0;
698 }
699
700 /*
701  * Device section with a single regex entry ("^.foo:(bar|baz|ba\.)$")
702  */
703 static void test_regex_hwe(const struct hwt_state *hwt)
704 {
705         struct path *pp;
706
707         /* foo:bar matches */
708         pp = mock_path(vnd_foo.value, prd_bar.value);
709         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
710
711         /* foo:baz matches */
712         pp = mock_path(vnd_foo.value, prd_baz.value);
713         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
714
715         /* boo:baz matches */
716         pp = mock_path(vnd_boo.value, prd_bar.value);
717         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
718
719         /* foo:BAR doesn't match */
720         pp = mock_path(vnd_foo.value, "BAR");
721         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
722
723         /* bboo:bar doesn't match */
724         pp = mock_path("bboo", prd_bar.value);
725         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
726 }
727
728 static int setup_regex_hwe(void **state)
729 {
730         struct hwt_state *hwt = CHECK_STATE(state);
731         const struct key_value kv[] = { vnd_t_oo, prd_ba_s, prio_emc };
732
733         WRITE_ONE_DEVICE(hwt, kv);
734         SET_TEST_FUNC(hwt, test_regex_hwe);
735         return 0;
736 }
737
738 /*
739  * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
740  * kv2 a string match (foo:bar) which matches a subset of the regex.
741  * Both are added to the main config file.
742  *
743  * Expected: Devices matching both get properties from both, kv2 taking
744  * precedence. Devices matching kv1 only just get props from kv1.
745  */
746 static void test_regex_string_hwe(const struct hwt_state *hwt)
747 {
748         struct path *pp;
749
750         /* foo:baz matches kv1 */
751         pp = mock_path(vnd_foo.value, prd_baz.value);
752         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
753         TEST_PROP(pp->getuid, NULL);
754         TEST_PROP(pp->checker.name, chk_hp.value);
755
756         /* boo:baz matches kv1 */
757         pp = mock_path(vnd_boo.value, prd_baz.value);
758         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
759         TEST_PROP(pp->getuid, NULL);
760         TEST_PROP(pp->checker.name, chk_hp.value);
761
762         /* .oo:ba. matches kv1 */
763         pp = mock_path(vnd__oo.value, prd_ba_.value);
764         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
765         TEST_PROP(pp->getuid, NULL);
766         TEST_PROP(pp->checker.name, chk_hp.value);
767
768         /* .foo:(bar|baz|ba\.) doesn't match */
769         pp = mock_path(vnd__oo.value, prd_ba_s.value);
770         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
771         TEST_PROP(pp->getuid, NULL);
772         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
773
774         /* foo:bar matches kv2 and kv1 */
775         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
776         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
777         TEST_PROP(pp->getuid, gui_foo.value);
778         TEST_PROP(pp->checker.name, chk_hp.value);
779 }
780
781 static int setup_regex_string_hwe(void **state)
782 {
783         struct hwt_state *hwt = CHECK_STATE(state);
784         const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
785         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
786
787         WRITE_TWO_DEVICES(hwt, kv1, kv2);
788         SET_TEST_FUNC(hwt, test_regex_string_hwe);
789         return 0;
790 }
791
792 /*
793  * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
794  * kv2 a string match (foo:bar) which matches a subset of the regex.
795  * kv1 is added to the main config file, kv2 to a config_dir file.
796  * This case is more important as you may think, because it's equivalent
797  * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
798  *
799  * Expected: Devices matching kv2 (and thus, both) get properties
800  * from both, kv2 taking precedence.
801  * Devices matching kv1 only just get props from kv1.
802  */
803 static void test_regex_string_hwe_dir(const struct hwt_state *hwt)
804 {
805         struct path *pp;
806
807         /* foo:baz matches kv1 */
808         pp = mock_path(vnd_foo.value, prd_baz.value);
809         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
810         TEST_PROP(pp->getuid, NULL);
811         TEST_PROP(pp->checker.name, chk_hp.value);
812
813         /* boo:baz matches kv1 */
814         pp = mock_path(vnd_boo.value, prd_baz.value);
815         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
816         TEST_PROP(pp->getuid, NULL);
817         TEST_PROP(pp->checker.name, chk_hp.value);
818
819         /* .oo:ba. matches kv1 */
820         pp = mock_path(vnd__oo.value, prd_ba_.value);
821         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
822         TEST_PROP(pp->getuid, NULL);
823         TEST_PROP(pp->checker.name, chk_hp.value);
824
825         /* .oo:(bar|baz|ba\.)$ doesn't match */
826         pp = mock_path(vnd__oo.value, prd_ba_s.value);
827         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
828         TEST_PROP(pp->getuid, NULL);
829         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
830
831         /* foo:bar matches kv2 */
832         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
833         /* Later match takes prio */
834         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
835         TEST_PROP(pp->getuid, gui_foo.value);
836         TEST_PROP(pp->checker.name, chk_hp.value);
837 }
838
839 static int setup_regex_string_hwe_dir(void **state)
840 {
841         const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
842         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
843         struct hwt_state *hwt = CHECK_STATE(state);
844
845         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
846         SET_TEST_FUNC(hwt, test_regex_string_hwe_dir);
847         return 0;
848 }
849
850 /*
851  * Three device entries, kv1 is a regex match and kv2 and kv3 string
852  * matches, where kv3 is a substring of kv2. All in different config
853  * files.
854  *
855  * Expected: Devices matching kv3 get props from all, devices matching
856  * kv2 from kv2 and kv1, and devices matching kv1 only just from kv1.
857  */
858 static void test_regex_2_strings_hwe_dir(const struct hwt_state *hwt)
859 {
860         struct path *pp;
861
862         /* foo:baz matches kv1 */
863         pp = mock_path(vnd_foo.value, prd_baz.value);
864         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
865         TEST_PROP(pp->getuid, NULL);
866         TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
867         TEST_PROP(pp->checker.name, chk_hp.value);
868
869         /* boo:baz doesn't match */
870         pp = mock_path(vnd_boo.value, prd_baz.value);
871         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
872         TEST_PROP(pp->getuid, NULL);
873         TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
874         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
875
876         /* foo:bar matches kv2 and kv1 */
877         pp = mock_path(vnd_foo.value, prd_bar.value);
878         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
879         TEST_PROP(pp->getuid, NULL);
880         TEST_PROP(pp->uid_attribute, uid_baz.value);
881         TEST_PROP(pp->checker.name, chk_hp.value);
882
883         /* foo:barz matches kv3 and kv2 and kv1 */
884         pp = mock_path_flags(vnd_foo.value, prd_barz.value, USE_GETUID);
885         TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
886         TEST_PROP(pp->getuid, gui_foo.value);
887         TEST_PROP(pp->uid_attribute, NULL);
888         TEST_PROP(pp->checker.name, chk_hp.value);
889 }
890
891 static int setup_regex_2_strings_hwe_dir(void **state)
892 {
893         const struct key_value kv1[] = { vnd_foo, prd_ba_, prio_emc, chk_hp };
894         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, uid_baz };
895         const struct key_value kv3[] = { vnd_foo, prd_barz,
896                                          prio_rdac, gui_foo };
897         struct hwt_state *hwt = CHECK_STATE(state);
898
899         begin_config(hwt);
900         begin_section_all(hwt, "devices");
901         write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
902         write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
903         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv3), kv3);
904         end_section_all(hwt);
905         finish_config(hwt);
906         SET_TEST_FUNC(hwt, test_regex_2_strings_hwe_dir);
907         return 0;
908 }
909
910 /*
911  * Like test_regex_string_hwe_dir, but the order of kv1 and kv2 is exchanged.
912  *
913  * Expected: Devices matching kv1 (and thus, both) get properties
914  * from both, kv1 taking precedence.
915  * Devices matching kv1 only just get props from kv1.
916  */
917 static void test_string_regex_hwe_dir(const struct hwt_state *hwt)
918 {
919         struct path *pp;
920
921         /* foo:bar matches kv2 and kv1 */
922         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
923         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
924         TEST_PROP(pp->getuid, gui_foo.value);
925         TEST_PROP(pp->checker.name, chk_hp.value);
926
927         /* foo:baz matches kv1 */
928         pp = mock_path(vnd_foo.value, prd_baz.value);
929         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
930         TEST_PROP(pp->getuid, NULL);
931         TEST_PROP(pp->checker.name, chk_hp.value);
932
933         /* boo:baz matches kv1 */
934         pp = mock_path(vnd_boo.value, prd_baz.value);
935         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
936         TEST_PROP(pp->getuid, NULL);
937         TEST_PROP(pp->checker.name, chk_hp.value);
938
939         /* .oo:ba. matches kv1 */
940         pp = mock_path(vnd__oo.value, prd_ba_.value);
941         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
942         TEST_PROP(pp->getuid, NULL);
943         TEST_PROP(pp->checker.name, chk_hp.value);
944
945         /* .oo:(bar|baz|ba\.)$ doesn't match */
946         pp = mock_path(vnd__oo.value, prd_ba_s.value);
947         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
948         TEST_PROP(pp->getuid, NULL);
949         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
950 }
951
952 static int setup_string_regex_hwe_dir(void **state)
953 {
954         const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
955         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
956         struct hwt_state *hwt = CHECK_STATE(state);
957
958         WRITE_TWO_DEVICES_W_DIR(hwt, kv2, kv1);
959         SET_TEST_FUNC(hwt, test_string_regex_hwe_dir);
960         return 0;
961 }
962
963 /*
964  * Two identical device entries kv1 and kv2, trival regex ("string").
965  * Both are added to the main config file.
966  * These entries are NOT merged.
967  * This could happen in a large multipath.conf file.
968  *
969  * Expected: matching devices get props from both, kv2 taking precedence.
970  */
971 static void test_2_ident_strings_hwe(const struct hwt_state *hwt)
972 {
973         struct path *pp;
974
975         /* foo:baz doesn't match */
976         pp = mock_path(vnd_foo.value, prd_baz.value);
977         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
978         TEST_PROP(pp->getuid, NULL);
979         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
980
981         /* foo:bar matches both */
982         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
983         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
984         TEST_PROP(pp->getuid, gui_foo.value);
985         TEST_PROP(pp->checker.name, chk_hp.value);
986 }
987
988 static int setup_2_ident_strings_hwe(void **state)
989 {
990         const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
991         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
992         struct hwt_state *hwt = CHECK_STATE(state);
993
994         WRITE_TWO_DEVICES(hwt, kv1, kv2);
995         SET_TEST_FUNC(hwt, test_2_ident_strings_hwe);
996         return 0;
997 }
998
999 /*
1000  * Two identical device entries kv1 and kv2, trival regex ("string").
1001  * Both are added to an extra config file.
1002  * This could happen in a large multipath.conf file.
1003  *
1004  * Expected: matching devices get props from both, kv2 taking precedence.
1005  */
1006 static void test_2_ident_strings_both_dir(const struct hwt_state *hwt)
1007 {
1008         struct path *pp;
1009
1010         /* foo:baz doesn't match */
1011         pp = mock_path(vnd_foo.value, prd_baz.value);
1012         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1013         TEST_PROP(pp->getuid, NULL);
1014         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1015
1016         /* foo:bar matches both */
1017         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1018         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1019         TEST_PROP(pp->getuid, gui_foo.value);
1020         TEST_PROP(pp->checker.name, chk_hp.value);
1021 }
1022
1023 static int setup_2_ident_strings_both_dir(void **state)
1024 {
1025         const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1026         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1027         struct hwt_state *hwt = CHECK_STATE(state);
1028
1029         begin_config(hwt);
1030         begin_section_all(hwt, "devices");
1031         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1032         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1033         end_section_all(hwt);
1034         finish_config(hwt);
1035         SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir);
1036         return 0;
1037 }
1038
1039 /*
1040  * Two identical device entries kv1 and kv2, trival regex ("string").
1041  * Both are added to an extra config file.
1042  * An empty entry kv0 with the same string exists in the main config file.
1043  *
1044  * Expected: matching devices get props from both, kv2 taking precedence.
1045  */
1046 static void test_2_ident_strings_both_dir_w_prev(const struct hwt_state *hwt)
1047 {
1048         struct path *pp;
1049
1050         /* foo:baz doesn't match */
1051         pp = mock_path(vnd_foo.value, prd_baz.value);
1052         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1053         TEST_PROP(pp->getuid, NULL);
1054         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1055
1056         /* foo:bar matches both */
1057         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1058         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1059         TEST_PROP(pp->getuid, gui_foo.value);
1060         TEST_PROP(pp->checker.name, chk_hp.value);
1061 }
1062
1063 static int setup_2_ident_strings_both_dir_w_prev(void **state)
1064 {
1065         struct hwt_state *hwt = CHECK_STATE(state);
1066
1067         const struct key_value kv0[] = { vnd_foo, prd_bar };
1068         const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1069         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1070
1071         begin_config(hwt);
1072         begin_section_all(hwt, "devices");
1073         write_device(hwt->config_file, ARRAY_SIZE(kv0), kv0);
1074         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1075         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1076         end_section_all(hwt);
1077         finish_config(hwt);
1078         SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir_w_prev);
1079         return 0;
1080 }
1081
1082 /*
1083  * Two identical device entries kv1 and kv2, trival regex ("string").
1084  * kv1 is added to the main config file, kv2 to a config_dir file.
1085  * These entries are merged.
1086  * This case is more important as you may think, because it's equivalent
1087  * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1088  *
1089  * Expected: matching devices get props from both, kv2 taking precedence.
1090  */
1091 static void test_2_ident_strings_hwe_dir(const struct hwt_state *hwt)
1092 {
1093         struct path *pp;
1094
1095         /* foo:baz doesn't match */
1096         pp = mock_path(vnd_foo.value, prd_baz.value);
1097         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1098         TEST_PROP(pp->getuid, NULL);
1099         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1100
1101         /* foo:bar matches both */
1102         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1103         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1104         TEST_PROP(pp->getuid, gui_foo.value);
1105         TEST_PROP(pp->checker.name, chk_hp.value);
1106 }
1107
1108 static int setup_2_ident_strings_hwe_dir(void **state)
1109 {
1110         const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1111         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1112         struct hwt_state *hwt = CHECK_STATE(state);
1113
1114         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1115         SET_TEST_FUNC(hwt, test_2_ident_strings_hwe_dir);
1116         return 0;
1117 }
1118
1119 /*
1120  * Like test_2_ident_strings_hwe_dir, but this time the config_dir file
1121  * contains an additional, empty entry (kv0).
1122  *
1123  * Expected: matching devices get props from kv1 and kv2, kv2 taking precedence.
1124  */
1125 static void test_3_ident_strings_hwe_dir(const struct hwt_state *hwt)
1126 {
1127         struct path *pp;
1128
1129         /* foo:baz doesn't match */
1130         pp = mock_path(vnd_foo.value, prd_baz.value);
1131         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1132         TEST_PROP(pp->getuid, NULL);
1133         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1134
1135         /* foo:bar matches both */
1136         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1137         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1138         TEST_PROP(pp->getuid, gui_foo.value);
1139         TEST_PROP(pp->checker.name, chk_hp.value);
1140 }
1141
1142 static int setup_3_ident_strings_hwe_dir(void **state)
1143 {
1144         const struct key_value kv0[] = { vnd_foo, prd_bar };
1145         const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1146         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1147         struct hwt_state *hwt = CHECK_STATE(state);
1148
1149         begin_config(hwt);
1150         begin_section_all(hwt, "devices");
1151         write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1152         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv0), kv0);
1153         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1154         end_section_all(hwt);
1155         finish_config(hwt);
1156         SET_TEST_FUNC(hwt, test_3_ident_strings_hwe_dir);
1157         return 0;
1158 }
1159
1160 /*
1161  * Two identical device entries kv1 and kv2, non-trival regex that matches
1162  * itself (string ".oo" matches regex ".oo").
1163  * kv1 is added to the main config file, kv2 to a config_dir file.
1164  * This case is more important as you may think, because it's equivalent
1165  * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1166  *
1167  * Expected: matching devices get props from both, kv2 taking precedence.
1168  */
1169 static void test_2_ident_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1170 {
1171         struct path *pp;
1172
1173         /* foo:baz doesn't match */
1174         pp = mock_path(vnd_foo.value, prd_baz.value);
1175         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1176         TEST_PROP(pp->getuid, NULL);
1177         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1178
1179         /* foo:bar matches both */
1180         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1181         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1182         TEST_PROP(pp->getuid, gui_foo.value);
1183         TEST_PROP(pp->checker.name, chk_hp.value);
1184 }
1185
1186 static int setup_2_ident_self_matching_re_hwe_dir(void **state)
1187 {
1188         const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1189         const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1190         struct hwt_state *hwt = CHECK_STATE(state);
1191
1192         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1193         SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe_dir);
1194         return 0;
1195 }
1196
1197 /*
1198  * Two identical device entries kv1 and kv2, non-trival regex that matches
1199  * itself (string ".oo" matches regex ".oo").
1200  * kv1 and kv2 are added to the main config file.
1201  *
1202  * Expected: matching devices get props from both, kv2 taking precedence.
1203  */
1204 static void test_2_ident_self_matching_re_hwe(const struct hwt_state *hwt)
1205 {
1206         struct path *pp;
1207
1208         /* foo:baz doesn't match */
1209         pp = mock_path(vnd_foo.value, prd_baz.value);
1210         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1211         TEST_PROP(pp->getuid, NULL);
1212         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1213
1214         /* foo:bar matches */
1215         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1216         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1217         TEST_PROP(pp->getuid, gui_foo.value);
1218         TEST_PROP(pp->checker.name, chk_hp.value);
1219 }
1220
1221 static int setup_2_ident_self_matching_re_hwe(void **state)
1222 {
1223         const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1224         const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1225         struct hwt_state *hwt = CHECK_STATE(state);
1226
1227         WRITE_TWO_DEVICES(hwt, kv1, kv2);
1228         SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe);
1229         return 0;
1230 }
1231
1232 /*
1233  * Two identical device entries kv1 and kv2, non-trival regex that doesn't
1234  * match itself (string "^.oo" doesn't match regex "^.oo").
1235  * kv1 is added to the main config file, kv2 to a config_dir file.
1236  * This case is more important as you may think, see above.
1237  *
1238  * Expected: matching devices get props from both, kv2 taking precedence.
1239  */
1240 static void
1241 test_2_ident_not_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1242 {
1243         struct path *pp;
1244
1245         /* foo:baz doesn't match */
1246         pp = mock_path(vnd_foo.value, prd_baz.value);
1247         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1248         TEST_PROP(pp->getuid, NULL);
1249         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1250
1251         /* foo:bar matches both */
1252         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1253         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1254         TEST_PROP(pp->getuid, gui_foo.value);
1255         TEST_PROP(pp->checker.name, chk_hp.value);
1256 }
1257
1258 static int setup_2_ident_not_self_matching_re_hwe_dir(void **state)
1259 {
1260         const struct key_value kv1[] = { vnd_t_oo, prd_bar, prio_emc, chk_hp };
1261         const struct key_value kv2[] = { vnd_t_oo, prd_bar, prio_hds, gui_foo };
1262         struct hwt_state *hwt = CHECK_STATE(state);
1263
1264         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1265         SET_TEST_FUNC(hwt, test_2_ident_not_self_matching_re_hwe_dir);
1266         return 0;
1267 }
1268
1269 /*
1270  * Two different non-trivial regexes kv1, kv2. The 1st one matches the 2nd, but
1271  * it doesn't match all possible strings matching the second.
1272  * ("ba[zy]" matches regex "ba[[rxy]", but "baz" does not).
1273  *
1274  * Expected: Devices matching both regexes get properties from both, kv2
1275  * taking precedence. Devices matching just one regex get properties from
1276  * that one regex only.
1277  */
1278 static void test_2_matching_res_hwe_dir(const struct hwt_state *hwt)
1279 {
1280         struct path *pp;
1281
1282         /* foo:bar matches k1 only */
1283         pp = mock_path(vnd_foo.value, prd_bar.value);
1284         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1285         TEST_PROP(pp->getuid, NULL);
1286         TEST_PROP(pp->checker.name, chk_hp.value);
1287
1288         /* foo:bay matches k1 and k2 */
1289         pp = mock_path_flags(vnd_foo.value, "bay", USE_GETUID);
1290         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1291         TEST_PROP(pp->getuid, gui_foo.value);
1292         TEST_PROP(pp->checker.name, chk_hp.value);
1293
1294         /* foo:baz matches k2 only. */
1295         pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1296         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1297         TEST_PROP(pp->getuid, gui_foo.value);
1298         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1299 }
1300
1301 static int setup_2_matching_res_hwe_dir(void **state)
1302 {
1303         const struct key_value kv1[] = { vnd_foo, prd_barx, prio_emc, chk_hp };
1304         const struct key_value kv2[] = { vnd_foo, prd_bazy, prio_hds, gui_foo };
1305         struct hwt_state *hwt = CHECK_STATE(state);
1306
1307         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1308         SET_TEST_FUNC(hwt, test_2_matching_res_hwe_dir);
1309         return 0;
1310 }
1311
1312 /*
1313  * Two different non-trivial regexes which match the same set of strings.
1314  * But they don't match each other.
1315  * "baz" matches both regex "ba[zy]" and "ba(z|y)"
1316  *
1317  * Expected: matching devices get properties from both, kv2 taking precedence.
1318  */
1319 static void test_2_nonmatching_res_hwe_dir(const struct hwt_state *hwt)
1320 {
1321         struct path *pp;
1322
1323         /* foo:bar doesn't match */
1324         pp = mock_path(vnd_foo.value, prd_bar.value);
1325         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1326         TEST_PROP(pp->getuid, NULL);
1327         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1328
1329         pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1330         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1331         TEST_PROP(pp->getuid, gui_foo.value);
1332         TEST_PROP(pp->checker.name, chk_hp.value);
1333 }
1334
1335 static int setup_2_nonmatching_res_hwe_dir(void **state)
1336 {
1337         const struct key_value kv1[] = { vnd_foo, prd_bazy, prio_emc, chk_hp };
1338         const struct key_value kv2[] = { vnd_foo, prd_bazy1,
1339                                          prio_hds, gui_foo };
1340         struct hwt_state *hwt = CHECK_STATE(state);
1341
1342         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1343         SET_TEST_FUNC(hwt, test_2_nonmatching_res_hwe_dir);
1344         return 0;
1345 }
1346
1347 /*
1348  * Simple blacklist test.
1349  *
1350  * NOTE: test failures in blacklisting tests will manifest as cmocka errors
1351  * "Could not get value to mock function XYZ", because pathinfo() takes
1352  * different code paths for blacklisted devices.
1353  */
1354 static void test_blacklist(const struct hwt_state *hwt)
1355 {
1356         mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1357         mock_path(vnd_foo.value, prd_baz.value);
1358 }
1359
1360 static int setup_blacklist(void **state)
1361 {
1362         const struct key_value kv1[] = { vnd_foo, prd_bar };
1363         struct hwt_state *hwt = CHECK_STATE(state);
1364
1365         begin_config(hwt);
1366         begin_section_all(hwt, "blacklist");
1367         write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1368         end_section_all(hwt);
1369         finish_config(hwt);
1370         SET_TEST_FUNC(hwt, test_blacklist);
1371         return 0;
1372 }
1373
1374 /*
1375  * Simple blacklist test with regex and exception
1376  */
1377 static void test_blacklist_regex(const struct hwt_state *hwt)
1378 {
1379         mock_path(vnd_foo.value, prd_bar.value);
1380         mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1381         mock_path(vnd_foo.value, prd_bam.value);
1382 }
1383
1384 static int setup_blacklist_regex(void **state)
1385 {
1386         const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1387         const struct key_value kv2[] = { vnd_foo, prd_bar };
1388         struct hwt_state *hwt = CHECK_STATE(state);
1389
1390         hwt = CHECK_STATE(state);
1391         begin_config(hwt);
1392         begin_section_all(hwt, "blacklist");
1393         write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1394         end_section_all(hwt);
1395         begin_section_all(hwt, "blacklist_exceptions");
1396         write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1397         end_section_all(hwt);
1398         finish_config(hwt);
1399         SET_TEST_FUNC(hwt, test_blacklist_regex);
1400         return 0;
1401 }
1402
1403 /*
1404  * Simple blacklist test with regex and exception
1405  * config file order inverted wrt test_blacklist_regex
1406  */
1407 static int setup_blacklist_regex_inv(void **state)
1408 {
1409         const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1410         const struct key_value kv2[] = { vnd_foo, prd_bar };
1411         struct hwt_state *hwt = CHECK_STATE(state);
1412
1413         begin_config(hwt);
1414         begin_section_all(hwt, "blacklist");
1415         write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv1), kv1);
1416         end_section_all(hwt);
1417         begin_section_all(hwt, "blacklist_exceptions");
1418         write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2);
1419         end_section_all(hwt);
1420         finish_config(hwt);
1421         SET_TEST_FUNC(hwt, test_blacklist_regex);
1422         return 0;
1423 }
1424
1425 /*
1426  * Simple blacklist test with regex and exception
1427  * config file order inverted wrt test_blacklist_regex
1428  */
1429 static void test_blacklist_regex_matching(const struct hwt_state *hwt)
1430 {
1431         mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1432         mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1433         mock_path(vnd_foo.value, prd_bam.value);
1434 }
1435
1436 static int setup_blacklist_regex_matching(void **state)
1437 {
1438         const struct key_value kv1[] = { vnd_foo, prd_barx };
1439         const struct key_value kv2[] = { vnd_foo, prd_bazy };
1440         struct hwt_state *hwt = CHECK_STATE(state);
1441
1442         begin_config(hwt);
1443         begin_section_all(hwt, "blacklist");
1444         write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1445         write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1446         end_section_all(hwt);
1447         finish_config(hwt);
1448         SET_TEST_FUNC(hwt, test_blacklist_regex_matching);
1449         return 0;
1450 }
1451
1452 /*
1453  * Test for blacklisting by WWID
1454  *
1455  * Note that default_wwid is a substring of default_wwid_1. Because
1456  * matching is done by regex, both paths are blacklisted.
1457  */
1458 static void test_blacklist_wwid(const struct hwt_state *hwt)
1459 {
1460         mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_WWID);
1461         mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1462                              BL_BY_WWID);
1463 }
1464
1465 static int setup_blacklist_wwid(void **state)
1466 {
1467         const struct key_value kv[] = { wwid_test };
1468         struct hwt_state *hwt = CHECK_STATE(state);
1469
1470         begin_config(hwt);
1471         write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1472         finish_config(hwt);
1473         SET_TEST_FUNC(hwt, test_blacklist_wwid);
1474         return 0;
1475 }
1476
1477 /*
1478  * Test for blacklisting by WWID
1479  *
1480  * Here the blacklist contains only default_wwid_1. Thus the path
1481  * with default_wwid is NOT blacklisted.
1482  */
1483 static void test_blacklist_wwid_1(const struct hwt_state *hwt)
1484 {
1485         mock_path(vnd_foo.value, prd_bar.value);
1486         mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1487                              BL_BY_WWID);
1488 }
1489
1490 static int setup_blacklist_wwid_1(void **state)
1491 {
1492         const struct key_value kv[] = { { _wwid, default_wwid_1 }, };
1493         struct hwt_state *hwt = CHECK_STATE(state);
1494
1495         begin_config(hwt);
1496         write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1497         finish_config(hwt);
1498         SET_TEST_FUNC(hwt, test_blacklist_wwid_1);
1499         return 0;
1500 }
1501
1502 /*
1503  * Test for product_blacklist. Two entries blacklisting each other.
1504  *
1505  * Expected: Both are blacklisted.
1506  */
1507 static void test_product_blacklist(const struct hwt_state *hwt)
1508 {
1509         mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1510         mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1511         mock_path(vnd_foo.value, prd_bam.value);
1512 }
1513
1514 static int setup_product_blacklist(void **state)
1515 {
1516         const struct key_value kv1[] = { vnd_foo, prd_bar, bl_baz };
1517         const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bar };
1518         struct hwt_state *hwt = CHECK_STATE(state);
1519
1520         WRITE_TWO_DEVICES(hwt, kv1, kv2);
1521         SET_TEST_FUNC(hwt, test_product_blacklist);
1522         return 0;
1523 }
1524
1525 /*
1526  * Test for product_blacklist. The second regex "matches" the first.
1527  * This is a pathological example.
1528  *
1529  * Expected: "foo:bar", "foo:baz" are blacklisted.
1530  */
1531 static void test_product_blacklist_matching(const struct hwt_state *hwt)
1532 {
1533         mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1534         mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1535         mock_path(vnd_foo.value, prd_bam.value);
1536 }
1537
1538 static int setup_product_blacklist_matching(void **state)
1539 {
1540         const struct key_value kv1[] = { vnd_foo, prd_bar, bl_barx };
1541         const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bazy };
1542         struct hwt_state *hwt = CHECK_STATE(state);
1543
1544         WRITE_TWO_DEVICES(hwt, kv1, kv2);
1545         SET_TEST_FUNC(hwt, test_product_blacklist_matching);
1546         return 0;
1547 }
1548
1549 /*
1550  * Basic test for multipath-based configuration.
1551  *
1552  * Expected: properties, including pp->prio, are taken from multipath
1553  * section.
1554  */
1555 static void test_multipath_config(const struct hwt_state *hwt)
1556 {
1557         struct path *pp;
1558         struct multipath *mp;
1559
1560         pp = mock_path(vnd_foo.value, prd_bar.value);
1561         mp = mock_multipath(pp);
1562         assert_ptr_not_equal(mp->mpe, NULL);
1563         TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1564         assert_int_equal(mp->minio, atoi(minio_99.value));
1565         TEST_PROP(pp->uid_attribute, uid_baz.value);
1566
1567         /* test different wwid */
1568         pp = mock_path_wwid(vnd_foo.value, prd_bar.value, default_wwid_1);
1569         mp = mock_multipath(pp);
1570         // assert_ptr_equal(mp->mpe, NULL);
1571         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1572         assert_int_equal(mp->minio, DEFAULT_MINIO_RQ);
1573         TEST_PROP(pp->uid_attribute, uid_baz.value);
1574 }
1575
1576 static int setup_multipath_config(void **state)
1577 {
1578         struct hwt_state *hwt = CHECK_STATE(state);
1579         const struct key_value kvm[] = { wwid_test, prio_rdac, minio_99 };
1580         const struct key_value kvp[] = { vnd_foo, prd_bar, prio_emc, uid_baz };
1581
1582         begin_config(hwt);
1583         begin_section_all(hwt, "devices");
1584         write_section(hwt->conf_dir_file[0], "device", ARRAY_SIZE(kvp), kvp);
1585         end_section_all(hwt);
1586         begin_section_all(hwt, "multipaths");
1587         write_section(hwt->config_file, "multipath", ARRAY_SIZE(kvm), kvm);
1588         end_section_all(hwt);
1589         finish_config(hwt);
1590         SET_TEST_FUNC(hwt, test_multipath_config);
1591         return 0;
1592 }
1593
1594 /*
1595  * Basic test for multipath-based configuration. Two sections for the same wwid.
1596  *
1597  * Expected: properties are taken from both multipath sections, later taking
1598  * precedence
1599  */
1600 static void test_multipath_config_2(const struct hwt_state *hwt)
1601 {
1602         struct path *pp;
1603         struct multipath *mp;
1604
1605         pp = mock_path(vnd_foo.value, prd_bar.value);
1606         mp = mock_multipath(pp);
1607         assert_ptr_not_equal(mp, NULL);
1608         assert_ptr_not_equal(mp->mpe, NULL);
1609         TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1610         assert_int_equal(mp->minio, atoi(minio_99.value));
1611         assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1612 }
1613
1614 static int setup_multipath_config_2(void **state)
1615 {
1616         const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1617         const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1618         struct hwt_state *hwt = CHECK_STATE(state);
1619
1620         begin_config(hwt);
1621         begin_section_all(hwt, "multipaths");
1622         write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1623         write_section(hwt->conf_dir_file[1], "multipath", ARRAY_SIZE(kv2), kv2);
1624         end_section_all(hwt);
1625         finish_config(hwt);
1626         SET_TEST_FUNC(hwt, test_multipath_config_2);
1627         return 0;
1628 }
1629
1630 /*
1631  * Same as test_multipath_config_2, both entries in the same config file.
1632  *
1633  * Expected: properties are taken from both multipath sections.
1634  */
1635 static void test_multipath_config_3(const struct hwt_state *hwt)
1636 {
1637         struct path *pp;
1638         struct multipath *mp;
1639
1640         pp = mock_path(vnd_foo.value, prd_bar.value);
1641         mp = mock_multipath(pp);
1642         assert_ptr_not_equal(mp, NULL);
1643         assert_ptr_not_equal(mp->mpe, NULL);
1644         TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1645         assert_int_equal(mp->minio, atoi(minio_99.value));
1646         assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1647 }
1648
1649 static int setup_multipath_config_3(void **state)
1650 {
1651         const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1652         const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1653         struct hwt_state *hwt = CHECK_STATE(state);
1654
1655         begin_config(hwt);
1656         begin_section_all(hwt, "multipaths");
1657         write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1658         write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv2), kv2);
1659         end_section_all(hwt);
1660         finish_config(hwt);
1661         SET_TEST_FUNC(hwt, test_multipath_config_3);
1662         return 0;
1663 }
1664
1665 /*
1666  * Create wrapper functions around test_driver() to avoid that cmocka
1667  * always uses the same test name. That makes it easier to read test results.
1668  */
1669
1670 #define define_test(x)                          \
1671         static void run_##x(void **state)       \
1672         {                                       \
1673                 return test_driver(state);      \
1674         }
1675
1676 define_test(string_hwe)
1677 define_test(broken_hwe)
1678 define_test(broken_hwe_dir)
1679 define_test(quoted_hwe)
1680 define_test(internal_nvme)
1681 define_test(regex_hwe)
1682 define_test(regex_string_hwe)
1683 define_test(regex_string_hwe_dir)
1684 define_test(regex_2_strings_hwe_dir)
1685 define_test(string_regex_hwe_dir)
1686 define_test(2_ident_strings_hwe)
1687 define_test(2_ident_strings_both_dir)
1688 define_test(2_ident_strings_both_dir_w_prev)
1689 define_test(2_ident_strings_hwe_dir)
1690 define_test(3_ident_strings_hwe_dir)
1691 define_test(2_ident_self_matching_re_hwe_dir)
1692 define_test(2_ident_self_matching_re_hwe)
1693 define_test(2_ident_not_self_matching_re_hwe_dir)
1694 define_test(2_matching_res_hwe_dir)
1695 define_test(2_nonmatching_res_hwe_dir)
1696 define_test(blacklist)
1697 define_test(blacklist_wwid)
1698 define_test(blacklist_wwid_1)
1699 define_test(blacklist_regex)
1700 define_test(blacklist_regex_inv)
1701 define_test(blacklist_regex_matching)
1702 define_test(product_blacklist)
1703 define_test(product_blacklist_matching)
1704 define_test(multipath_config)
1705 define_test(multipath_config_2)
1706 define_test(multipath_config_3)
1707
1708 #define test_entry(x) \
1709         cmocka_unit_test_setup(run_##x, setup_##x)
1710
1711 static int test_hwtable(void)
1712 {
1713         const struct CMUnitTest tests[] = {
1714                 cmocka_unit_test(test_sanity_globals),
1715                 test_entry(internal_nvme),
1716                 test_entry(string_hwe),
1717                 test_entry(broken_hwe),
1718                 test_entry(broken_hwe_dir),
1719                 test_entry(quoted_hwe),
1720                 test_entry(regex_hwe),
1721                 test_entry(regex_string_hwe),
1722                 test_entry(regex_string_hwe_dir),
1723                 test_entry(regex_2_strings_hwe_dir),
1724                 test_entry(string_regex_hwe_dir),
1725                 test_entry(2_ident_strings_hwe),
1726                 test_entry(2_ident_strings_both_dir),
1727                 test_entry(2_ident_strings_both_dir_w_prev),
1728                 test_entry(2_ident_strings_hwe_dir),
1729                 test_entry(3_ident_strings_hwe_dir),
1730                 test_entry(2_ident_self_matching_re_hwe_dir),
1731                 test_entry(2_ident_self_matching_re_hwe),
1732                 test_entry(2_ident_not_self_matching_re_hwe_dir),
1733                 test_entry(2_matching_res_hwe_dir),
1734                 test_entry(2_nonmatching_res_hwe_dir),
1735                 test_entry(blacklist),
1736                 test_entry(blacklist_wwid),
1737                 test_entry(blacklist_wwid_1),
1738                 test_entry(blacklist_regex),
1739                 test_entry(blacklist_regex_inv),
1740                 test_entry(blacklist_regex_matching),
1741                 test_entry(product_blacklist),
1742                 test_entry(product_blacklist_matching),
1743                 test_entry(multipath_config),
1744                 test_entry(multipath_config_2),
1745                 test_entry(multipath_config_3),
1746         };
1747
1748         return cmocka_run_group_tests(tests, setup, teardown);
1749 }
1750
1751 int main(void)
1752 {
1753         int ret = 0;
1754
1755         ret += test_hwtable();
1756         return ret;
1757 }