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