fixup "libmultipath: merge hwentries inside a conf file"
[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(prio_name(&pp->prio), DEFAULT_PRIO);
665
666         /* boo:bar doesn't match */
667         pp = mock_path(vnd_boo.value, prd_bar.value);
668         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
669 }
670
671 static int setup_broken_hwe(void **state)
672 {
673         struct hwt_state *hwt = CHECK_STATE(state);
674         const struct key_value kv[] = { vnd_foo, prio_emc };
675
676         WRITE_ONE_DEVICE(hwt, kv);
677         SET_TEST_FUNC(hwt, test_broken_hwe);
678         return 0;
679 }
680
681 /*
682  * Like test_broken_hwe, but in config_dir file.
683  */
684 static int setup_broken_hwe_dir(void **state)
685 {
686         struct hwt_state *hwt = CHECK_STATE(state);
687         const struct key_value kv[] = { vnd_foo, prio_emc };
688
689         begin_config(hwt);
690         begin_section_all(hwt, "devices");
691         write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv), kv);
692         end_section_all(hwt);
693         finish_config(hwt);
694         hwt->test = test_broken_hwe;
695         hwt->test_name = "test_broken_hwe_dir";
696         return 0;
697 }
698
699 /*
700  * Device section with a single regex entry ("^.foo:(bar|baz|ba\.)$")
701  */
702 static void test_regex_hwe(const struct hwt_state *hwt)
703 {
704         struct path *pp;
705
706         /* foo:bar matches */
707         pp = mock_path(vnd_foo.value, prd_bar.value);
708         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
709
710         /* foo:baz matches */
711         pp = mock_path(vnd_foo.value, prd_baz.value);
712         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
713
714         /* boo:baz matches */
715         pp = mock_path(vnd_boo.value, prd_bar.value);
716         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
717
718         /* foo:BAR doesn't match */
719         pp = mock_path(vnd_foo.value, "BAR");
720         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
721
722         /* bboo:bar doesn't match */
723         pp = mock_path("bboo", prd_bar.value);
724         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
725 }
726
727 static int setup_regex_hwe(void **state)
728 {
729         struct hwt_state *hwt = CHECK_STATE(state);
730         const struct key_value kv[] = { vnd_t_oo, prd_ba_s, prio_emc };
731
732         WRITE_ONE_DEVICE(hwt, kv);
733         SET_TEST_FUNC(hwt, test_regex_hwe);
734         return 0;
735 }
736
737 /*
738  * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
739  * kv2 a string match (foo:bar) which matches a subset of the regex.
740  * Both are added to the main config file.
741  *
742  * Expected: Devices matching both get properties from both, kv2 taking
743  * precedence. Devices matching kv1 only just get props from kv1.
744  */
745 static void test_regex_string_hwe(const struct hwt_state *hwt)
746 {
747         struct path *pp;
748
749         /* foo:baz matches kv1 */
750         pp = mock_path(vnd_foo.value, prd_baz.value);
751         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
752         TEST_PROP(pp->getuid, NULL);
753         TEST_PROP(pp->checker.name, chk_hp.value);
754
755         /* boo:baz matches kv1 */
756         pp = mock_path(vnd_boo.value, prd_baz.value);
757         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
758         TEST_PROP(pp->getuid, NULL);
759         TEST_PROP(pp->checker.name, chk_hp.value);
760
761         /* .oo:ba. matches kv1 */
762         pp = mock_path(vnd__oo.value, prd_ba_.value);
763         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
764         TEST_PROP(pp->getuid, NULL);
765         TEST_PROP(pp->checker.name, chk_hp.value);
766
767         /* .foo:(bar|baz|ba\.) doesn't match */
768         pp = mock_path(vnd__oo.value, prd_ba_s.value);
769         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
770         TEST_PROP(pp->getuid, NULL);
771         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
772
773         /* foo:bar matches kv2 and kv1 */
774         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
775         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
776         TEST_PROP(pp->getuid, gui_foo.value);
777         TEST_PROP(pp->checker.name, chk_hp.value);
778 }
779
780 static int setup_regex_string_hwe(void **state)
781 {
782         struct hwt_state *hwt = CHECK_STATE(state);
783         const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
784         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
785
786         WRITE_TWO_DEVICES(hwt, kv1, kv2);
787         SET_TEST_FUNC(hwt, test_regex_string_hwe);
788         return 0;
789 }
790
791 /*
792  * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
793  * kv2 a string match (foo:bar) which matches a subset of the regex.
794  * kv1 is added to the main config file, kv2 to a config_dir file.
795  * This case is more important as you may think, because it's equivalent
796  * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
797  *
798  * Expected: Devices matching kv2 (and thus, both) get properties
799  * from both, kv2 taking precedence.
800  * Devices matching kv1 only just get props from kv1.
801  */
802 static void test_regex_string_hwe_dir(const struct hwt_state *hwt)
803 {
804         struct path *pp;
805
806         /* foo:baz matches kv1 */
807         pp = mock_path(vnd_foo.value, prd_baz.value);
808         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
809         TEST_PROP(pp->getuid, NULL);
810         TEST_PROP(pp->checker.name, chk_hp.value);
811
812         /* boo:baz matches kv1 */
813         pp = mock_path(vnd_boo.value, prd_baz.value);
814         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
815         TEST_PROP(pp->getuid, NULL);
816         TEST_PROP(pp->checker.name, chk_hp.value);
817
818         /* .oo:ba. matches kv1 */
819         pp = mock_path(vnd__oo.value, prd_ba_.value);
820         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
821         TEST_PROP(pp->getuid, NULL);
822         TEST_PROP(pp->checker.name, chk_hp.value);
823
824         /* .oo:(bar|baz|ba\.)$ doesn't match */
825         pp = mock_path(vnd__oo.value, prd_ba_s.value);
826         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
827         TEST_PROP(pp->getuid, NULL);
828         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
829
830         /* foo:bar matches kv2 */
831         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
832         /* Later match takes prio */
833         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
834         TEST_PROP(pp->getuid, gui_foo.value);
835         TEST_PROP(pp->checker.name, chk_hp.value);
836 }
837
838 static int setup_regex_string_hwe_dir(void **state)
839 {
840         const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
841         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
842         struct hwt_state *hwt = CHECK_STATE(state);
843
844         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
845         SET_TEST_FUNC(hwt, test_regex_string_hwe_dir);
846         return 0;
847 }
848
849 /*
850  * Three device entries, kv1 is a regex match and kv2 and kv3 string
851  * matches, where kv3 is a substring of kv2. All in different config
852  * files.
853  *
854  * Expected: Devices matching kv3 get props from all, devices matching
855  * kv2 from kv2 and kv1, and devices matching kv1 only just from kv1.
856  */
857 static void test_regex_2_strings_hwe_dir(const struct hwt_state *hwt)
858 {
859         struct path *pp;
860
861         /* foo:baz matches kv1 */
862         pp = mock_path(vnd_foo.value, prd_baz.value);
863         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
864         TEST_PROP(pp->getuid, NULL);
865         TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
866         TEST_PROP(pp->checker.name, chk_hp.value);
867
868         /* boo:baz doesn't match */
869         pp = mock_path(vnd_boo.value, prd_baz.value);
870         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
871         TEST_PROP(pp->getuid, NULL);
872         TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
873         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
874
875         /* foo:bar matches kv2 and kv1 */
876         pp = mock_path(vnd_foo.value, prd_bar.value);
877         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
878         TEST_PROP(pp->getuid, NULL);
879         TEST_PROP(pp->uid_attribute, uid_baz.value);
880         TEST_PROP(pp->checker.name, chk_hp.value);
881
882         /* foo:barz matches kv3 and kv2 and kv1 */
883         pp = mock_path_flags(vnd_foo.value, prd_barz.value, USE_GETUID);
884         TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
885         TEST_PROP(pp->getuid, gui_foo.value);
886         TEST_PROP(pp->uid_attribute, NULL);
887         TEST_PROP(pp->checker.name, chk_hp.value);
888 }
889
890 static int setup_regex_2_strings_hwe_dir(void **state)
891 {
892         const struct key_value kv1[] = { vnd_foo, prd_ba_, prio_emc, chk_hp };
893         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, uid_baz };
894         const struct key_value kv3[] = { vnd_foo, prd_barz,
895                                          prio_rdac, gui_foo };
896         struct hwt_state *hwt = CHECK_STATE(state);
897
898         begin_config(hwt);
899         begin_section_all(hwt, "devices");
900         write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
901         write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
902         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv3), kv3);
903         end_section_all(hwt);
904         finish_config(hwt);
905         SET_TEST_FUNC(hwt, test_regex_2_strings_hwe_dir);
906         return 0;
907 }
908
909 /*
910  * Like test_regex_string_hwe_dir, but the order of kv1 and kv2 is exchanged.
911  *
912  * Expected: Devices matching kv1 (and thus, both) get properties
913  * from both, kv1 taking precedence.
914  * Devices matching kv1 only just get props from kv1.
915  */
916 static void test_string_regex_hwe_dir(const struct hwt_state *hwt)
917 {
918         struct path *pp;
919
920         /* foo:bar matches kv2 and kv1 */
921         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
922         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
923         TEST_PROP(pp->getuid, gui_foo.value);
924         TEST_PROP(pp->checker.name, chk_hp.value);
925
926         /* foo:baz matches kv1 */
927         pp = mock_path(vnd_foo.value, prd_baz.value);
928         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
929         TEST_PROP(pp->getuid, NULL);
930         TEST_PROP(pp->checker.name, chk_hp.value);
931
932         /* boo:baz matches kv1 */
933         pp = mock_path(vnd_boo.value, prd_baz.value);
934         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
935         TEST_PROP(pp->getuid, NULL);
936         TEST_PROP(pp->checker.name, chk_hp.value);
937
938         /* .oo:ba. matches kv1 */
939         pp = mock_path(vnd__oo.value, prd_ba_.value);
940         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
941         TEST_PROP(pp->getuid, NULL);
942         TEST_PROP(pp->checker.name, chk_hp.value);
943
944         /* .oo:(bar|baz|ba\.)$ doesn't match */
945         pp = mock_path(vnd__oo.value, prd_ba_s.value);
946         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
947         TEST_PROP(pp->getuid, NULL);
948         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
949 }
950
951 static int setup_string_regex_hwe_dir(void **state)
952 {
953         const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
954         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
955         struct hwt_state *hwt = CHECK_STATE(state);
956
957         WRITE_TWO_DEVICES_W_DIR(hwt, kv2, kv1);
958         SET_TEST_FUNC(hwt, test_string_regex_hwe_dir);
959         return 0;
960 }
961
962 /*
963  * Two identical device entries kv1 and kv2, trival regex ("string").
964  * Both are added to the main config file.
965  * These entries are NOT merged.
966  * This could happen in a large multipath.conf file.
967  *
968  * Expected: matching devices get props from both, kv2 taking precedence.
969  */
970 static void test_2_ident_strings_hwe(const struct hwt_state *hwt)
971 {
972         struct path *pp;
973
974         /* foo:baz doesn't match */
975         pp = mock_path(vnd_foo.value, prd_baz.value);
976         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
977         TEST_PROP(pp->getuid, NULL);
978         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
979
980         /* foo:bar matches both */
981         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
982         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
983         TEST_PROP(pp->getuid, gui_foo.value);
984         TEST_PROP(pp->checker.name, chk_hp.value);
985 }
986
987 static int setup_2_ident_strings_hwe(void **state)
988 {
989         const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
990         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
991         struct hwt_state *hwt = CHECK_STATE(state);
992
993         WRITE_TWO_DEVICES(hwt, kv1, kv2);
994         SET_TEST_FUNC(hwt, test_2_ident_strings_hwe);
995         return 0;
996 }
997
998 /*
999  * Two identical device entries kv1 and kv2, trival regex ("string").
1000  * Both are added to an extra config file.
1001  * This could happen in a large multipath.conf file.
1002  *
1003  * Expected: matching devices get props from both, kv2 taking precedence.
1004  */
1005 static void test_2_ident_strings_both_dir(const struct hwt_state *hwt)
1006 {
1007         struct path *pp;
1008
1009         /* foo:baz doesn't match */
1010         pp = mock_path(vnd_foo.value, prd_baz.value);
1011         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1012         TEST_PROP(pp->getuid, NULL);
1013         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1014
1015         /* foo:bar matches both */
1016         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1017         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1018         TEST_PROP(pp->getuid, gui_foo.value);
1019         TEST_PROP(pp->checker.name, chk_hp.value);
1020 }
1021
1022 static int setup_2_ident_strings_both_dir(void **state)
1023 {
1024         const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1025         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1026         struct hwt_state *hwt = CHECK_STATE(state);
1027
1028         begin_config(hwt);
1029         begin_section_all(hwt, "devices");
1030         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1031         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1032         end_section_all(hwt);
1033         finish_config(hwt);
1034         SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir);
1035         return 0;
1036 }
1037
1038 /*
1039  * Two identical device entries kv1 and kv2, trival regex ("string").
1040  * Both are added to an extra config file.
1041  * An empty entry kv0 with the same string exists in the main config file.
1042  *
1043  * Expected: matching devices get props from both, kv2 taking precedence.
1044  */
1045 static void test_2_ident_strings_both_dir_w_prev(const struct hwt_state *hwt)
1046 {
1047         struct path *pp;
1048
1049         /* foo:baz doesn't match */
1050         pp = mock_path(vnd_foo.value, prd_baz.value);
1051         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1052         TEST_PROP(pp->getuid, NULL);
1053         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1054
1055         /* foo:bar matches both */
1056         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1057         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1058         TEST_PROP(pp->getuid, gui_foo.value);
1059         TEST_PROP(pp->checker.name, chk_hp.value);
1060 }
1061
1062 static int setup_2_ident_strings_both_dir_w_prev(void **state)
1063 {
1064         struct hwt_state *hwt = CHECK_STATE(state);
1065
1066         const struct key_value kv0[] = { vnd_foo, prd_bar };
1067         const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1068         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1069
1070         begin_config(hwt);
1071         begin_section_all(hwt, "devices");
1072         write_device(hwt->config_file, ARRAY_SIZE(kv0), kv0);
1073         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1074         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1075         end_section_all(hwt);
1076         finish_config(hwt);
1077         SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir_w_prev);
1078         return 0;
1079 }
1080
1081 /*
1082  * Two identical device entries kv1 and kv2, trival regex ("string").
1083  * kv1 is added to the main config file, kv2 to a config_dir file.
1084  * These entries are merged.
1085  * This case is more important as you may think, because it's equivalent
1086  * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1087  *
1088  * Expected: matching devices get props from both, kv2 taking precedence.
1089  */
1090 static void test_2_ident_strings_hwe_dir(const struct hwt_state *hwt)
1091 {
1092         struct path *pp;
1093
1094         /* foo:baz doesn't match */
1095         pp = mock_path(vnd_foo.value, prd_baz.value);
1096         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1097         TEST_PROP(pp->getuid, NULL);
1098         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1099
1100         /* foo:bar matches both */
1101         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1102         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1103         TEST_PROP(pp->getuid, gui_foo.value);
1104         TEST_PROP(pp->checker.name, chk_hp.value);
1105 }
1106
1107 static int setup_2_ident_strings_hwe_dir(void **state)
1108 {
1109         const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1110         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1111         struct hwt_state *hwt = CHECK_STATE(state);
1112
1113         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1114         SET_TEST_FUNC(hwt, test_2_ident_strings_hwe_dir);
1115         return 0;
1116 }
1117
1118 /*
1119  * Like test_2_ident_strings_hwe_dir, but this time the config_dir file
1120  * contains an additional, empty entry (kv0).
1121  *
1122  * Expected: matching devices get props from kv1 and kv2, kv2 taking precedence.
1123  */
1124 static void test_3_ident_strings_hwe_dir(const struct hwt_state *hwt)
1125 {
1126         struct path *pp;
1127
1128         /* foo:baz doesn't match */
1129         pp = mock_path(vnd_foo.value, prd_baz.value);
1130         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1131         TEST_PROP(pp->getuid, NULL);
1132         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1133
1134         /* foo:bar matches both */
1135         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1136         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1137         TEST_PROP(pp->getuid, gui_foo.value);
1138         TEST_PROP(pp->checker.name, chk_hp.value);
1139 }
1140
1141 static int setup_3_ident_strings_hwe_dir(void **state)
1142 {
1143         const struct key_value kv0[] = { vnd_foo, prd_bar };
1144         const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1145         const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1146         struct hwt_state *hwt = CHECK_STATE(state);
1147
1148         begin_config(hwt);
1149         begin_section_all(hwt, "devices");
1150         write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1151         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv0), kv0);
1152         write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1153         end_section_all(hwt);
1154         finish_config(hwt);
1155         SET_TEST_FUNC(hwt, test_3_ident_strings_hwe_dir);
1156         return 0;
1157 }
1158
1159 /*
1160  * Two identical device entries kv1 and kv2, non-trival regex that matches
1161  * itself (string ".oo" matches regex ".oo").
1162  * kv1 is added to the main config file, kv2 to a config_dir file.
1163  * This case is more important as you may think, because it's equivalent
1164  * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1165  *
1166  * Expected: matching devices get props from both, kv2 taking precedence.
1167  */
1168 static void test_2_ident_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1169 {
1170         struct path *pp;
1171
1172         /* foo:baz doesn't match */
1173         pp = mock_path(vnd_foo.value, prd_baz.value);
1174         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1175         TEST_PROP(pp->getuid, NULL);
1176         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1177
1178         /* foo:bar matches both */
1179         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1180         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1181         TEST_PROP(pp->getuid, gui_foo.value);
1182         TEST_PROP(pp->checker.name, chk_hp.value);
1183 }
1184
1185 static int setup_2_ident_self_matching_re_hwe_dir(void **state)
1186 {
1187         const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1188         const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1189         struct hwt_state *hwt = CHECK_STATE(state);
1190
1191         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1192         SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe_dir);
1193         return 0;
1194 }
1195
1196 /*
1197  * Two identical device entries kv1 and kv2, non-trival regex that matches
1198  * itself (string ".oo" matches regex ".oo").
1199  * kv1 and kv2 are added to the main config file.
1200  *
1201  * Expected: matching devices get props from both, kv2 taking precedence.
1202  */
1203 static void test_2_ident_self_matching_re_hwe(const struct hwt_state *hwt)
1204 {
1205         struct path *pp;
1206
1207         /* foo:baz doesn't match */
1208         pp = mock_path(vnd_foo.value, prd_baz.value);
1209         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1210         TEST_PROP(pp->getuid, NULL);
1211         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1212
1213         /* foo:bar matches */
1214         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1215         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1216         TEST_PROP(pp->getuid, gui_foo.value);
1217         TEST_PROP(pp->checker.name, chk_hp.value);
1218 }
1219
1220 static int setup_2_ident_self_matching_re_hwe(void **state)
1221 {
1222         const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1223         const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1224         struct hwt_state *hwt = CHECK_STATE(state);
1225
1226         WRITE_TWO_DEVICES(hwt, kv1, kv2);
1227         SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe);
1228         return 0;
1229 }
1230
1231 /*
1232  * Two identical device entries kv1 and kv2, non-trival regex that doesn't
1233  * match itself (string "^.oo" doesn't match regex "^.oo").
1234  * kv1 is added to the main config file, kv2 to a config_dir file.
1235  * This case is more important as you may think, see above.
1236  *
1237  * Expected: matching devices get props from both, kv2 taking precedence.
1238  */
1239 static void
1240 test_2_ident_not_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1241 {
1242         struct path *pp;
1243
1244         /* foo:baz doesn't match */
1245         pp = mock_path(vnd_foo.value, prd_baz.value);
1246         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1247         TEST_PROP(pp->getuid, NULL);
1248         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1249
1250         /* foo:bar matches both */
1251         pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1252         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1253         TEST_PROP(pp->getuid, gui_foo.value);
1254         TEST_PROP(pp->checker.name, chk_hp.value);
1255 }
1256
1257 static int setup_2_ident_not_self_matching_re_hwe_dir(void **state)
1258 {
1259         const struct key_value kv1[] = { vnd_t_oo, prd_bar, prio_emc, chk_hp };
1260         const struct key_value kv2[] = { vnd_t_oo, prd_bar, prio_hds, gui_foo };
1261         struct hwt_state *hwt = CHECK_STATE(state);
1262
1263         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1264         SET_TEST_FUNC(hwt, test_2_ident_not_self_matching_re_hwe_dir);
1265         return 0;
1266 }
1267
1268 /*
1269  * Two different non-trivial regexes kv1, kv2. The 1st one matches the 2nd, but
1270  * it doesn't match all possible strings matching the second.
1271  * ("ba[zy]" matches regex "ba[[rxy]", but "baz" does not).
1272  *
1273  * Expected: Devices matching both regexes get properties from both, kv2
1274  * taking precedence. Devices matching just one regex get properties from
1275  * that one regex only.
1276  */
1277 static void test_2_matching_res_hwe_dir(const struct hwt_state *hwt)
1278 {
1279         struct path *pp;
1280
1281         /* foo:bar matches k1 only */
1282         pp = mock_path(vnd_foo.value, prd_bar.value);
1283         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1284         TEST_PROP(pp->getuid, NULL);
1285         TEST_PROP(pp->checker.name, chk_hp.value);
1286
1287         /* foo:bay matches k1 and k2 */
1288         pp = mock_path_flags(vnd_foo.value, "bay", USE_GETUID);
1289         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1290         TEST_PROP(pp->getuid, gui_foo.value);
1291         TEST_PROP(pp->checker.name, chk_hp.value);
1292
1293         /* foo:baz matches k2 only. */
1294         pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1295         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1296         TEST_PROP(pp->getuid, gui_foo.value);
1297         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1298 }
1299
1300 static int setup_2_matching_res_hwe_dir(void **state)
1301 {
1302         const struct key_value kv1[] = { vnd_foo, prd_barx, prio_emc, chk_hp };
1303         const struct key_value kv2[] = { vnd_foo, prd_bazy, prio_hds, gui_foo };
1304         struct hwt_state *hwt = CHECK_STATE(state);
1305
1306         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1307         SET_TEST_FUNC(hwt, test_2_matching_res_hwe_dir);
1308         return 0;
1309 }
1310
1311 /*
1312  * Two different non-trivial regexes which match the same set of strings.
1313  * But they don't match each other.
1314  * "baz" matches both regex "ba[zy]" and "ba(z|y)"
1315  *
1316  * Expected: matching devices get properties from both, kv2 taking precedence.
1317  */
1318 static void test_2_nonmatching_res_hwe_dir(const struct hwt_state *hwt)
1319 {
1320         struct path *pp;
1321
1322         /* foo:bar doesn't match */
1323         pp = mock_path(vnd_foo.value, prd_bar.value);
1324         TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1325         TEST_PROP(pp->getuid, NULL);
1326         TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1327
1328         pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1329         TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1330         TEST_PROP(pp->getuid, gui_foo.value);
1331         TEST_PROP(pp->checker.name, chk_hp.value);
1332 }
1333
1334 static int setup_2_nonmatching_res_hwe_dir(void **state)
1335 {
1336         const struct key_value kv1[] = { vnd_foo, prd_bazy, prio_emc, chk_hp };
1337         const struct key_value kv2[] = { vnd_foo, prd_bazy1,
1338                                          prio_hds, gui_foo };
1339         struct hwt_state *hwt = CHECK_STATE(state);
1340
1341         WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1342         SET_TEST_FUNC(hwt, test_2_nonmatching_res_hwe_dir);
1343         return 0;
1344 }
1345
1346 /*
1347  * Simple blacklist test.
1348  *
1349  * NOTE: test failures in blacklisting tests will manifest as cmocka errors
1350  * "Could not get value to mock function XYZ", because pathinfo() takes
1351  * different code paths for blacklisted devices.
1352  */
1353 static void test_blacklist(const struct hwt_state *hwt)
1354 {
1355         mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1356         mock_path(vnd_foo.value, prd_baz.value);
1357 }
1358
1359 static int setup_blacklist(void **state)
1360 {
1361         const struct key_value kv1[] = { vnd_foo, prd_bar };
1362         struct hwt_state *hwt = CHECK_STATE(state);
1363
1364         begin_config(hwt);
1365         begin_section_all(hwt, "blacklist");
1366         write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1367         end_section_all(hwt);
1368         finish_config(hwt);
1369         SET_TEST_FUNC(hwt, test_blacklist);
1370         return 0;
1371 }
1372
1373 /*
1374  * Simple blacklist test with regex and exception
1375  */
1376 static void test_blacklist_regex(const struct hwt_state *hwt)
1377 {
1378         mock_path(vnd_foo.value, prd_bar.value);
1379         mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1380         mock_path(vnd_foo.value, prd_bam.value);
1381 }
1382
1383 static int setup_blacklist_regex(void **state)
1384 {
1385         const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1386         const struct key_value kv2[] = { vnd_foo, prd_bar };
1387         struct hwt_state *hwt = CHECK_STATE(state);
1388
1389         hwt = CHECK_STATE(state);
1390         begin_config(hwt);
1391         begin_section_all(hwt, "blacklist");
1392         write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1393         end_section_all(hwt);
1394         begin_section_all(hwt, "blacklist_exceptions");
1395         write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1396         end_section_all(hwt);
1397         finish_config(hwt);
1398         SET_TEST_FUNC(hwt, test_blacklist_regex);
1399         return 0;
1400 }
1401
1402 /*
1403  * Simple blacklist test with regex and exception
1404  * config file order inverted wrt test_blacklist_regex
1405  */
1406 static int setup_blacklist_regex_inv(void **state)
1407 {
1408         const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1409         const struct key_value kv2[] = { vnd_foo, prd_bar };
1410         struct hwt_state *hwt = CHECK_STATE(state);
1411
1412         begin_config(hwt);
1413         begin_section_all(hwt, "blacklist");
1414         write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv1), kv1);
1415         end_section_all(hwt);
1416         begin_section_all(hwt, "blacklist_exceptions");
1417         write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2);
1418         end_section_all(hwt);
1419         finish_config(hwt);
1420         SET_TEST_FUNC(hwt, test_blacklist_regex);
1421         return 0;
1422 }
1423
1424 /*
1425  * Simple blacklist test with regex and exception
1426  * config file order inverted wrt test_blacklist_regex
1427  */
1428 static void test_blacklist_regex_matching(const struct hwt_state *hwt)
1429 {
1430         mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1431         mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1432         mock_path(vnd_foo.value, prd_bam.value);
1433 }
1434
1435 static int setup_blacklist_regex_matching(void **state)
1436 {
1437         const struct key_value kv1[] = { vnd_foo, prd_barx };
1438         const struct key_value kv2[] = { vnd_foo, prd_bazy };
1439         struct hwt_state *hwt = CHECK_STATE(state);
1440
1441         begin_config(hwt);
1442         begin_section_all(hwt, "blacklist");
1443         write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1444         write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1445         end_section_all(hwt);
1446         finish_config(hwt);
1447         SET_TEST_FUNC(hwt, test_blacklist_regex_matching);
1448         return 0;
1449 }
1450
1451 /*
1452  * Test for blacklisting by WWID
1453  *
1454  * Note that default_wwid is a substring of default_wwid_1. Because
1455  * matching is done by regex, both paths are blacklisted.
1456  */
1457 static void test_blacklist_wwid(const struct hwt_state *hwt)
1458 {
1459         mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_WWID);
1460         mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1461                              BL_BY_WWID);
1462 }
1463
1464 static int setup_blacklist_wwid(void **state)
1465 {
1466         const struct key_value kv[] = { wwid_test };
1467         struct hwt_state *hwt = CHECK_STATE(state);
1468
1469         begin_config(hwt);
1470         write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1471         finish_config(hwt);
1472         SET_TEST_FUNC(hwt, test_blacklist_wwid);
1473         return 0;
1474 }
1475
1476 /*
1477  * Test for blacklisting by WWID
1478  *
1479  * Here the blacklist contains only default_wwid_1. Thus the path
1480  * with default_wwid is NOT blacklisted.
1481  */
1482 static void test_blacklist_wwid_1(const struct hwt_state *hwt)
1483 {
1484         mock_path(vnd_foo.value, prd_bar.value);
1485         mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1486                              BL_BY_WWID);
1487 }
1488
1489 static int setup_blacklist_wwid_1(void **state)
1490 {
1491         const struct key_value kv[] = { { _wwid, default_wwid_1 }, };
1492         struct hwt_state *hwt = CHECK_STATE(state);
1493
1494         begin_config(hwt);
1495         write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1496         finish_config(hwt);
1497         SET_TEST_FUNC(hwt, test_blacklist_wwid_1);
1498         return 0;
1499 }
1500
1501 /*
1502  * Test for product_blacklist. Two entries blacklisting each other.
1503  *
1504  * Expected: Both are blacklisted.
1505  */
1506 static void test_product_blacklist(const struct hwt_state *hwt)
1507 {
1508         mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1509         mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1510         mock_path(vnd_foo.value, prd_bam.value);
1511 }
1512
1513 static int setup_product_blacklist(void **state)
1514 {
1515         const struct key_value kv1[] = { vnd_foo, prd_bar, bl_baz };
1516         const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bar };
1517         struct hwt_state *hwt = CHECK_STATE(state);
1518
1519         WRITE_TWO_DEVICES(hwt, kv1, kv2);
1520         SET_TEST_FUNC(hwt, test_product_blacklist);
1521         return 0;
1522 }
1523
1524 /*
1525  * Test for product_blacklist. The second regex "matches" the first.
1526  * This is a pathological example.
1527  *
1528  * Expected: "foo:bar", "foo:baz" are blacklisted.
1529  */
1530 static void test_product_blacklist_matching(const struct hwt_state *hwt)
1531 {
1532         mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1533         mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1534         mock_path(vnd_foo.value, prd_bam.value);
1535 }
1536
1537 static int setup_product_blacklist_matching(void **state)
1538 {
1539         const struct key_value kv1[] = { vnd_foo, prd_bar, bl_barx };
1540         const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bazy };
1541         struct hwt_state *hwt = CHECK_STATE(state);
1542
1543         WRITE_TWO_DEVICES(hwt, kv1, kv2);
1544         SET_TEST_FUNC(hwt, test_product_blacklist_matching);
1545         return 0;
1546 }
1547
1548 /*
1549  * Basic test for multipath-based configuration.
1550  *
1551  * Expected: properties, including pp->prio, are taken from multipath
1552  * section.
1553  */
1554 static void test_multipath_config(const struct hwt_state *hwt)
1555 {
1556         struct path *pp;
1557         struct multipath *mp;
1558
1559         pp = mock_path(vnd_foo.value, prd_bar.value);
1560         mp = mock_multipath(pp);
1561         assert_ptr_not_equal(mp->mpe, NULL);
1562         TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1563         assert_int_equal(mp->minio, atoi(minio_99.value));
1564         TEST_PROP(pp->uid_attribute, uid_baz.value);
1565
1566         /* test different wwid */
1567         pp = mock_path_wwid(vnd_foo.value, prd_bar.value, default_wwid_1);
1568         mp = mock_multipath(pp);
1569         // assert_ptr_equal(mp->mpe, NULL);
1570         TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1571         assert_int_equal(mp->minio, DEFAULT_MINIO_RQ);
1572         TEST_PROP(pp->uid_attribute, uid_baz.value);
1573 }
1574
1575 static int setup_multipath_config(void **state)
1576 {
1577         struct hwt_state *hwt = CHECK_STATE(state);
1578         const struct key_value kvm[] = { wwid_test, prio_rdac, minio_99 };
1579         const struct key_value kvp[] = { vnd_foo, prd_bar, prio_emc, uid_baz };
1580
1581         begin_config(hwt);
1582         begin_section_all(hwt, "devices");
1583         write_section(hwt->conf_dir_file[0], "device", ARRAY_SIZE(kvp), kvp);
1584         end_section_all(hwt);
1585         begin_section_all(hwt, "multipaths");
1586         write_section(hwt->config_file, "multipath", ARRAY_SIZE(kvm), kvm);
1587         end_section_all(hwt);
1588         finish_config(hwt);
1589         SET_TEST_FUNC(hwt, test_multipath_config);
1590         return 0;
1591 }
1592
1593 /*
1594  * Basic test for multipath-based configuration. Two sections for the same wwid.
1595  *
1596  * Expected: properties are taken from both multipath sections, later taking
1597  * precedence
1598  */
1599 static void test_multipath_config_2(const struct hwt_state *hwt)
1600 {
1601         struct path *pp;
1602         struct multipath *mp;
1603
1604         pp = mock_path(vnd_foo.value, prd_bar.value);
1605         mp = mock_multipath(pp);
1606         assert_ptr_not_equal(mp, NULL);
1607         assert_ptr_not_equal(mp->mpe, NULL);
1608         TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1609         assert_int_equal(mp->minio, atoi(minio_99.value));
1610         assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1611 }
1612
1613 static int setup_multipath_config_2(void **state)
1614 {
1615         const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1616         const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1617         struct hwt_state *hwt = CHECK_STATE(state);
1618
1619         begin_config(hwt);
1620         begin_section_all(hwt, "multipaths");
1621         write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1622         write_section(hwt->conf_dir_file[1], "multipath", ARRAY_SIZE(kv2), kv2);
1623         end_section_all(hwt);
1624         finish_config(hwt);
1625         SET_TEST_FUNC(hwt, test_multipath_config_2);
1626         return 0;
1627 }
1628
1629 /*
1630  * Same as test_multipath_config_2, both entries in the same config file.
1631  *
1632  * Expected: properties are taken from both multipath sections.
1633  */
1634 static void test_multipath_config_3(const struct hwt_state *hwt)
1635 {
1636         struct path *pp;
1637         struct multipath *mp;
1638
1639         pp = mock_path(vnd_foo.value, prd_bar.value);
1640         mp = mock_multipath(pp);
1641         assert_ptr_not_equal(mp, NULL);
1642         assert_ptr_not_equal(mp->mpe, NULL);
1643         TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1644         assert_int_equal(mp->minio, atoi(minio_99.value));
1645         assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1646 }
1647
1648 static int setup_multipath_config_3(void **state)
1649 {
1650         const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1651         const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1652         struct hwt_state *hwt = CHECK_STATE(state);
1653
1654         begin_config(hwt);
1655         begin_section_all(hwt, "multipaths");
1656         write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1657         write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv2), kv2);
1658         end_section_all(hwt);
1659         finish_config(hwt);
1660         SET_TEST_FUNC(hwt, test_multipath_config_3);
1661         return 0;
1662 }
1663
1664 /*
1665  * Create wrapper functions around test_driver() to avoid that cmocka
1666  * always uses the same test name. That makes it easier to read test results.
1667  */
1668
1669 #define define_test(x)                          \
1670         static void run_##x(void **state)       \
1671         {                                       \
1672                 return test_driver(state);      \
1673         }
1674
1675 define_test(string_hwe)
1676 define_test(broken_hwe)
1677 define_test(broken_hwe_dir)
1678 define_test(quoted_hwe)
1679 define_test(internal_nvme)
1680 define_test(regex_hwe)
1681 define_test(regex_string_hwe)
1682 define_test(regex_string_hwe_dir)
1683 define_test(regex_2_strings_hwe_dir)
1684 define_test(string_regex_hwe_dir)
1685 define_test(2_ident_strings_hwe)
1686 define_test(2_ident_strings_both_dir)
1687 define_test(2_ident_strings_both_dir_w_prev)
1688 define_test(2_ident_strings_hwe_dir)
1689 define_test(3_ident_strings_hwe_dir)
1690 define_test(2_ident_self_matching_re_hwe_dir)
1691 define_test(2_ident_self_matching_re_hwe)
1692 define_test(2_ident_not_self_matching_re_hwe_dir)
1693 define_test(2_matching_res_hwe_dir)
1694 define_test(2_nonmatching_res_hwe_dir)
1695 define_test(blacklist)
1696 define_test(blacklist_wwid)
1697 define_test(blacklist_wwid_1)
1698 define_test(blacklist_regex)
1699 define_test(blacklist_regex_inv)
1700 define_test(blacklist_regex_matching)
1701 define_test(product_blacklist)
1702 define_test(product_blacklist_matching)
1703 define_test(multipath_config)
1704 define_test(multipath_config_2)
1705 define_test(multipath_config_3)
1706
1707 #define test_entry(x) \
1708         cmocka_unit_test_setup(run_##x, setup_##x)
1709
1710 static int test_hwtable(void)
1711 {
1712         const struct CMUnitTest tests[] = {
1713                 cmocka_unit_test(test_sanity_globals),
1714                 test_entry(internal_nvme),
1715                 test_entry(string_hwe),
1716                 test_entry(broken_hwe),
1717                 test_entry(broken_hwe_dir),
1718                 test_entry(quoted_hwe),
1719                 test_entry(regex_hwe),
1720                 test_entry(regex_string_hwe),
1721                 test_entry(regex_string_hwe_dir),
1722                 test_entry(regex_2_strings_hwe_dir),
1723                 test_entry(string_regex_hwe_dir),
1724                 test_entry(2_ident_strings_hwe),
1725                 test_entry(2_ident_strings_both_dir),
1726                 test_entry(2_ident_strings_both_dir_w_prev),
1727                 test_entry(2_ident_strings_hwe_dir),
1728                 test_entry(3_ident_strings_hwe_dir),
1729                 test_entry(2_ident_self_matching_re_hwe_dir),
1730                 test_entry(2_ident_self_matching_re_hwe),
1731                 test_entry(2_ident_not_self_matching_re_hwe_dir),
1732                 test_entry(2_matching_res_hwe_dir),
1733                 test_entry(2_nonmatching_res_hwe_dir),
1734                 test_entry(blacklist),
1735                 test_entry(blacklist_wwid),
1736                 test_entry(blacklist_wwid_1),
1737                 test_entry(blacklist_regex),
1738                 test_entry(blacklist_regex_inv),
1739                 test_entry(blacklist_regex_matching),
1740                 test_entry(product_blacklist),
1741                 test_entry(product_blacklist_matching),
1742                 test_entry(multipath_config),
1743                 test_entry(multipath_config_2),
1744                 test_entry(multipath_config_3),
1745         };
1746
1747         return cmocka_run_group_tests(tests, setup, teardown);
1748 }
1749
1750 int main(void)
1751 {
1752         int ret = 0;
1753
1754         ret += test_hwtable();
1755         return ret;
1756 }