1 /* Set BROKEN to 1 to treat broken behavior as success */
18 #include <sys/sysmacros.h>
20 #include "structs_vec.h"
24 #include "pgpolicies.h"
29 #define N_CONF_FILES 2
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 };
44 FILE *conf_dir_file[N_CONF_FILES];
46 void (*test)(const struct hwt_state *);
47 const char *test_name;
50 #define SET_TEST_FUNC(hwt, func) do { \
52 hwt->test_name = #func; \
55 static struct config *_conf;
59 struct config *get_multipath_config(void)
64 void put_multipath_config(void *arg)
67 void make_config_file_path(char *buf, int buflen,
68 const struct hwt_state *hwt, int i)
70 static const char fn_template[] = "%s/test-%02d.conf";
73 /* main config file */
74 snprintf(buf, buflen, fn_template, hwt->tmpname, 0);
76 snprintf(buf, buflen, fn_template, hwt->dirname, i);
79 static void reset_vecs(struct vectors *vecs)
82 free_pathvec(vecs->pathvec, FREE_PATHS);
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);
90 static void free_hwt(struct hwt_state *hwt)
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]);
102 if (hwt->tmpname != NULL) {
103 make_config_file_path(buf, sizeof(buf), hwt, -1);
109 if (hwt->dirname != NULL) {
110 for (i = 0; i < N_CONF_FILES; i++) {
111 make_config_file_path(buf, sizeof(buf), hwt, i);
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);
129 static int setup(void **state)
131 struct hwt_state *hwt;
136 hwt = calloc(1, sizeof(*hwt));
140 snprintf(buf, sizeof(buf), "%s", tmplate);
141 if (mkdtemp(buf) == NULL) {
142 condlog(0, "mkdtemp: %s", strerror(errno));
145 hwt->tmpname = strdup(buf);
147 snprintf(buf, sizeof(buf), "%s", tmplate);
148 if (mkdtemp(buf) == NULL) {
149 condlog(0, "mkdtemp (2): %s", strerror(errno));
152 hwt->dirname = strdup(buf);
154 make_config_file_path(buf, sizeof(buf), hwt, -1);
155 hwt->config_file = fopen(buf, "w+");
156 if (hwt->config_file == NULL)
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)
166 hwt->vecs = calloc(1, sizeof(*hwt->vecs));
167 if (hwt->vecs == NULL)
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)
183 static int teardown(void **state)
185 if (state == NULL || *state == NULL)
195 * Helpers for creating the config file(s)
198 static void reset_config(FILE *ff)
203 if (ftruncate(fileno(ff), 0) == -1)
204 condlog(1, "ftruncate: %s", strerror(errno));
207 static void reset_configs(const struct hwt_state *hwt)
211 reset_config(hwt->config_file);
212 for (i = 0; i < N_CONF_FILES; i++)
213 reset_config(hwt->conf_dir_file[i]);
216 static void write_key_values(FILE *ff, int nkv, const struct key_value *kv)
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);
225 fprintf(ff, "\t%s \"%s\"\n", kv[i].key, kv[i].value);
229 static void begin_section(FILE *ff, const char *section)
231 fprintf(ff, "%s {\n", section);
234 static void end_section(FILE *ff)
239 static void write_section(FILE *ff, const char *section,
240 int nkv, const struct key_value *kv)
242 begin_section(ff, section);
243 write_key_values(ff, nkv, kv);
247 static void write_defaults(const struct hwt_state *hwt)
249 static const char bindings_name[] = "bindings";
250 static struct key_value defaults[] = {
251 { "config_dir", NULL },
252 { "bindings_file", NULL },
253 { "multipath_dir", NULL },
254 { "detect_prio", "no" },
255 { "detect_checker", "no" },
257 char buf[sizeof(tmplate) + sizeof(bindings_name)];
258 char dirbuf[PATH_MAX];
260 snprintf(buf, sizeof(buf), "%s/%s", hwt->tmpname, bindings_name);
261 defaults[0].value = hwt->dirname;
262 defaults[1].value = buf;
263 assert_ptr_not_equal(getcwd(dirbuf, sizeof(dirbuf)), NULL);
264 strncat(dirbuf, "/lib", sizeof(dirbuf) - 5);
265 defaults[2].value = dirbuf;
266 write_section(hwt->config_file, "defaults",
267 ARRAY_SIZE(defaults), defaults);
270 static void begin_config(const struct hwt_state *hwt)
276 static void begin_section_all(const struct hwt_state *hwt, const char *section)
280 begin_section(hwt->config_file, section);
281 for (i = 0; i < N_CONF_FILES; i++)
282 begin_section(hwt->conf_dir_file[i], section);
285 static void end_section_all(const struct hwt_state *hwt)
289 end_section(hwt->config_file);
290 for (i = 0; i < N_CONF_FILES; i++)
291 end_section(hwt->conf_dir_file[i]);
294 static void finish_config(const struct hwt_state *hwt)
298 fflush(hwt->config_file);
299 for (i = 0; i < N_CONF_FILES; i++) {
300 fflush(hwt->conf_dir_file[i]);
304 static void write_device(FILE *ff, int nkv, const struct key_value *kv)
306 write_section(ff, "device", nkv, kv);
310 * Some macros to avoid boilerplace code
313 #define CHECK_STATE(state) ({ \
314 assert_ptr_not_equal(state, NULL); \
315 assert_ptr_not_equal(*(state), NULL); \
318 #define WRITE_EMPTY_CONF(hwt) do { \
320 finish_config(hwt); \
323 #define WRITE_ONE_DEVICE(hwt, kv) do { \
325 begin_section_all(hwt, "devices"); \
326 write_device(hwt->config_file, ARRAY_SIZE(kv), kv); \
327 end_section_all(hwt); \
328 finish_config(hwt); \
331 #define WRITE_TWO_DEVICES(hwt, kv1, kv2) do { \
333 begin_section_all(hwt, "devices"); \
334 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1); \
335 write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2); \
336 end_section_all(hwt); \
337 finish_config(hwt); \
340 #define WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2) do { \
342 begin_section_all(hwt, "devices"); \
343 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1); \
344 write_device(hwt->conf_dir_file[0], \
345 ARRAY_SIZE(kv2), kv2); \
346 end_section_all(hwt); \
347 finish_config(hwt); \
350 #define LOAD_CONFIG(hwt) ({ \
351 char buf[PATH_MAX]; \
352 struct config *__cf; \
354 make_config_file_path(buf, sizeof(buf), hwt, -1); \
355 __cf = load_config(buf); \
356 assert_ptr_not_equal(__cf, NULL); \
357 assert_ptr_not_equal(__cf->hwtable, NULL); \
358 __cf->verbosity = VERBOSITY; \
359 memcpy(&__cf->version, dm_tgt_version, sizeof(__cf->version)); \
362 #define FREE_CONFIG(conf) do { \
367 static void replace_config(const struct hwt_state *hwt,
368 const char *conf_str)
372 fprintf(hwt->config_file, "%s", conf_str);
373 fflush(hwt->config_file);
374 _conf = LOAD_CONFIG(hwt);
377 #define TEST_PROP(prop, val) do { \
379 assert_ptr_equal(prop, NULL); \
381 assert_ptr_not_equal(prop, NULL); \
382 assert_string_equal(prop, val); \
387 #define TEST_PROP_BROKEN(name, prop, bad, good) do { \
388 condlog(1, "%s: WARNING: Broken test for %s == \"%s\" on line %d, should be \"%s\"", \
389 __func__, name, bad ? bad : "NULL", \
390 __LINE__, good ? good : "NULL"); \
391 TEST_PROP(prop, bad); \
394 #define TEST_PROP_BROKEN(name, prop, bad, good) TEST_PROP(prop, good)
398 * Some predefined key/value pairs
401 static const char _wwid[] = "wwid";
402 static const char _vendor[] = "vendor";
403 static const char _product[] = "product";
404 static const char _prio[] = "prio";
405 static const char _checker[] = "path_checker";
406 static const char _getuid[] = "getuid_callout";
407 static const char _uid_attr[] = "uid_attribute";
408 static const char _bl_product[] = "product_blacklist";
409 static const char _minio[] = "rr_min_io_rq";
410 static const char _no_path_retry[] = "no_path_retry";
412 /* Device identifiers */
413 static const struct key_value vnd_foo = { _vendor, "foo" };
414 static const struct key_value prd_bar = { _product, "bar" };
415 static const struct key_value prd_bam = { _product, "bam" };
416 static const struct key_value prd_baq = { _product, "\"bar\"" };
417 static const struct key_value prd_baqq = { _product, "\"\"bar\"\"" };
418 static const struct key_value prd_barz = { _product, "barz" };
419 static const struct key_value vnd_boo = { _vendor, "boo" };
420 static const struct key_value prd_baz = { _product, "baz" };
421 static const struct key_value wwid_test = { _wwid, default_wwid };
423 /* Regular expresssions */
424 static const struct key_value vnd__oo = { _vendor, ".oo" };
425 static const struct key_value vnd_t_oo = { _vendor, "^.oo" };
426 static const struct key_value prd_ba_ = { _product, "ba." };
427 static const struct key_value prd_ba_s = { _product, "(bar|baz|ba\\.)$" };
428 /* Pathological cases, see below */
429 static const struct key_value prd_barx = { _product, "ba[[rxy]" };
430 static const struct key_value prd_bazy = { _product, "ba[zy]" };
431 static const struct key_value prd_bazy1 = { _product, "ba(z|y)" };
434 static const struct key_value prio_emc = { _prio, "emc" };
435 static const struct key_value prio_hds = { _prio, "hds" };
436 static const struct key_value prio_rdac = { _prio, "rdac" };
437 static const struct key_value chk_hp = { _checker, "hp_sw" };
438 static const struct key_value gui_foo = { _getuid, "/tmp/foo" };
439 static const struct key_value uid_baz = { _uid_attr, "BAZ_ATTR" };
440 static const struct key_value bl_bar = { _bl_product, "bar" };
441 static const struct key_value bl_baz = { _bl_product, "baz" };
442 static const struct key_value bl_barx = { _bl_product, "ba[[rxy]" };
443 static const struct key_value bl_bazy = { _bl_product, "ba[zy]" };
444 static const struct key_value minio_99 = { _minio, "99" };
445 static const struct key_value npr_37 = { _no_path_retry, "37" };
446 static const struct key_value npr_queue = { _no_path_retry, "queue" };
448 /***** BEGIN TESTS SECTION *****/
451 * Dump the configuration, subistitute the dumped configuration
452 * for the current one, and verify that the result is identical.
454 static void replicate_config(const struct hwt_state *hwt, bool local)
460 condlog(3, "--- %s: replicating %s configuration", __func__,
461 local ? "local" : "full");
463 conf = get_multipath_config();
465 /* "full" configuration */
466 cfg1 = snprint_config(conf, NULL, NULL, NULL);
468 /* "local" configuration */
469 hwtable = get_used_hwes(hwt->vecs->pathvec);
470 cfg1 = snprint_config(conf, NULL, hwtable, hwt->vecs->mpvec);
473 assert_non_null(cfg1);
474 put_multipath_config(conf);
476 replace_config(hwt, cfg1);
479 * The local configuration adds multipath entries, and may move device
480 * entries for local devices to the end of the list. Identical config
481 * strings therefore can't be expected in the "local" case.
482 * That doesn't matter. The important thing is that, with the reloaded
483 * configuration, the test case still passes.
490 conf = get_multipath_config();
491 cfg2 = snprint_config(conf, NULL, NULL, NULL);
492 assert_non_null(cfg2);
493 put_multipath_config(conf);
495 // #define DBG_CONFIG 1
497 #define DUMP_CFG_STR(x) do { \
498 FILE *tmp = fopen("/tmp/hwtable-" #x ".txt", "w"); \
499 fprintf(tmp, "%s", x); \
507 assert_int_equal(strlen(cfg2), strlen(cfg1));
508 assert_string_equal(cfg2, cfg1);
514 * Run hwt->test three times; once with the constructed configuration,
515 * once after re-reading the full dumped configuration, and once with the
516 * dumped local configuration.
518 * Expected: test passes every time.
520 static void test_driver(void **state)
522 const struct hwt_state *hwt;
524 hwt = CHECK_STATE(state);
525 _conf = LOAD_CONFIG(hwt);
528 replicate_config(hwt, false);
529 reset_vecs(hwt->vecs);
532 replicate_config(hwt, true);
533 reset_vecs(hwt->vecs);
536 reset_vecs(hwt->vecs);
541 * Sanity check for the test itself, because defaults may be changed
544 * Our checking for match or non-match relies on the defaults being
545 * different from what our device sections contain.
547 static void test_sanity_globals(void **state)
549 assert_string_not_equal(prio_emc.value, DEFAULT_PRIO);
550 assert_string_not_equal(prio_hds.value, DEFAULT_PRIO);
551 assert_string_not_equal(chk_hp.value, DEFAULT_CHECKER);
552 assert_int_not_equal(MULTIBUS, DEFAULT_PGPOLICY);
553 assert_int_not_equal(NO_PATH_RETRY_QUEUE, DEFAULT_NO_PATH_RETRY);
554 assert_int_not_equal(atoi(minio_99.value), DEFAULT_MINIO_RQ);
555 assert_int_not_equal(atoi(npr_37.value), DEFAULT_NO_PATH_RETRY);
559 * Regression test for internal hwtable. NVME is an example of two entries
560 * in the built-in hwtable, one if which matches a subset of the other.
562 static void test_internal_nvme(const struct hwt_state *hwt)
565 struct multipath *mp;
568 * Generic NVMe: expect defaults for pgpolicy and no_path_retry
570 pp = mock_path("NVME", "NoName");
571 mp = mock_multipath(pp);
572 assert_ptr_not_equal(mp, NULL);
573 TEST_PROP(checker_name(&pp->checker), NONE);
574 TEST_PROP(pp->uid_attribute, DEFAULT_NVME_UID_ATTRIBUTE);
575 assert_int_equal(mp->pgpolicy, DEFAULT_PGPOLICY);
576 assert_int_equal(mp->no_path_retry, DEFAULT_NO_PATH_RETRY);
577 assert_int_equal(mp->retain_hwhandler, RETAIN_HWHANDLER_OFF);
580 * NetApp NVMe: expect special values for pgpolicy and no_path_retry
582 pp = mock_path_wwid("NVME", "NetApp ONTAP Controller",
584 mp = mock_multipath(pp);
585 assert_ptr_not_equal(mp, NULL);
586 TEST_PROP(checker_name(&pp->checker), NONE);
587 TEST_PROP(pp->uid_attribute, "ID_WWN");
588 assert_int_equal(mp->pgpolicy, MULTIBUS);
589 assert_int_equal(mp->no_path_retry, NO_PATH_RETRY_QUEUE);
590 assert_int_equal(mp->retain_hwhandler, RETAIN_HWHANDLER_OFF);
593 static int setup_internal_nvme(void **state)
595 struct hwt_state *hwt = CHECK_STATE(state);
597 WRITE_EMPTY_CONF(hwt);
598 SET_TEST_FUNC(hwt, test_internal_nvme);
604 * Device section with a simple entry qith double quotes ('foo:"bar"')
606 static void test_quoted_hwe(const struct hwt_state *hwt)
610 /* foo:"bar" matches */
611 pp = mock_path(vnd_foo.value, prd_baq.value);
612 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
614 /* foo:bar doesn't match */
615 pp = mock_path(vnd_foo.value, prd_bar.value);
616 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
619 static int setup_quoted_hwe(void **state)
621 struct hwt_state *hwt = CHECK_STATE(state);
622 const struct key_value kv[] = { vnd_foo, prd_baqq, prio_emc };
624 WRITE_ONE_DEVICE(hwt, kv);
625 SET_TEST_FUNC(hwt, test_quoted_hwe);
630 * Device section with a single simple entry ("foo:bar")
632 static void test_string_hwe(const struct hwt_state *hwt)
636 /* foo:bar matches */
637 pp = mock_path(vnd_foo.value, prd_bar.value);
638 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
640 /* foo:baz doesn't match */
641 pp = mock_path(vnd_foo.value, prd_baz.value);
642 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
644 /* boo:bar doesn't match */
645 pp = mock_path(vnd_boo.value, prd_bar.value);
646 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
649 static int setup_string_hwe(void **state)
651 struct hwt_state *hwt = CHECK_STATE(state);
652 const struct key_value kv[] = { vnd_foo, prd_bar, prio_emc };
654 WRITE_ONE_DEVICE(hwt, kv);
655 SET_TEST_FUNC(hwt, test_string_hwe);
660 * Device section with a broken entry (no product)
661 * It should be ignored.
663 static void test_broken_hwe(const struct hwt_state *hwt)
667 /* foo:bar doesn't match, as hwentry is ignored */
668 pp = mock_path(vnd_foo.value, prd_bar.value);
669 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
671 /* boo:bar doesn't match */
672 pp = mock_path(vnd_boo.value, prd_bar.value);
673 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
676 static int setup_broken_hwe(void **state)
678 struct hwt_state *hwt = CHECK_STATE(state);
679 const struct key_value kv[] = { vnd_foo, prio_emc };
681 WRITE_ONE_DEVICE(hwt, kv);
682 SET_TEST_FUNC(hwt, test_broken_hwe);
687 * Like test_broken_hwe, but in config_dir file.
689 static int setup_broken_hwe_dir(void **state)
691 struct hwt_state *hwt = CHECK_STATE(state);
692 const struct key_value kv[] = { vnd_foo, prio_emc };
695 begin_section_all(hwt, "devices");
696 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv), kv);
697 end_section_all(hwt);
699 hwt->test = test_broken_hwe;
700 hwt->test_name = "test_broken_hwe_dir";
705 * Device section with a single regex entry ("^.foo:(bar|baz|ba\.)$")
707 static void test_regex_hwe(const struct hwt_state *hwt)
711 /* foo:bar matches */
712 pp = mock_path(vnd_foo.value, prd_bar.value);
713 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
715 /* foo:baz matches */
716 pp = mock_path(vnd_foo.value, prd_baz.value);
717 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
719 /* boo:baz matches */
720 pp = mock_path(vnd_boo.value, prd_bar.value);
721 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
723 /* foo:BAR doesn't match */
724 pp = mock_path(vnd_foo.value, "BAR");
725 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
727 /* bboo:bar doesn't match */
728 pp = mock_path("bboo", prd_bar.value);
729 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
732 static int setup_regex_hwe(void **state)
734 struct hwt_state *hwt = CHECK_STATE(state);
735 const struct key_value kv[] = { vnd_t_oo, prd_ba_s, prio_emc };
737 WRITE_ONE_DEVICE(hwt, kv);
738 SET_TEST_FUNC(hwt, test_regex_hwe);
743 * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
744 * kv2 a string match (foo:bar) which matches a subset of the regex.
745 * Both are added to the main config file.
747 * Expected: Devices matching both get properties from both, kv2 taking
748 * precedence. Devices matching kv1 only just get props from kv1.
750 static void test_regex_string_hwe(const struct hwt_state *hwt)
754 /* foo:baz matches kv1 */
755 pp = mock_path(vnd_foo.value, prd_baz.value);
756 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
757 TEST_PROP(pp->getuid, NULL);
758 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
760 /* boo:baz matches kv1 */
761 pp = mock_path(vnd_boo.value, prd_baz.value);
762 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
763 TEST_PROP(pp->getuid, NULL);
764 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
766 /* .oo:ba. matches kv1 */
767 pp = mock_path(vnd__oo.value, prd_ba_.value);
768 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
769 TEST_PROP(pp->getuid, NULL);
770 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
772 /* .foo:(bar|baz|ba\.) doesn't match */
773 pp = mock_path(vnd__oo.value, prd_ba_s.value);
774 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
775 TEST_PROP(pp->getuid, NULL);
776 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
778 /* foo:bar matches kv2 and kv1 */
779 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
780 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
781 TEST_PROP(pp->getuid, gui_foo.value);
782 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
785 static int setup_regex_string_hwe(void **state)
787 struct hwt_state *hwt = CHECK_STATE(state);
788 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
789 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
791 WRITE_TWO_DEVICES(hwt, kv1, kv2);
792 SET_TEST_FUNC(hwt, test_regex_string_hwe);
797 * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
798 * kv2 a string match (foo:bar) which matches a subset of the regex.
799 * kv1 is added to the main config file, kv2 to a config_dir file.
800 * This case is more important as you may think, because it's equivalent
801 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
803 * Expected: Devices matching kv2 (and thus, both) get properties
804 * from both, kv2 taking precedence.
805 * Devices matching kv1 only just get props from kv1.
807 static void test_regex_string_hwe_dir(const struct hwt_state *hwt)
811 /* foo:baz matches kv1 */
812 pp = mock_path(vnd_foo.value, prd_baz.value);
813 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
814 TEST_PROP(pp->getuid, NULL);
815 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
817 /* boo:baz matches kv1 */
818 pp = mock_path(vnd_boo.value, prd_baz.value);
819 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
820 TEST_PROP(pp->getuid, NULL);
821 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
823 /* .oo:ba. matches kv1 */
824 pp = mock_path(vnd__oo.value, prd_ba_.value);
825 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
826 TEST_PROP(pp->getuid, NULL);
827 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
829 /* .oo:(bar|baz|ba\.)$ doesn't match */
830 pp = mock_path(vnd__oo.value, prd_ba_s.value);
831 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
832 TEST_PROP(pp->getuid, NULL);
833 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
835 /* foo:bar matches kv2 */
836 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
837 /* Later match takes prio */
838 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
839 TEST_PROP(pp->getuid, gui_foo.value);
840 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
843 static int setup_regex_string_hwe_dir(void **state)
845 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
846 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
847 struct hwt_state *hwt = CHECK_STATE(state);
849 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
850 SET_TEST_FUNC(hwt, test_regex_string_hwe_dir);
855 * Three device entries, kv1 is a regex match and kv2 and kv3 string
856 * matches, where kv3 is a substring of kv2. All in different config
859 * Expected: Devices matching kv3 get props from all, devices matching
860 * kv2 from kv2 and kv1, and devices matching kv1 only just from kv1.
862 static void test_regex_2_strings_hwe_dir(const struct hwt_state *hwt)
866 /* foo:baz matches kv1 */
867 pp = mock_path(vnd_foo.value, prd_baz.value);
868 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
869 TEST_PROP(pp->getuid, NULL);
870 TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
871 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
873 /* boo:baz doesn't match */
874 pp = mock_path(vnd_boo.value, prd_baz.value);
875 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
876 TEST_PROP(pp->getuid, NULL);
877 TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
878 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
880 /* foo:bar matches kv2 and kv1 */
881 pp = mock_path(vnd_foo.value, prd_bar.value);
882 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
883 TEST_PROP(pp->getuid, NULL);
884 TEST_PROP(pp->uid_attribute, uid_baz.value);
885 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
887 /* foo:barz matches kv3 and kv2 and kv1 */
888 pp = mock_path_flags(vnd_foo.value, prd_barz.value, USE_GETUID);
889 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
890 TEST_PROP(pp->getuid, gui_foo.value);
891 TEST_PROP(pp->uid_attribute, NULL);
892 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
895 static int setup_regex_2_strings_hwe_dir(void **state)
897 const struct key_value kv1[] = { vnd_foo, prd_ba_, prio_emc, chk_hp };
898 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, uid_baz };
899 const struct key_value kv3[] = { vnd_foo, prd_barz,
900 prio_rdac, gui_foo };
901 struct hwt_state *hwt = CHECK_STATE(state);
904 begin_section_all(hwt, "devices");
905 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
906 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
907 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv3), kv3);
908 end_section_all(hwt);
910 SET_TEST_FUNC(hwt, test_regex_2_strings_hwe_dir);
915 * Like test_regex_string_hwe_dir, but the order of kv1 and kv2 is exchanged.
917 * Expected: Devices matching kv1 (and thus, both) get properties
918 * from both, kv1 taking precedence.
919 * Devices matching kv1 only just get props from kv1.
921 static void test_string_regex_hwe_dir(const struct hwt_state *hwt)
925 /* foo:bar matches kv2 and kv1 */
926 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
927 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
928 TEST_PROP(pp->getuid, gui_foo.value);
929 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
931 /* foo:baz matches kv1 */
932 pp = mock_path(vnd_foo.value, prd_baz.value);
933 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
934 TEST_PROP(pp->getuid, NULL);
935 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
937 /* boo:baz matches kv1 */
938 pp = mock_path(vnd_boo.value, prd_baz.value);
939 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
940 TEST_PROP(pp->getuid, NULL);
941 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
943 /* .oo:ba. matches kv1 */
944 pp = mock_path(vnd__oo.value, prd_ba_.value);
945 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
946 TEST_PROP(pp->getuid, NULL);
947 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
949 /* .oo:(bar|baz|ba\.)$ doesn't match */
950 pp = mock_path(vnd__oo.value, prd_ba_s.value);
951 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
952 TEST_PROP(pp->getuid, NULL);
953 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
956 static int setup_string_regex_hwe_dir(void **state)
958 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
959 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
960 struct hwt_state *hwt = CHECK_STATE(state);
962 WRITE_TWO_DEVICES_W_DIR(hwt, kv2, kv1);
963 SET_TEST_FUNC(hwt, test_string_regex_hwe_dir);
968 * Two identical device entries kv1 and kv2, trival regex ("string").
969 * Both are added to the main config file.
970 * These entries are NOT merged.
971 * This could happen in a large multipath.conf file.
973 * Expected: matching devices get props from both, kv2 taking precedence.
975 static void test_2_ident_strings_hwe(const struct hwt_state *hwt)
979 /* foo:baz doesn't match */
980 pp = mock_path(vnd_foo.value, prd_baz.value);
981 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
982 TEST_PROP(pp->getuid, NULL);
983 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
985 /* foo:bar matches both */
986 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
987 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
988 TEST_PROP(pp->getuid, gui_foo.value);
989 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
992 static int setup_2_ident_strings_hwe(void **state)
994 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
995 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
996 struct hwt_state *hwt = CHECK_STATE(state);
998 WRITE_TWO_DEVICES(hwt, kv1, kv2);
999 SET_TEST_FUNC(hwt, test_2_ident_strings_hwe);
1004 * Two identical device entries kv1 and kv2, trival regex ("string").
1005 * Both are added to an extra config file.
1006 * This could happen in a large multipath.conf file.
1008 * Expected: matching devices get props from both, kv2 taking precedence.
1010 static void test_2_ident_strings_both_dir(const struct hwt_state *hwt)
1014 /* foo:baz doesn't match */
1015 pp = mock_path(vnd_foo.value, prd_baz.value);
1016 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1017 TEST_PROP(pp->getuid, NULL);
1018 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1020 /* foo:bar matches both */
1021 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1022 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1023 TEST_PROP(pp->getuid, gui_foo.value);
1024 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1027 static int setup_2_ident_strings_both_dir(void **state)
1029 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1030 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1031 struct hwt_state *hwt = CHECK_STATE(state);
1034 begin_section_all(hwt, "devices");
1035 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1036 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1037 end_section_all(hwt);
1039 SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir);
1044 * Two identical device entries kv1 and kv2, trival regex ("string").
1045 * Both are added to an extra config file.
1046 * An empty entry kv0 with the same string exists in the main config file.
1048 * Expected: matching devices get props from both, kv2 taking precedence.
1050 static void test_2_ident_strings_both_dir_w_prev(const struct hwt_state *hwt)
1054 /* foo:baz doesn't match */
1055 pp = mock_path(vnd_foo.value, prd_baz.value);
1056 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1057 TEST_PROP(pp->getuid, NULL);
1058 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1060 /* foo:bar matches both */
1061 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1062 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1063 TEST_PROP(pp->getuid, gui_foo.value);
1064 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1067 static int setup_2_ident_strings_both_dir_w_prev(void **state)
1069 struct hwt_state *hwt = CHECK_STATE(state);
1071 const struct key_value kv0[] = { vnd_foo, prd_bar };
1072 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1073 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1076 begin_section_all(hwt, "devices");
1077 write_device(hwt->config_file, ARRAY_SIZE(kv0), kv0);
1078 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1079 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1080 end_section_all(hwt);
1082 SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir_w_prev);
1087 * Two identical device entries kv1 and kv2, trival regex ("string").
1088 * kv1 is added to the main config file, kv2 to a config_dir file.
1089 * These entries are merged.
1090 * This case is more important as you may think, because it's equivalent
1091 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1093 * Expected: matching devices get props from both, kv2 taking precedence.
1095 static void test_2_ident_strings_hwe_dir(const struct hwt_state *hwt)
1099 /* foo:baz doesn't match */
1100 pp = mock_path(vnd_foo.value, prd_baz.value);
1101 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1102 TEST_PROP(pp->getuid, NULL);
1103 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1105 /* foo:bar matches both */
1106 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1107 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1108 TEST_PROP(pp->getuid, gui_foo.value);
1109 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1112 static int setup_2_ident_strings_hwe_dir(void **state)
1114 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1115 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1116 struct hwt_state *hwt = CHECK_STATE(state);
1118 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1119 SET_TEST_FUNC(hwt, test_2_ident_strings_hwe_dir);
1124 * Like test_2_ident_strings_hwe_dir, but this time the config_dir file
1125 * contains an additional, empty entry (kv0).
1127 * Expected: matching devices get props from kv1 and kv2, kv2 taking precedence.
1129 static void test_3_ident_strings_hwe_dir(const struct hwt_state *hwt)
1133 /* foo:baz doesn't match */
1134 pp = mock_path(vnd_foo.value, prd_baz.value);
1135 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1136 TEST_PROP(pp->getuid, NULL);
1137 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1139 /* foo:bar matches both */
1140 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1141 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1142 TEST_PROP(pp->getuid, gui_foo.value);
1143 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1146 static int setup_3_ident_strings_hwe_dir(void **state)
1148 const struct key_value kv0[] = { vnd_foo, prd_bar };
1149 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1150 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1151 struct hwt_state *hwt = CHECK_STATE(state);
1154 begin_section_all(hwt, "devices");
1155 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1156 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv0), kv0);
1157 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1158 end_section_all(hwt);
1160 SET_TEST_FUNC(hwt, test_3_ident_strings_hwe_dir);
1165 * Two identical device entries kv1 and kv2, non-trival regex that matches
1166 * itself (string ".oo" matches regex ".oo").
1167 * kv1 is added to the main config file, kv2 to a config_dir file.
1168 * This case is more important as you may think, because it's equivalent
1169 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1171 * Expected: matching devices get props from both, kv2 taking precedence.
1173 static void test_2_ident_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1177 /* foo:baz doesn't match */
1178 pp = mock_path(vnd_foo.value, prd_baz.value);
1179 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1180 TEST_PROP(pp->getuid, NULL);
1181 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1183 /* foo:bar matches both */
1184 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1185 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1186 TEST_PROP(pp->getuid, gui_foo.value);
1187 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1190 static int setup_2_ident_self_matching_re_hwe_dir(void **state)
1192 const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1193 const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1194 struct hwt_state *hwt = CHECK_STATE(state);
1196 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1197 SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe_dir);
1202 * Two identical device entries kv1 and kv2, non-trival regex that matches
1203 * itself (string ".oo" matches regex ".oo").
1204 * kv1 and kv2 are added to the main config file.
1206 * Expected: matching devices get props from both, kv2 taking precedence.
1208 static void test_2_ident_self_matching_re_hwe(const struct hwt_state *hwt)
1212 /* foo:baz doesn't match */
1213 pp = mock_path(vnd_foo.value, prd_baz.value);
1214 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1215 TEST_PROP(pp->getuid, NULL);
1216 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1218 /* foo:bar matches */
1219 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1220 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1221 TEST_PROP(pp->getuid, gui_foo.value);
1222 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1225 static int setup_2_ident_self_matching_re_hwe(void **state)
1227 const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1228 const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1229 struct hwt_state *hwt = CHECK_STATE(state);
1231 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1232 SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe);
1237 * Two identical device entries kv1 and kv2, non-trival regex that doesn't
1238 * match itself (string "^.oo" doesn't match regex "^.oo").
1239 * kv1 is added to the main config file, kv2 to a config_dir file.
1240 * This case is more important as you may think, see above.
1242 * Expected: matching devices get props from both, kv2 taking precedence.
1245 test_2_ident_not_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1249 /* foo:baz doesn't match */
1250 pp = mock_path(vnd_foo.value, prd_baz.value);
1251 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1252 TEST_PROP(pp->getuid, NULL);
1253 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1255 /* foo:bar matches both */
1256 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1257 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1258 TEST_PROP(pp->getuid, gui_foo.value);
1259 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1262 static int setup_2_ident_not_self_matching_re_hwe_dir(void **state)
1264 const struct key_value kv1[] = { vnd_t_oo, prd_bar, prio_emc, chk_hp };
1265 const struct key_value kv2[] = { vnd_t_oo, prd_bar, prio_hds, gui_foo };
1266 struct hwt_state *hwt = CHECK_STATE(state);
1268 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1269 SET_TEST_FUNC(hwt, test_2_ident_not_self_matching_re_hwe_dir);
1274 * Two different non-trivial regexes kv1, kv2. The 1st one matches the 2nd, but
1275 * it doesn't match all possible strings matching the second.
1276 * ("ba[zy]" matches regex "ba[[rxy]", but "baz" does not).
1278 * Expected: Devices matching both regexes get properties from both, kv2
1279 * taking precedence. Devices matching just one regex get properties from
1280 * that one regex only.
1282 static void test_2_matching_res_hwe_dir(const struct hwt_state *hwt)
1286 /* foo:bar matches k1 only */
1287 pp = mock_path(vnd_foo.value, prd_bar.value);
1288 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1289 TEST_PROP(pp->getuid, NULL);
1290 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1292 /* foo:bay matches k1 and k2 */
1293 pp = mock_path_flags(vnd_foo.value, "bay", USE_GETUID);
1294 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1295 TEST_PROP(pp->getuid, gui_foo.value);
1296 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1298 /* foo:baz matches k2 only. */
1299 pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1300 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1301 TEST_PROP(pp->getuid, gui_foo.value);
1302 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1305 static int setup_2_matching_res_hwe_dir(void **state)
1307 const struct key_value kv1[] = { vnd_foo, prd_barx, prio_emc, chk_hp };
1308 const struct key_value kv2[] = { vnd_foo, prd_bazy, prio_hds, gui_foo };
1309 struct hwt_state *hwt = CHECK_STATE(state);
1311 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1312 SET_TEST_FUNC(hwt, test_2_matching_res_hwe_dir);
1317 * Two different non-trivial regexes which match the same set of strings.
1318 * But they don't match each other.
1319 * "baz" matches both regex "ba[zy]" and "ba(z|y)"
1321 * Expected: matching devices get properties from both, kv2 taking precedence.
1323 static void test_2_nonmatching_res_hwe_dir(const struct hwt_state *hwt)
1327 /* foo:bar doesn't match */
1328 pp = mock_path(vnd_foo.value, prd_bar.value);
1329 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1330 TEST_PROP(pp->getuid, NULL);
1331 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1333 pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1334 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1335 TEST_PROP(pp->getuid, gui_foo.value);
1336 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1339 static int setup_2_nonmatching_res_hwe_dir(void **state)
1341 const struct key_value kv1[] = { vnd_foo, prd_bazy, prio_emc, chk_hp };
1342 const struct key_value kv2[] = { vnd_foo, prd_bazy1,
1343 prio_hds, gui_foo };
1344 struct hwt_state *hwt = CHECK_STATE(state);
1346 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1347 SET_TEST_FUNC(hwt, test_2_nonmatching_res_hwe_dir);
1352 * Simple blacklist test.
1354 * NOTE: test failures in blacklisting tests will manifest as cmocka errors
1355 * "Could not get value to mock function XYZ", because pathinfo() takes
1356 * different code paths for blacklisted devices.
1358 static void test_blacklist(const struct hwt_state *hwt)
1360 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1361 mock_path(vnd_foo.value, prd_baz.value);
1364 static int setup_blacklist(void **state)
1366 const struct key_value kv1[] = { vnd_foo, prd_bar };
1367 struct hwt_state *hwt = CHECK_STATE(state);
1370 begin_section_all(hwt, "blacklist");
1371 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1372 end_section_all(hwt);
1374 SET_TEST_FUNC(hwt, test_blacklist);
1379 * Simple blacklist test with regex and exception
1381 static void test_blacklist_regex(const struct hwt_state *hwt)
1383 mock_path(vnd_foo.value, prd_bar.value);
1384 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1385 mock_path(vnd_foo.value, prd_bam.value);
1388 static int setup_blacklist_regex(void **state)
1390 const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1391 const struct key_value kv2[] = { vnd_foo, prd_bar };
1392 struct hwt_state *hwt = CHECK_STATE(state);
1394 hwt = CHECK_STATE(state);
1396 begin_section_all(hwt, "blacklist");
1397 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1398 end_section_all(hwt);
1399 begin_section_all(hwt, "blacklist_exceptions");
1400 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1401 end_section_all(hwt);
1403 SET_TEST_FUNC(hwt, test_blacklist_regex);
1408 * Simple blacklist test with regex and exception
1409 * config file order inverted wrt test_blacklist_regex
1411 static int setup_blacklist_regex_inv(void **state)
1413 const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1414 const struct key_value kv2[] = { vnd_foo, prd_bar };
1415 struct hwt_state *hwt = CHECK_STATE(state);
1418 begin_section_all(hwt, "blacklist");
1419 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv1), kv1);
1420 end_section_all(hwt);
1421 begin_section_all(hwt, "blacklist_exceptions");
1422 write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2);
1423 end_section_all(hwt);
1425 SET_TEST_FUNC(hwt, test_blacklist_regex);
1430 * Simple blacklist test with regex and exception
1431 * config file order inverted wrt test_blacklist_regex
1433 static void test_blacklist_regex_matching(const struct hwt_state *hwt)
1435 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1436 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1437 mock_path(vnd_foo.value, prd_bam.value);
1440 static int setup_blacklist_regex_matching(void **state)
1442 const struct key_value kv1[] = { vnd_foo, prd_barx };
1443 const struct key_value kv2[] = { vnd_foo, prd_bazy };
1444 struct hwt_state *hwt = CHECK_STATE(state);
1447 begin_section_all(hwt, "blacklist");
1448 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1449 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1450 end_section_all(hwt);
1452 SET_TEST_FUNC(hwt, test_blacklist_regex_matching);
1457 * Test for blacklisting by WWID
1459 * Note that default_wwid is a substring of default_wwid_1. Because
1460 * matching is done by regex, both paths are blacklisted.
1462 static void test_blacklist_wwid(const struct hwt_state *hwt)
1464 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_WWID);
1465 mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1469 static int setup_blacklist_wwid(void **state)
1471 const struct key_value kv[] = { wwid_test };
1472 struct hwt_state *hwt = CHECK_STATE(state);
1475 write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1477 SET_TEST_FUNC(hwt, test_blacklist_wwid);
1482 * Test for blacklisting by WWID
1484 * Here the blacklist contains only default_wwid_1. Thus the path
1485 * with default_wwid is NOT blacklisted.
1487 static void test_blacklist_wwid_1(const struct hwt_state *hwt)
1489 mock_path(vnd_foo.value, prd_bar.value);
1490 mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1494 static int setup_blacklist_wwid_1(void **state)
1496 const struct key_value kv[] = { { _wwid, default_wwid_1 }, };
1497 struct hwt_state *hwt = CHECK_STATE(state);
1500 write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1502 SET_TEST_FUNC(hwt, test_blacklist_wwid_1);
1507 * Test for product_blacklist. Two entries blacklisting each other.
1509 * Expected: Both are blacklisted.
1511 static void test_product_blacklist(const struct hwt_state *hwt)
1513 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1514 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1515 mock_path(vnd_foo.value, prd_bam.value);
1518 static int setup_product_blacklist(void **state)
1520 const struct key_value kv1[] = { vnd_foo, prd_bar, bl_baz };
1521 const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bar };
1522 struct hwt_state *hwt = CHECK_STATE(state);
1524 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1525 SET_TEST_FUNC(hwt, test_product_blacklist);
1530 * Test for product_blacklist. The second regex "matches" the first.
1531 * This is a pathological example.
1533 * Expected: "foo:bar", "foo:baz" are blacklisted.
1535 static void test_product_blacklist_matching(const struct hwt_state *hwt)
1537 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1538 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1539 mock_path(vnd_foo.value, prd_bam.value);
1542 static int setup_product_blacklist_matching(void **state)
1544 const struct key_value kv1[] = { vnd_foo, prd_bar, bl_barx };
1545 const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bazy };
1546 struct hwt_state *hwt = CHECK_STATE(state);
1548 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1549 SET_TEST_FUNC(hwt, test_product_blacklist_matching);
1554 * Basic test for multipath-based configuration.
1556 * Expected: properties, including pp->prio, are taken from multipath
1559 static void test_multipath_config(const struct hwt_state *hwt)
1562 struct multipath *mp;
1564 pp = mock_path(vnd_foo.value, prd_bar.value);
1565 mp = mock_multipath(pp);
1566 assert_ptr_not_equal(mp->mpe, NULL);
1567 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1568 assert_int_equal(mp->minio, atoi(minio_99.value));
1569 TEST_PROP(pp->uid_attribute, uid_baz.value);
1571 /* test different wwid */
1572 pp = mock_path_wwid(vnd_foo.value, prd_bar.value, default_wwid_1);
1573 mp = mock_multipath(pp);
1574 // assert_ptr_equal(mp->mpe, NULL);
1575 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1576 assert_int_equal(mp->minio, DEFAULT_MINIO_RQ);
1577 TEST_PROP(pp->uid_attribute, uid_baz.value);
1580 static int setup_multipath_config(void **state)
1582 struct hwt_state *hwt = CHECK_STATE(state);
1583 const struct key_value kvm[] = { wwid_test, prio_rdac, minio_99 };
1584 const struct key_value kvp[] = { vnd_foo, prd_bar, prio_emc, uid_baz };
1587 begin_section_all(hwt, "devices");
1588 write_section(hwt->conf_dir_file[0], "device", ARRAY_SIZE(kvp), kvp);
1589 end_section_all(hwt);
1590 begin_section_all(hwt, "multipaths");
1591 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kvm), kvm);
1592 end_section_all(hwt);
1594 SET_TEST_FUNC(hwt, test_multipath_config);
1599 * Basic test for multipath-based configuration. Two sections for the same wwid.
1601 * Expected: properties are taken from both multipath sections, later taking
1604 static void test_multipath_config_2(const struct hwt_state *hwt)
1607 struct multipath *mp;
1609 pp = mock_path(vnd_foo.value, prd_bar.value);
1610 mp = mock_multipath(pp);
1611 assert_ptr_not_equal(mp, NULL);
1612 assert_ptr_not_equal(mp->mpe, NULL);
1613 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1614 assert_int_equal(mp->minio, atoi(minio_99.value));
1615 assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1618 static int setup_multipath_config_2(void **state)
1620 const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1621 const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1622 struct hwt_state *hwt = CHECK_STATE(state);
1625 begin_section_all(hwt, "multipaths");
1626 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1627 write_section(hwt->conf_dir_file[1], "multipath", ARRAY_SIZE(kv2), kv2);
1628 end_section_all(hwt);
1630 SET_TEST_FUNC(hwt, test_multipath_config_2);
1635 * Same as test_multipath_config_2, both entries in the same config file.
1637 * Expected: properties are taken from both multipath sections.
1639 static void test_multipath_config_3(const struct hwt_state *hwt)
1642 struct multipath *mp;
1644 pp = mock_path(vnd_foo.value, prd_bar.value);
1645 mp = mock_multipath(pp);
1646 assert_ptr_not_equal(mp, NULL);
1647 assert_ptr_not_equal(mp->mpe, NULL);
1648 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1649 assert_int_equal(mp->minio, atoi(minio_99.value));
1650 assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1653 static int setup_multipath_config_3(void **state)
1655 const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1656 const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1657 struct hwt_state *hwt = CHECK_STATE(state);
1660 begin_section_all(hwt, "multipaths");
1661 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1662 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv2), kv2);
1663 end_section_all(hwt);
1665 SET_TEST_FUNC(hwt, test_multipath_config_3);
1670 * Test for device with "hidden" attribute
1672 static void test_hidden(const struct hwt_state *hwt)
1674 mock_path_flags("NVME", "NoName", DEV_HIDDEN|BL_MASK);
1677 static int setup_hidden(void **state)
1679 struct hwt_state *hwt = CHECK_STATE(state);
1681 WRITE_EMPTY_CONF(hwt);
1682 SET_TEST_FUNC(hwt, test_hidden);
1688 * Create wrapper functions around test_driver() to avoid that cmocka
1689 * always uses the same test name. That makes it easier to read test results.
1692 #define define_test(x) \
1693 static void run_##x(void **state) \
1695 return test_driver(state); \
1698 define_test(string_hwe)
1699 define_test(broken_hwe)
1700 define_test(broken_hwe_dir)
1701 define_test(quoted_hwe)
1702 define_test(internal_nvme)
1703 define_test(regex_hwe)
1704 define_test(regex_string_hwe)
1705 define_test(regex_string_hwe_dir)
1706 define_test(regex_2_strings_hwe_dir)
1707 define_test(string_regex_hwe_dir)
1708 define_test(2_ident_strings_hwe)
1709 define_test(2_ident_strings_both_dir)
1710 define_test(2_ident_strings_both_dir_w_prev)
1711 define_test(2_ident_strings_hwe_dir)
1712 define_test(3_ident_strings_hwe_dir)
1713 define_test(2_ident_self_matching_re_hwe_dir)
1714 define_test(2_ident_self_matching_re_hwe)
1715 define_test(2_ident_not_self_matching_re_hwe_dir)
1716 define_test(2_matching_res_hwe_dir)
1717 define_test(2_nonmatching_res_hwe_dir)
1718 define_test(blacklist)
1719 define_test(blacklist_wwid)
1720 define_test(blacklist_wwid_1)
1721 define_test(blacklist_regex)
1722 define_test(blacklist_regex_inv)
1723 define_test(blacklist_regex_matching)
1724 define_test(product_blacklist)
1725 define_test(product_blacklist_matching)
1726 define_test(multipath_config)
1727 define_test(multipath_config_2)
1728 define_test(multipath_config_3)
1731 #define test_entry(x) \
1732 cmocka_unit_test_setup(run_##x, setup_##x)
1734 static int test_hwtable(void)
1736 const struct CMUnitTest tests[] = {
1737 cmocka_unit_test(test_sanity_globals),
1738 test_entry(internal_nvme),
1739 test_entry(string_hwe),
1740 test_entry(broken_hwe),
1741 test_entry(broken_hwe_dir),
1742 test_entry(quoted_hwe),
1743 test_entry(regex_hwe),
1744 test_entry(regex_string_hwe),
1745 test_entry(regex_string_hwe_dir),
1746 test_entry(regex_2_strings_hwe_dir),
1747 test_entry(string_regex_hwe_dir),
1748 test_entry(2_ident_strings_hwe),
1749 test_entry(2_ident_strings_both_dir),
1750 test_entry(2_ident_strings_both_dir_w_prev),
1751 test_entry(2_ident_strings_hwe_dir),
1752 test_entry(3_ident_strings_hwe_dir),
1753 test_entry(2_ident_self_matching_re_hwe_dir),
1754 test_entry(2_ident_self_matching_re_hwe),
1755 test_entry(2_ident_not_self_matching_re_hwe_dir),
1756 test_entry(2_matching_res_hwe_dir),
1757 test_entry(2_nonmatching_res_hwe_dir),
1758 test_entry(blacklist),
1759 test_entry(blacklist_wwid),
1760 test_entry(blacklist_wwid_1),
1761 test_entry(blacklist_regex),
1762 test_entry(blacklist_regex_inv),
1763 test_entry(blacklist_regex_matching),
1764 test_entry(product_blacklist),
1765 test_entry(product_blacklist_matching),
1766 test_entry(multipath_config),
1767 test_entry(multipath_config_2),
1768 test_entry(multipath_config_3),
1772 return cmocka_run_group_tests(tests, setup, teardown);
1779 ret += test_hwtable();