All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cyril Hrubis <chrubis@suse.cz>
To: ltp@lists.linux.it
Subject: [LTP] [PATCH v2 1/2] syscalls/clock_settime01.c: create syscall clock_settime
Date: Tue, 11 Dec 2018 15:27:51 +0100	[thread overview]
Message-ID: <20181211142750.GA27159@rei> (raw)
In-Reply-To: <20181206190710.22471-1-rafael.tinoco@linaro.org>

Hi!
> new file mode 100644
> index 000000000..97d720fa2
> --- /dev/null
> +++ b/testcases/kernel/syscalls/clock_settime/clock_settime01.c
> @@ -0,0 +1,122 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2018 Linaro Limited. All rights reserved.
> + * Author: Rafael David Tinoco <rafael.tinoco@linaro.org>
> + */
> +
> +/*
> + * Basic test for clock_settime(2) on REALTIME clock:
> + *
> + *      1) advance DELTA_SEC seconds
> + *      2) go backwards DELTA_SEC seconds
> + *
> + * Accept DELTA_PER deviation on both (specially going backwards).
> + */
> +
> +#include "config.h"
> +#include "tst_test.h"
> +#include "lapi/syscalls.h"
> +
> +#define DELTA_SEC 10	/* 10 seconds delta    */
> +#define DELTA_PER 0.1	/* 1 percent deviation */
> +
> +static struct timespec real_begin, mono_begin, mono_end;
> +
> +static void clock_elapsed(struct timespec *begin, struct timespec *end,
> +		struct timespec *elapsed)
> +{
> +	elapsed->tv_sec = end->tv_sec - begin->tv_sec;
> +	elapsed->tv_nsec = end->tv_nsec - begin->tv_nsec;

If you do this the elapsed may end up in non-normalized state, i.e.
elapsed->tv_nsec may end up negative.

We do have all kinds of inline functions for conversion and arimetic in
tst_timer.h so there is no point of rolling your own here.

> +}
> +
> +static void clock_return(void)
                      ^
		      I would have named this restore, but that is very
		      minor.

