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