Skip to content

Commit

Permalink
Merge branch 'bld/clitoris'
Browse files Browse the repository at this point in the history
* bld/clitoris:
  chore, zap to latest clitoris version
  • Loading branch information
hroptatyr committed Sep 10, 2015
2 parents c51c7c1 + 053adec commit 84df27e
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 32 deletions.
172 changes: 140 additions & 32 deletions test/clitoris.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@
# define countof(x) (sizeof(x) / sizeof(*x))
#endif /* !countof */

#if !defined strlenof
# define strlenof(x) (sizeof(x) - 1U)
#endif /* !strlenof */

#if !defined with
# define with(args...) for (args, *__ep__ = (void*)1; __ep__; __ep__ = 0)
#endif /* !with */
Expand All @@ -81,6 +85,17 @@
# define PATH_MAX 256U
#endif /* !PATH_MAX */

#if defined HAVE_SPLICE
# ifdef __INTEL_COMPILER
# pragma warning(disable:1419)
# endif /* __INTEL_COMPILER */
extern ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out,
size_t len, unsigned int flags);
# ifdef __INTEL_COMPILER
# pragma warning(default:1419)
# endif /* __INTEL_COMPILER */
#endif /* HAVE_SPLICE */

typedef struct clitf_s clitf_t;
typedef struct clit_buf_s clit_buf_t;
typedef struct clit_bit_s clit_bit_t;
Expand Down Expand Up @@ -111,6 +126,9 @@ struct clit_opt_s {
unsigned int ptyp:1;
unsigned int keep_going_p:1;
unsigned int shcmdp:1;
/* just some padding to start afresh on an 8-bit boundary */
unsigned int:4;
unsigned int xcod:8;

/* use this instead of /bin/sh */
char *shcmd;
Expand Down Expand Up @@ -310,18 +328,80 @@ cmdify(char *restrict cmd)
{
/* prep for about 16 params */
char **v = calloc(16U, sizeof(*v));
size_t i = 0U;
const char *ifs = getenv("IFS") ?: " \t\n";

v[0U] = strtok(cmd, ifs);
do {
if (UNLIKELY((i % 16U) == 15U)) {
v = realloc(v, (i + 1U + 16U) * sizeof(*v));
}
} while ((v[++i] = strtok(NULL, ifs)) != NULL);
if (LIKELY(v != NULL)) {
const char *ifs = getenv("IFS") ?: " \t\n";
size_t i = 0U;

v[0U] = strtok(cmd, ifs);
do {
if (UNLIKELY((i % 16U) == 15U)) {
v = realloc(v, (i + 1U + 16U) * sizeof(*v));
}
} while ((v[++i] = strtok(NULL, ifs)) != NULL);
}
return v;
}

/* takes ideas from Gregory Pakosz's whereami */
static char*
get_argv0dir(const char *argv0)
{
/* return current executable */
char *res;

if (0) {
#if 0
#elif defined __linux__
/* don't rely on argv0 at all */
} else if (1) {
if ((res = realpath("/proc/self/exe", NULL)) == NULL) {
/* we've got a plan B */
goto planb;
}
#elif defined __APPLE__
} else if (1) {
char buf[PATH_MAX];
uint32_t bsz = strlenof(buf);

if (_NSGetExecutablePath(buf, &bsz) < 0) {
/* plan B again */
goto planb;
}
/* strdup BUF quickly */
res = strdup(buf);
#endif /* OS */
} else {
planb:
/* backup plan, massage argv0 */
if (argv0 == NULL) {
return NULL;
}
/* otherwise simply copy ARGV0 */
res = strdup(argv0);
}

/* path extraction aka dirname'ing, absolute or otherwise */
if (res == NULL) {
return NULL;
}
with (char *dir0 = strrchr(res, '/')) {
if (dir0 == NULL) {
free(res);
return NULL;
}
*dir0 = '\0';
}
return res;
}

static void
free_argv0dir(char *a0)
{
free(a0);
return;
}


/* clit bit handling */
#define CLIT_BIT_FD(x) (clit_bit_fd_p(x) ? (int)(x).z : -1)
Expand Down Expand Up @@ -559,27 +639,27 @@ find_ignore(struct clit_tst_s tst[static 1])
static char tok_out[] = "output";
static char tok_ret[] = "return";

if (strncmp(cmd, tok_ign, sizeof(tok_ign) - 1U)) {
if (strncmp(cmd, tok_ign, strlenof(tok_ign))) {
/* don't bother */
break;
}
/* fast-forward a little */
cmd += sizeof(tok_ign) - 1U;
cmd += strlenof(tok_ign);

if (isspace(*cmd)) {
/* it's our famous ignore token it seems */
tst->ign_out = tst->ign_ret = 1U;
} else if (*cmd++ != '-') {
/* unknown token then */
break;
} else if (!strncmp(cmd, tok_out, sizeof(tok_out) - 1U)) {
} else if (!strncmp(cmd, tok_out, strlenof(tok_out))) {
/* ignore-output it is */
tst->ign_out = 1U;
cmd += sizeof(tok_out) - 1U;
} else if (!strncmp(cmd, tok_ret, sizeof(tok_ret) - 1U)) {
cmd += strlenof(tok_out);
} else if (!strncmp(cmd, tok_ret, strlenof(tok_ret))) {
/* ignore-return it is */
tst->ign_ret = 1U;
cmd += sizeof(tok_ret) - 1U;
cmd += strlenof(tok_ret);
} else {
/* don't know what's going on */
break;
Expand Down Expand Up @@ -727,7 +807,7 @@ find_opt(struct clit_opt_s options, const char *bp, size_t bz)
static const char magic[] = "setopt ";

for (const char *mp;
(mp = xmemmem(bp, bz, magic, sizeof(magic) - 1U)) != NULL;
(mp = xmemmem(bp, bz, magic, strlenof(magic))) != NULL;
bz -= (mp + 1U) - bp, bp = mp + 1U) {
unsigned int opt;

Expand All @@ -741,12 +821,14 @@ find_opt(struct clit_opt_s options, const char *bp, size_t bz)
opt = 0U;
} else {
/* found rubbish then */
mp += sizeof(magic) - 1U;
mp += strlenof(magic);
continue;
}
#define CMP(x, lit) (strncmp((x), (lit), sizeof(lit) - 1))
#define CMP(x, lit) (strncmp((x), (lit), strlenof(lit)))
/* parse the option value */
if ((mp += sizeof(magic) - 1U) == NULL) {
mp += strlenof(magic);
if (NULL) {
/* not reached */
;
} else if (CMP(mp, "verbose\n") == 0) {
options.verbosep = opt;
Expand All @@ -772,6 +854,14 @@ find_opt(struct clit_opt_s options, const char *bp, size_t bz)
}
options.shcmd = xstrndup(arg, eol - arg);
options.shcmdp = 1U;
} else if (CMP(mp, "exit-code") == 0) {
const char *arg = mp + sizeof("exit-code");
char *p;
long unsigned int xc;

if ((xc = strtoul(arg, &p, 0), *p == '\n')) {
options.xcod = (unsigned int)xc;
}
}
#undef CMP
}
Expand Down Expand Up @@ -1067,9 +1157,6 @@ differ(struct clit_chld_s ctx[static 1], clit_bit_t exp, bool xpnd_proto_p)
if (expfd >= 0) {
close(expfd);
}
if (actfd >= 0) {
close(actfd);
}
kill(difftool, SIGTERM);
difftool = -1;
break;
Expand Down Expand Up @@ -1223,6 +1310,8 @@ run_tst(struct clit_chld_s ctx[static 1], struct clit_tst_s tst[static 1])
goto wait;
}
if (ctx->options.timeo > 0 && (ctx->feed > 0 || ctx->diff > 0)) {
alrm_handler_closure.feed = ctx->feed;
alrm_handler_closure.diff = ctx->diff;
alrm_handler_closure.old_hdl = signal(SIGALRM, alrm_handler);
}
with (const char *p = tst->cmd.d, *const ep = tst->cmd.d + tst->cmd.z) {
Expand All @@ -1238,6 +1327,7 @@ run_tst(struct clit_chld_s ctx[static 1], struct clit_tst_s tst[static 1])
* or in case of a pty, send exit command and keep fingers
* crossed the pty will close itself */
close(ctx->pin);
ctx->pin = -1;
}

/* wait for the beef child */
Expand All @@ -1249,8 +1339,8 @@ run_tst(struct clit_chld_s ctx[static 1], struct clit_tst_s tst[static 1])
rc = 0;
} else if (tst->exp_ret == 255U && rc) {
rc = 0;
} else {
rc = 1;
} else if (ctx->options.xcod) {
rc = ctx->options.xcod;
}
} else {
rc = 1;
Expand Down Expand Up @@ -1289,7 +1379,7 @@ run_tst(struct clit_chld_s ctx[static 1], struct clit_tst_s tst[static 1])
}