> +{
> +	static struct timespec elapsed, adjust;
> +
> +	clock_elapsed(&mono_begin, &mono_end, &elapsed);
> +
> +	adjust.tv_sec = real_begin.tv_sec + elapsed.tv_sec;
> +	adjust.tv_nsec = real_begin.tv_nsec + elapsed.tv_nsec;

We should normalize the addition here as well, i.e. carry over to
seconds if the number of nanoseconds gets greater than 1s.

Ideally we should add a function to add two timespec structures into the
tst_timer.h header (in a separate patch).

> +	if (clock_settime(CLOCK_REALTIME, &adjust) != 0)
> +		tst_res(TBROK | TTERRNO, "could restore realtime clock");
> +}
> +
> +static void clock_fixnow(void)
> +{
> +	if (clock_gettime(CLOCK_MONOTONIC_RAW, &mono_end) != 0)
> +		tst_res(TBROK | TTERRNO, "could not get elapsed time");

We should make sure here that both real_begin and mono_begin were set
before we attempt to restore the system time. A restore_time flag se to
1 after we successfully read both will do.

> +	clock_return();
> +}
> +
> +static void setup(void)
> +{
> +	/* save initial monotonic time to restore it when needed */
> +
> +	if (clock_gettime(CLOCK_REALTIME, &real_begin) != 0)
> +		tst_res(TBROK | TTERRNO, "could not get initial real time");
> +
> +	if (clock_gettime(CLOCK_MONOTONIC_RAW, &mono_begin) != 0)
> +		tst_res(TBROK | TTERRNO, "couldn't get initial monotonic time");
                  ^
		  This should have been tst_brk() doing tst_res() with
		  TBROK does not make much sense.

Also we do have tst_safe_clocks.h, if you include that you can use
SAFE_CLOCK_GETTIME() instead.

Overall the idea of restoring wall clock using monotonic timer is a good
one, maybe we should even move this code to a library so that all tests
that change wall clock would need just set restore_wallclock flag in the
tst_test structure...

> +}
> +
> +static void cleanup(void)
> +{
> +	clock_fixnow();
> +}
> +
> +static void verify_clock_settime(void)
> +{
> +	static struct timespec begin, change, end, elapsed;
> +
> +	/* test 01: move forward */
> +
> +	if (clock_gettime(CLOCK_REALTIME, &begin) != 0)
> +		tst_res(TBROK | TTERRNO, "could not get realtime at the begin");
> +
> +	change.tv_sec = begin.tv_sec + DELTA_SEC;
> +
> +	if (clock_settime(CLOCK_REALTIME, &change) != 0)
> +		tst_res(TBROK | TTERRNO, "could not set realtime change");
> +
> +	if (clock_gettime(CLOCK_REALTIME, &end) != 0)
> +		tst_res(TBROK | TTERRNO, "could not get realtime after change");

Here as well.

> +	clock_elapsed(&begin, &end, &elapsed);
> +
> +	if (elapsed.tv_sec < (float) (DELTA_SEC - (DELTA_SEC * DELTA_PER)))

It would be much easier to just use tst_timespec_diff_ms() and check
that the result is in reasonable range. I.e. check lower bound as well.

> +		tst_res(TFAIL, "clock_settime(2): could not advance time");
> +	else
> +		tst_res(TPASS, "clock_settime(2): was able to advance time");
> +
> +	/* test 02: move backward */
> +
> +	if (clock_gettime(CLOCK_REALTIME, &begin) != 0)
> +		tst_res(TBROK | TTERRNO, "could not get realtime at the begin");
> +
> +	change.tv_sec = begin.tv_sec - DELTA_SEC;
> +
> +	if (clock_settime(CLOCK_REALTIME, &change) != 0)
> +		tst_res(TBROK | TTERRNO, "could not set realtime change");
> +
> +	if (clock_gettime(CLOCK_REALTIME, &end) != 0)
> +		tst_res(TBROK | TTERRNO, "could not get realtime after change");
> +
> +	clock_elapsed(&begin, &end, &elapsed);
> +
> +	elapsed.tv_sec = ~elapsed.tv_sec;
> +	elapsed.tv_nsec = ~elapsed.tv_nsec;
> +
> +	if (elapsed.tv_sec < (float) (DELTA_SEC - (DELTA_SEC * DELTA_PER)))
> +		tst_res(TFAIL, "clock_settime(2): could not recede time");
> +	else
> +		tst_res(TPASS, "clock_settime(2): was able to recede time");

Here as well.

> +}
> +
> +static struct tst_test test = {
> +	.setup = setup,
> +	.test_all = verify_clock_settime,
> +	.cleanup = cleanup,
> +	.needs_root = 1,
> +};
>
> diff --git a/testcases/kernel/syscalls/clock_settime/clock_settime02.c b/testcases/kernel/syscalls/clock_settime/clock_settime02.c
> new file mode 100644
> index 000000000..710f37219
> --- /dev/null
> +++ b/testcases/kernel/syscalls/clock_settime/clock_settime02.c
> @@ -0,0 +1,171 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2018 Linaro Limited. All rights reserved.
> + * Author: Rafael David Tinoco <rafael.tinoco@linaro.org>
> + */
> +
> +/*
> + * Basic tests for errors of clock_settime(2) on different clock types.
> + */
> +
> +#include "config.h"
> +#include "tst_test.h"
> +#include "lapi/syscalls.h"
> +
> +#define DELTA_SEC 10
> +#define NSEC_PER_SEC (1000000000L)
> +#define MAX_CLOCKS 16
> +
> +static struct timespec clock_realtime_saved;
> +
> +struct test_case {
> +	clockid_t type;
> +	struct timespec newtime;
> +	int exp_err;
> +	int replace;
> +};
> +
> +struct test_case tc[] = {
> +	{				/* case 01: REALTIME: timespec NULL   */
> +	 .type = CLOCK_REALTIME,
> +	 .newtime.tv_sec = -2,
> +	 .exp_err = EFAULT,
> +	 .replace = 1,
> +	 },
> +	{				/* case 02: REALTIME: tv_sec = -1     */
> +	 .type = CLOCK_REALTIME,
> +	 .newtime.tv_sec = -1,
> +	 .exp_err = EINVAL,
> +	 .replace = 1,
> +	 },
> +	{				/* case 03: REALTIME: tv_nsec = -1    */
> +	 .type = CLOCK_REALTIME,
> +	 .newtime.tv_nsec = -1,
> +	 .exp_err = EINVAL,
> +	 .replace = 1,
> +	 },
> +	{				/* case 04: REALTIME: tv_nsec = 1s+1  */
> +	 .type = CLOCK_REALTIME,
> +	 .newtime.tv_nsec = NSEC_PER_SEC + 1,
> +	 .exp_err = EINVAL,
> +	 .replace = 1,
> +	 },
> +	{				/* case 05: MONOTONIC		      */
> +	 .type = CLOCK_MONOTONIC,
> +	 .exp_err = EINVAL,
> +	 },
> +	{				/* case 06: MAXCLOCK		      */
> +	 .type = MAX_CLOCKS,
> +	 .exp_err = EINVAL,
> +	 },
> +	{				/* case 07: MAXCLOCK+1		      */
> +	 .type = MAX_CLOCKS + 1,
> +	 .exp_err = EINVAL,
> +	 },
> +	/* Linux specific */
> +	{				/* case 08: CLOCK_MONOTONIC_COARSE    */
> +	 .type = CLOCK_MONOTONIC_COARSE,
> +	 .exp_err = EINVAL,
> +	 },
> +	{				/* case 09: CLOCK_MONOTONIC_RAW       */
> +	 .type = CLOCK_MONOTONIC_RAW,
> +	 .exp_err = EINVAL,
> +	 },
> +	{				/* case 10: CLOCK_BOOTTIME	      */
> +	 .type = CLOCK_BOOTTIME,
> +	 .exp_err = EINVAL,
> +	 },
> +	{				/* case 11: CLOCK_PROCESS_CPUTIME_ID  */
> +	 .type = CLOCK_PROCESS_CPUTIME_ID,
> +	 .exp_err = EINVAL,
> +	 },
> +	{				/* case 12: CLOCK_THREAD_CPUTIME_ID   */
> +	 .type = CLOCK_THREAD_CPUTIME_ID,
> +	 .exp_err = EINVAL,
> +	 },
> +};
> +
> +/*
> + * Some tests may cause libc to segfault when passing bad arguments.
> + */
> +static int sys_clock_settime(clockid_t clk_id, struct timespec *tp)
> +{
> +	return tst_syscall(__NR_clock_settime, clk_id, tp);
> +}
> +
> +static int sys_clock_gettime(clockid_t clk_id, struct timespec *tp)
> +{
> +	return tst_syscall(__NR_clock_gettime, clk_id, tp);
> +}
> +
> +static void cleanup(void)
> +{
> +	/* restore realtime clock */
> +
> +	if (sys_clock_settime(CLOCK_REALTIME, &clock_realtime_saved) < 0)
> +		tst_res(TBROK | TTERRNO, "clock_settime(2): could not set "
> +				"current time back");
> +}
> +
> +static void setup(void)
> +{
> +	if (sys_clock_gettime(CLOCK_REALTIME, &clock_realtime_saved) < 0)
> +		tst_res(TBROK | TTERRNO, "clock_gettime(2): could not get "
> +				"current time");
> +}
> +
> +static void verify_clock_settime(unsigned int i)
> +{
> +	struct timespec spec, *specptr;
> +
> +	if (tc[i].replace == 0) {
> +
> +		/* add 1 sec to test clock */
> +
> +		specptr = &spec;
> +		specptr->tv_sec = clock_realtime_saved.tv_sec + 1;
> +		specptr->tv_nsec = clock_realtime_saved.tv_nsec;
> +
> +	} else {
> +
> +		/* bad pointer case */
> +
> +		if (tc[i].newtime.tv_sec == -2)
> +			specptr = tst_get_bad_addr(cleanup);
> +
> +		/* use given values */
> +
> +		else {

Still curly braces missing here, but that is minor.

And maybe we just need to turn the newtime into a pointer in the tcases
structure. Then you can initialize global variable to current time +
epsion and use pointer to it or even initialize it inline as:

static struct timespec valid_time;

struct test_case tc[] = {
	{
	 .type = CLOCK_REALTIME,
	 .exp_err = EFAULT,
	},
	{
	 .type = CLOCK_REALTIME;
	 .newtime = &valid_time;
	 .exp_err = EINVAL,
	{
	 .type = CLOCK_REALTIME,
	 .newtime = &(struct timespec){},
	 .exp_err = EINVAL,
	 .replace = 1,
	},
	...
};

And we can loop in the test setup and set NULL address to the result of
tst_get_bad_addr() as well.

> +			specptr = &spec;
> +			specptr->tv_sec = tc[i].newtime.tv_sec;
> +			specptr->tv_nsec = tc[i].newtime.tv_nsec;
> +		}
> +	}
> +
> +	TEST(sys_clock_settime(tc[i].type, specptr));
> +
> +	if (TST_RET == -1) {
> +
> +		if (tc[i].exp_err == TST_ERR) {
> +
> +			tst_res(TPASS, "clock_settime(2): failed as expected");
> +
> +		} else {
> +			tst_res(TFAIL | TTERRNO, "clock_settime(2): "
> +					"failed with different error");
> +		}
> +
> +		return;
> +	}
> +
> +	tst_res(TFAIL | TTERRNO, "clock_settime(2): clock type %d failed",
> +			tc[i].type);
> +}
> +
> +static struct tst_test test = {
> +	.setup = setup,
> +	.test = verify_clock_settime,
> +	.cleanup = cleanup,
> +	.tcnt = ARRAY_SIZE(tc),
> +	.needs_root = 1,
> +};
> -- 
> 2.20.0.rc1
> 

-- 
Cyril Hrubis
chrubis@suse.cz

  parent reply	other threads:[~2018-12-11 14:27 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-05 19:30 [LTP] [PATCH 1/2] syscalls/clock_settime01.c: create syscall clock_settime test Rafael David Tinoco
2018-12-05 19:30 ` [LTP] [PATCH 2/2] timers/clock_settime: remove clock_settime tests Rafael David Tinoco
2018-12-06 13:03 ` [LTP] [PATCH 1/2] syscalls/clock_settime01.c: create syscall clock_settime test Cyril Hrubis
2018-12-06 14:49   ` Rafael David Tinoco
2018-12-06 19:07   ` [LTP] [PATCH v2 1/2] syscalls/clock_settime01.c: create syscall clock_settime Rafael David Tinoco
2018-12-06 19:07     ` [LTP] [PATCH v2 2/2] timers/clock_settime: remove clock_settime tests Rafael David Tinoco
2018-12-06 19:11     ` [LTP] [PATCH v2 1/2] syscalls/clock_settime01.c: create syscall clock_settime Rafael David Tinoco
2018-12-11 14:27     ` Cyril Hrubis [this message]
2018-12-11 16:05       ` Rafael David Tinoco
2018-12-12 20:37       ` [LTP] [PATCH v3 1/6] tst_timer.h: add tst_timespect_rem_us() function Rafael David Tinoco
2018-12-12 20:37         ` [LTP] [PATCH v3 2/6] lib: add tst_clock_settime() to tst_clocks.h Rafael David Tinoco
2018-12-12 20:37         ` [LTP] [PATCH v3 3/6] lib: include SAFE_CLOCK_SETTIME() macro Rafael David Tinoco
2018-12-12 20:37         ` [LTP] [PATCH v3 4/6] lib: new restore_wallclock field to restore realtime clock Rafael David Tinoco
2019-01-24 15:12           ` Cyril Hrubis
2018-12-12 20:37         ` [LTP] [PATCH v3 5/6] syscalls/clock_settime: create syscall clock_settime tests Rafael David Tinoco
2018-12-12 20:46           ` Rafael David Tinoco
2019-01-24 16:11           ` Cyril Hrubis
2019-01-29 17:36             ` [LTP] [PATCH v4 1/8] lib: add tst_clock_settime() to tst_clocks.h Rafael David Tinoco
2019-01-29 17:36               ` [LTP] [PATCH v4 2/8] lib: include SAFE_CLOCK_SETTIME() macro Rafael David Tinoco
2019-01-29 17:36               ` [LTP] [PATCH v4 3/8] tst_timer: Add tst_timespec_add() Rafael David Tinoco
2019-01-29 17:36               ` [LTP] [PATCH v4 4/8] lib: new restore_wallclock field to restore realtime clock Rafael David Tinoco
2019-01-30 13:53                 ` Cyril Hrubis
2019-01-29 17:36               ` [LTP] [PATCH v4 5/8] tst_timer: Add tst_timespec_sub_us() Rafael David Tinoco
2019-01-29 17:36               ` [LTP] [PATCH v4 6/8] tst_timer: Turn clock_name() function public Rafael David Tinoco
2019-01-30 13:54                 ` Cyril Hrubis
2019-01-29 17:36               ` [LTP] [PATCH v4 7/8] syscalls/clock_settime: create syscall clock_settime tests Rafael David Tinoco
2019-01-30 13:56                 ` Cyril Hrubis
2019-01-29 17:36               ` [LTP] [PATCH v4 8/8] timers/clock_settime: remove " Rafael David Tinoco
2019-01-30 13:50               ` [LTP] [PATCH v4 1/8] lib: add tst_clock_settime() to tst_clocks.h Cyril Hrubis
2019-01-30 14:50                 ` Rafael David Tinoco
2018-12-12 20:37         ` [LTP] [PATCH v3 6/6] timers/clock_settime: remove clock_settime tests Rafael David Tinoco
2019-01-08 12:04           ` Rafael David Tinoco
2019-01-08 12:42             ` Cyril Hrubis
2019-01-08 12:46               ` Rafael David Tinoco
2019-01-24 12:58             ` Rafael David Tinoco
2019-01-24 13:18               ` Cyril Hrubis
2019-01-24 15:06         ` [LTP] [PATCH v3 1/6] tst_timer.h: add tst_timespect_rem_us() function Cyril Hrubis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181211142750.GA27159@rei \
    --to=chrubis@suse.cz \
    --cc=ltp@lists.linux.it \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.