[LTP] [PATCH 2/2] testcases/clock_nanosleep01: convert to use new test library API
Cyril Hrubis
chrubis@suse.cz
Mon Nov 21 16:23:40 CET 2016
Hi!
> +#include "linux_syscall_numbers.h"
> +#include "tst_sig_proc.h"
> +#include "tst_test.h"
>
> - tst_rmdir();
> +int testno;
^
Is this used for anything?
> +static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
> +{
> }
>
> -/* Local Functions */
> -/******************************************************************************/
> -/* */
> -/* Function: setup */
> -/* */
> -/* Description: Performs all one time setup for this test. This function is */
> -/* typically used to capture signals, create temporary dirs */
> -/* and temporary files that may be used in the course of this */
> -/* test. */
> -/* */
> -/* Input: None. */
> -/* */
> -/* Output: None. */
> -/* */
> -/* Return: On failure - Exits by calling cleanup(). */
> -/* On success - returns 0. */
> -/* */
> -/******************************************************************************/
> void setup(void)
> {
> - /* Capture signals if any */
> - act.sa_handler = sighandler;
> - sigfillset(&act.sa_mask);
> - sigaction(SIGINT, &act, NULL);
> -
> - /* Create temporary directories */
> - TEST_PAUSE;
> - tst_tmpdir();
> + SAFE_SIGNAL(SIGINT, sighandler);
> }
>
> -/*
> - * Macros
> - */
> -#define SYSCALL_NAME "clock_nanosleep"
> -
> enum test_type {
> NORMAL,
> - NULL_POINTER,
> SEND_SIGINT,
> };
>
> -/*
> - * Data Structure
> - */
> +#define TYPE_NAME(x) .ttype = x, .desc = #x
> +
> struct test_case {
> - clockid_t clk_id;
> - int ttype;
> - int flags;
> + clockid_t clk_id; /* clock_* clock type parameter */
> + int ttype; /* test type (enum) */
> + const char *desc; /* test description (name) */
> + int flags; /* clock_nanosleep flags parameter */
> time_t sec;
> long nsec;
> - int ret;
> - int err;
> + int ret; /* expected ret code */
> + int err; /* expected errno code */
It's a bit better to name these variables so that the names are clear
and avoid comments. Here exp_ret and exp_err should be descriptive
enough so that we don't have to explain it.
I tend to avoid comments unless necessary.
> };
>
> /* Test cases
> @@ -161,58 +57,57 @@ struct test_case {
> *
> * EINTR v (function was interrupted by a signal)
> * EINVAL v (invalid tv_nsec, etc.)
> - * ENOTSUP can't check because not supported clk_id generates
> - * EINVAL
> + * ENOTSUP can't check because not supported clk_id generates EINVAL
> */
>
> static struct test_case tcase[] = {
> - { // case00
> + {
> .clk_id = CLOCK_REALTIME,
> - .ttype = NORMAL,
> + TYPE_NAME(NORMAL),
> .flags = 0,
> .sec = 0,
> - .nsec = 500000000, // 500msec
> + .nsec = 500000000,
> .ret = 0,
> .err = 0,
> },
> - { // case01
> + {
> .clk_id = CLOCK_MONOTONIC,
> - .ttype = NORMAL,
> + TYPE_NAME(NORMAL),
> .flags = 0,
> .sec = 0,
> - .nsec = 500000000, // 500msec
> + .nsec = 500000000,
> .ret = 0,
> .err = 0,
> },
> - { // case02
> - .ttype = NORMAL,
> + {
> + TYPE_NAME(NORMAL),
> .clk_id = CLOCK_REALTIME,
> .flags = 0,
> .sec = 0,
> - .nsec = -1, // invalid
> + .nsec = -1,
> .ret = EINVAL,
> .err = 0,
> },
> - { // case03
> - .ttype = NORMAL,
> + {
> + TYPE_NAME(NORMAL),
> .clk_id = CLOCK_REALTIME,
> .flags = 0,
> .sec = 0,
> - .nsec = 1000000000, // invalid
> + .nsec = 1000000000,
> .ret = EINVAL,
> .err = 0,
> },
> - { // case04
> - .ttype = NORMAL,
> - .clk_id = CLOCK_THREAD_CPUTIME_ID, // not supported
> + {
> + TYPE_NAME(NORMAL),
> + .clk_id = CLOCK_THREAD_CPUTIME_ID,
> .flags = 0,
> .sec = 0,
> - .nsec = 500000000, // 500msec
> - .ret = EINVAL, // RHEL4U1 + 2.6.18 returns EINVAL
> + .nsec = 500000000,
> + .ret = EINVAL,
> .err = 0,
> },
> - { // case05
> - .ttype = SEND_SIGINT,
> + {
> + TYPE_NAME(SEND_SIGINT),
> .clk_id = CLOCK_REALTIME,
> .flags = 0,
> .sec = 10,
> @@ -220,23 +115,8 @@ static struct test_case tcase[] = {
> .ret = EINTR,
> .err = 0,
> },
> -#if 0 // glibc generates SEGV error (RHEL4U1 + 2.6.18)
> - { // caseXX
> - .ttype = NULL_POINTER,
> - .clk_id = CLOCK_REALTIME,
> - .flags = 0,
> - .sec = 0,
> - .nsec = 500000000, // 500msec
> - .ret = EFAULT,
> - .err = 0,
> - },
> -#endif
> };
>
> -/*
> - * chk_difftime()
> - * Return : OK(0), NG(-1)
> - */
> #define MAX_MSEC_DIFF 20
>
> static int chk_difftime(struct timespec *bef, struct timespec *aft,
> @@ -254,152 +134,83 @@ static int chk_difftime(struct timespec *bef, struct timespec *aft,
> }
> expect = (sec * 1000) + (nsec / 1000000);
> result = (t.tv_sec * 1000) + (t.tv_nsec / 1000000);
> - tst_resm(TINFO, "check sleep time: (min:%ld) < %ld < (max:%ld) (msec)",
> +
> + tst_res(TINFO, "check sleep time: (min: %ld) < %ld < (max: %ld) (msec)",
> expect - MAX_MSEC_DIFF, result, expect + MAX_MSEC_DIFF);
> +
> if (result < expect - MAX_MSEC_DIFF || result > expect + MAX_MSEC_DIFF)
> return -1;
> +
> return 0;
> }
We do have helper functions for measuring elapsed time in LTP. See
2.2.21 Measuring elapsed time in test-writing-guidelines.
> -/*
> - * do_test()
> - *
> - * Input : TestCase Data
> - * Return : RESULT_OK(0), RESULT_NG(1)
> - *
> - */
> -static int do_test(struct test_case *tc)
> +static void do_test(unsigned int i)
> {
> - int sys_ret;
> - int sys_errno;
> - int result = RESULT_OK;
> + int sys_ret, sys_errno, dummy;
> struct timespec beftp, afttp, rq, rm;
> - int rc, range_ok = 1, remain_ok = 1;
> + int rc;
> pid_t pid = 0;
> + struct test_case *tc = &tcase[i];
>
> - /*
> - * Check before sleep time
> - */
> + tst_res(TINFO, "case %s", tc->desc);
> +
> + /* setup */
> if (tc->ttype == SEND_SIGINT) {
> - pid = create_sig_proc(500000, SIGINT, UINT_MAX);
> - if (pid < 0)
> - return 1;
> + pid = create_sig_proc(SIGINT, 40, 500000);
> }
>
> - /*
> - * Check before sleep time
> - */
> TEST(rc = clock_gettime(tc->clk_id, &beftp));
> if (rc < 0) {
> - tst_resm(TFAIL | TTERRNO, "clock_gettime failed");
> - result = 1;
> - goto EXIT;
> + tst_brk(TBROK, "clock_gettime failed");
> }
> - /*
> - * Execute system call
> - */
> +
> + /* test */
> rq.tv_sec = tc->sec;
> rq.tv_nsec = tc->nsec;
> - // !!!CAUTION: 'clock_gettime' returns errno itself
> errno = 0;
> - if (tc->ttype == NULL_POINTER)
> - TEST(sys_ret =
> - clock_nanosleep(tc->clk_id, tc->flags, NULL, &rm));
> - else
> - TEST(sys_ret =
> - clock_nanosleep(tc->clk_id, tc->flags, &rq, &rm));
> + TEST(sys_ret = clock_nanosleep(tc->clk_id, tc->flags, &rq, &rm));
If you use TEST macro, the errno is zeroed before the call and stored
into TEST_ERRNO right after the call. There is no need to do anything
else than examine TEST_RETURN after a call to clock_nanoslee().
> sys_errno = errno;
> - if (sys_ret != 0)
> - goto TEST_END;
> -
> - /*
> - * Check after sleep time
> - */
> - TEST(rc = clock_gettime(tc->clk_id, &afttp));
> - if (TEST_RETURN < 0) {
> - EPRINTF("clock_gettime failed.\n");
> - result = 1;
> - goto EXIT;
> - }
> - range_ok = chk_difftime(&beftp, &afttp, tc->sec, tc->nsec) == 0;
> - /*
> - * Check remaining time
> - */
> -TEST_END:
> - if (tc->ttype == NORMAL || tc->ttype == SEND_SIGINT) {
> - tst_resm(TINFO, "remain time: %ld %ld", rm.tv_sec, rm.tv_nsec);
> - if (tc->ttype == NORMAL)
> - remain_ok = 1;
> - else
> - remain_ok = rm.tv_sec != 0 || rm.tv_nsec != 0;
> + if (sys_ret == 0) {
> + TEST(rc = clock_gettime(tc->clk_id, &afttp));
> + if (TEST_RETURN < 0) {
> + tst_brk(TBROK, "clock_gettime failed");
> + }
> }
>
> - /*
> - * Check results
> - */
> - result |= (sys_ret != tc->ret) || !range_ok || !remain_ok;
> - if (!range_ok)
> - PRINT_RESULT_EXTRA(0, tc->ret, tc->err, sys_ret, sys_errno,
> - "time range check", range_ok);
> - else
> - PRINT_RESULT_EXTRA(0, tc->ret, tc->err, sys_ret, sys_errno,
> - "remain time check", remain_ok);
> -EXIT:
> + tst_res(TINFO, "remain time: %ld %ld", rm.tv_sec, rm.tv_nsec);
> +
> + /* cleanup */
> if (pid > 0) {
> - int st;
> - TEST(kill(pid, SIGTERM));
> - TEST(wait(&st));
> + kill(pid, SIGTERM);
> + SAFE_WAIT(&dummy);
You can pass NULL to wait() if you are not going to examine the status.
> }
> - return result;
> -}
> -
> -/*
> - * main()
> - */
> -
> -int main(int ac, char **av)
> -{
> - int result = RESULT_OK;
> - int i;
> - int lc;
> -
> - tst_parse_opts(ac, av, NULL, NULL);
> -
> - setup();
> -
> - for (lc = 0; TEST_LOOPING(lc); ++lc) {
> -
> - tst_count = 0;
> -
> - for (testno = 0; testno < TST_TOTAL; ++testno) {
> -
> - for (i = 0; i < (int)(sizeof(tcase) / sizeof(tcase[0]));
> - i++) {
> - int ret;
> - tst_resm(TINFO, "(case%02d) START", i);
> - ret = do_test(&tcase[i]);
> - tst_resm(TINFO, "(case%02d) END => %s",
> - i, (ret == 0) ? "OK" : "NG");
> - result |= ret;
> - }
> -
> - switch (result) {
> - case RESULT_OK:
> - tst_resm(TPASS,
> - "clock_nanosleep call succeeded");
> - break;
> -
> - default:
> - tst_brkm(TFAIL | TERRNO, cleanup,
> - "clock_nanosleep failed");
> - break;
> - }
> -
> - }
>
> + /* result check */
> + if (sys_ret == 0 && chk_difftime(&beftp, &afttp, tc->sec, tc->nsec) != 0) {
> + tst_res(TFAIL, "time range check ret: %d, exp: %d, ret_errno: %s (%d),"
> + " exp_errno: %s (%d)", sys_ret, tc->ret,
> + tst_strerrno(sys_errno), sys_errno,
> + tst_strerrno(tc->err), tc->err);
> + } else if (tc->ttype == SEND_SIGINT && !rm.tv_sec && !rm.tv_nsec) {
> + tst_res(TFAIL, "remain time check ret: %d, exp: %d, ret_errno: %s (%d),"
> + " exp_errno: %s (%d)", sys_ret, tc->ret,
> + tst_strerrno(sys_errno), sys_errno,
> + tst_strerrno(tc->err), tc->err);
> + } else if (sys_ret != tc->ret) {
> + tst_res(TFAIL, "ret: %d, exp: %d, ret_errno: %s (%d),"
> + " exp_errno: %s (%d)", sys_ret, tc->ret,
> + tst_strerrno(sys_errno), sys_errno,
> + tst_strerrno(tc->err), tc->err);
> + } else {
> + tst_res(TPASS, "ret: %d", sys_ret);
> }
Can we get rid of this else if spaghetti and use return instead?
> - cleanup();
> - tst_exit();
> -
> }
> +
> +static struct tst_test test = {
> + .tid = "clock_nanosleep01",
> + .tcnt = ARRAY_SIZE(tcase),
> + .test = do_test,
> + .setup = setup,
> + .forks_child = 1,
> + .needs_tmpdir = 1,
Do we really need tmpdir here?
> +};
> --
> 2.10.2
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
--
Cyril Hrubis
chrubis@suse.cz
More information about the ltp
mailing list