#if defined HAVE_PTY_H
if (UNLIKELY(ctx->options.ptyp)) {
if (UNLIKELY(ctx->options.ptyp && ctx->pin >= 0)) {
/* also close child's stdin here */
close(ctx->pin);
}
Expand Down Expand Up @@ -1527,24 +1617,42 @@ main(int argc, char *argv[])
} else if (getenv("DIFF") != NULL) {
cmd_diff = getenv("DIFF");
}

/* prepend our current directory and our argv[0] directory */
with (char *arg0 = argv[0]) {
char *dir0;
if ((dir0 = strrchr(arg0, '/')) != NULL) {
*dir0 = '\0';
if (argi->exit_code_arg == (const char*)0x1U) {
options.xcod = 0U;
} else if (argi->exit_code_arg) {
options.xcod = strtoul(argi->exit_code_arg, NULL, 0);
} else {
options.xcod = 1U;
}

/* Although I cannot support my claim with a hard survey, I would
* say in 99.9 cases out of a hundred the cli tool in question
* has not been installed at the time of testing it, so somehow
* we must make sure to test the version in the build directory
* rather than a globally installed one.
*
* On the other hand, in general we won't know where the build
* directory is, we've got --builddir for that, however we can
* assist our users by prepending the current working directory
* and the directory we're run from to PATH.
*
* So let's prepend our argv[0] directory */
with (char *arg0 = get_argv0dir(argv[0])) {
if (LIKELY(arg0 != NULL)) {
prepend_path(arg0);
free_argv0dir(arg0);
}
}
/* ... and our current directory */
prepend_path(".");
/* also bang builddir to path */
with (char *blddir = getenv("builddir")) {
if (LIKELY(blddir != NULL)) {
/* use at most 256U bytes for blddir */
char _blddir[256U];

memccpy(_blddir, blddir, '\0', sizeof(_blddir) - 1U);
_blddir[sizeof(_blddir) - 1U] = '\0';
memccpy(_blddir, blddir, '\0', strlenof(_blddir));
_blddir[strlenof(_blddir)] = '\0';
prepend_path(_blddir);
}
}
Expand Down
3 changes: 3 additions & 0 deletions test/clitoris.yuck
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ Run .clit regression test files.
-k, --keep-going Don't break on the first failure or differing output

--diff=CMD Use specified diff command instead of the one in PATH.
-x, --exit-code[=N] Map any non-0 exit code from the commands to N,
(default: 1), or, if N is omitted, pass the exit
code through as is.

0 comments on commit 84df27e

Please sign in to comment.