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