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