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"
30 #define N_CONF_FILES 2
32 static const char tmplate[] = "/tmp/hwtable-XXXXXX";
43 FILE *conf_dir_file[N_CONF_FILES];
45 void (*test)(const struct hwt_state *);
46 const char *test_name;
49 #define SET_TEST_FUNC(hwt, func) do { \
51 hwt->test_name = #func; \
54 static struct config *_conf;
56 int logsink = LOGSINK_STDERR_WITHOUT_TIME;
58 struct config *get_multipath_config(void)
63 void put_multipath_config(void *arg)
66 void make_config_file_path(char *buf, int buflen,
67 const struct hwt_state *hwt, int i)
69 static const char fn_template[] = "%s/test-%02d.conf";
72 /* main config file */
73 snprintf(buf, buflen, fn_template, hwt->tmpname, 0);
75 snprintf(buf, buflen, fn_template, hwt->dirname, i);
78 static void reset_vecs(struct vectors *vecs)
81 free_pathvec(vecs->pathvec, FREE_PATHS);
83 vecs->pathvec = vector_alloc();
84 assert_ptr_not_equal(vecs->pathvec, NULL);
85 vecs->mpvec = vector_alloc();
86 assert_ptr_not_equal(vecs->mpvec, NULL);
89 static void free_hwt(struct hwt_state *hwt)
94 if (hwt->config_file != NULL)
95 fclose(hwt->config_file);
96 for (i = 0; i < N_CONF_FILES; i++) {
97 if (hwt->conf_dir_file[i] != NULL)
98 fclose(hwt->conf_dir_file[i]);
101 if (hwt->tmpname != NULL) {
102 make_config_file_path(buf, sizeof(buf), hwt, -1);
108 if (hwt->dirname != NULL) {
109 for (i = 0; i < N_CONF_FILES; i++) {
110 make_config_file_path(buf, sizeof(buf), hwt, i);
117 if (hwt->vecs != NULL) {
118 if (hwt->vecs->mpvec != NULL)
119 remove_maps(hwt->vecs);
120 if (hwt->vecs->pathvec != NULL)
121 free_pathvec(hwt->vecs->pathvec, FREE_PATHS);
122 pthread_mutex_destroy(&hwt->vecs->lock.mutex);
128 static int setup(void **state)
130 struct hwt_state *hwt;
135 hwt = calloc(1, sizeof(*hwt));
139 snprintf(buf, sizeof(buf), "%s", tmplate);
140 if (mkdtemp(buf) == NULL) {
141 condlog(0, "mkdtemp: %s", strerror(errno));
144 hwt->tmpname = strdup(buf);
146 snprintf(buf, sizeof(buf), "%s", tmplate);
147 if (mkdtemp(buf) == NULL) {
148 condlog(0, "mkdtemp (2): %s", strerror(errno));
151 hwt->dirname = strdup(buf);
153 make_config_file_path(buf, sizeof(buf), hwt, -1);
154 hwt->config_file = fopen(buf, "w+");
155 if (hwt->config_file == NULL)
158 for (i = 0; i < N_CONF_FILES; i++) {
159 make_config_file_path(buf, sizeof(buf), hwt, i);
160 hwt->conf_dir_file[i] = fopen(buf, "w+");
161 if (hwt->conf_dir_file[i] == NULL)
165 hwt->vecs = calloc(1, sizeof(*hwt->vecs));
166 if (hwt->vecs == NULL)
168 pthread_mutex_init(&hwt->vecs->lock.mutex, NULL);
169 hwt->vecs->pathvec = vector_alloc();
170 hwt->vecs->mpvec = vector_alloc();
171 if (hwt->vecs->pathvec == NULL || hwt->vecs->mpvec == NULL)
182 static int teardown(void **state)
184 if (state == NULL || *state == NULL)
197 * Helpers for creating the config file(s)
200 static void reset_config(FILE *ff)
205 if (ftruncate(fileno(ff), 0) == -1)
206 condlog(1, "ftruncate: %s", strerror(errno));
209 static void reset_configs(const struct hwt_state *hwt)
213 reset_config(hwt->config_file);
214 for (i = 0; i < N_CONF_FILES; i++)
215 reset_config(hwt->conf_dir_file[i]);
218 static void write_key_values(FILE *ff, int nkv, const struct key_value *kv)
222 for (i = 0; i < nkv; i++) {
223 if (strchr(kv[i].value, ' ') == NULL &&
224 strchr(kv[i].value, '\"') == NULL)
225 fprintf(ff, "\t%s %s\n", kv[i].key, kv[i].value);
227 fprintf(ff, "\t%s \"%s\"\n", kv[i].key, kv[i].value);
231 static void begin_section(FILE *ff, const char *section)
233 fprintf(ff, "%s {\n", section);
236 static void end_section(FILE *ff)
241 static void write_section(FILE *ff, const char *section,
242 int nkv, const struct key_value *kv)
244 begin_section(ff, section);
245 write_key_values(ff, nkv, kv);
249 static void write_defaults(const struct hwt_state *hwt)
251 static const char bindings_name[] = "bindings";
252 static struct key_value defaults[] = {
253 { "config_dir", NULL },
254 { "bindings_file", NULL },
255 { "multipath_dir", NULL },
256 { "detect_prio", "no" },
257 { "detect_checker", "no" },
259 char buf[sizeof(tmplate) + sizeof(bindings_name)];
260 char dirbuf[PATH_MAX];
262 snprintf(buf, sizeof(buf), "%s/%s", hwt->tmpname, bindings_name);
263 defaults[0].value = hwt->dirname;
264 defaults[1].value = buf;
265 assert_ptr_not_equal(getcwd(dirbuf, sizeof(dirbuf)), NULL);
266 strncat(dirbuf, "/lib", sizeof(dirbuf) - 5);
267 defaults[2].value = dirbuf;
268 write_section(hwt->config_file, "defaults",
269 ARRAY_SIZE(defaults), defaults);
272 static void begin_config(const struct hwt_state *hwt)
278 static void begin_section_all(const struct hwt_state *hwt, const char *section)
282 begin_section(hwt->config_file, section);
283 for (i = 0; i < N_CONF_FILES; i++)
284 begin_section(hwt->conf_dir_file[i], section);
287 static void end_section_all(const struct hwt_state *hwt)
291 end_section(hwt->config_file);
292 for (i = 0; i < N_CONF_FILES; i++)
293 end_section(hwt->conf_dir_file[i]);
296 static void finish_config(const struct hwt_state *hwt)
300 fflush(hwt->config_file);
301 for (i = 0; i < N_CONF_FILES; i++) {
302 fflush(hwt->conf_dir_file[i]);
306 static void write_device(FILE *ff, int nkv, const struct key_value *kv)
308 write_section(ff, "device", nkv, kv);
312 * Some macros to avoid boilerplace code
315 #define CHECK_STATE(state) ({ \
316 assert_ptr_not_equal(state, NULL); \
317 assert_ptr_not_equal(*(state), NULL); \
320 #define WRITE_EMPTY_CONF(hwt) do { \
322 finish_config(hwt); \
325 #define WRITE_ONE_DEVICE(hwt, kv) do { \
327 begin_section_all(hwt, "devices"); \
328 write_device(hwt->config_file, ARRAY_SIZE(kv), kv); \
329 end_section_all(hwt); \
330 finish_config(hwt); \
333 #define WRITE_TWO_DEVICES(hwt, kv1, kv2) do { \
335 begin_section_all(hwt, "devices"); \
336 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1); \
337 write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2); \
338 end_section_all(hwt); \
339 finish_config(hwt); \
342 #define WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2) do { \
344 begin_section_all(hwt, "devices"); \
345 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1); \
346 write_device(hwt->conf_dir_file[0], \
347 ARRAY_SIZE(kv2), kv2); \
348 end_section_all(hwt); \
349 finish_config(hwt); \
352 #define LOAD_CONFIG(hwt) ({ \
353 char buf[PATH_MAX]; \
354 struct config *__cf; \
356 make_config_file_path(buf, sizeof(buf), hwt, -1); \
357 __cf = load_config(buf); \
358 assert_ptr_not_equal(__cf, NULL); \
359 assert_ptr_not_equal(__cf->hwtable, NULL); \
360 __cf->verbosity = VERBOSITY; \
363 #define FREE_CONFIG(conf) do { \
368 static void replace_config(const struct hwt_state *hwt,
369 const char *conf_str)
373 fprintf(hwt->config_file, "%s", conf_str);
374 fflush(hwt->config_file);
375 _conf = LOAD_CONFIG(hwt);
378 #define TEST_PROP(prop, val) do { \
380 assert_ptr_equal(prop, NULL); \
382 assert_ptr_not_equal(prop, NULL); \
383 assert_string_equal(prop, val); \
388 #define TEST_PROP_BROKEN(name, prop, bad, good) do { \
389 condlog(1, "%s: WARNING: Broken test for %s == \"%s\" on line %d, should be \"%s\"", \
390 __func__, name, bad ? bad : "NULL", \
391 __LINE__, good ? good : "NULL"); \
392 TEST_PROP(prop, bad); \
395 #define TEST_PROP_BROKEN(name, prop, bad, good) TEST_PROP(prop, good)
399 * Some predefined key/value pairs
402 static const char _wwid[] = "wwid";
403 static const char _vendor[] = "vendor";
404 static const char _product[] = "product";
405 static const char _prio[] = "prio";
406 static const char _checker[] = "path_checker";
407 static const char _getuid[] = "getuid_callout";
408 static const char _uid_attr[] = "uid_attribute";
409 static const char _bl_product[] = "product_blacklist";
410 static const char _minio[] = "rr_min_io_rq";
411 static const char _no_path_retry[] = "no_path_retry";
413 /* Device identifiers */
414 static const struct key_value vnd_foo = { _vendor, "foo" };
415 static const struct key_value prd_bar = { _product, "bar" };
416 static const struct key_value prd_bam = { _product, "bam" };
417 static const struct key_value prd_baq = { _product, "\"bar\"" };
418 static const struct key_value prd_baqq = { _product, "\"\"bar\"\"" };
419 static const struct key_value prd_barz = { _product, "barz" };
420 static const struct key_value vnd_boo = { _vendor, "boo" };
421 static const struct key_value prd_baz = { _product, "baz" };
422 static const struct key_value wwid_test = { _wwid, default_wwid };
424 /* Regular expressions */
425 static const struct key_value vnd__oo = { _vendor, ".oo" };
426 static const struct key_value vnd_t_oo = { _vendor, "^.oo" };
427 static const struct key_value prd_ba_ = { _product, "ba." };
428 static const struct key_value prd_ba_s = { _product, "(bar|baz|ba\\.)$" };
429 /* Pathological cases, see below */
430 static const struct key_value prd_barx = { _product, "ba[[rxy]" };
431 static const struct key_value prd_bazy = { _product, "ba[zy]" };
432 static const struct key_value prd_bazy1 = { _product, "ba(z|y)" };
435 static const struct key_value prio_emc = { _prio, "emc" };
436 static const struct key_value prio_hds = { _prio, "hds" };
437 static const struct key_value prio_rdac = { _prio, "rdac" };
438 static const struct key_value chk_hp = { _checker, "hp_sw" };
439 static const struct key_value gui_foo = { _getuid, "/tmp/foo" };
440 static const struct key_value uid_baz = { _uid_attr, "BAZ_ATTR" };
441 static const struct key_value bl_bar = { _bl_product, "bar" };
442 static const struct key_value bl_baz = { _bl_product, "baz" };
443 static const struct key_value bl_barx = { _bl_product, "ba[[rxy]" };
444 static const struct key_value bl_bazy = { _bl_product, "ba[zy]" };
445 static const struct key_value minio_99 = { _minio, "99" };
446 static const struct key_value npr_37 = { _no_path_retry, "37" };
447 static const struct key_value npr_queue = { _no_path_retry, "queue" };
449 /***** BEGIN TESTS SECTION *****/
452 * Dump the configuration, subistitute the dumped configuration
453 * for the current one, and verify that the result is identical.
455 static void replicate_config(const struct hwt_state *hwt, bool local)
461 condlog(3, "--- %s: replicating %s configuration", __func__,
462 local ? "local" : "full");
464 conf = get_multipath_config();
466 /* "full" configuration */
467 cfg1 = snprint_config(conf, NULL, NULL, NULL);
469 /* "local" configuration */
470 hwtable = get_used_hwes(hwt->vecs->pathvec);
471 cfg1 = snprint_config(conf, NULL, hwtable, hwt->vecs->mpvec);
472 vector_free(hwtable);
475 assert_non_null(cfg1);
476 put_multipath_config(conf);
478 replace_config(hwt, cfg1);
481 * The local configuration adds multipath entries, and may move device
482 * entries for local devices to the end of the list. Identical config
483 * strings therefore can't be expected in the "local" case.
484 * That doesn't matter. The important thing is that, with the reloaded
485 * configuration, the test case still passes.
492 conf = get_multipath_config();
493 cfg2 = snprint_config(conf, NULL, NULL, NULL);
494 assert_non_null(cfg2);
495 put_multipath_config(conf);
497 // #define DBG_CONFIG 1
499 #define DUMP_CFG_STR(x) do { \
500 FILE *tmp = fopen("/tmp/hwtable-" #x ".txt", "w"); \
501 fprintf(tmp, "%s", x); \
509 assert_int_equal(strlen(cfg2), strlen(cfg1));
510 assert_string_equal(cfg2, cfg1);
516 * Run hwt->test three times; once with the constructed configuration,
517 * once after re-reading the full dumped configuration, and once with the
518 * dumped local configuration.
520 * Expected: test passes every time.
522 static void test_driver(void **state)
524 const struct hwt_state *hwt;
526 hwt = CHECK_STATE(state);
527 _conf = LOAD_CONFIG(hwt);
530 replicate_config(hwt, false);
531 reset_vecs(hwt->vecs);
534 replicate_config(hwt, true);
535 reset_vecs(hwt->vecs);
538 reset_vecs(hwt->vecs);
543 * Sanity check for the test itself, because defaults may be changed
546 * Our checking for match or non-match relies on the defaults being
547 * different from what our device sections contain.
549 static void test_sanity_globals(void **state)
551 assert_string_not_equal(prio_emc.value, DEFAULT_PRIO);
552 assert_string_not_equal(prio_hds.value, DEFAULT_PRIO);
553 assert_string_not_equal(chk_hp.value, DEFAULT_CHECKER);
554 assert_int_not_equal(MULTIBUS, DEFAULT_PGPOLICY);
555 assert_int_not_equal(NO_PATH_RETRY_QUEUE, DEFAULT_NO_PATH_RETRY);
556 assert_int_not_equal(atoi(minio_99.value), DEFAULT_MINIO_RQ);
557 assert_int_not_equal(atoi(npr_37.value), DEFAULT_NO_PATH_RETRY);
561 * Regression test for internal hwtable. NVME is an example of two entries
562 * in the built-in hwtable, one if which matches a subset of the other.
564 static void test_internal_nvme(const struct hwt_state *hwt)
567 struct multipath *mp;
570 * Generic NVMe: expect defaults for pgpolicy and no_path_retry
572 pp = mock_path("NVME", "NoName");
573 mp = mock_multipath(pp);
574 assert_ptr_not_equal(mp, NULL);
575 TEST_PROP(checker_name(&pp->checker), NONE);
576 TEST_PROP(pp->uid_attribute, DEFAULT_NVME_UID_ATTRIBUTE);
577 assert_int_equal(mp->pgpolicy, DEFAULT_PGPOLICY);
578 assert_int_equal(mp->no_path_retry, DEFAULT_NO_PATH_RETRY);
579 assert_int_equal(mp->retain_hwhandler, RETAIN_HWHANDLER_OFF);
582 * NetApp NVMe: expect special values for pgpolicy and no_path_retry
584 pp = mock_path_wwid("NVME", "NetApp ONTAP Controller",
586 mp = mock_multipath(pp);
587 assert_ptr_not_equal(mp, NULL);
588 TEST_PROP(checker_name(&pp->checker), NONE);
589 TEST_PROP(pp->uid_attribute, "ID_WWN");
590 assert_int_equal(mp->pgpolicy, MULTIBUS);
591 assert_int_equal(mp->no_path_retry, NO_PATH_RETRY_QUEUE);
592 assert_int_equal(mp->retain_hwhandler, RETAIN_HWHANDLER_OFF);
595 static int setup_internal_nvme(void **state)
597 struct hwt_state *hwt = CHECK_STATE(state);
599 WRITE_EMPTY_CONF(hwt);
600 SET_TEST_FUNC(hwt, test_internal_nvme);
606 * Device section with a simple entry with double quotes ('foo:"bar"')
608 static void test_quoted_hwe(const struct hwt_state *hwt)
612 /* foo:"bar" matches */
613 pp = mock_path(vnd_foo.value, prd_baq.value);
614 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
616 /* foo:bar doesn't match */
617 pp = mock_path(vnd_foo.value, prd_bar.value);
618 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
621 static int setup_quoted_hwe(void **state)
623 struct hwt_state *hwt = CHECK_STATE(state);
624 const struct key_value kv[] = { vnd_foo, prd_baqq, prio_emc };
626 WRITE_ONE_DEVICE(hwt, kv);
627 SET_TEST_FUNC(hwt, test_quoted_hwe);
632 * Device section with a single simple entry ("foo:bar")
634 static void test_string_hwe(const struct hwt_state *hwt)
638 /* foo:bar matches */
639 pp = mock_path(vnd_foo.value, prd_bar.value);
640 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
642 /* foo:baz doesn't match */
643 pp = mock_path(vnd_foo.value, prd_baz.value);
644 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
646 /* boo:bar doesn't match */
647 pp = mock_path(vnd_boo.value, prd_bar.value);
648 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
651 static int setup_string_hwe(void **state)
653 struct hwt_state *hwt = CHECK_STATE(state);
654 const struct key_value kv[] = { vnd_foo, prd_bar, prio_emc };
656 WRITE_ONE_DEVICE(hwt, kv);
657 SET_TEST_FUNC(hwt, test_string_hwe);
662 * Device section with a broken entry (no product)
663 * It should be ignored.
665 static void test_broken_hwe(const struct hwt_state *hwt)
669 /* foo:bar doesn't match, as hwentry is ignored */
670 pp = mock_path(vnd_foo.value, prd_bar.value);
671 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
673 /* boo:bar doesn't match */
674 pp = mock_path(vnd_boo.value, prd_bar.value);
675 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
678 static int setup_broken_hwe(void **state)
680 struct hwt_state *hwt = CHECK_STATE(state);
681 const struct key_value kv[] = { vnd_foo, prio_emc };
683 WRITE_ONE_DEVICE(hwt, kv);
684 SET_TEST_FUNC(hwt, test_broken_hwe);
689 * Like test_broken_hwe, but in config_dir file.
691 static int setup_broken_hwe_dir(void **state)
693 struct hwt_state *hwt = CHECK_STATE(state);
694 const struct key_value kv[] = { vnd_foo, prio_emc };
697 begin_section_all(hwt, "devices");
698 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv), kv);
699 end_section_all(hwt);
701 hwt->test = test_broken_hwe;
702 hwt->test_name = "test_broken_hwe_dir";
707 * Device section with a single regex entry ("^.foo:(bar|baz|ba\.)$")
709 static void test_regex_hwe(const struct hwt_state *hwt)
713 /* foo:bar matches */
714 pp = mock_path(vnd_foo.value, prd_bar.value);
715 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
717 /* foo:baz matches */
718 pp = mock_path(vnd_foo.value, prd_baz.value);
719 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
721 /* boo:baz matches */
722 pp = mock_path(vnd_boo.value, prd_bar.value);
723 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
725 /* foo:BAR doesn't match */
726 pp = mock_path(vnd_foo.value, "BAR");
727 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
729 /* bboo:bar doesn't match */
730 pp = mock_path("bboo", prd_bar.value);
731 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
734 static int setup_regex_hwe(void **state)
736 struct hwt_state *hwt = CHECK_STATE(state);
737 const struct key_value kv[] = { vnd_t_oo, prd_ba_s, prio_emc };
739 WRITE_ONE_DEVICE(hwt, kv);
740 SET_TEST_FUNC(hwt, test_regex_hwe);
745 * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
746 * kv2 a string match (foo:bar) which matches a subset of the regex.
747 * Both are added to the main config file.
749 * Expected: Devices matching both get properties from both, kv2 taking
750 * precedence. Devices matching kv1 only just get props from kv1.
752 static void test_regex_string_hwe(const struct hwt_state *hwt)
756 /* foo:baz matches kv1 */
757 pp = mock_path(vnd_foo.value, prd_baz.value);
758 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
759 TEST_PROP(pp->getuid, NULL);
760 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
762 /* boo:baz matches kv1 */
763 pp = mock_path(vnd_boo.value, prd_baz.value);
764 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
765 TEST_PROP(pp->getuid, NULL);
766 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
768 /* .oo:ba. matches kv1 */
769 pp = mock_path(vnd__oo.value, prd_ba_.value);
770 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
771 TEST_PROP(pp->getuid, NULL);
772 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
774 /* .foo:(bar|baz|ba\.) doesn't match */
775 pp = mock_path(vnd__oo.value, prd_ba_s.value);
776 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
777 TEST_PROP(pp->getuid, NULL);
778 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
780 /* foo:bar matches kv2 and kv1 */
781 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
782 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
783 TEST_PROP(pp->getuid, gui_foo.value);
784 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
787 static int setup_regex_string_hwe(void **state)
789 struct hwt_state *hwt = CHECK_STATE(state);
790 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
791 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
793 WRITE_TWO_DEVICES(hwt, kv1, kv2);
794 SET_TEST_FUNC(hwt, test_regex_string_hwe);
799 * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
800 * kv2 a string match (foo:bar) which matches a subset of the regex.
801 * kv1 is added to the main config file, kv2 to a config_dir file.
802 * This case is more important as you may think, because it's equivalent
803 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
805 * Expected: Devices matching kv2 (and thus, both) get properties
806 * from both, kv2 taking precedence.
807 * Devices matching kv1 only just get props from kv1.
809 static void test_regex_string_hwe_dir(const struct hwt_state *hwt)
813 /* foo:baz matches kv1 */
814 pp = mock_path(vnd_foo.value, prd_baz.value);
815 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
816 TEST_PROP(pp->getuid, NULL);
817 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
819 /* boo:baz matches kv1 */
820 pp = mock_path(vnd_boo.value, prd_baz.value);
821 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
822 TEST_PROP(pp->getuid, NULL);
823 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
825 /* .oo:ba. matches kv1 */
826 pp = mock_path(vnd__oo.value, prd_ba_.value);
827 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
828 TEST_PROP(pp->getuid, NULL);
829 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
831 /* .oo:(bar|baz|ba\.)$ doesn't match */
832 pp = mock_path(vnd__oo.value, prd_ba_s.value);
833 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
834 TEST_PROP(pp->getuid, NULL);
835 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
837 /* foo:bar matches kv2 */
838 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
839 /* Later match takes prio */
840 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
841 TEST_PROP(pp->getuid, gui_foo.value);
842 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
845 static int setup_regex_string_hwe_dir(void **state)
847 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
848 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
849 struct hwt_state *hwt = CHECK_STATE(state);
851 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
852 SET_TEST_FUNC(hwt, test_regex_string_hwe_dir);
857 * Three device entries, kv1 is a regex match and kv2 and kv3 string
858 * matches, where kv3 is a substring of kv2. All in different config
861 * Expected: Devices matching kv3 get props from all, devices matching
862 * kv2 from kv2 and kv1, and devices matching kv1 only just from kv1.
864 static void test_regex_2_strings_hwe_dir(const struct hwt_state *hwt)
868 /* foo:baz matches kv1 */
869 pp = mock_path(vnd_foo.value, prd_baz.value);
870 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
871 TEST_PROP(pp->getuid, NULL);
872 TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
873 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
875 /* boo:baz doesn't match */
876 pp = mock_path(vnd_boo.value, prd_baz.value);
877 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
878 TEST_PROP(pp->getuid, NULL);
879 TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
880 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
882 /* foo:bar matches kv2 and kv1 */
883 pp = mock_path(vnd_foo.value, prd_bar.value);
884 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
885 TEST_PROP(pp->getuid, NULL);
886 TEST_PROP(pp->uid_attribute, uid_baz.value);
887 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
889 /* foo:barz matches kv3 and kv2 and kv1 */
890 pp = mock_path_flags(vnd_foo.value, prd_barz.value, USE_GETUID);
891 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
892 TEST_PROP(pp->getuid, gui_foo.value);
893 TEST_PROP(pp->uid_attribute, NULL);
894 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
897 static int setup_regex_2_strings_hwe_dir(void **state)
899 const struct key_value kv1[] = { vnd_foo, prd_ba_, prio_emc, chk_hp };
900 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, uid_baz };
901 const struct key_value kv3[] = { vnd_foo, prd_barz,
902 prio_rdac, gui_foo };
903 struct hwt_state *hwt = CHECK_STATE(state);
906 begin_section_all(hwt, "devices");
907 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
908 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
909 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv3), kv3);
910 end_section_all(hwt);
912 SET_TEST_FUNC(hwt, test_regex_2_strings_hwe_dir);
917 * Like test_regex_string_hwe_dir, but the order of kv1 and kv2 is exchanged.
919 * Expected: Devices matching kv1 (and thus, both) get properties
920 * from both, kv1 taking precedence.
921 * Devices matching kv1 only just get props from kv1.
923 static void test_string_regex_hwe_dir(const struct hwt_state *hwt)
927 /* foo:bar matches kv2 and kv1 */
928 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
929 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
930 TEST_PROP(pp->getuid, gui_foo.value);
931 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
933 /* foo:baz matches kv1 */
934 pp = mock_path(vnd_foo.value, prd_baz.value);
935 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
936 TEST_PROP(pp->getuid, NULL);
937 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
939 /* boo:baz matches kv1 */
940 pp = mock_path(vnd_boo.value, prd_baz.value);
941 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
942 TEST_PROP(pp->getuid, NULL);
943 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
945 /* .oo:ba. matches kv1 */
946 pp = mock_path(vnd__oo.value, prd_ba_.value);
947 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
948 TEST_PROP(pp->getuid, NULL);
949 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
951 /* .oo:(bar|baz|ba\.)$ doesn't match */
952 pp = mock_path(vnd__oo.value, prd_ba_s.value);
953 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
954 TEST_PROP(pp->getuid, NULL);
955 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
958 static int setup_string_regex_hwe_dir(void **state)
960 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
961 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
962 struct hwt_state *hwt = CHECK_STATE(state);
964 WRITE_TWO_DEVICES_W_DIR(hwt, kv2, kv1);
965 SET_TEST_FUNC(hwt, test_string_regex_hwe_dir);
970 * Two identical device entries kv1 and kv2, trivial regex ("string").
971 * Both are added to the main config file.
972 * These entries are NOT merged.
973 * This could happen in a large multipath.conf file.
975 * Expected: matching devices get props from both, kv2 taking precedence.
977 static void test_2_ident_strings_hwe(const struct hwt_state *hwt)
981 /* foo:baz doesn't match */
982 pp = mock_path(vnd_foo.value, prd_baz.value);
983 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
984 TEST_PROP(pp->getuid, NULL);
985 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
987 /* foo:bar matches both */
988 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
989 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
990 TEST_PROP(pp->getuid, gui_foo.value);
991 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
994 static int setup_2_ident_strings_hwe(void **state)
996 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
997 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
998 struct hwt_state *hwt = CHECK_STATE(state);
1000 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1001 SET_TEST_FUNC(hwt, test_2_ident_strings_hwe);
1006 * Two identical device entries kv1 and kv2, trivial regex ("string").
1007 * Both are added to an extra config file.
1008 * This could happen in a large multipath.conf file.
1010 * Expected: matching devices get props from both, kv2 taking precedence.
1012 static void test_2_ident_strings_both_dir(const struct hwt_state *hwt)
1016 /* foo:baz doesn't match */
1017 pp = mock_path(vnd_foo.value, prd_baz.value);
1018 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1019 TEST_PROP(pp->getuid, NULL);
1020 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1022 /* foo:bar matches both */
1023 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1024 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1025 TEST_PROP(pp->getuid, gui_foo.value);
1026 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1029 static int setup_2_ident_strings_both_dir(void **state)
1031 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1032 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1033 struct hwt_state *hwt = CHECK_STATE(state);
1036 begin_section_all(hwt, "devices");
1037 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1038 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1039 end_section_all(hwt);
1041 SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir);
1046 * Two identical device entries kv1 and kv2, trivial regex ("string").
1047 * Both are added to an extra config file.
1048 * An empty entry kv0 with the same string exists in the main config file.
1050 * Expected: matching devices get props from both, kv2 taking precedence.
1052 static void test_2_ident_strings_both_dir_w_prev(const struct hwt_state *hwt)
1056 /* foo:baz doesn't match */
1057 pp = mock_path(vnd_foo.value, prd_baz.value);
1058 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1059 TEST_PROP(pp->getuid, NULL);
1060 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1062 /* foo:bar matches both */
1063 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1064 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1065 TEST_PROP(pp->getuid, gui_foo.value);
1066 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1069 static int setup_2_ident_strings_both_dir_w_prev(void **state)
1071 struct hwt_state *hwt = CHECK_STATE(state);
1073 const struct key_value kv0[] = { vnd_foo, prd_bar };
1074 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1075 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1078 begin_section_all(hwt, "devices");
1079 write_device(hwt->config_file, ARRAY_SIZE(kv0), kv0);
1080 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1081 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1082 end_section_all(hwt);
1084 SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir_w_prev);
1089 * Two identical device entries kv1 and kv2, trivial regex ("string").
1090 * kv1 is added to the main config file, kv2 to a config_dir file.
1091 * These entries are merged.
1092 * This case is more important as you may think, because it's equivalent
1093 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1095 * Expected: matching devices get props from both, kv2 taking precedence.
1097 static void test_2_ident_strings_hwe_dir(const struct hwt_state *hwt)
1101 /* foo:baz doesn't match */
1102 pp = mock_path(vnd_foo.value, prd_baz.value);
1103 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1104 TEST_PROP(pp->getuid, NULL);
1105 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1107 /* foo:bar matches both */
1108 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1109 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1110 TEST_PROP(pp->getuid, gui_foo.value);
1111 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1114 static int setup_2_ident_strings_hwe_dir(void **state)
1116 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1117 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1118 struct hwt_state *hwt = CHECK_STATE(state);
1120 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1121 SET_TEST_FUNC(hwt, test_2_ident_strings_hwe_dir);
1126 * Like test_2_ident_strings_hwe_dir, but this time the config_dir file
1127 * contains an additional, empty entry (kv0).
1129 * Expected: matching devices get props from kv1 and kv2, kv2 taking precedence.
1131 static void test_3_ident_strings_hwe_dir(const struct hwt_state *hwt)
1135 /* foo:baz doesn't match */
1136 pp = mock_path(vnd_foo.value, prd_baz.value);
1137 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1138 TEST_PROP(pp->getuid, NULL);
1139 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1141 /* foo:bar matches both */
1142 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1143 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1144 TEST_PROP(pp->getuid, gui_foo.value);
1145 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1148 static int setup_3_ident_strings_hwe_dir(void **state)
1150 const struct key_value kv0[] = { vnd_foo, prd_bar };
1151 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1152 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1153 struct hwt_state *hwt = CHECK_STATE(state);
1156 begin_section_all(hwt, "devices");
1157 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1158 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv0), kv0);
1159 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1160 end_section_all(hwt);
1162 SET_TEST_FUNC(hwt, test_3_ident_strings_hwe_dir);
1167 * Two identical device entries kv1 and kv2, non-trival regex that matches
1168 * itself (string ".oo" matches regex ".oo").
1169 * kv1 is added to the main config file, kv2 to a config_dir file.
1170 * This case is more important as you may think, because it's equivalent
1171 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1173 * Expected: matching devices get props from both, kv2 taking precedence.
1175 static void test_2_ident_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1179 /* foo:baz doesn't match */
1180 pp = mock_path(vnd_foo.value, prd_baz.value);
1181 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1182 TEST_PROP(pp->getuid, NULL);
1183 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1185 /* foo:bar matches both */
1186 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1187 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1188 TEST_PROP(pp->getuid, gui_foo.value);
1189 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1192 static int setup_2_ident_self_matching_re_hwe_dir(void **state)
1194 const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1195 const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1196 struct hwt_state *hwt = CHECK_STATE(state);
1198 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1199 SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe_dir);
1204 * Two identical device entries kv1 and kv2, non-trival regex that matches
1205 * itself (string ".oo" matches regex ".oo").
1206 * kv1 and kv2 are added to the main config file.
1208 * Expected: matching devices get props from both, kv2 taking precedence.
1210 static void test_2_ident_self_matching_re_hwe(const struct hwt_state *hwt)
1214 /* foo:baz doesn't match */
1215 pp = mock_path(vnd_foo.value, prd_baz.value);
1216 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1217 TEST_PROP(pp->getuid, NULL);
1218 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1220 /* foo:bar matches */
1221 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1222 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1223 TEST_PROP(pp->getuid, gui_foo.value);
1224 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1227 static int setup_2_ident_self_matching_re_hwe(void **state)
1229 const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1230 const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1231 struct hwt_state *hwt = CHECK_STATE(state);
1233 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1234 SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe);
1239 * Two identical device entries kv1 and kv2, non-trival regex that doesn't
1240 * match itself (string "^.oo" doesn't match regex "^.oo").
1241 * kv1 is added to the main config file, kv2 to a config_dir file.
1242 * This case is more important as you may think, see above.
1244 * Expected: matching devices get props from both, kv2 taking precedence.
1247 test_2_ident_not_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1251 /* foo:baz doesn't match */
1252 pp = mock_path(vnd_foo.value, prd_baz.value);
1253 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1254 TEST_PROP(pp->getuid, NULL);
1255 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1257 /* foo:bar matches both */
1258 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1259 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1260 TEST_PROP(pp->getuid, gui_foo.value);
1261 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1264 static int setup_2_ident_not_self_matching_re_hwe_dir(void **state)
1266 const struct key_value kv1[] = { vnd_t_oo, prd_bar, prio_emc, chk_hp };
1267 const struct key_value kv2[] = { vnd_t_oo, prd_bar, prio_hds, gui_foo };
1268 struct hwt_state *hwt = CHECK_STATE(state);
1270 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1271 SET_TEST_FUNC(hwt, test_2_ident_not_self_matching_re_hwe_dir);
1276 * Two different non-trivial regexes kv1, kv2. The 1st one matches the 2nd, but
1277 * it doesn't match all possible strings matching the second.
1278 * ("ba[zy]" matches regex "ba[[rxy]", but "baz" does not).
1280 * Expected: Devices matching both regexes get properties from both, kv2
1281 * taking precedence. Devices matching just one regex get properties from
1282 * that one regex only.
1284 static void test_2_matching_res_hwe_dir(const struct hwt_state *hwt)
1288 /* foo:bar matches k1 only */
1289 pp = mock_path(vnd_foo.value, prd_bar.value);
1290 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1291 TEST_PROP(pp->getuid, NULL);
1292 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1294 /* foo:bay matches k1 and k2 */
1295 pp = mock_path_flags(vnd_foo.value, "bay", USE_GETUID);
1296 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1297 TEST_PROP(pp->getuid, gui_foo.value);
1298 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1300 /* foo:baz matches k2 only. */
1301 pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1302 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1303 TEST_PROP(pp->getuid, gui_foo.value);
1304 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1307 static int setup_2_matching_res_hwe_dir(void **state)
1309 const struct key_value kv1[] = { vnd_foo, prd_barx, prio_emc, chk_hp };
1310 const struct key_value kv2[] = { vnd_foo, prd_bazy, prio_hds, gui_foo };
1311 struct hwt_state *hwt = CHECK_STATE(state);
1313 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1314 SET_TEST_FUNC(hwt, test_2_matching_res_hwe_dir);
1319 * Two different non-trivial regexes which match the same set of strings.
1320 * But they don't match each other.
1321 * "baz" matches both regex "ba[zy]" and "ba(z|y)"
1323 * Expected: matching devices get properties from both, kv2 taking precedence.
1325 static void test_2_nonmatching_res_hwe_dir(const struct hwt_state *hwt)
1329 /* foo:bar doesn't match */
1330 pp = mock_path(vnd_foo.value, prd_bar.value);
1331 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1332 TEST_PROP(pp->getuid, NULL);
1333 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1335 pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1336 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1337 TEST_PROP(pp->getuid, gui_foo.value);
1338 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1341 static int setup_2_nonmatching_res_hwe_dir(void **state)
1343 const struct key_value kv1[] = { vnd_foo, prd_bazy, prio_emc, chk_hp };
1344 const struct key_value kv2[] = { vnd_foo, prd_bazy1,
1345 prio_hds, gui_foo };
1346 struct hwt_state *hwt = CHECK_STATE(state);
1348 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1349 SET_TEST_FUNC(hwt, test_2_nonmatching_res_hwe_dir);
1354 * Simple blacklist test.
1356 * NOTE: test failures in blacklisting tests will manifest as cmocka errors
1357 * "Could not get value to mock function XYZ", because pathinfo() takes
1358 * different code paths for blacklisted devices.
1360 static void test_blacklist(const struct hwt_state *hwt)
1362 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1363 mock_path(vnd_foo.value, prd_baz.value);
1366 static int setup_blacklist(void **state)
1368 const struct key_value kv1[] = { vnd_foo, prd_bar };
1369 struct hwt_state *hwt = CHECK_STATE(state);
1372 begin_section_all(hwt, "blacklist");
1373 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1374 end_section_all(hwt);
1376 SET_TEST_FUNC(hwt, test_blacklist);
1381 * Simple blacklist test with regex and exception
1383 static void test_blacklist_regex(const struct hwt_state *hwt)
1385 mock_path(vnd_foo.value, prd_bar.value);
1386 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1387 mock_path(vnd_foo.value, prd_bam.value);
1390 static int setup_blacklist_regex(void **state)
1392 const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1393 const struct key_value kv2[] = { vnd_foo, prd_bar };
1394 struct hwt_state *hwt = CHECK_STATE(state);
1396 hwt = CHECK_STATE(state);
1398 begin_section_all(hwt, "blacklist");
1399 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1400 end_section_all(hwt);
1401 begin_section_all(hwt, "blacklist_exceptions");
1402 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1403 end_section_all(hwt);
1405 SET_TEST_FUNC(hwt, test_blacklist_regex);
1410 * Simple blacklist test with regex and exception
1411 * config file order inverted wrt test_blacklist_regex
1413 static int setup_blacklist_regex_inv(void **state)
1415 const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1416 const struct key_value kv2[] = { vnd_foo, prd_bar };
1417 struct hwt_state *hwt = CHECK_STATE(state);
1420 begin_section_all(hwt, "blacklist");
1421 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv1), kv1);
1422 end_section_all(hwt);
1423 begin_section_all(hwt, "blacklist_exceptions");
1424 write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2);
1425 end_section_all(hwt);
1427 SET_TEST_FUNC(hwt, test_blacklist_regex);
1432 * Simple blacklist test with regex and exception
1433 * config file order inverted wrt test_blacklist_regex
1435 static void test_blacklist_regex_matching(const struct hwt_state *hwt)
1437 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1438 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1439 mock_path(vnd_foo.value, prd_bam.value);
1442 static int setup_blacklist_regex_matching(void **state)
1444 const struct key_value kv1[] = { vnd_foo, prd_barx };
1445 const struct key_value kv2[] = { vnd_foo, prd_bazy };
1446 struct hwt_state *hwt = CHECK_STATE(state);
1449 begin_section_all(hwt, "blacklist");
1450 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1451 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1452 end_section_all(hwt);
1454 SET_TEST_FUNC(hwt, test_blacklist_regex_matching);
1459 * Test for blacklisting by WWID
1461 * Note that default_wwid is a substring of default_wwid_1. Because
1462 * matching is done by regex, both paths are blacklisted.
1464 static void test_blacklist_wwid(const struct hwt_state *hwt)
1466 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_WWID);
1467 mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1471 static int setup_blacklist_wwid(void **state)
1473 const struct key_value kv[] = { wwid_test };
1474 struct hwt_state *hwt = CHECK_STATE(state);
1477 write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1479 SET_TEST_FUNC(hwt, test_blacklist_wwid);
1484 * Test for blacklisting by WWID
1486 * Here the blacklist contains only default_wwid_1. Thus the path
1487 * with default_wwid is NOT blacklisted.
1489 static void test_blacklist_wwid_1(const struct hwt_state *hwt)
1491 mock_path(vnd_foo.value, prd_bar.value);
1492 mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1496 static int setup_blacklist_wwid_1(void **state)
1498 const struct key_value kv[] = { { _wwid, default_wwid_1 }, };
1499 struct hwt_state *hwt = CHECK_STATE(state);
1502 write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1504 SET_TEST_FUNC(hwt, test_blacklist_wwid_1);
1509 * Test for product_blacklist. Two entries blacklisting each other.
1511 * Expected: Both are blacklisted.
1513 static void test_product_blacklist(const struct hwt_state *hwt)
1515 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1516 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1517 mock_path(vnd_foo.value, prd_bam.value);
1520 static int setup_product_blacklist(void **state)
1522 const struct key_value kv1[] = { vnd_foo, prd_bar, bl_baz };
1523 const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bar };
1524 struct hwt_state *hwt = CHECK_STATE(state);
1526 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1527 SET_TEST_FUNC(hwt, test_product_blacklist);
1532 * Test for product_blacklist. The second regex "matches" the first.
1533 * This is a pathological example.
1535 * Expected: "foo:bar", "foo:baz" are blacklisted.
1537 static void test_product_blacklist_matching(const struct hwt_state *hwt)
1539 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1540 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1541 mock_path(vnd_foo.value, prd_bam.value);
1544 static int setup_product_blacklist_matching(void **state)
1546 const struct key_value kv1[] = { vnd_foo, prd_bar, bl_barx };
1547 const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bazy };
1548 struct hwt_state *hwt = CHECK_STATE(state);
1550 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1551 SET_TEST_FUNC(hwt, test_product_blacklist_matching);
1556 * Basic test for multipath-based configuration.
1558 * Expected: properties, including pp->prio, are taken from multipath
1561 static void test_multipath_config(const struct hwt_state *hwt)
1564 struct multipath *mp;
1566 pp = mock_path(vnd_foo.value, prd_bar.value);
1567 mp = mock_multipath(pp);
1568 assert_ptr_not_equal(mp->mpe, NULL);
1569 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1570 assert_int_equal(mp->minio, atoi(minio_99.value));
1571 TEST_PROP(pp->uid_attribute, uid_baz.value);
1573 /* test different wwid */
1574 pp = mock_path_wwid(vnd_foo.value, prd_bar.value, default_wwid_1);
1575 mp = mock_multipath(pp);
1576 // assert_ptr_equal(mp->mpe, NULL);
1577 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1578 assert_int_equal(mp->minio, DEFAULT_MINIO_RQ);
1579 TEST_PROP(pp->uid_attribute, uid_baz.value);
1582 static int setup_multipath_config(void **state)
1584 struct hwt_state *hwt = CHECK_STATE(state);
1585 const struct key_value kvm[] = { wwid_test, prio_rdac, minio_99 };
1586 const struct key_value kvp[] = { vnd_foo, prd_bar, prio_emc, uid_baz };
1589 begin_section_all(hwt, "devices");
1590 write_section(hwt->conf_dir_file[0], "device", ARRAY_SIZE(kvp), kvp);
1591 end_section_all(hwt);
1592 begin_section_all(hwt, "multipaths");
1593 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kvm), kvm);
1594 end_section_all(hwt);
1596 SET_TEST_FUNC(hwt, test_multipath_config);
1601 * Basic test for multipath-based configuration. Two sections for the same wwid.
1603 * Expected: properties are taken from both multipath sections, later taking
1606 static void test_multipath_config_2(const struct hwt_state *hwt)
1609 struct multipath *mp;
1611 pp = mock_path(vnd_foo.value, prd_bar.value);
1612 mp = mock_multipath(pp);
1613 assert_ptr_not_equal(mp, NULL);
1614 assert_ptr_not_equal(mp->mpe, NULL);
1615 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1616 assert_int_equal(mp->minio, atoi(minio_99.value));
1617 assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1620 static int setup_multipath_config_2(void **state)
1622 const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1623 const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1624 struct hwt_state *hwt = CHECK_STATE(state);
1627 begin_section_all(hwt, "multipaths");
1628 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1629 write_section(hwt->conf_dir_file[1], "multipath", ARRAY_SIZE(kv2), kv2);
1630 end_section_all(hwt);
1632 SET_TEST_FUNC(hwt, test_multipath_config_2);
1637 * Same as test_multipath_config_2, both entries in the same config file.
1639 * Expected: properties are taken from both multipath sections.
1641 static void test_multipath_config_3(const struct hwt_state *hwt)
1644 struct multipath *mp;
1646 pp = mock_path(vnd_foo.value, prd_bar.value);
1647 mp = mock_multipath(pp);
1648 assert_ptr_not_equal(mp, NULL);
1649 assert_ptr_not_equal(mp->mpe, NULL);
1650 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1651 assert_int_equal(mp->minio, atoi(minio_99.value));
1652 assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1655 static int setup_multipath_config_3(void **state)
1657 const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1658 const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1659 struct hwt_state *hwt = CHECK_STATE(state);
1662 begin_section_all(hwt, "multipaths");
1663 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1664 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv2), kv2);
1665 end_section_all(hwt);
1667 SET_TEST_FUNC(hwt, test_multipath_config_3);
1672 * Test for device with "hidden" attribute
1674 static void test_hidden(const struct hwt_state *hwt)
1676 mock_path_flags("NVME", "NoName", DEV_HIDDEN|BL_MASK);
1679 static int setup_hidden(void **state)
1681 struct hwt_state *hwt = CHECK_STATE(state);
1683 WRITE_EMPTY_CONF(hwt);
1684 SET_TEST_FUNC(hwt, test_hidden);
1690 * Create wrapper functions around test_driver() to avoid that cmocka
1691 * always uses the same test name. That makes it easier to read test results.
1694 #define define_test(x) \
1695 static void run_##x(void **state) \
1697 return test_driver(state); \
1700 define_test(string_hwe)
1701 define_test(broken_hwe)
1702 define_test(broken_hwe_dir)
1703 define_test(quoted_hwe)
1704 define_test(internal_nvme)
1705 define_test(regex_hwe)
1706 define_test(regex_string_hwe)
1707 define_test(regex_string_hwe_dir)
1708 define_test(regex_2_strings_hwe_dir)
1709 define_test(string_regex_hwe_dir)
1710 define_test(2_ident_strings_hwe)
1711 define_test(2_ident_strings_both_dir)
1712 define_test(2_ident_strings_both_dir_w_prev)
1713 define_test(2_ident_strings_hwe_dir)
1714 define_test(3_ident_strings_hwe_dir)
1715 define_test(2_ident_self_matching_re_hwe_dir)
1716 define_test(2_ident_self_matching_re_hwe)
1717 define_test(2_ident_not_self_matching_re_hwe_dir)
1718 define_test(2_matching_res_hwe_dir)
1719 define_test(2_nonmatching_res_hwe_dir)
1720 define_test(blacklist)
1721 define_test(blacklist_wwid)
1722 define_test(blacklist_wwid_1)
1723 define_test(blacklist_regex)
1724 define_test(blacklist_regex_inv)
1725 define_test(blacklist_regex_matching)
1726 define_test(product_blacklist)
1727 define_test(product_blacklist_matching)
1728 define_test(multipath_config)
1729 define_test(multipath_config_2)
1730 define_test(multipath_config_3)
1733 #define test_entry(x) \
1734 cmocka_unit_test_setup(run_##x, setup_##x)
1736 static int test_hwtable(void)
1738 const struct CMUnitTest tests[] = {
1739 cmocka_unit_test(test_sanity_globals),
1740 test_entry(internal_nvme),
1741 test_entry(string_hwe),
1742 test_entry(broken_hwe),
1743 test_entry(broken_hwe_dir),
1744 test_entry(quoted_hwe),
1745 test_entry(regex_hwe),
1746 test_entry(regex_string_hwe),
1747 test_entry(regex_string_hwe_dir),
1748 test_entry(regex_2_strings_hwe_dir),
1749 test_entry(string_regex_hwe_dir),
1750 test_entry(2_ident_strings_hwe),
1751 test_entry(2_ident_strings_both_dir),
1752 test_entry(2_ident_strings_both_dir_w_prev),
1753 test_entry(2_ident_strings_hwe_dir),
1754 test_entry(3_ident_strings_hwe_dir),
1755 test_entry(2_ident_self_matching_re_hwe_dir),
1756 test_entry(2_ident_self_matching_re_hwe),
1757 test_entry(2_ident_not_self_matching_re_hwe_dir),
1758 test_entry(2_matching_res_hwe_dir),
1759 test_entry(2_nonmatching_res_hwe_dir),
1760 test_entry(blacklist),
1761 test_entry(blacklist_wwid),
1762 test_entry(blacklist_wwid_1),
1763 test_entry(blacklist_regex),
1764 test_entry(blacklist_regex_inv),
1765 test_entry(blacklist_regex_matching),
1766 test_entry(product_blacklist),
1767 test_entry(product_blacklist_matching),
1768 test_entry(multipath_config),
1769 test_entry(multipath_config_2),
1770 test_entry(multipath_config_3),
1774 return cmocka_run_group_tests(tests, setup, teardown);
1781 /* We can't use init_test_verbosity in this test */
1782 libmp_verbosity = VERBOSITY;
1783 ret += test_hwtable();