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";
33 /* pretend new dm, use minio_rq */
34 static const unsigned int dm_tgt_version[3] = { 1, 1, 1 };
45 FILE *conf_dir_file[N_CONF_FILES];
47 void (*test)(const struct hwt_state *);
48 const char *test_name;
51 #define SET_TEST_FUNC(hwt, func) do { \
53 hwt->test_name = #func; \
56 static struct config *_conf;
60 struct config *get_multipath_config(void)
65 void put_multipath_config(void *arg)
68 void make_config_file_path(char *buf, int buflen,
69 const struct hwt_state *hwt, int i)
71 static const char fn_template[] = "%s/test-%02d.conf";
74 /* main config file */
75 snprintf(buf, buflen, fn_template, hwt->tmpname, 0);
77 snprintf(buf, buflen, fn_template, hwt->dirname, i);
80 static void reset_vecs(struct vectors *vecs)
83 free_pathvec(vecs->pathvec, FREE_PATHS);
85 vecs->pathvec = vector_alloc();
86 assert_ptr_not_equal(vecs->pathvec, NULL);
87 vecs->mpvec = vector_alloc();
88 assert_ptr_not_equal(vecs->mpvec, NULL);
91 static void free_hwt(struct hwt_state *hwt)
96 if (hwt->config_file != NULL)
97 fclose(hwt->config_file);
98 for (i = 0; i < N_CONF_FILES; i++) {
99 if (hwt->conf_dir_file[i] != NULL)
100 fclose(hwt->conf_dir_file[i]);
103 if (hwt->tmpname != NULL) {
104 make_config_file_path(buf, sizeof(buf), hwt, -1);
110 if (hwt->dirname != NULL) {
111 for (i = 0; i < N_CONF_FILES; i++) {
112 make_config_file_path(buf, sizeof(buf), hwt, i);
119 if (hwt->vecs != NULL) {
120 if (hwt->vecs->mpvec != NULL)
121 remove_maps(hwt->vecs);
122 if (hwt->vecs->pathvec != NULL)
123 free_pathvec(hwt->vecs->pathvec, FREE_PATHS);
124 pthread_mutex_destroy(&hwt->vecs->lock.mutex);
130 static int setup(void **state)
132 struct hwt_state *hwt;
137 hwt = calloc(1, sizeof(*hwt));
141 snprintf(buf, sizeof(buf), "%s", tmplate);
142 if (mkdtemp(buf) == NULL) {
143 condlog(0, "mkdtemp: %s", strerror(errno));
146 hwt->tmpname = strdup(buf);
148 snprintf(buf, sizeof(buf), "%s", tmplate);
149 if (mkdtemp(buf) == NULL) {
150 condlog(0, "mkdtemp (2): %s", strerror(errno));
153 hwt->dirname = strdup(buf);
155 make_config_file_path(buf, sizeof(buf), hwt, -1);
156 hwt->config_file = fopen(buf, "w+");
157 if (hwt->config_file == NULL)
160 for (i = 0; i < N_CONF_FILES; i++) {
161 make_config_file_path(buf, sizeof(buf), hwt, i);
162 hwt->conf_dir_file[i] = fopen(buf, "w+");
163 if (hwt->conf_dir_file[i] == NULL)
167 hwt->vecs = calloc(1, sizeof(*hwt->vecs));
168 if (hwt->vecs == NULL)
170 pthread_mutex_init(&hwt->vecs->lock.mutex, NULL);
171 hwt->vecs->pathvec = vector_alloc();
172 hwt->vecs->mpvec = vector_alloc();
173 if (hwt->vecs->pathvec == NULL || hwt->vecs->mpvec == NULL)
184 static int teardown(void **state)
186 if (state == NULL || *state == NULL)
199 * Helpers for creating the config file(s)
202 static void reset_config(FILE *ff)
207 if (ftruncate(fileno(ff), 0) == -1)
208 condlog(1, "ftruncate: %s", strerror(errno));
211 static void reset_configs(const struct hwt_state *hwt)
215 reset_config(hwt->config_file);
216 for (i = 0; i < N_CONF_FILES; i++)
217 reset_config(hwt->conf_dir_file[i]);
220 static void write_key_values(FILE *ff, int nkv, const struct key_value *kv)
224 for (i = 0; i < nkv; i++) {
225 if (strchr(kv[i].value, ' ') == NULL &&
226 strchr(kv[i].value, '\"') == NULL)
227 fprintf(ff, "\t%s %s\n", kv[i].key, kv[i].value);
229 fprintf(ff, "\t%s \"%s\"\n", kv[i].key, kv[i].value);
233 static void begin_section(FILE *ff, const char *section)
235 fprintf(ff, "%s {\n", section);
238 static void end_section(FILE *ff)
243 static void write_section(FILE *ff, const char *section,
244 int nkv, const struct key_value *kv)
246 begin_section(ff, section);
247 write_key_values(ff, nkv, kv);
251 static void write_defaults(const struct hwt_state *hwt)
253 static const char bindings_name[] = "bindings";
254 static struct key_value defaults[] = {
255 { "config_dir", NULL },
256 { "bindings_file", NULL },
257 { "multipath_dir", NULL },
258 { "detect_prio", "no" },
259 { "detect_checker", "no" },
261 char buf[sizeof(tmplate) + sizeof(bindings_name)];
262 char dirbuf[PATH_MAX];
264 snprintf(buf, sizeof(buf), "%s/%s", hwt->tmpname, bindings_name);
265 defaults[0].value = hwt->dirname;
266 defaults[1].value = buf;
267 assert_ptr_not_equal(getcwd(dirbuf, sizeof(dirbuf)), NULL);
268 strncat(dirbuf, "/lib", sizeof(dirbuf) - 5);
269 defaults[2].value = dirbuf;
270 write_section(hwt->config_file, "defaults",
271 ARRAY_SIZE(defaults), defaults);
274 static void begin_config(const struct hwt_state *hwt)
280 static void begin_section_all(const struct hwt_state *hwt, const char *section)
284 begin_section(hwt->config_file, section);
285 for (i = 0; i < N_CONF_FILES; i++)
286 begin_section(hwt->conf_dir_file[i], section);
289 static void end_section_all(const struct hwt_state *hwt)
293 end_section(hwt->config_file);
294 for (i = 0; i < N_CONF_FILES; i++)
295 end_section(hwt->conf_dir_file[i]);
298 static void finish_config(const struct hwt_state *hwt)
302 fflush(hwt->config_file);
303 for (i = 0; i < N_CONF_FILES; i++) {
304 fflush(hwt->conf_dir_file[i]);
308 static void write_device(FILE *ff, int nkv, const struct key_value *kv)
310 write_section(ff, "device", nkv, kv);
314 * Some macros to avoid boilerplace code
317 #define CHECK_STATE(state) ({ \
318 assert_ptr_not_equal(state, NULL); \
319 assert_ptr_not_equal(*(state), NULL); \
322 #define WRITE_EMPTY_CONF(hwt) do { \
324 finish_config(hwt); \
327 #define WRITE_ONE_DEVICE(hwt, kv) do { \
329 begin_section_all(hwt, "devices"); \
330 write_device(hwt->config_file, ARRAY_SIZE(kv), kv); \
331 end_section_all(hwt); \
332 finish_config(hwt); \
335 #define WRITE_TWO_DEVICES(hwt, kv1, kv2) do { \
337 begin_section_all(hwt, "devices"); \
338 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1); \
339 write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2); \
340 end_section_all(hwt); \
341 finish_config(hwt); \
344 #define WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2) do { \
346 begin_section_all(hwt, "devices"); \
347 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1); \
348 write_device(hwt->conf_dir_file[0], \
349 ARRAY_SIZE(kv2), kv2); \
350 end_section_all(hwt); \
351 finish_config(hwt); \
354 #define LOAD_CONFIG(hwt) ({ \
355 char buf[PATH_MAX]; \
356 struct config *__cf; \
358 make_config_file_path(buf, sizeof(buf), hwt, -1); \
359 __cf = load_config(buf); \
360 assert_ptr_not_equal(__cf, NULL); \
361 assert_ptr_not_equal(__cf->hwtable, NULL); \
362 __cf->verbosity = VERBOSITY; \
363 memcpy(&__cf->version, dm_tgt_version, sizeof(__cf->version)); \
366 #define FREE_CONFIG(conf) do { \
371 static void replace_config(const struct hwt_state *hwt,
372 const char *conf_str)
376 fprintf(hwt->config_file, "%s", conf_str);
377 fflush(hwt->config_file);
378 _conf = LOAD_CONFIG(hwt);
381 #define TEST_PROP(prop, val) do { \
383 assert_ptr_equal(prop, NULL); \
385 assert_ptr_not_equal(prop, NULL); \
386 assert_string_equal(prop, val); \
391 #define TEST_PROP_BROKEN(name, prop, bad, good) do { \
392 condlog(1, "%s: WARNING: Broken test for %s == \"%s\" on line %d, should be \"%s\"", \
393 __func__, name, bad ? bad : "NULL", \
394 __LINE__, good ? good : "NULL"); \
395 TEST_PROP(prop, bad); \
398 #define TEST_PROP_BROKEN(name, prop, bad, good) TEST_PROP(prop, good)
402 * Some predefined key/value pairs
405 static const char _wwid[] = "wwid";
406 static const char _vendor[] = "vendor";
407 static const char _product[] = "product";
408 static const char _prio[] = "prio";
409 static const char _checker[] = "path_checker";
410 static const char _getuid[] = "getuid_callout";
411 static const char _uid_attr[] = "uid_attribute";
412 static const char _bl_product[] = "product_blacklist";
413 static const char _minio[] = "rr_min_io_rq";
414 static const char _no_path_retry[] = "no_path_retry";
416 /* Device identifiers */
417 static const struct key_value vnd_foo = { _vendor, "foo" };
418 static const struct key_value prd_bar = { _product, "bar" };
419 static const struct key_value prd_bam = { _product, "bam" };
420 static const struct key_value prd_baq = { _product, "\"bar\"" };
421 static const struct key_value prd_baqq = { _product, "\"\"bar\"\"" };
422 static const struct key_value prd_barz = { _product, "barz" };
423 static const struct key_value vnd_boo = { _vendor, "boo" };
424 static const struct key_value prd_baz = { _product, "baz" };
425 static const struct key_value wwid_test = { _wwid, default_wwid };
427 /* Regular expresssions */
428 static const struct key_value vnd__oo = { _vendor, ".oo" };
429 static const struct key_value vnd_t_oo = { _vendor, "^.oo" };
430 static const struct key_value prd_ba_ = { _product, "ba." };
431 static const struct key_value prd_ba_s = { _product, "(bar|baz|ba\\.)$" };
432 /* Pathological cases, see below */
433 static const struct key_value prd_barx = { _product, "ba[[rxy]" };
434 static const struct key_value prd_bazy = { _product, "ba[zy]" };
435 static const struct key_value prd_bazy1 = { _product, "ba(z|y)" };
438 static const struct key_value prio_emc = { _prio, "emc" };
439 static const struct key_value prio_hds = { _prio, "hds" };
440 static const struct key_value prio_rdac = { _prio, "rdac" };
441 static const struct key_value chk_hp = { _checker, "hp_sw" };
442 static const struct key_value gui_foo = { _getuid, "/tmp/foo" };
443 static const struct key_value uid_baz = { _uid_attr, "BAZ_ATTR" };
444 static const struct key_value bl_bar = { _bl_product, "bar" };
445 static const struct key_value bl_baz = { _bl_product, "baz" };
446 static const struct key_value bl_barx = { _bl_product, "ba[[rxy]" };
447 static const struct key_value bl_bazy = { _bl_product, "ba[zy]" };
448 static const struct key_value minio_99 = { _minio, "99" };
449 static const struct key_value npr_37 = { _no_path_retry, "37" };
450 static const struct key_value npr_queue = { _no_path_retry, "queue" };
452 /***** BEGIN TESTS SECTION *****/
455 * Dump the configuration, subistitute the dumped configuration
456 * for the current one, and verify that the result is identical.
458 static void replicate_config(const struct hwt_state *hwt, bool local)
464 condlog(3, "--- %s: replicating %s configuration", __func__,
465 local ? "local" : "full");
467 conf = get_multipath_config();
469 /* "full" configuration */
470 cfg1 = snprint_config(conf, NULL, NULL, NULL);
472 /* "local" configuration */
473 hwtable = get_used_hwes(hwt->vecs->pathvec);
474 cfg1 = snprint_config(conf, NULL, hwtable, hwt->vecs->mpvec);
475 vector_free(hwtable);
478 assert_non_null(cfg1);
479 put_multipath_config(conf);
481 replace_config(hwt, cfg1);
484 * The local configuration adds multipath entries, and may move device
485 * entries for local devices to the end of the list. Identical config
486 * strings therefore can't be expected in the "local" case.
487 * That doesn't matter. The important thing is that, with the reloaded
488 * configuration, the test case still passes.
495 conf = get_multipath_config();
496 cfg2 = snprint_config(conf, NULL, NULL, NULL);
497 assert_non_null(cfg2);
498 put_multipath_config(conf);
500 // #define DBG_CONFIG 1
502 #define DUMP_CFG_STR(x) do { \
503 FILE *tmp = fopen("/tmp/hwtable-" #x ".txt", "w"); \
504 fprintf(tmp, "%s", x); \
512 assert_int_equal(strlen(cfg2), strlen(cfg1));
513 assert_string_equal(cfg2, cfg1);
519 * Run hwt->test three times; once with the constructed configuration,
520 * once after re-reading the full dumped configuration, and once with the
521 * dumped local configuration.
523 * Expected: test passes every time.
525 static void test_driver(void **state)
527 const struct hwt_state *hwt;
529 hwt = CHECK_STATE(state);
530 _conf = LOAD_CONFIG(hwt);
533 replicate_config(hwt, false);
534 reset_vecs(hwt->vecs);
537 replicate_config(hwt, true);
538 reset_vecs(hwt->vecs);
541 reset_vecs(hwt->vecs);
546 * Sanity check for the test itself, because defaults may be changed
549 * Our checking for match or non-match relies on the defaults being
550 * different from what our device sections contain.
552 static void test_sanity_globals(void **state)
554 assert_string_not_equal(prio_emc.value, DEFAULT_PRIO);
555 assert_string_not_equal(prio_hds.value, DEFAULT_PRIO);
556 assert_string_not_equal(chk_hp.value, DEFAULT_CHECKER);
557 assert_int_not_equal(MULTIBUS, DEFAULT_PGPOLICY);
558 assert_int_not_equal(NO_PATH_RETRY_QUEUE, DEFAULT_NO_PATH_RETRY);
559 assert_int_not_equal(atoi(minio_99.value), DEFAULT_MINIO_RQ);
560 assert_int_not_equal(atoi(npr_37.value), DEFAULT_NO_PATH_RETRY);
564 * Regression test for internal hwtable. NVME is an example of two entries
565 * in the built-in hwtable, one if which matches a subset of the other.
567 static void test_internal_nvme(const struct hwt_state *hwt)
570 struct multipath *mp;
573 * Generic NVMe: expect defaults for pgpolicy and no_path_retry
575 pp = mock_path("NVME", "NoName");
576 mp = mock_multipath(pp);
577 assert_ptr_not_equal(mp, NULL);
578 TEST_PROP(checker_name(&pp->checker), NONE);
579 TEST_PROP(pp->uid_attribute, DEFAULT_NVME_UID_ATTRIBUTE);
580 assert_int_equal(mp->pgpolicy, DEFAULT_PGPOLICY);
581 assert_int_equal(mp->no_path_retry, DEFAULT_NO_PATH_RETRY);
582 assert_int_equal(mp->retain_hwhandler, RETAIN_HWHANDLER_OFF);
585 * NetApp NVMe: expect special values for pgpolicy and no_path_retry
587 pp = mock_path_wwid("NVME", "NetApp ONTAP Controller",
589 mp = mock_multipath(pp);
590 assert_ptr_not_equal(mp, NULL);
591 TEST_PROP(checker_name(&pp->checker), NONE);
592 TEST_PROP(pp->uid_attribute, "ID_WWN");
593 assert_int_equal(mp->pgpolicy, MULTIBUS);
594 assert_int_equal(mp->no_path_retry, NO_PATH_RETRY_QUEUE);
595 assert_int_equal(mp->retain_hwhandler, RETAIN_HWHANDLER_OFF);
598 static int setup_internal_nvme(void **state)
600 struct hwt_state *hwt = CHECK_STATE(state);
602 WRITE_EMPTY_CONF(hwt);
603 SET_TEST_FUNC(hwt, test_internal_nvme);
609 * Device section with a simple entry qith double quotes ('foo:"bar"')
611 static void test_quoted_hwe(const struct hwt_state *hwt)
615 /* foo:"bar" matches */
616 pp = mock_path(vnd_foo.value, prd_baq.value);
617 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
619 /* foo:bar doesn't match */
620 pp = mock_path(vnd_foo.value, prd_bar.value);
621 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
624 static int setup_quoted_hwe(void **state)
626 struct hwt_state *hwt = CHECK_STATE(state);
627 const struct key_value kv[] = { vnd_foo, prd_baqq, prio_emc };
629 WRITE_ONE_DEVICE(hwt, kv);
630 SET_TEST_FUNC(hwt, test_quoted_hwe);
635 * Device section with a single simple entry ("foo:bar")
637 static void test_string_hwe(const struct hwt_state *hwt)
641 /* foo:bar matches */
642 pp = mock_path(vnd_foo.value, prd_bar.value);
643 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
645 /* foo:baz doesn't match */
646 pp = mock_path(vnd_foo.value, prd_baz.value);
647 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
649 /* boo:bar doesn't match */
650 pp = mock_path(vnd_boo.value, prd_bar.value);
651 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
654 static int setup_string_hwe(void **state)
656 struct hwt_state *hwt = CHECK_STATE(state);
657 const struct key_value kv[] = { vnd_foo, prd_bar, prio_emc };
659 WRITE_ONE_DEVICE(hwt, kv);
660 SET_TEST_FUNC(hwt, test_string_hwe);
665 * Device section with a broken entry (no product)
666 * It should be ignored.
668 static void test_broken_hwe(const struct hwt_state *hwt)
672 /* foo:bar doesn't match, as hwentry is ignored */
673 pp = mock_path(vnd_foo.value, prd_bar.value);
674 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
676 /* boo:bar doesn't match */
677 pp = mock_path(vnd_boo.value, prd_bar.value);
678 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
681 static int setup_broken_hwe(void **state)
683 struct hwt_state *hwt = CHECK_STATE(state);
684 const struct key_value kv[] = { vnd_foo, prio_emc };
686 WRITE_ONE_DEVICE(hwt, kv);
687 SET_TEST_FUNC(hwt, test_broken_hwe);
692 * Like test_broken_hwe, but in config_dir file.
694 static int setup_broken_hwe_dir(void **state)
696 struct hwt_state *hwt = CHECK_STATE(state);
697 const struct key_value kv[] = { vnd_foo, prio_emc };
700 begin_section_all(hwt, "devices");
701 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv), kv);
702 end_section_all(hwt);
704 hwt->test = test_broken_hwe;
705 hwt->test_name = "test_broken_hwe_dir";
710 * Device section with a single regex entry ("^.foo:(bar|baz|ba\.)$")
712 static void test_regex_hwe(const struct hwt_state *hwt)
716 /* foo:bar matches */
717 pp = mock_path(vnd_foo.value, prd_bar.value);
718 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
720 /* foo:baz matches */
721 pp = mock_path(vnd_foo.value, prd_baz.value);
722 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
724 /* boo:baz matches */
725 pp = mock_path(vnd_boo.value, prd_bar.value);
726 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
728 /* foo:BAR doesn't match */
729 pp = mock_path(vnd_foo.value, "BAR");
730 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
732 /* bboo:bar doesn't match */
733 pp = mock_path("bboo", prd_bar.value);
734 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
737 static int setup_regex_hwe(void **state)
739 struct hwt_state *hwt = CHECK_STATE(state);
740 const struct key_value kv[] = { vnd_t_oo, prd_ba_s, prio_emc };
742 WRITE_ONE_DEVICE(hwt, kv);
743 SET_TEST_FUNC(hwt, test_regex_hwe);
748 * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
749 * kv2 a string match (foo:bar) which matches a subset of the regex.
750 * Both are added to the main config file.
752 * Expected: Devices matching both get properties from both, kv2 taking
753 * precedence. Devices matching kv1 only just get props from kv1.
755 static void test_regex_string_hwe(const struct hwt_state *hwt)
759 /* foo:baz matches kv1 */
760 pp = mock_path(vnd_foo.value, prd_baz.value);
761 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
762 TEST_PROP(pp->getuid, NULL);
763 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
765 /* boo:baz matches kv1 */
766 pp = mock_path(vnd_boo.value, prd_baz.value);
767 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
768 TEST_PROP(pp->getuid, NULL);
769 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
771 /* .oo:ba. matches kv1 */
772 pp = mock_path(vnd__oo.value, prd_ba_.value);
773 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
774 TEST_PROP(pp->getuid, NULL);
775 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
777 /* .foo:(bar|baz|ba\.) doesn't match */
778 pp = mock_path(vnd__oo.value, prd_ba_s.value);
779 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
780 TEST_PROP(pp->getuid, NULL);
781 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
783 /* foo:bar matches kv2 and kv1 */
784 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
785 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
786 TEST_PROP(pp->getuid, gui_foo.value);
787 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
790 static int setup_regex_string_hwe(void **state)
792 struct hwt_state *hwt = CHECK_STATE(state);
793 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
794 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
796 WRITE_TWO_DEVICES(hwt, kv1, kv2);
797 SET_TEST_FUNC(hwt, test_regex_string_hwe);
802 * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
803 * kv2 a string match (foo:bar) which matches a subset of the regex.
804 * kv1 is added to the main config file, kv2 to a config_dir file.
805 * This case is more important as you may think, because it's equivalent
806 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
808 * Expected: Devices matching kv2 (and thus, both) get properties
809 * from both, kv2 taking precedence.
810 * Devices matching kv1 only just get props from kv1.
812 static void test_regex_string_hwe_dir(const struct hwt_state *hwt)
816 /* foo:baz matches kv1 */
817 pp = mock_path(vnd_foo.value, prd_baz.value);
818 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
819 TEST_PROP(pp->getuid, NULL);
820 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
822 /* boo:baz matches kv1 */
823 pp = mock_path(vnd_boo.value, prd_baz.value);
824 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
825 TEST_PROP(pp->getuid, NULL);
826 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
828 /* .oo:ba. matches kv1 */
829 pp = mock_path(vnd__oo.value, prd_ba_.value);
830 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
831 TEST_PROP(pp->getuid, NULL);
832 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
834 /* .oo:(bar|baz|ba\.)$ doesn't match */
835 pp = mock_path(vnd__oo.value, prd_ba_s.value);
836 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
837 TEST_PROP(pp->getuid, NULL);
838 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
840 /* foo:bar matches kv2 */
841 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
842 /* Later match takes prio */
843 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
844 TEST_PROP(pp->getuid, gui_foo.value);
845 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
848 static int setup_regex_string_hwe_dir(void **state)
850 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
851 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
852 struct hwt_state *hwt = CHECK_STATE(state);
854 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
855 SET_TEST_FUNC(hwt, test_regex_string_hwe_dir);
860 * Three device entries, kv1 is a regex match and kv2 and kv3 string
861 * matches, where kv3 is a substring of kv2. All in different config
864 * Expected: Devices matching kv3 get props from all, devices matching
865 * kv2 from kv2 and kv1, and devices matching kv1 only just from kv1.
867 static void test_regex_2_strings_hwe_dir(const struct hwt_state *hwt)
871 /* foo:baz matches kv1 */
872 pp = mock_path(vnd_foo.value, prd_baz.value);
873 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
874 TEST_PROP(pp->getuid, NULL);
875 TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
876 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
878 /* boo:baz doesn't match */
879 pp = mock_path(vnd_boo.value, prd_baz.value);
880 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
881 TEST_PROP(pp->getuid, NULL);
882 TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
883 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
885 /* foo:bar matches kv2 and kv1 */
886 pp = mock_path(vnd_foo.value, prd_bar.value);
887 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
888 TEST_PROP(pp->getuid, NULL);
889 TEST_PROP(pp->uid_attribute, uid_baz.value);
890 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
892 /* foo:barz matches kv3 and kv2 and kv1 */
893 pp = mock_path_flags(vnd_foo.value, prd_barz.value, USE_GETUID);
894 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
895 TEST_PROP(pp->getuid, gui_foo.value);
896 TEST_PROP(pp->uid_attribute, NULL);
897 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
900 static int setup_regex_2_strings_hwe_dir(void **state)
902 const struct key_value kv1[] = { vnd_foo, prd_ba_, prio_emc, chk_hp };
903 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, uid_baz };
904 const struct key_value kv3[] = { vnd_foo, prd_barz,
905 prio_rdac, gui_foo };
906 struct hwt_state *hwt = CHECK_STATE(state);
909 begin_section_all(hwt, "devices");
910 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
911 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
912 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv3), kv3);
913 end_section_all(hwt);
915 SET_TEST_FUNC(hwt, test_regex_2_strings_hwe_dir);
920 * Like test_regex_string_hwe_dir, but the order of kv1 and kv2 is exchanged.
922 * Expected: Devices matching kv1 (and thus, both) get properties
923 * from both, kv1 taking precedence.
924 * Devices matching kv1 only just get props from kv1.
926 static void test_string_regex_hwe_dir(const struct hwt_state *hwt)
930 /* foo:bar matches kv2 and kv1 */
931 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
932 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
933 TEST_PROP(pp->getuid, gui_foo.value);
934 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
936 /* foo:baz matches kv1 */
937 pp = mock_path(vnd_foo.value, prd_baz.value);
938 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
939 TEST_PROP(pp->getuid, NULL);
940 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
942 /* boo:baz matches kv1 */
943 pp = mock_path(vnd_boo.value, prd_baz.value);
944 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
945 TEST_PROP(pp->getuid, NULL);
946 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
948 /* .oo:ba. matches kv1 */
949 pp = mock_path(vnd__oo.value, prd_ba_.value);
950 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
951 TEST_PROP(pp->getuid, NULL);
952 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
954 /* .oo:(bar|baz|ba\.)$ doesn't match */
955 pp = mock_path(vnd__oo.value, prd_ba_s.value);
956 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
957 TEST_PROP(pp->getuid, NULL);
958 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
961 static int setup_string_regex_hwe_dir(void **state)
963 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
964 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
965 struct hwt_state *hwt = CHECK_STATE(state);
967 WRITE_TWO_DEVICES_W_DIR(hwt, kv2, kv1);
968 SET_TEST_FUNC(hwt, test_string_regex_hwe_dir);
973 * Two identical device entries kv1 and kv2, trival regex ("string").
974 * Both are added to the main config file.
975 * These entries are NOT merged.
976 * This could happen in a large multipath.conf file.
978 * Expected: matching devices get props from both, kv2 taking precedence.
980 static void test_2_ident_strings_hwe(const struct hwt_state *hwt)
984 /* foo:baz doesn't match */
985 pp = mock_path(vnd_foo.value, prd_baz.value);
986 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
987 TEST_PROP(pp->getuid, NULL);
988 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
990 /* foo:bar matches both */
991 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
992 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
993 TEST_PROP(pp->getuid, gui_foo.value);
994 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
997 static int setup_2_ident_strings_hwe(void **state)
999 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1000 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1001 struct hwt_state *hwt = CHECK_STATE(state);
1003 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1004 SET_TEST_FUNC(hwt, test_2_ident_strings_hwe);
1009 * Two identical device entries kv1 and kv2, trival regex ("string").
1010 * Both are added to an extra config file.
1011 * This could happen in a large multipath.conf file.
1013 * Expected: matching devices get props from both, kv2 taking precedence.
1015 static void test_2_ident_strings_both_dir(const struct hwt_state *hwt)
1019 /* foo:baz doesn't match */
1020 pp = mock_path(vnd_foo.value, prd_baz.value);
1021 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1022 TEST_PROP(pp->getuid, NULL);
1023 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1025 /* foo:bar matches both */
1026 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1027 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1028 TEST_PROP(pp->getuid, gui_foo.value);
1029 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1032 static int setup_2_ident_strings_both_dir(void **state)
1034 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1035 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1036 struct hwt_state *hwt = CHECK_STATE(state);
1039 begin_section_all(hwt, "devices");
1040 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1041 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1042 end_section_all(hwt);
1044 SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir);
1049 * Two identical device entries kv1 and kv2, trival regex ("string").
1050 * Both are added to an extra config file.
1051 * An empty entry kv0 with the same string exists in the main config file.
1053 * Expected: matching devices get props from both, kv2 taking precedence.
1055 static void test_2_ident_strings_both_dir_w_prev(const struct hwt_state *hwt)
1059 /* foo:baz doesn't match */
1060 pp = mock_path(vnd_foo.value, prd_baz.value);
1061 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1062 TEST_PROP(pp->getuid, NULL);
1063 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1065 /* foo:bar matches both */
1066 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1067 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1068 TEST_PROP(pp->getuid, gui_foo.value);
1069 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1072 static int setup_2_ident_strings_both_dir_w_prev(void **state)
1074 struct hwt_state *hwt = CHECK_STATE(state);
1076 const struct key_value kv0[] = { vnd_foo, prd_bar };
1077 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1078 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1081 begin_section_all(hwt, "devices");
1082 write_device(hwt->config_file, ARRAY_SIZE(kv0), kv0);
1083 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1084 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1085 end_section_all(hwt);
1087 SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir_w_prev);
1092 * Two identical device entries kv1 and kv2, trival regex ("string").
1093 * kv1 is added to the main config file, kv2 to a config_dir file.
1094 * These entries are merged.
1095 * This case is more important as you may think, because it's equivalent
1096 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1098 * Expected: matching devices get props from both, kv2 taking precedence.
1100 static void test_2_ident_strings_hwe_dir(const struct hwt_state *hwt)
1104 /* foo:baz doesn't match */
1105 pp = mock_path(vnd_foo.value, prd_baz.value);
1106 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1107 TEST_PROP(pp->getuid, NULL);
1108 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1110 /* foo:bar matches both */
1111 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1112 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1113 TEST_PROP(pp->getuid, gui_foo.value);
1114 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1117 static int setup_2_ident_strings_hwe_dir(void **state)
1119 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1120 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1121 struct hwt_state *hwt = CHECK_STATE(state);
1123 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1124 SET_TEST_FUNC(hwt, test_2_ident_strings_hwe_dir);
1129 * Like test_2_ident_strings_hwe_dir, but this time the config_dir file
1130 * contains an additional, empty entry (kv0).
1132 * Expected: matching devices get props from kv1 and kv2, kv2 taking precedence.
1134 static void test_3_ident_strings_hwe_dir(const struct hwt_state *hwt)
1138 /* foo:baz doesn't match */
1139 pp = mock_path(vnd_foo.value, prd_baz.value);
1140 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1141 TEST_PROP(pp->getuid, NULL);
1142 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1144 /* foo:bar matches both */
1145 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1146 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1147 TEST_PROP(pp->getuid, gui_foo.value);
1148 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1151 static int setup_3_ident_strings_hwe_dir(void **state)
1153 const struct key_value kv0[] = { vnd_foo, prd_bar };
1154 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1155 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1156 struct hwt_state *hwt = CHECK_STATE(state);
1159 begin_section_all(hwt, "devices");
1160 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1161 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv0), kv0);
1162 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1163 end_section_all(hwt);
1165 SET_TEST_FUNC(hwt, test_3_ident_strings_hwe_dir);
1170 * Two identical device entries kv1 and kv2, non-trival regex that matches
1171 * itself (string ".oo" matches regex ".oo").
1172 * kv1 is added to the main config file, kv2 to a config_dir file.
1173 * This case is more important as you may think, because it's equivalent
1174 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1176 * Expected: matching devices get props from both, kv2 taking precedence.
1178 static void test_2_ident_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1182 /* foo:baz doesn't match */
1183 pp = mock_path(vnd_foo.value, prd_baz.value);
1184 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1185 TEST_PROP(pp->getuid, NULL);
1186 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1188 /* foo:bar matches both */
1189 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1190 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1191 TEST_PROP(pp->getuid, gui_foo.value);
1192 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1195 static int setup_2_ident_self_matching_re_hwe_dir(void **state)
1197 const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1198 const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1199 struct hwt_state *hwt = CHECK_STATE(state);
1201 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1202 SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe_dir);
1207 * Two identical device entries kv1 and kv2, non-trival regex that matches
1208 * itself (string ".oo" matches regex ".oo").
1209 * kv1 and kv2 are added to the main config file.
1211 * Expected: matching devices get props from both, kv2 taking precedence.
1213 static void test_2_ident_self_matching_re_hwe(const struct hwt_state *hwt)
1217 /* foo:baz doesn't match */
1218 pp = mock_path(vnd_foo.value, prd_baz.value);
1219 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1220 TEST_PROP(pp->getuid, NULL);
1221 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1223 /* foo:bar matches */
1224 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1225 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1226 TEST_PROP(pp->getuid, gui_foo.value);
1227 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1230 static int setup_2_ident_self_matching_re_hwe(void **state)
1232 const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1233 const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1234 struct hwt_state *hwt = CHECK_STATE(state);
1236 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1237 SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe);
1242 * Two identical device entries kv1 and kv2, non-trival regex that doesn't
1243 * match itself (string "^.oo" doesn't match regex "^.oo").
1244 * kv1 is added to the main config file, kv2 to a config_dir file.
1245 * This case is more important as you may think, see above.
1247 * Expected: matching devices get props from both, kv2 taking precedence.
1250 test_2_ident_not_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1254 /* foo:baz doesn't match */
1255 pp = mock_path(vnd_foo.value, prd_baz.value);
1256 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1257 TEST_PROP(pp->getuid, NULL);
1258 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1260 /* foo:bar matches both */
1261 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1262 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1263 TEST_PROP(pp->getuid, gui_foo.value);
1264 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1267 static int setup_2_ident_not_self_matching_re_hwe_dir(void **state)
1269 const struct key_value kv1[] = { vnd_t_oo, prd_bar, prio_emc, chk_hp };
1270 const struct key_value kv2[] = { vnd_t_oo, prd_bar, prio_hds, gui_foo };
1271 struct hwt_state *hwt = CHECK_STATE(state);
1273 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1274 SET_TEST_FUNC(hwt, test_2_ident_not_self_matching_re_hwe_dir);
1279 * Two different non-trivial regexes kv1, kv2. The 1st one matches the 2nd, but
1280 * it doesn't match all possible strings matching the second.
1281 * ("ba[zy]" matches regex "ba[[rxy]", but "baz" does not).
1283 * Expected: Devices matching both regexes get properties from both, kv2
1284 * taking precedence. Devices matching just one regex get properties from
1285 * that one regex only.
1287 static void test_2_matching_res_hwe_dir(const struct hwt_state *hwt)
1291 /* foo:bar matches k1 only */
1292 pp = mock_path(vnd_foo.value, prd_bar.value);
1293 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1294 TEST_PROP(pp->getuid, NULL);
1295 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1297 /* foo:bay matches k1 and k2 */
1298 pp = mock_path_flags(vnd_foo.value, "bay", USE_GETUID);
1299 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1300 TEST_PROP(pp->getuid, gui_foo.value);
1301 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1303 /* foo:baz matches k2 only. */
1304 pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1305 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1306 TEST_PROP(pp->getuid, gui_foo.value);
1307 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1310 static int setup_2_matching_res_hwe_dir(void **state)
1312 const struct key_value kv1[] = { vnd_foo, prd_barx, prio_emc, chk_hp };
1313 const struct key_value kv2[] = { vnd_foo, prd_bazy, prio_hds, gui_foo };
1314 struct hwt_state *hwt = CHECK_STATE(state);
1316 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1317 SET_TEST_FUNC(hwt, test_2_matching_res_hwe_dir);
1322 * Two different non-trivial regexes which match the same set of strings.
1323 * But they don't match each other.
1324 * "baz" matches both regex "ba[zy]" and "ba(z|y)"
1326 * Expected: matching devices get properties from both, kv2 taking precedence.
1328 static void test_2_nonmatching_res_hwe_dir(const struct hwt_state *hwt)
1332 /* foo:bar doesn't match */
1333 pp = mock_path(vnd_foo.value, prd_bar.value);
1334 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1335 TEST_PROP(pp->getuid, NULL);
1336 TEST_PROP(checker_name(&pp->checker), DEFAULT_CHECKER);
1338 pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1339 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1340 TEST_PROP(pp->getuid, gui_foo.value);
1341 TEST_PROP(checker_name(&pp->checker), chk_hp.value);
1344 static int setup_2_nonmatching_res_hwe_dir(void **state)
1346 const struct key_value kv1[] = { vnd_foo, prd_bazy, prio_emc, chk_hp };
1347 const struct key_value kv2[] = { vnd_foo, prd_bazy1,
1348 prio_hds, gui_foo };
1349 struct hwt_state *hwt = CHECK_STATE(state);
1351 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1352 SET_TEST_FUNC(hwt, test_2_nonmatching_res_hwe_dir);
1357 * Simple blacklist test.
1359 * NOTE: test failures in blacklisting tests will manifest as cmocka errors
1360 * "Could not get value to mock function XYZ", because pathinfo() takes
1361 * different code paths for blacklisted devices.
1363 static void test_blacklist(const struct hwt_state *hwt)
1365 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1366 mock_path(vnd_foo.value, prd_baz.value);
1369 static int setup_blacklist(void **state)
1371 const struct key_value kv1[] = { vnd_foo, prd_bar };
1372 struct hwt_state *hwt = CHECK_STATE(state);
1375 begin_section_all(hwt, "blacklist");
1376 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1377 end_section_all(hwt);
1379 SET_TEST_FUNC(hwt, test_blacklist);
1384 * Simple blacklist test with regex and exception
1386 static void test_blacklist_regex(const struct hwt_state *hwt)
1388 mock_path(vnd_foo.value, prd_bar.value);
1389 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1390 mock_path(vnd_foo.value, prd_bam.value);
1393 static int setup_blacklist_regex(void **state)
1395 const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1396 const struct key_value kv2[] = { vnd_foo, prd_bar };
1397 struct hwt_state *hwt = CHECK_STATE(state);
1399 hwt = CHECK_STATE(state);
1401 begin_section_all(hwt, "blacklist");
1402 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1403 end_section_all(hwt);
1404 begin_section_all(hwt, "blacklist_exceptions");
1405 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1406 end_section_all(hwt);
1408 SET_TEST_FUNC(hwt, test_blacklist_regex);
1413 * Simple blacklist test with regex and exception
1414 * config file order inverted wrt test_blacklist_regex
1416 static int setup_blacklist_regex_inv(void **state)
1418 const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1419 const struct key_value kv2[] = { vnd_foo, prd_bar };
1420 struct hwt_state *hwt = CHECK_STATE(state);
1423 begin_section_all(hwt, "blacklist");
1424 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv1), kv1);
1425 end_section_all(hwt);
1426 begin_section_all(hwt, "blacklist_exceptions");
1427 write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2);
1428 end_section_all(hwt);
1430 SET_TEST_FUNC(hwt, test_blacklist_regex);
1435 * Simple blacklist test with regex and exception
1436 * config file order inverted wrt test_blacklist_regex
1438 static void test_blacklist_regex_matching(const struct hwt_state *hwt)
1440 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1441 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1442 mock_path(vnd_foo.value, prd_bam.value);
1445 static int setup_blacklist_regex_matching(void **state)
1447 const struct key_value kv1[] = { vnd_foo, prd_barx };
1448 const struct key_value kv2[] = { vnd_foo, prd_bazy };
1449 struct hwt_state *hwt = CHECK_STATE(state);
1452 begin_section_all(hwt, "blacklist");
1453 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1454 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1455 end_section_all(hwt);
1457 SET_TEST_FUNC(hwt, test_blacklist_regex_matching);
1462 * Test for blacklisting by WWID
1464 * Note that default_wwid is a substring of default_wwid_1. Because
1465 * matching is done by regex, both paths are blacklisted.
1467 static void test_blacklist_wwid(const struct hwt_state *hwt)
1469 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_WWID);
1470 mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1474 static int setup_blacklist_wwid(void **state)
1476 const struct key_value kv[] = { wwid_test };
1477 struct hwt_state *hwt = CHECK_STATE(state);
1480 write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1482 SET_TEST_FUNC(hwt, test_blacklist_wwid);
1487 * Test for blacklisting by WWID
1489 * Here the blacklist contains only default_wwid_1. Thus the path
1490 * with default_wwid is NOT blacklisted.
1492 static void test_blacklist_wwid_1(const struct hwt_state *hwt)
1494 mock_path(vnd_foo.value, prd_bar.value);
1495 mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1499 static int setup_blacklist_wwid_1(void **state)
1501 const struct key_value kv[] = { { _wwid, default_wwid_1 }, };
1502 struct hwt_state *hwt = CHECK_STATE(state);
1505 write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1507 SET_TEST_FUNC(hwt, test_blacklist_wwid_1);
1512 * Test for product_blacklist. Two entries blacklisting each other.
1514 * Expected: Both are blacklisted.
1516 static void test_product_blacklist(const struct hwt_state *hwt)
1518 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1519 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1520 mock_path(vnd_foo.value, prd_bam.value);
1523 static int setup_product_blacklist(void **state)
1525 const struct key_value kv1[] = { vnd_foo, prd_bar, bl_baz };
1526 const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bar };
1527 struct hwt_state *hwt = CHECK_STATE(state);
1529 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1530 SET_TEST_FUNC(hwt, test_product_blacklist);
1535 * Test for product_blacklist. The second regex "matches" the first.
1536 * This is a pathological example.
1538 * Expected: "foo:bar", "foo:baz" are blacklisted.
1540 static void test_product_blacklist_matching(const struct hwt_state *hwt)
1542 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1543 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1544 mock_path(vnd_foo.value, prd_bam.value);
1547 static int setup_product_blacklist_matching(void **state)
1549 const struct key_value kv1[] = { vnd_foo, prd_bar, bl_barx };
1550 const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bazy };
1551 struct hwt_state *hwt = CHECK_STATE(state);
1553 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1554 SET_TEST_FUNC(hwt, test_product_blacklist_matching);
1559 * Basic test for multipath-based configuration.
1561 * Expected: properties, including pp->prio, are taken from multipath
1564 static void test_multipath_config(const struct hwt_state *hwt)
1567 struct multipath *mp;
1569 pp = mock_path(vnd_foo.value, prd_bar.value);
1570 mp = mock_multipath(pp);
1571 assert_ptr_not_equal(mp->mpe, NULL);
1572 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1573 assert_int_equal(mp->minio, atoi(minio_99.value));
1574 TEST_PROP(pp->uid_attribute, uid_baz.value);
1576 /* test different wwid */
1577 pp = mock_path_wwid(vnd_foo.value, prd_bar.value, default_wwid_1);
1578 mp = mock_multipath(pp);
1579 // assert_ptr_equal(mp->mpe, NULL);
1580 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1581 assert_int_equal(mp->minio, DEFAULT_MINIO_RQ);
1582 TEST_PROP(pp->uid_attribute, uid_baz.value);
1585 static int setup_multipath_config(void **state)
1587 struct hwt_state *hwt = CHECK_STATE(state);
1588 const struct key_value kvm[] = { wwid_test, prio_rdac, minio_99 };
1589 const struct key_value kvp[] = { vnd_foo, prd_bar, prio_emc, uid_baz };
1592 begin_section_all(hwt, "devices");
1593 write_section(hwt->conf_dir_file[0], "device", ARRAY_SIZE(kvp), kvp);
1594 end_section_all(hwt);
1595 begin_section_all(hwt, "multipaths");
1596 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kvm), kvm);
1597 end_section_all(hwt);
1599 SET_TEST_FUNC(hwt, test_multipath_config);
1604 * Basic test for multipath-based configuration. Two sections for the same wwid.
1606 * Expected: properties are taken from both multipath sections, later taking
1609 static void test_multipath_config_2(const struct hwt_state *hwt)
1612 struct multipath *mp;
1614 pp = mock_path(vnd_foo.value, prd_bar.value);
1615 mp = mock_multipath(pp);
1616 assert_ptr_not_equal(mp, NULL);
1617 assert_ptr_not_equal(mp->mpe, NULL);
1618 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1619 assert_int_equal(mp->minio, atoi(minio_99.value));
1620 assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1623 static int setup_multipath_config_2(void **state)
1625 const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1626 const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1627 struct hwt_state *hwt = CHECK_STATE(state);
1630 begin_section_all(hwt, "multipaths");
1631 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1632 write_section(hwt->conf_dir_file[1], "multipath", ARRAY_SIZE(kv2), kv2);
1633 end_section_all(hwt);
1635 SET_TEST_FUNC(hwt, test_multipath_config_2);
1640 * Same as test_multipath_config_2, both entries in the same config file.
1642 * Expected: properties are taken from both multipath sections.
1644 static void test_multipath_config_3(const struct hwt_state *hwt)
1647 struct multipath *mp;
1649 pp = mock_path(vnd_foo.value, prd_bar.value);
1650 mp = mock_multipath(pp);
1651 assert_ptr_not_equal(mp, NULL);
1652 assert_ptr_not_equal(mp->mpe, NULL);
1653 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1654 assert_int_equal(mp->minio, atoi(minio_99.value));
1655 assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1658 static int setup_multipath_config_3(void **state)
1660 const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1661 const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1662 struct hwt_state *hwt = CHECK_STATE(state);
1665 begin_section_all(hwt, "multipaths");
1666 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1667 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv2), kv2);
1668 end_section_all(hwt);
1670 SET_TEST_FUNC(hwt, test_multipath_config_3);
1675 * Test for device with "hidden" attribute
1677 static void test_hidden(const struct hwt_state *hwt)
1679 mock_path_flags("NVME", "NoName", DEV_HIDDEN|BL_MASK);
1682 static int setup_hidden(void **state)
1684 struct hwt_state *hwt = CHECK_STATE(state);
1686 WRITE_EMPTY_CONF(hwt);
1687 SET_TEST_FUNC(hwt, test_hidden);
1693 * Create wrapper functions around test_driver() to avoid that cmocka
1694 * always uses the same test name. That makes it easier to read test results.
1697 #define define_test(x) \
1698 static void run_##x(void **state) \
1700 return test_driver(state); \
1703 define_test(string_hwe)
1704 define_test(broken_hwe)
1705 define_test(broken_hwe_dir)
1706 define_test(quoted_hwe)
1707 define_test(internal_nvme)
1708 define_test(regex_hwe)
1709 define_test(regex_string_hwe)
1710 define_test(regex_string_hwe_dir)
1711 define_test(regex_2_strings_hwe_dir)
1712 define_test(string_regex_hwe_dir)
1713 define_test(2_ident_strings_hwe)
1714 define_test(2_ident_strings_both_dir)
1715 define_test(2_ident_strings_both_dir_w_prev)
1716 define_test(2_ident_strings_hwe_dir)
1717 define_test(3_ident_strings_hwe_dir)
1718 define_test(2_ident_self_matching_re_hwe_dir)
1719 define_test(2_ident_self_matching_re_hwe)
1720 define_test(2_ident_not_self_matching_re_hwe_dir)
1721 define_test(2_matching_res_hwe_dir)
1722 define_test(2_nonmatching_res_hwe_dir)
1723 define_test(blacklist)
1724 define_test(blacklist_wwid)
1725 define_test(blacklist_wwid_1)
1726 define_test(blacklist_regex)
1727 define_test(blacklist_regex_inv)
1728 define_test(blacklist_regex_matching)
1729 define_test(product_blacklist)
1730 define_test(product_blacklist_matching)
1731 define_test(multipath_config)
1732 define_test(multipath_config_2)
1733 define_test(multipath_config_3)
1736 #define test_entry(x) \
1737 cmocka_unit_test_setup(run_##x, setup_##x)
1739 static int test_hwtable(void)
1741 const struct CMUnitTest tests[] = {
1742 cmocka_unit_test(test_sanity_globals),
1743 test_entry(internal_nvme),
1744 test_entry(string_hwe),
1745 test_entry(broken_hwe),
1746 test_entry(broken_hwe_dir),
1747 test_entry(quoted_hwe),
1748 test_entry(regex_hwe),
1749 test_entry(regex_string_hwe),
1750 test_entry(regex_string_hwe_dir),
1751 test_entry(regex_2_strings_hwe_dir),
1752 test_entry(string_regex_hwe_dir),
1753 test_entry(2_ident_strings_hwe),
1754 test_entry(2_ident_strings_both_dir),
1755 test_entry(2_ident_strings_both_dir_w_prev),
1756 test_entry(2_ident_strings_hwe_dir),
1757 test_entry(3_ident_strings_hwe_dir),
1758 test_entry(2_ident_self_matching_re_hwe_dir),
1759 test_entry(2_ident_self_matching_re_hwe),
1760 test_entry(2_ident_not_self_matching_re_hwe_dir),
1761 test_entry(2_matching_res_hwe_dir),
1762 test_entry(2_nonmatching_res_hwe_dir),
1763 test_entry(blacklist),
1764 test_entry(blacklist_wwid),
1765 test_entry(blacklist_wwid_1),
1766 test_entry(blacklist_regex),
1767 test_entry(blacklist_regex_inv),
1768 test_entry(blacklist_regex_matching),
1769 test_entry(product_blacklist),
1770 test_entry(product_blacklist_matching),
1771 test_entry(multipath_config),
1772 test_entry(multipath_config_2),
1773 test_entry(multipath_config_3),
1777 return cmocka_run_group_tests(tests, setup, teardown);
1784 ret += test_hwtable();