6 #include <sys/sysmacros.h>
11 #include "structs_vec.h"
13 #include "discovery.h"
17 const int default_mask = (DI_SYSFS|DI_BLACKLIST|DI_WWID|DI_CHECKER|DI_PRIO);
18 const char default_devnode[] = "sdTEST";
19 const char default_wwid[] = "TEST-WWID";
20 /* default_wwid should be a substring of default_wwid_1! */
21 const char default_wwid_1[] = "TEST-WWID-1";
24 * Helper wrappers for mock_path().
26 * We need to make pathinfo() think it has detected a device with
27 * certain vendor/product/rev. This requires faking lots of udev
28 * and sysfs function responses.
30 * This requires hwtable-test_OBJDEPS = ../libmultipath/discovery.o
31 * in the Makefile in order to wrap calls from discovery.o.
33 * Note that functions that are called and defined in discovery.o can't
34 * be wrapped this way (e.g. sysfs_get_vendor), because symbols are
35 * resolved by the assembler before the linking stage.
38 int __real_open(const char *path, int flags, int mode);
40 static const char _mocked_filename[] = "mocked_path";
41 int __wrap_open(const char *path, int flags, int mode)
43 condlog(4, "%s: %s", __func__, path);
45 if (!strcmp(path, _mocked_filename))
47 return __real_open(path, flags, mode);
50 int __wrap_execute_program(char *path, char *value, int len)
52 char *val = mock_ptr_type(char *);
54 condlog(5, "%s: %s", __func__, val);
55 strlcpy(value, val, len);
59 bool __wrap_is_claimed_by_foreign(struct udev_device *ud)
61 condlog(5, "%s: %p", __func__, ud);
65 struct udev_list_entry
66 *__wrap_udev_device_get_properties_list_entry(struct udev_device *ud)
68 void *p = (void*)0x12345678;
69 condlog(5, "%s: %p", __func__, p);
74 struct udev_list_entry
75 *__wrap_udev_list_entry_get_next(struct udev_list_entry *udle)
78 condlog(5, "%s: %p", __func__, p);
83 const char *__wrap_udev_list_entry_get_name(struct udev_list_entry *udle)
85 char *val = mock_ptr_type(char *);
87 condlog(5, "%s: %s", __func__, val);
91 struct udev_device *__wrap_udev_device_ref(struct udev_device *ud)
96 struct udev_device *__wrap_udev_device_unref(struct udev_device *ud)
101 char *__wrap_udev_device_get_subsystem(struct udev_device *ud)
103 char *val = mock_ptr_type(char *);
105 condlog(5, "%s: %s", __func__, val);
109 char *__wrap_udev_device_get_sysname(struct udev_device *ud)
111 char *val = mock_ptr_type(char *);
113 condlog(5, "%s: %s", __func__, val);
117 char *__wrap_udev_device_get_devnode(struct udev_device *ud)
119 char *val = mock_ptr_type(char *);
121 condlog(5, "%s: %s", __func__, val);
125 dev_t __wrap_udev_device_get_devnum(struct udev_device *ud)
127 condlog(5, "%s: %p", __func__, ud);
128 return makedev(17, 17);
131 char *__wrap_udev_device_get_sysattr_value(struct udev_device *ud,
134 char *val = mock_ptr_type(char *);
136 condlog(5, "%s: %s->%s", __func__, attr, val);
140 char *__wrap_udev_device_get_property_value(struct udev_device *ud,
143 char *val = mock_ptr_type(char *);
145 condlog(5, "%s: %s->%s", __func__, attr, val);
149 int __wrap_sysfs_get_size(struct path *pp, unsigned long long *sz)
155 void *__wrap_udev_device_get_parent_with_subsystem_devtype(
156 struct udev_device *ud, const char *subsys, char *type)
158 /* return non-NULL for sysfs_get_tgt_nodename */
162 void *__wrap_udev_device_get_parent(struct udev_device *ud)
164 char *val = mock_ptr_type(void *);
166 condlog(5, "%s: %p", __func__, val);
170 ssize_t __wrap_sysfs_attr_get_value(struct udev_device *dev,
171 const char *attr_name,
172 char *value, size_t sz)
174 char *val = mock_ptr_type(char *);
176 condlog(5, "%s: %s", __func__, val);
177 strlcpy(value, val, sz);
178 return strlen(value);
181 int __wrap_checker_check(struct checker *c, int st)
183 condlog(5, "%s: %d", __func__, st);
187 int __wrap_prio_getprio(struct prio *p, struct path *pp, unsigned int tmo)
191 condlog(5, "%s: %d", __func__, pr);
195 struct mocked_path *fill_mocked_path(struct mocked_path *mp,
196 const char *vendor, const char *product,
197 const char *rev, const char *wwid,
198 const char *devnode, unsigned int flags)
200 mp->vendor = (vendor ? vendor : "noname");
201 mp->product = (product ? product : "noprod");
202 mp->rev = (rev ? rev : "0");
203 mp->wwid = (wwid ? wwid : default_wwid);
204 mp->devnode = (devnode ? devnode : default_devnode);
205 mp->flags = flags|NEED_SELECT_PRIO|NEED_FD;
209 struct mocked_path *mocked_path_from_path(struct mocked_path *mp,
210 const struct path *pp)
212 mp->vendor = pp->vendor_id;
213 mp->product = pp->product_id;
216 mp->devnode = pp->dev;
217 mp->flags = (prio_selected(&pp->prio) ? 0 : NEED_SELECT_PRIO) |
218 (pp->fd < 0 ? NEED_FD : 0) |
219 (pp->getuid ? USE_GETUID : 0);
223 static void mock_sysfs_pathinfo(const struct mocked_path *mp)
225 static const char hbtl[] = "4:0:3:1";
227 will_return(__wrap_udev_device_get_subsystem, "scsi");
228 will_return(__wrap_udev_device_get_sysname, hbtl);
229 will_return(__wrap_udev_device_get_sysname, hbtl);
230 will_return(__wrap_udev_device_get_sysattr_value, mp->vendor);
231 will_return(__wrap_udev_device_get_sysname, hbtl);
232 will_return(__wrap_udev_device_get_sysattr_value, mp->product);
233 will_return(__wrap_udev_device_get_sysname, hbtl);
234 will_return(__wrap_udev_device_get_sysattr_value, mp->rev);
236 /* sysfs_get_tgt_nodename */
237 will_return(__wrap_udev_device_get_sysattr_value, NULL);
238 will_return(__wrap_udev_device_get_parent, NULL);
239 will_return(__wrap_udev_device_get_parent, NULL);
240 will_return(__wrap_udev_device_get_sysname, "nofibre");
241 will_return(__wrap_udev_device_get_sysname, "noiscsi");
242 will_return(__wrap_udev_device_get_parent, NULL);
243 will_return(__wrap_udev_device_get_sysname, "ata25");
247 * Pretend we detected a SCSI device with given vendor/prod/rev
249 void mock_pathinfo(int mask, const struct mocked_path *mp)
251 if (mp->flags & DEV_HIDDEN) {
252 will_return(__wrap_udev_device_get_sysattr_value, "1");
255 will_return(__wrap_udev_device_get_sysattr_value, "0");
257 /* filter_property */
258 will_return(__wrap_udev_device_get_sysname, mp->devnode);
259 if (mp->flags & BL_BY_PROPERTY) {
260 will_return(__wrap_udev_list_entry_get_name, "BAZ");
263 will_return(__wrap_udev_list_entry_get_name,
264 "SCSI_IDENT_LUN_NAA_EXT");
266 mock_sysfs_pathinfo(mp);
268 if (mp->flags & BL_BY_DEVICE &&
269 (mask & DI_BLACKLIST && mask & DI_SYSFS))
273 will_return(__wrap_udev_device_get_subsystem, "scsi");
274 will_return(__wrap_sysfs_attr_get_value, "running");
279 /* fake open() in pathinfo() */
280 if (mp->flags & NEED_FD)
281 will_return(__wrap_udev_device_get_devnode, _mocked_filename);
282 /* DI_SERIAL is unsupported */
283 assert_false(mask & DI_SERIAL);
285 if (mask & DI_WWID) {
286 if (mp->flags & USE_GETUID)
287 will_return(__wrap_execute_program, mp->wwid);
290 will_return(__wrap_udev_device_get_property_value,
294 if (mask & DI_CHECKER) {
295 /* get_state -> sysfs_get_timeout */
296 will_return(__wrap_udev_device_get_subsystem, "scsi");
297 will_return(__wrap_udev_device_get_sysattr_value, "180");
300 if (mask & DI_PRIO && mp->flags & NEED_SELECT_PRIO) {
302 /* sysfs_get_timeout, again (!?) */
303 will_return(__wrap_udev_device_get_subsystem, "scsi");
304 will_return(__wrap_udev_device_get_sysattr_value, "180");
309 void mock_store_pathinfo(int mask, const struct mocked_path *mp)
311 will_return(__wrap_udev_device_get_sysname, mp->devnode);
312 mock_pathinfo(mask, mp);
315 struct path *__mock_path(vector pathvec,
316 const char *vnd, const char *prd,
317 const char *rev, const char *wwid,
319 unsigned int flags, int mask)
321 struct mocked_path mop;
326 fill_mocked_path(&mop, vnd, prd, rev, wwid, dev, flags);
327 mock_store_pathinfo(mask, &mop);
329 conf = get_multipath_config();
330 r = store_pathinfo(pathvec, conf, (void *)&mop, mask, &pp);
331 put_multipath_config(conf);
333 if (flags & BL_MASK) {
334 assert_int_equal(r, PATHINFO_SKIPPED);
337 assert_int_equal(r, PATHINFO_OK);
343 struct multipath *__mock_multipath(struct vectors *vecs, struct path *pp)
345 struct multipath *mp;
347 struct mocked_path mop;
349 mocked_path_from_path(&mop, pp);
350 /* pathinfo() call in adopt_paths */
351 mock_pathinfo(DI_CHECKER|DI_PRIO, &mop);
353 mp = add_map_with_path(vecs, pp, 1);
354 assert_ptr_not_equal(mp, NULL);
356 /* TBD: mock setup_map() ... */
357 conf = get_multipath_config();
358 select_pgpolicy(conf, mp);
359 select_no_path_retry(conf, mp);
360 select_retain_hwhandler(conf, mp);
361 select_minio(conf, mp);
362 put_multipath_config(conf);