1 /* $NetBSD: t_refuse_opt.c,v 1.8 2017/01/13 21:30:41 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2016 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 #include <sys/cdefs.h> 29 __RCSID("$NetBSD: t_refuse_opt.c,v 1.8 2017/01/13 21:30:41 christos Exp $"); 30 31 #define _KERNTYPES 32 #include <sys/types.h> 33 34 #include <atf-c.h> 35 36 #include <fuse.h> 37 38 #include "h_macros.h" 39 40 ATF_TC(t_fuse_opt_add_arg); 41 ATF_TC_HEAD(t_fuse_opt_add_arg, tc) 42 { 43 atf_tc_set_md_var(tc, "descr", "Check that fuse_opt_add_arg(3) works"); 44 } 45 46 ATF_TC_BODY(t_fuse_opt_add_arg, tc) 47 { 48 struct fuse_args args = FUSE_ARGS_INIT(0, NULL); 49 50 RZ(fuse_opt_add_arg(&args, "foo")); 51 RZ(fuse_opt_add_arg(&args, "bar")); 52 53 ATF_REQUIRE_EQ(args.argc, 2); 54 ATF_CHECK_STREQ(args.argv[0], "foo"); 55 ATF_CHECK_STREQ(args.argv[1], "bar"); 56 ATF_CHECK(args.allocated != 0); 57 } 58 59 ATF_TC(t_fuse_opt_insert_arg); 60 ATF_TC_HEAD(t_fuse_opt_insert_arg, tc) 61 { 62 atf_tc_set_md_var(tc, "descr", "Check that fuse_opt_insert_arg(3) works"); 63 } 64 65 ATF_TC_BODY(t_fuse_opt_insert_arg, tc) 66 { 67 struct fuse_args args = FUSE_ARGS_INIT(0, NULL); 68 69 RZ(fuse_opt_insert_arg(&args, 0, "foo")); 70 RZ(fuse_opt_insert_arg(&args, 0, "bar")); 71 72 ATF_REQUIRE_EQ(args.argc, 2); 73 ATF_CHECK_STREQ(args.argv[0], "bar"); 74 ATF_CHECK_STREQ(args.argv[1], "foo"); 75 ATF_CHECK(args.allocated != 0); 76 } 77 78 ATF_TC(t_fuse_opt_add_opt); 79 ATF_TC_HEAD(t_fuse_opt_add_opt, tc) 80 { 81 atf_tc_set_md_var(tc, "descr", "Check that fuse_opt_add_opt(3) works"); 82 } 83 84 ATF_TC_BODY(t_fuse_opt_add_opt, tc) 85 { 86 char* opt = NULL; 87 88 RZ(fuse_opt_add_opt(&opt, "fo\\o")); 89 ATF_CHECK_STREQ(opt, "fo\\o"); 90 91 RZ(fuse_opt_add_opt(&opt, "ba,r")); 92 ATF_CHECK_STREQ(opt, "fo\\o,ba,r"); 93 } 94 95 ATF_TC(t_fuse_opt_add_opt_escaped); 96 ATF_TC_HEAD(t_fuse_opt_add_opt_escaped, tc) 97 { 98 atf_tc_set_md_var(tc, "descr", "Check that fuse_opt_add_opt_escaped(3) works"); 99 } 100 101 ATF_TC_BODY(t_fuse_opt_add_opt_escaped, tc) 102 { 103 char* opt = NULL; 104 105 RZ(fuse_opt_add_opt_escaped(&opt, "fo\\o")); 106 ATF_CHECK_STREQ(opt, "fo\\\\o"); 107 108 RZ(fuse_opt_add_opt_escaped(&opt, "ba,r")); 109 ATF_CHECK_STREQ(opt, "fo\\\\o,ba\\,r"); 110 } 111 112 ATF_TC(t_fuse_opt_match); 113 ATF_TC_HEAD(t_fuse_opt_match, tc) 114 { 115 atf_tc_set_md_var(tc, "descr", "Check that fuse_opt_match(3) works" 116 " for every form of templates"); 117 } 118 119 ATF_TC_BODY(t_fuse_opt_match, tc) 120 { 121 struct fuse_opt o1[] = { FUSE_OPT_KEY("-x" , 0), FUSE_OPT_END }; 122 struct fuse_opt o2[] = { FUSE_OPT_KEY("foo" , 0), FUSE_OPT_END }; 123 struct fuse_opt o3[] = { FUSE_OPT_KEY("foo=" , 0), FUSE_OPT_END }; 124 struct fuse_opt o4[] = { FUSE_OPT_KEY("foo=%s", 0), FUSE_OPT_END }; 125 struct fuse_opt o5[] = { FUSE_OPT_KEY("-x " , 0), FUSE_OPT_END }; 126 struct fuse_opt o6[] = { FUSE_OPT_KEY("-x %s" , 0), FUSE_OPT_END }; 127 128 ATF_CHECK(fuse_opt_match(o1, "-x") == 1); 129 ATF_CHECK(fuse_opt_match(o1, "x") == 0); 130 131 ATF_CHECK(fuse_opt_match(o2, "foo") == 1); 132 ATF_CHECK(fuse_opt_match(o2, "-foo") == 0); 133 134 ATF_CHECK(fuse_opt_match(o3, "foo=bar") == 1); 135 ATF_CHECK(fuse_opt_match(o3, "foo" ) == 0); 136 137 ATF_CHECK(fuse_opt_match(o4, "foo=bar") == 1); 138 ATF_CHECK(fuse_opt_match(o4, "foo" ) == 0); 139 140 ATF_CHECK(fuse_opt_match(o5, "-xbar" ) == 1); 141 ATF_CHECK(fuse_opt_match(o5, "-x" ) == 1); 142 ATF_CHECK(fuse_opt_match(o5, "-x=bar") == 1); 143 ATF_CHECK(fuse_opt_match(o5, "bar" ) == 0); 144 145 ATF_CHECK(fuse_opt_match(o6, "-xbar" ) == 1); 146 ATF_CHECK(fuse_opt_match(o6, "-x" ) == 1); 147 ATF_CHECK(fuse_opt_match(o6, "-x=bar") == 1); 148 ATF_CHECK(fuse_opt_match(o6, "bar" ) == 0); 149 } 150 151 struct foofs_config { 152 int number; 153 char *string; 154 char* nonopt; 155 }; 156 157 #define FOOFS_OPT(t, p, v) { t, offsetof(struct foofs_config, p), v } 158 159 static struct fuse_opt foofs_opts[] = { 160 FOOFS_OPT("number=%i" , number, 0), 161 FOOFS_OPT("-n %i" , number, 0), 162 FOOFS_OPT("string=%s" , string, 0), 163 FOOFS_OPT("number1" , number, 1), 164 FOOFS_OPT("number2" , number, 2), 165 FOOFS_OPT("--number=three", number, 3), 166 FOOFS_OPT("--number=four" , number, 4), 167 FUSE_OPT_END 168 }; 169 170 static int foo_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs) { 171 struct foofs_config *config = data; 172 173 if (key == FUSE_OPT_KEY_NONOPT && config->nonopt == NULL) { 174 config->nonopt = strdup(arg); 175 return 0; 176 } 177 else { 178 return 1; 179 } 180 } 181 182 ATF_TC(t_fuse_opt_parse_null_args); 183 ATF_TC_HEAD(t_fuse_opt_parse_null_args, tc) 184 { 185 atf_tc_set_md_var(tc, "descr", "NULL args means an empty arguments vector"); 186 } 187 188 ATF_TC_BODY(t_fuse_opt_parse_null_args, tc) 189 { 190 struct foofs_config config; 191 192 memset(&config, 0, sizeof(config)); 193 ATF_CHECK(fuse_opt_parse(NULL, &config, NULL, NULL) == 0); 194 ATF_CHECK_EQ(config.number, 0); 195 ATF_CHECK_EQ(config.string, NULL); 196 ATF_CHECK_EQ(config.nonopt, NULL); 197 } 198 199 ATF_TC(t_fuse_opt_parse_null_opts); 200 ATF_TC_HEAD(t_fuse_opt_parse_null_opts, tc) 201 { 202 atf_tc_set_md_var(tc, "descr", "NULL opts means an opts array which only has FUSE_OPT_END"); 203 } 204 205 ATF_TC_BODY(t_fuse_opt_parse_null_opts, tc) 206 { 207 struct fuse_args args = FUSE_ARGS_INIT(0, NULL); 208 struct foofs_config config; 209 210 RZ(fuse_opt_add_arg(&args, "foofs")); 211 RZ(fuse_opt_add_arg(&args, "-o")); 212 RZ(fuse_opt_add_arg(&args, "number=1,string=foo")); 213 RZ(fuse_opt_add_arg(&args, "bar")); 214 215 memset(&config, 0, sizeof(config)); 216 ATF_CHECK(fuse_opt_parse(&args, &config, NULL, NULL) == 0); 217 ATF_CHECK_EQ(config.number, 0); 218 ATF_CHECK_EQ(config.string, NULL); 219 ATF_CHECK_EQ(config.nonopt, NULL); 220 ATF_CHECK_EQ(args.argc, 4); 221 ATF_CHECK_STREQ(args.argv[0], "foofs"); 222 ATF_CHECK_STREQ(args.argv[1], "-o"); 223 ATF_CHECK_STREQ(args.argv[2], "number=1,string=foo"); 224 ATF_CHECK_STREQ(args.argv[3], "bar"); 225 } 226 227 ATF_TC(t_fuse_opt_parse_null_proc); 228 ATF_TC_HEAD(t_fuse_opt_parse_null_proc, tc) 229 { 230 atf_tc_set_md_var(tc, "descr", "NULL proc means a processor function always returning 1," 231 " i.e. keep the argument"); 232 } 233 234 ATF_TC_BODY(t_fuse_opt_parse_null_proc, tc) 235 { 236 struct fuse_args args = FUSE_ARGS_INIT(0, NULL); 237 struct foofs_config config; 238 239 RZ(fuse_opt_add_arg(&args, "foofs")); 240 RZ(fuse_opt_add_arg(&args, "-o")); 241 RZ(fuse_opt_add_arg(&args, "number=1,string=foo")); 242 RZ(fuse_opt_add_arg(&args, "bar")); 243 244 memset(&config, 0, sizeof(config)); 245 ATF_CHECK(fuse_opt_parse(&args, &config, foofs_opts, NULL) == 0); 246 ATF_CHECK_EQ(config.number, 1); 247 ATF_CHECK_STREQ(config.string, "foo"); 248 ATF_CHECK_EQ(config.nonopt, NULL); 249 ATF_CHECK_EQ(args.argc, 2); 250 ATF_CHECK_STREQ(args.argv[0], "foofs"); 251 ATF_CHECK_STREQ(args.argv[1], "bar"); 252 } 253 254 ATF_TC(t_fuse_opt_parse); 255 ATF_TC_HEAD(t_fuse_opt_parse, tc) 256 { 257 atf_tc_set_md_var(tc, "descr", "Check that fuse_opt_parse(3) fully works"); 258 } 259 260 ATF_TC_BODY(t_fuse_opt_parse, tc) 261 { 262 struct fuse_args args = FUSE_ARGS_INIT(0, NULL); 263 struct foofs_config config; 264 265 /* Standard form */ 266 fuse_opt_free_args(&args); 267 RZ(fuse_opt_add_arg(&args, "foofs")); 268 RZ(fuse_opt_add_arg(&args, "-o")); 269 RZ(fuse_opt_add_arg(&args, "number=1,string=foo")); 270 RZ(fuse_opt_add_arg(&args, "bar")); 271 272 memset(&config, 0, sizeof(config)); 273 ATF_CHECK(fuse_opt_parse(&args, &config, foofs_opts, foo_opt_proc) == 0); 274 ATF_CHECK_EQ(config.number, 1); 275 ATF_CHECK_STREQ(config.string, "foo"); 276 ATF_CHECK_STREQ(config.nonopt, "bar"); 277 ATF_CHECK_EQ(args.argc, 1); 278 ATF_CHECK_STREQ(args.argv[0], "foofs"); 279 280 /* Concatenated -o */ 281 fuse_opt_free_args(&args); 282 RZ(fuse_opt_add_arg(&args, "foofs")); 283 RZ(fuse_opt_add_arg(&args, "-onumber=1,unknown,string=foo")); 284 RZ(fuse_opt_add_arg(&args, "bar")); 285 286 memset(&config, 0, sizeof(config)); 287 ATF_CHECK(fuse_opt_parse(&args, &config, foofs_opts, foo_opt_proc) == 0); 288 ATF_CHECK_EQ(config.number, 1); 289 ATF_CHECK_STREQ(config.string, "foo"); 290 ATF_CHECK_STREQ(config.nonopt, "bar"); 291 ATF_CHECK_EQ(args.argc, 3); 292 ATF_CHECK_STREQ(args.argv[0], "foofs"); 293 ATF_CHECK_STREQ(args.argv[1], "-o"); 294 ATF_CHECK_STREQ(args.argv[2], "unknown"); 295 296 /* Sparse -o */ 297 fuse_opt_free_args(&args); 298 RZ(fuse_opt_add_arg(&args, "foofs")); 299 RZ(fuse_opt_add_arg(&args, "bar")); 300 RZ(fuse_opt_add_arg(&args, "baz")); 301 RZ(fuse_opt_add_arg(&args, "-o")); 302 RZ(fuse_opt_add_arg(&args, "number=1")); 303 RZ(fuse_opt_add_arg(&args, "-o")); 304 RZ(fuse_opt_add_arg(&args, "unknown")); 305 RZ(fuse_opt_add_arg(&args, "-o")); 306 RZ(fuse_opt_add_arg(&args, "string=foo")); 307 308 memset(&config, 0, sizeof(config)); 309 ATF_CHECK(fuse_opt_parse(&args, &config, foofs_opts, foo_opt_proc) == 0); 310 ATF_CHECK_EQ(config.number, 1); 311 ATF_CHECK_STREQ(config.string, "foo"); 312 ATF_CHECK_STREQ(config.nonopt, "bar"); 313 ATF_CHECK_EQ(args.argc, 4); 314 ATF_CHECK_STREQ(args.argv[0], "foofs"); 315 ATF_CHECK_STREQ(args.argv[1], "-o"); 316 ATF_CHECK_STREQ(args.argv[2], "unknown"); 317 ATF_CHECK_STREQ(args.argv[3], "baz"); 318 319 /* Separate -n %i */ 320 fuse_opt_free_args(&args); 321 RZ(fuse_opt_add_arg(&args, "foofs")); 322 RZ(fuse_opt_add_arg(&args, "-n")); 323 RZ(fuse_opt_add_arg(&args, "3")); 324 325 memset(&config, 0, sizeof(config)); 326 ATF_CHECK(fuse_opt_parse(&args, &config, foofs_opts, foo_opt_proc) == 0); 327 ATF_CHECK_EQ(config.number, 3); 328 ATF_CHECK_EQ(config.string, NULL); 329 ATF_CHECK_EQ(config.nonopt, NULL); 330 ATF_CHECK_EQ(args.argc, 1); 331 ATF_CHECK_STREQ(args.argv[0], "foofs"); 332 333 /* Concatenated -n %i */ 334 fuse_opt_free_args(&args); 335 RZ(fuse_opt_add_arg(&args, "foofs")); 336 RZ(fuse_opt_add_arg(&args, "-n3")); 337 338 memset(&config, 0, sizeof(config)); 339 ATF_CHECK(fuse_opt_parse(&args, &config, foofs_opts, foo_opt_proc) == 0); 340 ATF_CHECK_EQ(config.number, 3); 341 ATF_CHECK_EQ(config.string, NULL); 342 ATF_CHECK_EQ(config.nonopt, NULL); 343 ATF_CHECK_EQ(args.argc, 1); 344 ATF_CHECK_STREQ(args.argv[0], "foofs"); 345 346 /* -o constant */ 347 fuse_opt_free_args(&args); 348 RZ(fuse_opt_add_arg(&args, "foofs")); 349 RZ(fuse_opt_add_arg(&args, "-o")); 350 RZ(fuse_opt_add_arg(&args, "number2")); 351 352 memset(&config, 0, sizeof(config)); 353 ATF_CHECK(fuse_opt_parse(&args, &config, foofs_opts, foo_opt_proc) == 0); 354 ATF_CHECK_EQ(config.number, 2); 355 ATF_CHECK_EQ(config.string, NULL); 356 ATF_CHECK_EQ(config.nonopt, NULL); 357 ATF_CHECK_EQ(args.argc, 1); 358 ATF_CHECK_STREQ(args.argv[0], "foofs"); 359 360 /* -x constant */ 361 fuse_opt_free_args(&args); 362 RZ(fuse_opt_add_arg(&args, "foofs")); 363 RZ(fuse_opt_add_arg(&args, "--number=four")); 364 365 memset(&config, 0, sizeof(config)); 366 ATF_CHECK(fuse_opt_parse(&args, &config, foofs_opts, foo_opt_proc) == 0); 367 ATF_CHECK_EQ(config.number, 4); 368 ATF_CHECK_EQ(config.string, NULL); 369 ATF_CHECK_EQ(config.nonopt, NULL); 370 ATF_CHECK_EQ(args.argc, 1); 371 ATF_CHECK_STREQ(args.argv[0], "foofs"); 372 373 /* end-of-options "--" marker */ 374 fuse_opt_free_args(&args); 375 RZ(fuse_opt_add_arg(&args, "foofs")); 376 RZ(fuse_opt_add_arg(&args, "--")); 377 RZ(fuse_opt_add_arg(&args, "-onumber=1")); 378 RZ(fuse_opt_add_arg(&args, "-ostring=foo")); 379 380 memset(&config, 0, sizeof(config)); 381 ATF_CHECK(fuse_opt_parse(&args, &config, foofs_opts, foo_opt_proc) == 0); 382 ATF_CHECK_EQ(config.number, 0); 383 ATF_CHECK_EQ(config.string, NULL); 384 ATF_CHECK_STREQ(config.nonopt, "-onumber=1"); 385 ATF_CHECK_EQ(args.argc, 3); 386 ATF_CHECK_STREQ(args.argv[0], "foofs"); 387 ATF_CHECK_STREQ(args.argv[1], "--"); 388 ATF_CHECK_STREQ(args.argv[2], "-ostring=foo"); 389 390 /* The "--" marker at the last of outargs should be removed */ 391 fuse_opt_free_args(&args); 392 RZ(fuse_opt_add_arg(&args, "foofs")); 393 RZ(fuse_opt_add_arg(&args, "--")); 394 RZ(fuse_opt_add_arg(&args, "-onumber=1")); 395 396 memset(&config, 0, sizeof(config)); 397 ATF_CHECK(fuse_opt_parse(&args, &config, foofs_opts, foo_opt_proc) == 0); 398 ATF_CHECK_EQ(config.number, 0); 399 ATF_CHECK_EQ(config.string, NULL); 400 ATF_CHECK_STREQ(config.nonopt, "-onumber=1"); 401 ATF_CHECK_EQ(args.argc, 1); 402 ATF_CHECK_STREQ(args.argv[0], "foofs"); 403 } 404 405 ATF_TP_ADD_TCS(tp) 406 { 407 ATF_TP_ADD_TC(tp, t_fuse_opt_add_arg); 408 ATF_TP_ADD_TC(tp, t_fuse_opt_insert_arg); 409 ATF_TP_ADD_TC(tp, t_fuse_opt_add_opt); 410 ATF_TP_ADD_TC(tp, t_fuse_opt_add_opt_escaped); 411 ATF_TP_ADD_TC(tp, t_fuse_opt_match); 412 ATF_TP_ADD_TC(tp, t_fuse_opt_parse_null_args); 413 ATF_TP_ADD_TC(tp, t_fuse_opt_parse_null_opts); 414 ATF_TP_ADD_TC(tp, t_fuse_opt_parse_null_proc); 415 ATF_TP_ADD_TC(tp, t_fuse_opt_parse); 416 417 return atf_no_error(); 418 } 419