winfsp/tst/winfsp-tests/fuse-opt-test.c
2021-05-21 15:57:05 -07:00

382 lines
9.4 KiB
C

/**
* @file fuse-opt-test.c
*
* @copyright 2015-2021 Bill Zissimopoulos
*/
/*
* This file is part of WinFsp.
*
* You can redistribute it and/or modify it under the terms of the GNU
* General Public License version 3 as published by the Free Software
* Foundation.
*
* Licensees holding a valid commercial license may use this software
* in accordance with the commercial license agreement provided in
* conjunction with the software. The terms and conditions of any such
* commercial license agreement shall govern, supersede, and render
* ineffective any application of the GPLv3 license to this software,
* notwithstanding of any reference thereto in the software or
* associated repository.
*/
#include <fuse/fuse_opt.h>
#include <tlib/testsuite.h>
#include <stddef.h>
#include <string.h>
#include "winfsp-tests.h"
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, V;
char *w;
short x;
long y;
long long z;
int dec, neg, hex, oct;
int sel;
char *esc; int ESC;
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 'V':
ASSERT(0 == strcmp("-V118", 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;
case 'ESC':
ASSERT(0 == strcmp("ESC=\\FOO,BAR\\", arg));
data->ESC = 1;
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'),
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' },
{ "--dec=%d", offsetof(struct data, dec), 'dec' },
{ "--neg=%d", offsetof(struct data, neg), 'neg' },
{ "--hex=%x", offsetof(struct data, hex), 'hex' },
{ "--oct=%o", offsetof(struct data, oct), 'oct' },
{ "--sel=fortyone", offsetof(struct data, sel), 141 },
{ "--sel=fortytwo", offsetof(struct data, sel), 142 },
{ "--sel=fortythree", offsetof(struct data, sel), 143 },
{ "esc=%s", offsetof(struct data, esc), 'esc' },
FUSE_OPT_KEY("ESC=", 'ESC'),
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",
"-V118",
"-wWwWw",
"-x=65537",
"-y=040000000001",
"-z=0x100000001",
"--dec=+1234567890",
"--neg=-1234567890",
"--hex=ABCDEF",
"--oct=12345670",
"--sel=fortytwo",
"-oesc=\\\\foo\\,bar\\\\,ESC=\\\\FOO\\,BAR\\\\",
"--discard",
"--keep",
"--arg-discard",
"--arg-keep",
"-oopt-discard",
"-oopt-keep",
"--",
"--discard",
"--keep",
0
};
static char *outargv[] =
{
"exec",
"-o", "f,hlong,n=78,plong=80,ESC=\\\\FOO\\,BAR\\\\,opt-keep",
"-b",
"--dlong",
"-j=74",
"--llong=76",
"-v86",
"-V118",
"--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('v' == data.V);
ASSERT(0 == strcmp("WwWw", data.w));
ASSERT(1 == data.x);
ASSERT((long)040000000001 == data.y);
ASSERT((long long)0x100000001 == data.z);
ASSERT(+1234567890 == data.dec);
ASSERT(-1234567890 == data.neg);
ASSERT(0xABCDEF == data.hex);
ASSERT(012345670 == data.oct);
ASSERT(142 == data.sel);
ASSERT(0 == strcmp("\\foo,bar\\", data.esc));
ASSERT(1 == data.ESC);
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 (int 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);
free(data.esc);
}
void fuse_opt_tests(void)
{
if (OptExternal)
return;
TEST(fuse_opt_parse_test);
}