diff --git a/build/VStudio/testing/winfsp-tests.vcxproj b/build/VStudio/testing/winfsp-tests.vcxproj index 4c5555b8..0aca06df 100644 --- a/build/VStudio/testing/winfsp-tests.vcxproj +++ b/build/VStudio/testing/winfsp-tests.vcxproj @@ -185,6 +185,7 @@ + diff --git a/build/VStudio/testing/winfsp-tests.vcxproj.filters b/build/VStudio/testing/winfsp-tests.vcxproj.filters index b8248deb..54a96231 100644 --- a/build/VStudio/testing/winfsp-tests.vcxproj.filters +++ b/build/VStudio/testing/winfsp-tests.vcxproj.filters @@ -55,6 +55,9 @@ Source + + Source + diff --git a/inc/fuse/fuse_opt.h b/inc/fuse/fuse_opt.h index 7a34f706..cdde8fed 100644 --- a/inc/fuse/fuse_opt.h +++ b/inc/fuse/fuse_opt.h @@ -47,7 +47,7 @@ extern "C" { #define FSP_FUSE_MEMFN_V malloc, free #endif -#define FUSE_OPT_KEY(templ, key) { templ, -1U, key } +#define FUSE_OPT_KEY(templ, key) { templ, -1, key } #define FUSE_OPT_END { NULL, 0, 0 } #define FUSE_OPT_KEY_OPT -1 diff --git a/tst/winfsp-tests/fuse-opt-test.c b/tst/winfsp-tests/fuse-opt-test.c new file mode 100644 index 00000000..98dc39bb --- /dev/null +++ b/tst/winfsp-tests/fuse-opt-test.c @@ -0,0 +1,314 @@ +#include +#include +#include +#include + +struct data +{ + int fortytwo; + int a, b, c, d, e, f, g, h; + int i, j, k, l, m, n, o, p; + char *q, *r, *s, *t; + int u, v; + char *w; + short x; + long y; + long long z; + int arg_discard, arg_keep; + int opt_discard, opt_keep; + int nonopt_discard, nonopt_keep; +}; + +static int fuse_opt_parse_test_proc(void *data0, const char *arg, int key, + struct fuse_args *outargs) +{ + struct data *data = data0; + + switch (key) + { + default: + ASSERT(0); + return -1; + case FUSE_OPT_KEY_OPT: + if (0 == strcmp("--arg-discard", arg)) + { + data->arg_discard++; + return 0; + } + if (0 == strcmp("--arg-keep", arg)) + { + data->arg_keep++; + return 1; + } + if (0 == strcmp("opt-discard", arg)) + { + data->opt_discard++; + return 0; + } + if (0 == strcmp("opt-keep", arg)) + { + data->opt_keep++; + return 1; + } + ASSERT(0); + return -1; + case FUSE_OPT_KEY_NONOPT: + if (0 == strcmp("--discard", arg)) + { + data->nonopt_discard++; + return 1; + } + if (0 == strcmp("--keep", arg)) + { + data->nonopt_keep++; + return 0; + } + ASSERT(0); + return -1; + case 'a': + ASSERT(0); + return -1; + case 'b': + ASSERT(0 == strcmp("-b", arg)); + data->b = 'B'; + return 1; + case 'c': + ASSERT(0); + return -1; + case 'd': + ASSERT(0 == strcmp("--dlong", arg)); + data->d = 'D'; + return 1; + case 'e': + ASSERT(0); + return -1; + case 'f': + ASSERT(0 == strcmp("f", arg)); + data->f = 'F'; + return 1; + case 'g': + ASSERT(0); + return -1; + case 'h': + ASSERT(0 == strcmp("hlong", arg)); + data->h = 'H'; + return 1; + case 'i': + ASSERT(0); + return -1; + case 'j': + ASSERT(0 == strcmp("-j=74", arg)); + data->j = 'J'; + return 1; + case 'k': + ASSERT(0); + return -1; + case 'l': + ASSERT(0 == strcmp("--llong=76", arg)); + data->l = 'L'; + return 1; + case 'm': + ASSERT(0); + return -1; + case 'n': + ASSERT(0 == strcmp("n=78", arg)); + data->n = 'N'; + return 1; + case 'o': + ASSERT(0); + return -1; + case 'p': + ASSERT(0 == strcmp("plong=80", arg)); + data->p = 'P'; + return 1; + case 'q': + ASSERT(0); + return -1; + case 'r': + ASSERT(0); + return -1; + case 's': + ASSERT(0); + return -1; + case 't': + ASSERT(0); + return -1; + case 'u': + ASSERT(0); + return -1; + case 'v': + ASSERT(0 == strcmp("-v86", arg)); + data->v = 'V'; + return 1; + case 'w': + ASSERT(0); + return -1; + case 'x': + ASSERT(0); + return -1; + case 'y': + ASSERT(0); + return -1; + case 'z': + ASSERT(0); + return -1; + } +} + +void fuse_opt_parse_test(void) +{ + static struct fuse_opt opts[] = + { + { "-a", offsetof(struct data, a), 'a' }, + FUSE_OPT_KEY("-b", 'b'), + { "--clong", offsetof(struct data, c), 'c' }, + FUSE_OPT_KEY("--dlong", 'd'), + { "e", offsetof(struct data, e), 'e' }, + FUSE_OPT_KEY("f", 'f'), + { "glong", offsetof(struct data, g), 'g' }, + FUSE_OPT_KEY("hlong", 'h'), + + { "-i=", offsetof(struct data, i), 'i' }, + FUSE_OPT_KEY("-j=", 'j'), + { "--klong=", offsetof(struct data, k), 'k' }, + FUSE_OPT_KEY("--llong=", 'l'), + { "m=", offsetof(struct data, m), 'm' }, + FUSE_OPT_KEY("n=", 'n'), + { "olong=", offsetof(struct data, o), 'o' }, + FUSE_OPT_KEY("plong=", 'p'), + + { "-q=%s", offsetof(struct data, q), 'q' }, + { "--rlong=%s", offsetof(struct data, r), 'r' }, + { "s=%s", offsetof(struct data, s), 's' }, + { "tlong=%s", offsetof(struct data, t), 't' }, + + { "-u ", offsetof(struct data, u), 'u' }, + FUSE_OPT_KEY("-v ", 'v'), + + { "-w %s", offsetof(struct data, w), 'w' }, + + { "-x=%hi", offsetof(struct data, x), 'x' }, + { "-y=%li", offsetof(struct data, y), 'y' }, + { "-z=%lli", offsetof(struct data, z), 'z' }, + + FUSE_OPT_KEY("--discard", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("--keep", FUSE_OPT_KEY_KEEP), + + FUSE_OPT_END, + }; + static char *argv[] = + { + "exec", + "-a", + "-b", + "--clong", + "--dlong", + "-o", "e,f", + "-oglong,hlong", + "-i=73", + "-j=74", + "--klong=75", + "--llong=76", + "-om=77", + "-o", "n=78,olong=79,plong=80", + "-q=QqQq", + "--rlong=RrRrRrRr", + "-os=SsSs", + "-otlong=TtTtTtTt", + "-u85", + "-v", "86", + "-wWwWw", + "-x=65537", + "-y=0x100000001", + "-z=0x100000001", + "--discard", + "--keep", + "--arg-discard", + "--arg-keep", + "-oopt-discard", + "-oopt-keep", + "--", + "--discard", + "--keep", + 0 + }; + static char *outargv[] = + { + "exec", + "-o", "f,hlong,n=78,plong=80,opt-keep", + "-b", + "--dlong", + "-j=74", + "--llong=76", + "-v86", + "--keep", + "--arg-keep", + "--", + "--discard", + 0 + }; + struct fuse_args args = FUSE_ARGS_INIT(0, 0); + struct data data; + int result; + + args.argc = sizeof argv / sizeof argv[0] - 1; + args.argv = argv; + + memset(&data, 0, sizeof data); + data.fortytwo = 42; + result = fuse_opt_parse(&args, &data, opts, fuse_opt_parse_test_proc); + ASSERT(0 == result); + + ASSERT(42 == data.fortytwo); + ASSERT('a' == data.a); + ASSERT('B' == data.b); + ASSERT('c' == data.c); + ASSERT('D' == data.d); + ASSERT('e' == data.e); + ASSERT('F' == data.f); + ASSERT('g' == data.g); + ASSERT('H' == data.h); + ASSERT('i' == data.i); + ASSERT('J' == data.j); + ASSERT('k' == data.k); + ASSERT('L' == data.l); + ASSERT('m' == data.m); + ASSERT('N' == data.n); + ASSERT('o' == data.o); + ASSERT('P' == data.p); + ASSERT(0 == strcmp("QqQq", data.q)); + ASSERT(0 == strcmp("RrRrRrRr", data.r)); + ASSERT(0 == strcmp("SsSs", data.s)); + ASSERT(0 == strcmp("TtTtTtTt", data.t)); + ASSERT('u' == data.u); + ASSERT('V' == data.v); + ASSERT(0 == strcmp("WwWw", data.w)); + ASSERT(1 == data.x); + ASSERT((long)0x100000001 == data.y); + ASSERT((long long)0x100000001 == data.z); + ASSERT(1 == data.arg_discard); + ASSERT(1 == data.arg_keep); + ASSERT(1 == data.opt_discard); + ASSERT(1 == data.opt_keep); + ASSERT(1 == data.nonopt_discard); + ASSERT(1 == data.nonopt_keep); + + ASSERT(args.argc == sizeof outargv / sizeof outargv[0] - 1); + for (size_t i = 0; args.argc > i; i++) + ASSERT(0 == strcmp(args.argv[i], outargv[i])); + ASSERT(0 == args.argv[args.argc]); + ASSERT(args.allocated); + + fuse_opt_free_args(&args); + + free(data.q); + free(data.r); + free(data.s); + free(data.t); + free(data.w); +} + +void fuse_opt_tests(void) +{ + TEST(fuse_opt_parse_test); +} diff --git a/tst/winfsp-tests/winfsp-tests.c b/tst/winfsp-tests/winfsp-tests.c index 8fbe68a1..6967e1d6 100644 --- a/tst/winfsp-tests/winfsp-tests.c +++ b/tst/winfsp-tests/winfsp-tests.c @@ -6,6 +6,7 @@ int WinFspNetTests = 1; int main(int argc, char *argv[]) { + TESTSUITE(fuse_opt_tests); TESTSUITE(eventlog_tests); TESTSUITE(path_tests); TESTSUITE(mount_tests);