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"
28 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
29 #define N_CONF_FILES 2
31 static const char tmplate[] = "/tmp/hwtable-XXXXXX";
32 /* pretend new dm, use minio_rq */
33 static const unsigned int dm_tgt_version[3] = { 1, 1, 1 };
44 FILE *conf_dir_file[N_CONF_FILES];
46 void (*test)(const struct hwt_state *);
47 const char *test_name;
50 #define SET_TEST_FUNC(hwt, func) do { \
52 hwt->test_name = #func; \
55 static struct config *_conf;
59 struct config *get_multipath_config(void)
64 void put_multipath_config(void *arg)
67 void make_config_file_path(char *buf, int buflen,
68 const struct hwt_state *hwt, int i)
70 static const char fn_template[] = "%s/test-%02d.conf";
73 /* main config file */
74 snprintf(buf, buflen, fn_template, hwt->tmpname, 0);
76 snprintf(buf, buflen, fn_template, hwt->dirname, i);
79 static void reset_vecs(struct vectors *vecs)
82 free_pathvec(vecs->pathvec, FREE_PATHS);
84 vecs->pathvec = vector_alloc();
85 assert_ptr_not_equal(vecs->pathvec, NULL);
86 vecs->mpvec = vector_alloc();
87 assert_ptr_not_equal(vecs->mpvec, NULL);
90 static void free_hwt(struct hwt_state *hwt)
95 if (hwt->config_file != NULL)
96 fclose(hwt->config_file);
97 for (i = 0; i < N_CONF_FILES; i++) {
98 if (hwt->conf_dir_file[i] != NULL)
99 fclose(hwt->conf_dir_file[i]);
102 if (hwt->tmpname != NULL) {
103 make_config_file_path(buf, sizeof(buf), hwt, -1);
109 if (hwt->dirname != NULL) {
110 for (i = 0; i < N_CONF_FILES; i++) {
111 make_config_file_path(buf, sizeof(buf), hwt, i);
118 if (hwt->vecs != NULL) {
119 if (hwt->vecs->mpvec != NULL)
120 remove_maps(hwt->vecs);
121 if (hwt->vecs->pathvec != NULL)
122 free_pathvec(hwt->vecs->pathvec, FREE_PATHS);
123 pthread_mutex_destroy(&hwt->vecs->lock.mutex);
129 static int setup(void **state)
131 struct hwt_state *hwt;
136 hwt = calloc(1, sizeof(*hwt));
140 snprintf(buf, sizeof(buf), "%s", tmplate);
141 if (mkdtemp(buf) == NULL) {
142 condlog(0, "mkdtemp: %s", strerror(errno));
145 hwt->tmpname = strdup(buf);
147 snprintf(buf, sizeof(buf), "%s", tmplate);
148 if (mkdtemp(buf) == NULL) {
149 condlog(0, "mkdtemp (2): %s", strerror(errno));
152 hwt->dirname = strdup(buf);
154 make_config_file_path(buf, sizeof(buf), hwt, -1);
155 hwt->config_file = fopen(buf, "w+");
156 if (hwt->config_file == NULL)
159 for (i = 0; i < N_CONF_FILES; i++) {
160 make_config_file_path(buf, sizeof(buf), hwt, i);
161 hwt->conf_dir_file[i] = fopen(buf, "w+");
162 if (hwt->conf_dir_file[i] == NULL)
166 hwt->vecs = calloc(1, sizeof(*hwt->vecs));
167 if (hwt->vecs == NULL)
169 pthread_mutex_init(&hwt->vecs->lock.mutex, NULL);
170 hwt->vecs->pathvec = vector_alloc();
171 hwt->vecs->mpvec = vector_alloc();
172 if (hwt->vecs->pathvec == NULL || hwt->vecs->mpvec == NULL)
183 static int teardown(void **state)
185 if (state == NULL || *state == NULL)
195 * Helpers for creating the config file(s)
198 static void reset_config(FILE *ff)
203 if (ftruncate(fileno(ff), 0) == -1)
204 condlog(1, "ftruncate: %s", strerror(errno));
207 static void reset_configs(const struct hwt_state *hwt)
211 reset_config(hwt->config_file);
212 for (i = 0; i < N_CONF_FILES; i++)
213 reset_config(hwt->conf_dir_file[i]);
216 static void write_key_values(FILE *ff, int nkv, const struct key_value *kv)
220 for (i = 0; i < nkv; i++) {
221 if (strchr(kv[i].value, ' ') == NULL &&
222 strchr(kv[i].value, '\"') == NULL)
223 fprintf(ff, "\t%s %s\n", kv[i].key, kv[i].value);
225 fprintf(ff, "\t%s \"%s\"\n", kv[i].key, kv[i].value);
229 static void begin_section(FILE *ff, const char *section)
231 fprintf(ff, "%s {\n", section);
234 static void end_section(FILE *ff)
239 static void write_section(FILE *ff, const char *section,
240 int nkv, const struct key_value *kv)
242 begin_section(ff, section);
243 write_key_values(ff, nkv, kv);
247 static void write_defaults(const struct hwt_state *hwt)
249 static const char bindings_name[] = "bindings";
250 static struct key_value defaults[] = {
251 { "config_dir", NULL },
252 { "bindings_file", NULL },
253 { "detect_prio", "no" },
254 { "detect_checker", "no" },
256 char buf[sizeof(tmplate) + sizeof(bindings_name)];
258 snprintf(buf, sizeof(buf), "%s/%s", hwt->tmpname, bindings_name);
259 defaults[0].value = hwt->dirname;
260 defaults[1].value = buf;
261 write_section(hwt->config_file, "defaults",
262 ARRAY_SIZE(defaults), defaults);
265 static void begin_config(const struct hwt_state *hwt)
271 static void begin_section_all(const struct hwt_state *hwt, const char *section)
275 begin_section(hwt->config_file, section);
276 for (i = 0; i < N_CONF_FILES; i++)
277 begin_section(hwt->conf_dir_file[i], section);
280 static void end_section_all(const struct hwt_state *hwt)
284 end_section(hwt->config_file);
285 for (i = 0; i < N_CONF_FILES; i++)
286 end_section(hwt->conf_dir_file[i]);
289 static void finish_config(const struct hwt_state *hwt)
293 fflush(hwt->config_file);
294 for (i = 0; i < N_CONF_FILES; i++) {
295 fflush(hwt->conf_dir_file[i]);
299 static void write_device(FILE *ff, int nkv, const struct key_value *kv)
301 write_section(ff, "device", nkv, kv);
305 * Some macros to avoid boilerplace code
308 #define CHECK_STATE(state) ({ \
309 assert_ptr_not_equal(state, NULL); \
310 assert_ptr_not_equal(*(state), NULL); \
313 #define WRITE_EMPTY_CONF(hwt) do { \
315 finish_config(hwt); \
318 #define WRITE_ONE_DEVICE(hwt, kv) do { \
320 begin_section_all(hwt, "devices"); \
321 write_device(hwt->config_file, ARRAY_SIZE(kv), kv); \
322 end_section_all(hwt); \
323 finish_config(hwt); \
326 #define WRITE_TWO_DEVICES(hwt, kv1, kv2) do { \
328 begin_section_all(hwt, "devices"); \
329 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1); \
330 write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2); \
331 end_section_all(hwt); \
332 finish_config(hwt); \
335 #define WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2) do { \
337 begin_section_all(hwt, "devices"); \
338 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1); \
339 write_device(hwt->conf_dir_file[0], \
340 ARRAY_SIZE(kv2), kv2); \
341 end_section_all(hwt); \
342 finish_config(hwt); \
345 #define LOAD_CONFIG(hwt) ({ \
346 char buf[PATH_MAX]; \
347 struct config *__cf; \
349 make_config_file_path(buf, sizeof(buf), hwt, -1); \
350 __cf = load_config(buf); \
351 assert_ptr_not_equal(__cf, NULL); \
352 assert_ptr_not_equal(__cf->hwtable, NULL); \
353 __cf->verbosity = VERBOSITY; \
354 memcpy(&__cf->version, dm_tgt_version, sizeof(__cf->version)); \
357 #define FREE_CONFIG(conf) do { \
362 static void replace_config(const struct hwt_state *hwt,
363 const char *conf_str)
367 fprintf(hwt->config_file, "%s", conf_str);
368 fflush(hwt->config_file);
369 _conf = LOAD_CONFIG(hwt);
372 #define TEST_PROP(prop, val) do { \
374 assert_ptr_equal(prop, NULL); \
376 assert_ptr_not_equal(prop, NULL); \
377 assert_string_equal(prop, val); \
382 #define TEST_PROP_BROKEN(name, prop, bad, good) do { \
383 condlog(1, "%s: WARNING: Broken test for %s == \"%s\" on line %d, should be \"%s\"", \
384 __func__, name, bad ? bad : "NULL", \
385 __LINE__, good ? good : "NULL"); \
386 TEST_PROP(prop, bad); \
389 #define TEST_PROP_BROKEN(name, prop, bad, good) TEST_PROP(prop, good)
393 * Some predefined key/value pairs
396 static const char _wwid[] = "wwid";
397 static const char _vendor[] = "vendor";
398 static const char _product[] = "product";
399 static const char _prio[] = "prio";
400 static const char _checker[] = "path_checker";
401 static const char _getuid[] = "getuid_callout";
402 static const char _uid_attr[] = "uid_attribute";
403 static const char _bl_product[] = "product_blacklist";
404 static const char _minio[] = "rr_min_io_rq";
405 static const char _no_path_retry[] = "no_path_retry";
407 /* Device identifiers */
408 static const struct key_value vnd_foo = { _vendor, "foo" };
409 static const struct key_value prd_bar = { _product, "bar" };
410 static const struct key_value prd_bam = { _product, "bam" };
411 static const struct key_value prd_baq = { _product, "\"bar\"" };
412 static const struct key_value prd_baqq = { _product, "\"\"bar\"\"" };
413 static const struct key_value prd_barz = { _product, "barz" };
414 static const struct key_value vnd_boo = { _vendor, "boo" };
415 static const struct key_value prd_baz = { _product, "baz" };
416 static const struct key_value wwid_test = { _wwid, default_wwid };
418 /* Regular expresssions */
419 static const struct key_value vnd__oo = { _vendor, ".oo" };
420 static const struct key_value vnd_t_oo = { _vendor, "^.oo" };
421 static const struct key_value prd_ba_ = { _product, "ba." };
422 static const struct key_value prd_ba_s = { _product, "(bar|baz|ba\\.)$" };
423 /* Pathological cases, see below */
424 static const struct key_value prd_barx = { _product, "ba[[rxy]" };
425 static const struct key_value prd_bazy = { _product, "ba[zy]" };
426 static const struct key_value prd_bazy1 = { _product, "ba(z|y)" };
429 static const struct key_value prio_emc = { _prio, "emc" };
430 static const struct key_value prio_hds = { _prio, "hds" };
431 static const struct key_value prio_rdac = { _prio, "rdac" };
432 static const struct key_value chk_hp = { _checker, "hp_sw" };
433 static const struct key_value gui_foo = { _getuid, "/tmp/foo" };
434 static const struct key_value uid_baz = { _uid_attr, "BAZ_ATTR" };
435 static const struct key_value bl_bar = { _bl_product, "bar" };
436 static const struct key_value bl_baz = { _bl_product, "baz" };
437 static const struct key_value bl_barx = { _bl_product, "ba[[rxy]" };
438 static const struct key_value bl_bazy = { _bl_product, "ba[zy]" };
439 static const struct key_value minio_99 = { _minio, "99" };
440 static const struct key_value npr_37 = { _no_path_retry, "37" };
441 static const struct key_value npr_queue = { _no_path_retry, "queue" };
443 /***** BEGIN TESTS SECTION *****/
446 * Dump the configuration, subistitute the dumped configuration
447 * for the current one, and verify that the result is identical.
449 static void replicate_config(const struct hwt_state *hwt, bool local)
455 condlog(1, "--- %s: replicating %s configuration", __func__,
456 local ? "local" : "full");
458 conf = get_multipath_config();
460 /* "full" configuration */
461 cfg1 = snprint_config(conf, NULL, NULL, NULL);
463 /* "local" configuration */
464 hwtable = get_used_hwes(hwt->vecs->pathvec);
465 cfg1 = snprint_config(conf, NULL, hwtable, hwt->vecs->mpvec);
468 assert_non_null(cfg1);
469 put_multipath_config(conf);
471 replace_config(hwt, cfg1);
474 * The local configuration adds multipath entries, and may move device
475 * entries for local devices to the end of the list. Identical config
476 * strings therefore can't be expected in the "local" case.
477 * That doesn't matter. The important thing is that, with the reloaded
478 * configuration, the test case still passes.
485 conf = get_multipath_config();
486 cfg2 = snprint_config(conf, NULL, NULL, NULL);
487 assert_non_null(cfg2);
488 put_multipath_config(conf);
490 // #define DBG_CONFIG 1
492 #define DUMP_CFG_STR(x) do { \
493 FILE *tmp = fopen("/tmp/hwtable-" #x ".txt", "w"); \
494 fprintf(tmp, "%s", x); \
502 assert_int_equal(strlen(cfg2), strlen(cfg1));
503 assert_string_equal(cfg2, cfg1);
509 * Run hwt->test three times; once with the constructed configuration,
510 * once after re-reading the full dumped configuration, and once with the
511 * dumped local configuration.
513 * Expected: test passes every time.
515 static void test_driver(void **state)
517 const struct hwt_state *hwt;
519 hwt = CHECK_STATE(state);
520 _conf = LOAD_CONFIG(hwt);
523 replicate_config(hwt, false);
524 reset_vecs(hwt->vecs);
527 replicate_config(hwt, true);
528 reset_vecs(hwt->vecs);
531 reset_vecs(hwt->vecs);
536 * Sanity check for the test itself, because defaults may be changed
539 * Our checking for match or non-match relies on the defaults being
540 * different from what our device sections contain.
542 static void test_sanity_globals(void **state)
544 assert_string_not_equal(prio_emc.value, DEFAULT_PRIO);
545 assert_string_not_equal(prio_hds.value, DEFAULT_PRIO);
546 assert_string_not_equal(chk_hp.value, DEFAULT_CHECKER);
547 assert_int_not_equal(MULTIBUS, DEFAULT_PGPOLICY);
548 assert_int_not_equal(NO_PATH_RETRY_QUEUE, DEFAULT_NO_PATH_RETRY);
549 assert_int_not_equal(atoi(minio_99.value), DEFAULT_MINIO_RQ);
550 assert_int_not_equal(atoi(npr_37.value), DEFAULT_NO_PATH_RETRY);
554 * Regression test for internal hwtable. NVME is an example of two entries
555 * in the built-in hwtable, one if which matches a subset of the other.
557 static void test_internal_nvme(const struct hwt_state *hwt)
560 struct multipath *mp;
563 * Generic NVMe: expect defaults for pgpolicy and no_path_retry
565 pp = mock_path("NVME", "NoName");
566 mp = mock_multipath(pp);
567 assert_ptr_not_equal(mp, NULL);
568 TEST_PROP(pp->checker.name, NONE);
569 TEST_PROP(pp->uid_attribute, "ID_WWN");
570 assert_int_equal(mp->pgpolicy, DEFAULT_PGPOLICY);
571 assert_int_equal(mp->no_path_retry, DEFAULT_NO_PATH_RETRY);
572 assert_int_equal(mp->retain_hwhandler, RETAIN_HWHANDLER_OFF);
575 * NetApp NVMe: expect special values for pgpolicy and no_path_retry
577 pp = mock_path_wwid("NVME", "NetApp ONTAP Controller",
579 mp = mock_multipath(pp);
580 assert_ptr_not_equal(mp, NULL);
581 TEST_PROP(pp->checker.name, NONE);
582 TEST_PROP(pp->uid_attribute, "ID_WWN");
583 assert_int_equal(mp->pgpolicy, MULTIBUS);
584 assert_int_equal(mp->no_path_retry, NO_PATH_RETRY_QUEUE);
585 assert_int_equal(mp->retain_hwhandler, RETAIN_HWHANDLER_OFF);
588 static int setup_internal_nvme(void **state)
590 struct hwt_state *hwt = CHECK_STATE(state);
592 WRITE_EMPTY_CONF(hwt);
593 SET_TEST_FUNC(hwt, test_internal_nvme);
599 * Device section with a simple entry qith double quotes ('foo:"bar"')
601 static void test_quoted_hwe(const struct hwt_state *hwt)
605 /* foo:"bar" matches */
606 pp = mock_path(vnd_foo.value, prd_baq.value);
607 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
609 /* foo:bar doesn't match */
610 pp = mock_path(vnd_foo.value, prd_bar.value);
611 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
614 static int setup_quoted_hwe(void **state)
616 struct hwt_state *hwt = CHECK_STATE(state);
617 const struct key_value kv[] = { vnd_foo, prd_baqq, prio_emc };
619 WRITE_ONE_DEVICE(hwt, kv);
620 SET_TEST_FUNC(hwt, test_quoted_hwe);
625 * Device section with a single simple entry ("foo:bar")
627 static void test_string_hwe(const struct hwt_state *hwt)
631 /* foo:bar matches */
632 pp = mock_path(vnd_foo.value, prd_bar.value);
633 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
635 /* foo:baz doesn't match */
636 pp = mock_path(vnd_foo.value, prd_baz.value);
637 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
639 /* boo:bar doesn't match */
640 pp = mock_path(vnd_boo.value, prd_bar.value);
641 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
644 static int setup_string_hwe(void **state)
646 struct hwt_state *hwt = CHECK_STATE(state);
647 const struct key_value kv[] = { vnd_foo, prd_bar, prio_emc };
649 WRITE_ONE_DEVICE(hwt, kv);
650 SET_TEST_FUNC(hwt, test_string_hwe);
655 * Device section with a broken entry (no product)
656 * It should be ignored.
658 static void test_broken_hwe(const struct hwt_state *hwt)
662 /* foo:bar doesn't match, as hwentry is ignored */
663 pp = mock_path(vnd_foo.value, prd_bar.value);
664 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
666 /* boo:bar doesn't match */
667 pp = mock_path(vnd_boo.value, prd_bar.value);
668 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
671 static int setup_broken_hwe(void **state)
673 struct hwt_state *hwt = CHECK_STATE(state);
674 const struct key_value kv[] = { vnd_foo, prio_emc };
676 WRITE_ONE_DEVICE(hwt, kv);
677 SET_TEST_FUNC(hwt, test_broken_hwe);
682 * Like test_broken_hwe, but in config_dir file.
684 static int setup_broken_hwe_dir(void **state)
686 struct hwt_state *hwt = CHECK_STATE(state);
687 const struct key_value kv[] = { vnd_foo, prio_emc };
690 begin_section_all(hwt, "devices");
691 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv), kv);
692 end_section_all(hwt);
694 hwt->test = test_broken_hwe;
695 hwt->test_name = "test_broken_hwe_dir";
700 * Device section with a single regex entry ("^.foo:(bar|baz|ba\.)$")
702 static void test_regex_hwe(const struct hwt_state *hwt)
706 /* foo:bar matches */
707 pp = mock_path(vnd_foo.value, prd_bar.value);
708 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
710 /* foo:baz matches */
711 pp = mock_path(vnd_foo.value, prd_baz.value);
712 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
714 /* boo:baz matches */
715 pp = mock_path(vnd_boo.value, prd_bar.value);
716 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
718 /* foo:BAR doesn't match */
719 pp = mock_path(vnd_foo.value, "BAR");
720 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
722 /* bboo:bar doesn't match */
723 pp = mock_path("bboo", prd_bar.value);
724 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
727 static int setup_regex_hwe(void **state)
729 struct hwt_state *hwt = CHECK_STATE(state);
730 const struct key_value kv[] = { vnd_t_oo, prd_ba_s, prio_emc };
732 WRITE_ONE_DEVICE(hwt, kv);
733 SET_TEST_FUNC(hwt, test_regex_hwe);
738 * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
739 * kv2 a string match (foo:bar) which matches a subset of the regex.
740 * Both are added to the main config file.
742 * Expected: Devices matching both get properties from both, kv2 taking
743 * precedence. Devices matching kv1 only just get props from kv1.
745 static void test_regex_string_hwe(const struct hwt_state *hwt)
749 /* foo:baz matches kv1 */
750 pp = mock_path(vnd_foo.value, prd_baz.value);
751 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
752 TEST_PROP(pp->getuid, NULL);
753 TEST_PROP(pp->checker.name, chk_hp.value);
755 /* boo:baz matches kv1 */
756 pp = mock_path(vnd_boo.value, prd_baz.value);
757 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
758 TEST_PROP(pp->getuid, NULL);
759 TEST_PROP(pp->checker.name, chk_hp.value);
761 /* .oo:ba. matches kv1 */
762 pp = mock_path(vnd__oo.value, prd_ba_.value);
763 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
764 TEST_PROP(pp->getuid, NULL);
765 TEST_PROP(pp->checker.name, chk_hp.value);
767 /* .foo:(bar|baz|ba\.) doesn't match */
768 pp = mock_path(vnd__oo.value, prd_ba_s.value);
769 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
770 TEST_PROP(pp->getuid, NULL);
771 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
773 /* foo:bar matches kv2 and kv1 */
774 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
775 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
776 TEST_PROP(pp->getuid, gui_foo.value);
777 TEST_PROP(pp->checker.name, chk_hp.value);
780 static int setup_regex_string_hwe(void **state)
782 struct hwt_state *hwt = CHECK_STATE(state);
783 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
784 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
786 WRITE_TWO_DEVICES(hwt, kv1, kv2);
787 SET_TEST_FUNC(hwt, test_regex_string_hwe);
792 * Two device entries, kv1 is a regex match ("^.foo:(bar|baz|ba\.)$"),
793 * kv2 a string match (foo:bar) which matches a subset of the regex.
794 * kv1 is added to the main config file, kv2 to a config_dir file.
795 * This case is more important as you may think, because it's equivalent
796 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
798 * Expected: Devices matching kv2 (and thus, both) get properties
799 * from both, kv2 taking precedence.
800 * Devices matching kv1 only just get props from kv1.
802 static void test_regex_string_hwe_dir(const struct hwt_state *hwt)
806 /* foo:baz matches kv1 */
807 pp = mock_path(vnd_foo.value, prd_baz.value);
808 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
809 TEST_PROP(pp->getuid, NULL);
810 TEST_PROP(pp->checker.name, chk_hp.value);
812 /* boo:baz matches kv1 */
813 pp = mock_path(vnd_boo.value, prd_baz.value);
814 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
815 TEST_PROP(pp->getuid, NULL);
816 TEST_PROP(pp->checker.name, chk_hp.value);
818 /* .oo:ba. matches kv1 */
819 pp = mock_path(vnd__oo.value, prd_ba_.value);
820 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
821 TEST_PROP(pp->getuid, NULL);
822 TEST_PROP(pp->checker.name, chk_hp.value);
824 /* .oo:(bar|baz|ba\.)$ doesn't match */
825 pp = mock_path(vnd__oo.value, prd_ba_s.value);
826 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
827 TEST_PROP(pp->getuid, NULL);
828 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
830 /* foo:bar matches kv2 */
831 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
832 /* Later match takes prio */
833 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
834 TEST_PROP(pp->getuid, gui_foo.value);
835 TEST_PROP(pp->checker.name, chk_hp.value);
838 static int setup_regex_string_hwe_dir(void **state)
840 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
841 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
842 struct hwt_state *hwt = CHECK_STATE(state);
844 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
845 SET_TEST_FUNC(hwt, test_regex_string_hwe_dir);
850 * Three device entries, kv1 is a regex match and kv2 and kv3 string
851 * matches, where kv3 is a substring of kv2. All in different config
854 * Expected: Devices matching kv3 get props from all, devices matching
855 * kv2 from kv2 and kv1, and devices matching kv1 only just from kv1.
857 static void test_regex_2_strings_hwe_dir(const struct hwt_state *hwt)
861 /* foo:baz matches kv1 */
862 pp = mock_path(vnd_foo.value, prd_baz.value);
863 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
864 TEST_PROP(pp->getuid, NULL);
865 TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
866 TEST_PROP(pp->checker.name, chk_hp.value);
868 /* boo:baz doesn't match */
869 pp = mock_path(vnd_boo.value, prd_baz.value);
870 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
871 TEST_PROP(pp->getuid, NULL);
872 TEST_PROP(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE);
873 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
875 /* foo:bar matches kv2 and kv1 */
876 pp = mock_path(vnd_foo.value, prd_bar.value);
877 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
878 TEST_PROP(pp->getuid, NULL);
879 TEST_PROP(pp->uid_attribute, uid_baz.value);
880 TEST_PROP(pp->checker.name, chk_hp.value);
882 /* foo:barz matches kv3 and kv2 and kv1 */
883 pp = mock_path_flags(vnd_foo.value, prd_barz.value, USE_GETUID);
884 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
885 TEST_PROP(pp->getuid, gui_foo.value);
886 TEST_PROP(pp->uid_attribute, NULL);
887 TEST_PROP(pp->checker.name, chk_hp.value);
890 static int setup_regex_2_strings_hwe_dir(void **state)
892 const struct key_value kv1[] = { vnd_foo, prd_ba_, prio_emc, chk_hp };
893 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, uid_baz };
894 const struct key_value kv3[] = { vnd_foo, prd_barz,
895 prio_rdac, gui_foo };
896 struct hwt_state *hwt = CHECK_STATE(state);
899 begin_section_all(hwt, "devices");
900 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
901 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
902 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv3), kv3);
903 end_section_all(hwt);
905 SET_TEST_FUNC(hwt, test_regex_2_strings_hwe_dir);
910 * Like test_regex_string_hwe_dir, but the order of kv1 and kv2 is exchanged.
912 * Expected: Devices matching kv1 (and thus, both) get properties
913 * from both, kv1 taking precedence.
914 * Devices matching kv1 only just get props from kv1.
916 static void test_string_regex_hwe_dir(const struct hwt_state *hwt)
920 /* foo:bar matches kv2 and kv1 */
921 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
922 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
923 TEST_PROP(pp->getuid, gui_foo.value);
924 TEST_PROP(pp->checker.name, chk_hp.value);
926 /* foo:baz matches kv1 */
927 pp = mock_path(vnd_foo.value, prd_baz.value);
928 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
929 TEST_PROP(pp->getuid, NULL);
930 TEST_PROP(pp->checker.name, chk_hp.value);
932 /* boo:baz matches kv1 */
933 pp = mock_path(vnd_boo.value, prd_baz.value);
934 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
935 TEST_PROP(pp->getuid, NULL);
936 TEST_PROP(pp->checker.name, chk_hp.value);
938 /* .oo:ba. matches kv1 */
939 pp = mock_path(vnd__oo.value, prd_ba_.value);
940 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
941 TEST_PROP(pp->getuid, NULL);
942 TEST_PROP(pp->checker.name, chk_hp.value);
944 /* .oo:(bar|baz|ba\.)$ doesn't match */
945 pp = mock_path(vnd__oo.value, prd_ba_s.value);
946 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
947 TEST_PROP(pp->getuid, NULL);
948 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
951 static int setup_string_regex_hwe_dir(void **state)
953 const struct key_value kv1[] = { vnd_t_oo, prd_ba_s, prio_emc, chk_hp };
954 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
955 struct hwt_state *hwt = CHECK_STATE(state);
957 WRITE_TWO_DEVICES_W_DIR(hwt, kv2, kv1);
958 SET_TEST_FUNC(hwt, test_string_regex_hwe_dir);
963 * Two identical device entries kv1 and kv2, trival regex ("string").
964 * Both are added to the main config file.
965 * These entries are NOT merged.
966 * This could happen in a large multipath.conf file.
968 * Expected: matching devices get props from both, kv2 taking precedence.
970 static void test_2_ident_strings_hwe(const struct hwt_state *hwt)
974 /* foo:baz doesn't match */
975 pp = mock_path(vnd_foo.value, prd_baz.value);
976 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
977 TEST_PROP(pp->getuid, NULL);
978 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
980 /* foo:bar matches both */
981 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
982 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
983 TEST_PROP(pp->getuid, gui_foo.value);
984 TEST_PROP(pp->checker.name, chk_hp.value);
987 static int setup_2_ident_strings_hwe(void **state)
989 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
990 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
991 struct hwt_state *hwt = CHECK_STATE(state);
993 WRITE_TWO_DEVICES(hwt, kv1, kv2);
994 SET_TEST_FUNC(hwt, test_2_ident_strings_hwe);
999 * Two identical device entries kv1 and kv2, trival regex ("string").
1000 * Both are added to an extra config file.
1001 * This could happen in a large multipath.conf file.
1003 * Expected: matching devices get props from both, kv2 taking precedence.
1005 static void test_2_ident_strings_both_dir(const struct hwt_state *hwt)
1009 /* foo:baz doesn't match */
1010 pp = mock_path(vnd_foo.value, prd_baz.value);
1011 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1012 TEST_PROP(pp->getuid, NULL);
1013 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1015 /* foo:bar matches both */
1016 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1017 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1018 TEST_PROP(pp->getuid, gui_foo.value);
1019 TEST_PROP(pp->checker.name, chk_hp.value);
1022 static int setup_2_ident_strings_both_dir(void **state)
1024 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1025 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1026 struct hwt_state *hwt = CHECK_STATE(state);
1029 begin_section_all(hwt, "devices");
1030 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1031 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1032 end_section_all(hwt);
1034 SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir);
1039 * Two identical device entries kv1 and kv2, trival regex ("string").
1040 * Both are added to an extra config file.
1041 * An empty entry kv0 with the same string exists in the main config file.
1043 * Expected: matching devices get props from both, kv2 taking precedence.
1045 static void test_2_ident_strings_both_dir_w_prev(const struct hwt_state *hwt)
1049 /* foo:baz doesn't match */
1050 pp = mock_path(vnd_foo.value, prd_baz.value);
1051 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1052 TEST_PROP(pp->getuid, NULL);
1053 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1055 /* foo:bar matches both */
1056 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1057 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1058 TEST_PROP(pp->getuid, gui_foo.value);
1059 TEST_PROP(pp->checker.name, chk_hp.value);
1062 static int setup_2_ident_strings_both_dir_w_prev(void **state)
1064 struct hwt_state *hwt = CHECK_STATE(state);
1066 const struct key_value kv0[] = { vnd_foo, prd_bar };
1067 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1068 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1071 begin_section_all(hwt, "devices");
1072 write_device(hwt->config_file, ARRAY_SIZE(kv0), kv0);
1073 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv1), kv1);
1074 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1075 end_section_all(hwt);
1077 SET_TEST_FUNC(hwt, test_2_ident_strings_both_dir_w_prev);
1082 * Two identical device entries kv1 and kv2, trival regex ("string").
1083 * kv1 is added to the main config file, kv2 to a config_dir file.
1084 * These entries are merged.
1085 * This case is more important as you may think, because it's equivalent
1086 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1088 * Expected: matching devices get props from both, kv2 taking precedence.
1090 static void test_2_ident_strings_hwe_dir(const struct hwt_state *hwt)
1094 /* foo:baz doesn't match */
1095 pp = mock_path(vnd_foo.value, prd_baz.value);
1096 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1097 TEST_PROP(pp->getuid, NULL);
1098 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1100 /* foo:bar matches both */
1101 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1102 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1103 TEST_PROP(pp->getuid, gui_foo.value);
1104 TEST_PROP(pp->checker.name, chk_hp.value);
1107 static int setup_2_ident_strings_hwe_dir(void **state)
1109 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1110 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1111 struct hwt_state *hwt = CHECK_STATE(state);
1113 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1114 SET_TEST_FUNC(hwt, test_2_ident_strings_hwe_dir);
1119 * Like test_2_ident_strings_hwe_dir, but this time the config_dir file
1120 * contains an additional, empty entry (kv0).
1122 * Expected: matching devices get props from kv1 and kv2, kv2 taking precedence.
1124 static void test_3_ident_strings_hwe_dir(const struct hwt_state *hwt)
1128 /* foo:baz doesn't match */
1129 pp = mock_path(vnd_foo.value, prd_baz.value);
1130 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1131 TEST_PROP(pp->getuid, NULL);
1132 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1134 /* foo:bar matches both */
1135 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1136 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1137 TEST_PROP(pp->getuid, gui_foo.value);
1138 TEST_PROP(pp->checker.name, chk_hp.value);
1141 static int setup_3_ident_strings_hwe_dir(void **state)
1143 const struct key_value kv0[] = { vnd_foo, prd_bar };
1144 const struct key_value kv1[] = { vnd_foo, prd_bar, prio_emc, chk_hp };
1145 const struct key_value kv2[] = { vnd_foo, prd_bar, prio_hds, gui_foo };
1146 struct hwt_state *hwt = CHECK_STATE(state);
1149 begin_section_all(hwt, "devices");
1150 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1151 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv0), kv0);
1152 write_device(hwt->conf_dir_file[1], ARRAY_SIZE(kv2), kv2);
1153 end_section_all(hwt);
1155 SET_TEST_FUNC(hwt, test_3_ident_strings_hwe_dir);
1160 * Two identical device entries kv1 and kv2, non-trival regex that matches
1161 * itself (string ".oo" matches regex ".oo").
1162 * kv1 is added to the main config file, kv2 to a config_dir file.
1163 * This case is more important as you may think, because it's equivalent
1164 * to kv1 being in the built-in hwtable and kv2 in multipath.conf.
1166 * Expected: matching devices get props from both, kv2 taking precedence.
1168 static void test_2_ident_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1172 /* foo:baz doesn't match */
1173 pp = mock_path(vnd_foo.value, prd_baz.value);
1174 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1175 TEST_PROP(pp->getuid, NULL);
1176 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1178 /* foo:bar matches both */
1179 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1180 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1181 TEST_PROP(pp->getuid, gui_foo.value);
1182 TEST_PROP(pp->checker.name, chk_hp.value);
1185 static int setup_2_ident_self_matching_re_hwe_dir(void **state)
1187 const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1188 const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1189 struct hwt_state *hwt = CHECK_STATE(state);
1191 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1192 SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe_dir);
1197 * Two identical device entries kv1 and kv2, non-trival regex that matches
1198 * itself (string ".oo" matches regex ".oo").
1199 * kv1 and kv2 are added to the main config file.
1201 * Expected: matching devices get props from both, kv2 taking precedence.
1203 static void test_2_ident_self_matching_re_hwe(const struct hwt_state *hwt)
1207 /* foo:baz doesn't match */
1208 pp = mock_path(vnd_foo.value, prd_baz.value);
1209 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1210 TEST_PROP(pp->getuid, NULL);
1211 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1213 /* foo:bar matches */
1214 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1215 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1216 TEST_PROP(pp->getuid, gui_foo.value);
1217 TEST_PROP(pp->checker.name, chk_hp.value);
1220 static int setup_2_ident_self_matching_re_hwe(void **state)
1222 const struct key_value kv1[] = { vnd__oo, prd_bar, prio_emc, chk_hp };
1223 const struct key_value kv2[] = { vnd__oo, prd_bar, prio_hds, gui_foo };
1224 struct hwt_state *hwt = CHECK_STATE(state);
1226 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1227 SET_TEST_FUNC(hwt, test_2_ident_self_matching_re_hwe);
1232 * Two identical device entries kv1 and kv2, non-trival regex that doesn't
1233 * match itself (string "^.oo" doesn't match regex "^.oo").
1234 * kv1 is added to the main config file, kv2 to a config_dir file.
1235 * This case is more important as you may think, see above.
1237 * Expected: matching devices get props from both, kv2 taking precedence.
1240 test_2_ident_not_self_matching_re_hwe_dir(const struct hwt_state *hwt)
1244 /* foo:baz doesn't match */
1245 pp = mock_path(vnd_foo.value, prd_baz.value);
1246 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1247 TEST_PROP(pp->getuid, NULL);
1248 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1250 /* foo:bar matches both */
1251 pp = mock_path_flags(vnd_foo.value, prd_bar.value, USE_GETUID);
1252 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1253 TEST_PROP(pp->getuid, gui_foo.value);
1254 TEST_PROP(pp->checker.name, chk_hp.value);
1257 static int setup_2_ident_not_self_matching_re_hwe_dir(void **state)
1259 const struct key_value kv1[] = { vnd_t_oo, prd_bar, prio_emc, chk_hp };
1260 const struct key_value kv2[] = { vnd_t_oo, prd_bar, prio_hds, gui_foo };
1261 struct hwt_state *hwt = CHECK_STATE(state);
1263 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1264 SET_TEST_FUNC(hwt, test_2_ident_not_self_matching_re_hwe_dir);
1269 * Two different non-trivial regexes kv1, kv2. The 1st one matches the 2nd, but
1270 * it doesn't match all possible strings matching the second.
1271 * ("ba[zy]" matches regex "ba[[rxy]", but "baz" does not).
1273 * Expected: Devices matching both regexes get properties from both, kv2
1274 * taking precedence. Devices matching just one regex get properties from
1275 * that one regex only.
1277 static void test_2_matching_res_hwe_dir(const struct hwt_state *hwt)
1281 /* foo:bar matches k1 only */
1282 pp = mock_path(vnd_foo.value, prd_bar.value);
1283 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1284 TEST_PROP(pp->getuid, NULL);
1285 TEST_PROP(pp->checker.name, chk_hp.value);
1287 /* foo:bay matches k1 and k2 */
1288 pp = mock_path_flags(vnd_foo.value, "bay", USE_GETUID);
1289 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1290 TEST_PROP(pp->getuid, gui_foo.value);
1291 TEST_PROP(pp->checker.name, chk_hp.value);
1293 /* foo:baz matches k2 only. */
1294 pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1295 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1296 TEST_PROP(pp->getuid, gui_foo.value);
1297 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1300 static int setup_2_matching_res_hwe_dir(void **state)
1302 const struct key_value kv1[] = { vnd_foo, prd_barx, prio_emc, chk_hp };
1303 const struct key_value kv2[] = { vnd_foo, prd_bazy, prio_hds, gui_foo };
1304 struct hwt_state *hwt = CHECK_STATE(state);
1306 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1307 SET_TEST_FUNC(hwt, test_2_matching_res_hwe_dir);
1312 * Two different non-trivial regexes which match the same set of strings.
1313 * But they don't match each other.
1314 * "baz" matches both regex "ba[zy]" and "ba(z|y)"
1316 * Expected: matching devices get properties from both, kv2 taking precedence.
1318 static void test_2_nonmatching_res_hwe_dir(const struct hwt_state *hwt)
1322 /* foo:bar doesn't match */
1323 pp = mock_path(vnd_foo.value, prd_bar.value);
1324 TEST_PROP(prio_name(&pp->prio), DEFAULT_PRIO);
1325 TEST_PROP(pp->getuid, NULL);
1326 TEST_PROP(pp->checker.name, DEFAULT_CHECKER);
1328 pp = mock_path_flags(vnd_foo.value, prd_baz.value, USE_GETUID);
1329 TEST_PROP(prio_name(&pp->prio), prio_hds.value);
1330 TEST_PROP(pp->getuid, gui_foo.value);
1331 TEST_PROP(pp->checker.name, chk_hp.value);
1334 static int setup_2_nonmatching_res_hwe_dir(void **state)
1336 const struct key_value kv1[] = { vnd_foo, prd_bazy, prio_emc, chk_hp };
1337 const struct key_value kv2[] = { vnd_foo, prd_bazy1,
1338 prio_hds, gui_foo };
1339 struct hwt_state *hwt = CHECK_STATE(state);
1341 WRITE_TWO_DEVICES_W_DIR(hwt, kv1, kv2);
1342 SET_TEST_FUNC(hwt, test_2_nonmatching_res_hwe_dir);
1347 * Simple blacklist test.
1349 * NOTE: test failures in blacklisting tests will manifest as cmocka errors
1350 * "Could not get value to mock function XYZ", because pathinfo() takes
1351 * different code paths for blacklisted devices.
1353 static void test_blacklist(const struct hwt_state *hwt)
1355 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1356 mock_path(vnd_foo.value, prd_baz.value);
1359 static int setup_blacklist(void **state)
1361 const struct key_value kv1[] = { vnd_foo, prd_bar };
1362 struct hwt_state *hwt = CHECK_STATE(state);
1365 begin_section_all(hwt, "blacklist");
1366 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1367 end_section_all(hwt);
1369 SET_TEST_FUNC(hwt, test_blacklist);
1374 * Simple blacklist test with regex and exception
1376 static void test_blacklist_regex(const struct hwt_state *hwt)
1378 mock_path(vnd_foo.value, prd_bar.value);
1379 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1380 mock_path(vnd_foo.value, prd_bam.value);
1383 static int setup_blacklist_regex(void **state)
1385 const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1386 const struct key_value kv2[] = { vnd_foo, prd_bar };
1387 struct hwt_state *hwt = CHECK_STATE(state);
1389 hwt = CHECK_STATE(state);
1391 begin_section_all(hwt, "blacklist");
1392 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1393 end_section_all(hwt);
1394 begin_section_all(hwt, "blacklist_exceptions");
1395 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1396 end_section_all(hwt);
1398 SET_TEST_FUNC(hwt, test_blacklist_regex);
1403 * Simple blacklist test with regex and exception
1404 * config file order inverted wrt test_blacklist_regex
1406 static int setup_blacklist_regex_inv(void **state)
1408 const struct key_value kv1[] = { vnd_foo, prd_ba_s };
1409 const struct key_value kv2[] = { vnd_foo, prd_bar };
1410 struct hwt_state *hwt = CHECK_STATE(state);
1413 begin_section_all(hwt, "blacklist");
1414 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv1), kv1);
1415 end_section_all(hwt);
1416 begin_section_all(hwt, "blacklist_exceptions");
1417 write_device(hwt->config_file, ARRAY_SIZE(kv2), kv2);
1418 end_section_all(hwt);
1420 SET_TEST_FUNC(hwt, test_blacklist_regex);
1425 * Simple blacklist test with regex and exception
1426 * config file order inverted wrt test_blacklist_regex
1428 static void test_blacklist_regex_matching(const struct hwt_state *hwt)
1430 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1431 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1432 mock_path(vnd_foo.value, prd_bam.value);
1435 static int setup_blacklist_regex_matching(void **state)
1437 const struct key_value kv1[] = { vnd_foo, prd_barx };
1438 const struct key_value kv2[] = { vnd_foo, prd_bazy };
1439 struct hwt_state *hwt = CHECK_STATE(state);
1442 begin_section_all(hwt, "blacklist");
1443 write_device(hwt->config_file, ARRAY_SIZE(kv1), kv1);
1444 write_device(hwt->conf_dir_file[0], ARRAY_SIZE(kv2), kv2);
1445 end_section_all(hwt);
1447 SET_TEST_FUNC(hwt, test_blacklist_regex_matching);
1452 * Test for blacklisting by WWID
1454 * Note that default_wwid is a substring of default_wwid_1. Because
1455 * matching is done by regex, both paths are blacklisted.
1457 static void test_blacklist_wwid(const struct hwt_state *hwt)
1459 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_WWID);
1460 mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1464 static int setup_blacklist_wwid(void **state)
1466 const struct key_value kv[] = { wwid_test };
1467 struct hwt_state *hwt = CHECK_STATE(state);
1470 write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1472 SET_TEST_FUNC(hwt, test_blacklist_wwid);
1477 * Test for blacklisting by WWID
1479 * Here the blacklist contains only default_wwid_1. Thus the path
1480 * with default_wwid is NOT blacklisted.
1482 static void test_blacklist_wwid_1(const struct hwt_state *hwt)
1484 mock_path(vnd_foo.value, prd_bar.value);
1485 mock_path_wwid_flags(vnd_foo.value, prd_baz.value, default_wwid_1,
1489 static int setup_blacklist_wwid_1(void **state)
1491 const struct key_value kv[] = { { _wwid, default_wwid_1 }, };
1492 struct hwt_state *hwt = CHECK_STATE(state);
1495 write_section(hwt->config_file, "blacklist", ARRAY_SIZE(kv), kv);
1497 SET_TEST_FUNC(hwt, test_blacklist_wwid_1);
1502 * Test for product_blacklist. Two entries blacklisting each other.
1504 * Expected: Both are blacklisted.
1506 static void test_product_blacklist(const struct hwt_state *hwt)
1508 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1509 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1510 mock_path(vnd_foo.value, prd_bam.value);
1513 static int setup_product_blacklist(void **state)
1515 const struct key_value kv1[] = { vnd_foo, prd_bar, bl_baz };
1516 const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bar };
1517 struct hwt_state *hwt = CHECK_STATE(state);
1519 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1520 SET_TEST_FUNC(hwt, test_product_blacklist);
1525 * Test for product_blacklist. The second regex "matches" the first.
1526 * This is a pathological example.
1528 * Expected: "foo:bar", "foo:baz" are blacklisted.
1530 static void test_product_blacklist_matching(const struct hwt_state *hwt)
1532 mock_path_flags(vnd_foo.value, prd_bar.value, BL_BY_DEVICE);
1533 mock_path_flags(vnd_foo.value, prd_baz.value, BL_BY_DEVICE);
1534 mock_path(vnd_foo.value, prd_bam.value);
1537 static int setup_product_blacklist_matching(void **state)
1539 const struct key_value kv1[] = { vnd_foo, prd_bar, bl_barx };
1540 const struct key_value kv2[] = { vnd_foo, prd_baz, bl_bazy };
1541 struct hwt_state *hwt = CHECK_STATE(state);
1543 WRITE_TWO_DEVICES(hwt, kv1, kv2);
1544 SET_TEST_FUNC(hwt, test_product_blacklist_matching);
1549 * Basic test for multipath-based configuration.
1551 * Expected: properties, including pp->prio, are taken from multipath
1554 static void test_multipath_config(const struct hwt_state *hwt)
1557 struct multipath *mp;
1559 pp = mock_path(vnd_foo.value, prd_bar.value);
1560 mp = mock_multipath(pp);
1561 assert_ptr_not_equal(mp->mpe, NULL);
1562 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1563 assert_int_equal(mp->minio, atoi(minio_99.value));
1564 TEST_PROP(pp->uid_attribute, uid_baz.value);
1566 /* test different wwid */
1567 pp = mock_path_wwid(vnd_foo.value, prd_bar.value, default_wwid_1);
1568 mp = mock_multipath(pp);
1569 // assert_ptr_equal(mp->mpe, NULL);
1570 TEST_PROP(prio_name(&pp->prio), prio_emc.value);
1571 assert_int_equal(mp->minio, DEFAULT_MINIO_RQ);
1572 TEST_PROP(pp->uid_attribute, uid_baz.value);
1575 static int setup_multipath_config(void **state)
1577 struct hwt_state *hwt = CHECK_STATE(state);
1578 const struct key_value kvm[] = { wwid_test, prio_rdac, minio_99 };
1579 const struct key_value kvp[] = { vnd_foo, prd_bar, prio_emc, uid_baz };
1582 begin_section_all(hwt, "devices");
1583 write_section(hwt->conf_dir_file[0], "device", ARRAY_SIZE(kvp), kvp);
1584 end_section_all(hwt);
1585 begin_section_all(hwt, "multipaths");
1586 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kvm), kvm);
1587 end_section_all(hwt);
1589 SET_TEST_FUNC(hwt, test_multipath_config);
1594 * Basic test for multipath-based configuration. Two sections for the same wwid.
1596 * Expected: properties are taken from both multipath sections, later taking
1599 static void test_multipath_config_2(const struct hwt_state *hwt)
1602 struct multipath *mp;
1604 pp = mock_path(vnd_foo.value, prd_bar.value);
1605 mp = mock_multipath(pp);
1606 assert_ptr_not_equal(mp, NULL);
1607 assert_ptr_not_equal(mp->mpe, NULL);
1608 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1609 assert_int_equal(mp->minio, atoi(minio_99.value));
1610 assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1613 static int setup_multipath_config_2(void **state)
1615 const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1616 const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1617 struct hwt_state *hwt = CHECK_STATE(state);
1620 begin_section_all(hwt, "multipaths");
1621 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1622 write_section(hwt->conf_dir_file[1], "multipath", ARRAY_SIZE(kv2), kv2);
1623 end_section_all(hwt);
1625 SET_TEST_FUNC(hwt, test_multipath_config_2);
1630 * Same as test_multipath_config_2, both entries in the same config file.
1632 * Expected: properties are taken from both multipath sections.
1634 static void test_multipath_config_3(const struct hwt_state *hwt)
1637 struct multipath *mp;
1639 pp = mock_path(vnd_foo.value, prd_bar.value);
1640 mp = mock_multipath(pp);
1641 assert_ptr_not_equal(mp, NULL);
1642 assert_ptr_not_equal(mp->mpe, NULL);
1643 TEST_PROP(prio_name(&pp->prio), prio_rdac.value);
1644 assert_int_equal(mp->minio, atoi(minio_99.value));
1645 assert_int_equal(mp->no_path_retry, atoi(npr_37.value));
1648 static int setup_multipath_config_3(void **state)
1650 const struct key_value kv1[] = { wwid_test, prio_rdac, npr_queue };
1651 const struct key_value kv2[] = { wwid_test, minio_99, npr_37 };
1652 struct hwt_state *hwt = CHECK_STATE(state);
1655 begin_section_all(hwt, "multipaths");
1656 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv1), kv1);
1657 write_section(hwt->config_file, "multipath", ARRAY_SIZE(kv2), kv2);
1658 end_section_all(hwt);
1660 SET_TEST_FUNC(hwt, test_multipath_config_3);
1665 * Test for device with "hidden" attribute
1667 static void test_hidden(const struct hwt_state *hwt)
1669 mock_path_flags("NVME", "NoName", DEV_HIDDEN|BL_MASK);
1672 static int setup_hidden(void **state)
1674 struct hwt_state *hwt = CHECK_STATE(state);
1676 WRITE_EMPTY_CONF(hwt);
1677 SET_TEST_FUNC(hwt, test_hidden);
1683 * Create wrapper functions around test_driver() to avoid that cmocka
1684 * always uses the same test name. That makes it easier to read test results.
1687 #define define_test(x) \
1688 static void run_##x(void **state) \
1690 return test_driver(state); \
1693 define_test(string_hwe)
1694 define_test(broken_hwe)
1695 define_test(broken_hwe_dir)
1696 define_test(quoted_hwe)
1697 define_test(internal_nvme)
1698 define_test(regex_hwe)
1699 define_test(regex_string_hwe)
1700 define_test(regex_string_hwe_dir)
1701 define_test(regex_2_strings_hwe_dir)
1702 define_test(string_regex_hwe_dir)
1703 define_test(2_ident_strings_hwe)
1704 define_test(2_ident_strings_both_dir)
1705 define_test(2_ident_strings_both_dir_w_prev)
1706 define_test(2_ident_strings_hwe_dir)
1707 define_test(3_ident_strings_hwe_dir)
1708 define_test(2_ident_self_matching_re_hwe_dir)
1709 define_test(2_ident_self_matching_re_hwe)
1710 define_test(2_ident_not_self_matching_re_hwe_dir)
1711 define_test(2_matching_res_hwe_dir)
1712 define_test(2_nonmatching_res_hwe_dir)
1713 define_test(blacklist)
1714 define_test(blacklist_wwid)
1715 define_test(blacklist_wwid_1)
1716 define_test(blacklist_regex)
1717 define_test(blacklist_regex_inv)
1718 define_test(blacklist_regex_matching)
1719 define_test(product_blacklist)
1720 define_test(product_blacklist_matching)
1721 define_test(multipath_config)
1722 define_test(multipath_config_2)
1723 define_test(multipath_config_3)
1726 #define test_entry(x) \
1727 cmocka_unit_test_setup(run_##x, setup_##x)
1729 static int test_hwtable(void)
1731 const struct CMUnitTest tests[] = {
1732 cmocka_unit_test(test_sanity_globals),
1733 test_entry(internal_nvme),
1734 test_entry(string_hwe),
1735 test_entry(broken_hwe),
1736 test_entry(broken_hwe_dir),
1737 test_entry(quoted_hwe),
1738 test_entry(regex_hwe),
1739 test_entry(regex_string_hwe),
1740 test_entry(regex_string_hwe_dir),
1741 test_entry(regex_2_strings_hwe_dir),
1742 test_entry(string_regex_hwe_dir),
1743 test_entry(2_ident_strings_hwe),
1744 test_entry(2_ident_strings_both_dir),
1745 test_entry(2_ident_strings_both_dir_w_prev),
1746 test_entry(2_ident_strings_hwe_dir),
1747 test_entry(3_ident_strings_hwe_dir),
1748 test_entry(2_ident_self_matching_re_hwe_dir),
1749 test_entry(2_ident_self_matching_re_hwe),
1750 test_entry(2_ident_not_self_matching_re_hwe_dir),
1751 test_entry(2_matching_res_hwe_dir),
1752 test_entry(2_nonmatching_res_hwe_dir),
1753 test_entry(blacklist),
1754 test_entry(blacklist_wwid),
1755 test_entry(blacklist_wwid_1),
1756 test_entry(blacklist_regex),
1757 test_entry(blacklist_regex_inv),
1758 test_entry(blacklist_regex_matching),
1759 test_entry(product_blacklist),
1760 test_entry(product_blacklist_matching),
1761 test_entry(multipath_config),
1762 test_entry(multipath_config_2),
1763 test_entry(multipath_config_3),
1767 return cmocka_run_group_tests(tests, setup, teardown);
1774 ret += test_hwtable();