[v2] tst: Add test for adjtime

Message ID 20210324130102.9752-1-lukma@denx.de
State Dropped
Delegated to: Adhemerval Zanella Netto
Headers
Series [v2] tst: Add test for adjtime |

Commit Message

Lukasz Majewski March 24, 2021, 1:01 p.m. UTC
  This code provides test to check if time on target machine is properly
adjusted.
The time is altered only when cross-test-ssh.sh is executed with
--allow-time-setting flag.

As the delta added to clock is only 1 sec the original time is not
restored and further tests are executed with this bias.

It is important to note that adjtime() adjusts the system time with
small amounts in each second (it is in fact a wrapper on clock_adjtime
with modes = ADJ_OFFSET_SINGLESHOT). In other words some seconds
(may be a random value) needs to elapse until the required time offset
is added to the clock. It may take considerable time (in minutes) to
adjust clock by e.g. 1 second.

To handle that the struct timeval odelta is passed to adjtime (NULL,
&odelta) to get information of the still required delta to be added
to clock. This is done in loop until its members are equal to 0.

As a reference - CLOCK_MONOTONIC is used to check if CLOCK_REALTIME
has been adjusted. The difference between them is measured.

---
Changes for v2:
- Correct code indentation
---
 sysdeps/unix/sysv/linux/Makefile      |  3 +-
 sysdeps/unix/sysv/linux/tst-adjtime.c | 83 +++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 1 deletion(-)
 create mode 100644 sysdeps/unix/sysv/linux/tst-adjtime.c
  

Comments

Lukasz Majewski March 31, 2021, 12:49 p.m. UTC | #1
Dear Community,

> This code provides test to check if time on target machine is properly
> adjusted.
> The time is altered only when cross-test-ssh.sh is executed with
> --allow-time-setting flag.
> 
> As the delta added to clock is only 1 sec the original time is not
> restored and further tests are executed with this bias.
> 
> It is important to note that adjtime() adjusts the system time with
> small amounts in each second (it is in fact a wrapper on clock_adjtime
> with modes = ADJ_OFFSET_SINGLESHOT). In other words some seconds
> (may be a random value) needs to elapse until the required time offset
> is added to the clock. It may take considerable time (in minutes) to
> adjust clock by e.g. 1 second.
> 
> To handle that the struct timeval odelta is passed to adjtime (NULL,
> &odelta) to get information of the still required delta to be added
> to clock. This is done in loop until its members are equal to 0.
> 
> As a reference - CLOCK_MONOTONIC is used to check if CLOCK_REALTIME
> has been adjusted. The difference between them is measured.
> 
> ---
> Changes for v2:
> - Correct code indentation
> ---

Gentle ping on this patch. Is this approach acceptable for testing
adjtime? 

>  sysdeps/unix/sysv/linux/Makefile      |  3 +-
>  sysdeps/unix/sysv/linux/tst-adjtime.c | 83
> +++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1
> deletion(-) create mode 100644 sysdeps/unix/sysv/linux/tst-adjtime.c
> 
> diff --git a/sysdeps/unix/sysv/linux/Makefile
> b/sysdeps/unix/sysv/linux/Makefile index ddc1e748e6..30c8629386 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -113,7 +113,8 @@ tests += tst-clone tst-clone2 tst-clone3
> tst-fanotify tst-personality \ tst-tgkill tst-sysvsem-linux
> tst-sysvmsg-linux tst-sysvshm-linux \ tst-timerfd tst-ppoll
> tst-futimens tst-utime tst-utimes \ tst-clock_adjtime tst-adjtimex
> tst-ntp_adjtime tst-ntp_gettime \
> -	 tst-ntp_gettimex tst-sigtimedwait tst-futimes tst-lutimes
> +	 tst-ntp_gettimex tst-sigtimedwait tst-futimes tst-lutimes \
> +	 tst-adjtime
>  
>  # Test for the symbol version of fcntl that was replaced in glibc
> 2.28. ifeq ($(have-GLIBC_2.27)$(build-shared),yesyes)
> diff --git a/sysdeps/unix/sysv/linux/tst-adjtime.c
> b/sysdeps/unix/sysv/linux/tst-adjtime.c new file mode 100644
> index 0000000000..4b24fcb890
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/tst-adjtime.c
> @@ -0,0 +1,83 @@
> +/* Test for adjtime.
> +   Copyright (C) 2021 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be
> useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <time.h>
> +#include <stdlib.h>
> +#include <sys/time.h>
> +#include <sys/timerfd.h>
> +#include <support/check.h>
> +#include <support/xunistd.h>
> +#include <support/timespec.h>
> +
> +#define TIMEOUT (60*10)
> +#define ADJTIME_LOOP_SLEEP 10000
> +
> +static int
> +do_test (void)
> +{
> +  struct timespec tv_then, tv_now, tv_then_m, tv_now_m;
> +  struct timeval delta, odelta;
> +  int ret;
> +
> +  /* Check if altering target time is allowed.  */
> +  if (getenv (SETTIME_ENV_NAME) == NULL)
> +    FAIL_UNSUPPORTED ("adjtime is executed only when "\
> +                      SETTIME_ENV_NAME" is set\n");
> +
> +  tv_then = xclock_now (CLOCK_REALTIME);
> +  tv_then_m = xclock_now (CLOCK_MONOTONIC);
> +
> +  /* Setup time value to adjust - 1 sec. */
> +  delta.tv_sec = 1;
> +  delta.tv_usec = 0;
> +
> +  ret = adjtime (&delta, NULL);
> +  if (ret == -1)
> +    FAIL_EXIT1 ("adjtime failed: %m\n");
> +
> +  /* As adjtime adjust clock time gradually by some small percentage
> +     of delta in each second one needs to check if this process has
> +     been finished.  */
> +  do
> +    {
> +      ret = adjtime (NULL, &odelta);
> +      if (ret == -1)
> +        FAIL_EXIT1 ("adjtime failed: %m\n");
> +
> +      ret = usleep (ADJTIME_LOOP_SLEEP);
> +      if (ret != 0)
> +        FAIL_EXIT1 ("usleep failed: %m\n");
> +    }
> +  while ( ! (odelta.tv_sec == 0 && odelta.tv_usec == 0));
> +
> +  tv_now = xclock_now (CLOCK_REALTIME);
> +  tv_now_m = xclock_now (CLOCK_MONOTONIC);
> +
> +  /* Check if adjtime adjusted the system time.  */
> +  struct timespec r = timespec_sub (tv_now, tv_then);
> +  struct timespec r_m = timespec_sub (tv_now_m, tv_then_m);
> +
> +  struct timespec r_adjtime = timespec_sub (r, r_m);
> +
> +  TEST_COMPARE (support_timespec_check_in_range
> +                ((struct timespec) { 1, 0 }, r_adjtime, 0.9, 1.1),
> 1); +
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Lukasz Majewski April 13, 2021, 8:28 a.m. UTC | #2
Dear Community,

> Dear Community,
> 
> > This code provides test to check if time on target machine is
> > properly adjusted.
> > The time is altered only when cross-test-ssh.sh is executed with
> > --allow-time-setting flag.
> > 
> > As the delta added to clock is only 1 sec the original time is not
> > restored and further tests are executed with this bias.
> > 
> > It is important to note that adjtime() adjusts the system time with
> > small amounts in each second (it is in fact a wrapper on
> > clock_adjtime with modes = ADJ_OFFSET_SINGLESHOT). In other words
> > some seconds (may be a random value) needs to elapse until the
> > required time offset is added to the clock. It may take
> > considerable time (in minutes) to adjust clock by e.g. 1 second.
> > 
> > To handle that the struct timeval odelta is passed to adjtime (NULL,
> > &odelta) to get information of the still required delta to be added
> > to clock. This is done in loop until its members are equal to 0.
> > 
> > As a reference - CLOCK_MONOTONIC is used to check if CLOCK_REALTIME
> > has been adjusted. The difference between them is measured.
> > 
> > ---
> > Changes for v2:
> > - Correct code indentation
> > ---  
> 
> Gentle ping on this patch. Is this approach acceptable for testing
> adjtime? 

Gentle ping on this patch...

> 
> >  sysdeps/unix/sysv/linux/Makefile      |  3 +-
> >  sysdeps/unix/sysv/linux/tst-adjtime.c | 83
> > +++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1
> > deletion(-) create mode 100644 sysdeps/unix/sysv/linux/tst-adjtime.c
> > 
> > diff --git a/sysdeps/unix/sysv/linux/Makefile
> > b/sysdeps/unix/sysv/linux/Makefile index ddc1e748e6..30c8629386
> > 100644 --- a/sysdeps/unix/sysv/linux/Makefile
> > +++ b/sysdeps/unix/sysv/linux/Makefile
> > @@ -113,7 +113,8 @@ tests += tst-clone tst-clone2 tst-clone3
> > tst-fanotify tst-personality \ tst-tgkill tst-sysvsem-linux
> > tst-sysvmsg-linux tst-sysvshm-linux \ tst-timerfd tst-ppoll
> > tst-futimens tst-utime tst-utimes \ tst-clock_adjtime tst-adjtimex
> > tst-ntp_adjtime tst-ntp_gettime \
> > -	 tst-ntp_gettimex tst-sigtimedwait tst-futimes tst-lutimes
> > +	 tst-ntp_gettimex tst-sigtimedwait tst-futimes tst-lutimes
> > \
> > +	 tst-adjtime
> >  
> >  # Test for the symbol version of fcntl that was replaced in glibc
> > 2.28. ifeq ($(have-GLIBC_2.27)$(build-shared),yesyes)
> > diff --git a/sysdeps/unix/sysv/linux/tst-adjtime.c
> > b/sysdeps/unix/sysv/linux/tst-adjtime.c new file mode 100644
> > index 0000000000..4b24fcb890
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/tst-adjtime.c
> > @@ -0,0 +1,83 @@
> > +/* Test for adjtime.
> > +   Copyright (C) 2021 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it
> > and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later
> > version. +
> > +   The GNU C Library is distributed in the hope that it will be
> > useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <time.h>
> > +#include <stdlib.h>
> > +#include <sys/time.h>
> > +#include <sys/timerfd.h>
> > +#include <support/check.h>
> > +#include <support/xunistd.h>
> > +#include <support/timespec.h>
> > +
> > +#define TIMEOUT (60*10)
> > +#define ADJTIME_LOOP_SLEEP 10000
> > +
> > +static int
> > +do_test (void)
> > +{
> > +  struct timespec tv_then, tv_now, tv_then_m, tv_now_m;
> > +  struct timeval delta, odelta;
> > +  int ret;
> > +
> > +  /* Check if altering target time is allowed.  */
> > +  if (getenv (SETTIME_ENV_NAME) == NULL)
> > +    FAIL_UNSUPPORTED ("adjtime is executed only when "\
> > +                      SETTIME_ENV_NAME" is set\n");
> > +
> > +  tv_then = xclock_now (CLOCK_REALTIME);
> > +  tv_then_m = xclock_now (CLOCK_MONOTONIC);
> > +
> > +  /* Setup time value to adjust - 1 sec. */
> > +  delta.tv_sec = 1;
> > +  delta.tv_usec = 0;
> > +
> > +  ret = adjtime (&delta, NULL);
> > +  if (ret == -1)
> > +    FAIL_EXIT1 ("adjtime failed: %m\n");
> > +
> > +  /* As adjtime adjust clock time gradually by some small
> > percentage
> > +     of delta in each second one needs to check if this process has
> > +     been finished.  */
> > +  do
> > +    {
> > +      ret = adjtime (NULL, &odelta);
> > +      if (ret == -1)
> > +        FAIL_EXIT1 ("adjtime failed: %m\n");
> > +
> > +      ret = usleep (ADJTIME_LOOP_SLEEP);
> > +      if (ret != 0)
> > +        FAIL_EXIT1 ("usleep failed: %m\n");
> > +    }
> > +  while ( ! (odelta.tv_sec == 0 && odelta.tv_usec == 0));
> > +
> > +  tv_now = xclock_now (CLOCK_REALTIME);
> > +  tv_now_m = xclock_now (CLOCK_MONOTONIC);
> > +
> > +  /* Check if adjtime adjusted the system time.  */
> > +  struct timespec r = timespec_sub (tv_now, tv_then);
> > +  struct timespec r_m = timespec_sub (tv_now_m, tv_then_m);
> > +
> > +  struct timespec r_adjtime = timespec_sub (r, r_m);
> > +
> > +  TEST_COMPARE (support_timespec_check_in_range
> > +                ((struct timespec) { 1, 0 }, r_adjtime, 0.9, 1.1),
> > 1); +
> > +  return 0;
> > +}
> > +
> > +#include <support/test-driver.c>  
> 
> 
> 
> 
> Best regards,
> 
> Lukasz Majewski
> 
> --
> 
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> lukma@denx.de



Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  
Lukasz Majewski May 6, 2021, 9:10 a.m. UTC | #3
On Wed, 31 Mar 2021 14:49:52 +0200
Lukasz Majewski <lukma@denx.de> wrote:

> Dear Community,
> 
> > This code provides test to check if time on target machine is
> > properly adjusted.
> > The time is altered only when cross-test-ssh.sh is executed with
> > --allow-time-setting flag.
> > 
> > As the delta added to clock is only 1 sec the original time is not
> > restored and further tests are executed with this bias.
> > 
> > It is important to note that adjtime() adjusts the system time with
> > small amounts in each second (it is in fact a wrapper on
> > clock_adjtime with modes = ADJ_OFFSET_SINGLESHOT). In other words
> > some seconds (may be a random value) needs to elapse until the
> > required time offset is added to the clock. It may take
> > considerable time (in minutes) to adjust clock by e.g. 1 second.
> > 
> > To handle that the struct timeval odelta is passed to adjtime (NULL,
> > &odelta) to get information of the still required delta to be added
> > to clock. This is done in loop until its members are equal to 0.
> > 
> > As a reference - CLOCK_MONOTONIC is used to check if CLOCK_REALTIME
> > has been adjusted. The difference between them is measured.
> > 
> > ---
> > Changes for v2:
> > - Correct code indentation
> > ---  
> 
> Gentle ping on this patch. Is this approach acceptable for testing
> adjtime? 

Gentle ping on this test.

> 
> >  sysdeps/unix/sysv/linux/Makefile      |  3 +-
> >  sysdeps/unix/sysv/linux/tst-adjtime.c | 83
> > +++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1
> > deletion(-) create mode 100644 sysdeps/unix/sysv/linux/tst-adjtime.c
> > 
> > diff --git a/sysdeps/unix/sysv/linux/Makefile
> > b/sysdeps/unix/sysv/linux/Makefile index ddc1e748e6..30c8629386
> > 100644 --- a/sysdeps/unix/sysv/linux/Makefile
> > +++ b/sysdeps/unix/sysv/linux/Makefile
> > @@ -113,7 +113,8 @@ tests += tst-clone tst-clone2 tst-clone3
> > tst-fanotify tst-personality \ tst-tgkill tst-sysvsem-linux
> > tst-sysvmsg-linux tst-sysvshm-linux \ tst-timerfd tst-ppoll
> > tst-futimens tst-utime tst-utimes \ tst-clock_adjtime tst-adjtimex
> > tst-ntp_adjtime tst-ntp_gettime \
> > -	 tst-ntp_gettimex tst-sigtimedwait tst-futimes tst-lutimes
> > +	 tst-ntp_gettimex tst-sigtimedwait tst-futimes tst-lutimes
> > \
> > +	 tst-adjtime
> >  
> >  # Test for the symbol version of fcntl that was replaced in glibc
> > 2.28. ifeq ($(have-GLIBC_2.27)$(build-shared),yesyes)
> > diff --git a/sysdeps/unix/sysv/linux/tst-adjtime.c
> > b/sysdeps/unix/sysv/linux/tst-adjtime.c new file mode 100644
> > index 0000000000..4b24fcb890
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/tst-adjtime.c
> > @@ -0,0 +1,83 @@
> > +/* Test for adjtime.
> > +   Copyright (C) 2021 Free Software Foundation, Inc.
> > +   This file is part of the GNU C Library.
> > +
> > +   The GNU C Library is free software; you can redistribute it
> > and/or
> > +   modify it under the terms of the GNU Lesser General Public
> > +   License as published by the Free Software Foundation; either
> > +   version 2.1 of the License, or (at your option) any later
> > version. +
> > +   The GNU C Library is distributed in the hope that it will be
> > useful,
> > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > GNU
> > +   Lesser General Public License for more details.
> > +
> > +   You should have received a copy of the GNU Lesser General Public
> > +   License along with the GNU C Library; if not, see
> > +   <https://www.gnu.org/licenses/>.  */
> > +
> > +#include <time.h>
> > +#include <stdlib.h>
> > +#include <sys/time.h>
> > +#include <sys/timerfd.h>
> > +#include <support/check.h>
> > +#include <support/xunistd.h>
> > +#include <support/timespec.h>
> > +
> > +#define TIMEOUT (60*10)
> > +#define ADJTIME_LOOP_SLEEP 10000
> > +
> > +static int
> > +do_test (void)
> > +{
> > +  struct timespec tv_then, tv_now, tv_then_m, tv_now_m;
> > +  struct timeval delta, odelta;
> > +  int ret;
> > +
> > +  /* Check if altering target time is allowed.  */
> > +  if (getenv (SETTIME_ENV_NAME) == NULL)
> > +    FAIL_UNSUPPORTED ("adjtime is executed only when "\
> > +                      SETTIME_ENV_NAME" is set\n");
> > +
> > +  tv_then = xclock_now (CLOCK_REALTIME);
> > +  tv_then_m = xclock_now (CLOCK_MONOTONIC);
> > +
> > +  /* Setup time value to adjust - 1 sec. */
> > +  delta.tv_sec = 1;
> > +  delta.tv_usec = 0;
> > +
> > +  ret = adjtime (&delta, NULL);
> > +  if (ret == -1)
> > +    FAIL_EXIT1 ("adjtime failed: %m\n");
> > +
> > +  /* As adjtime adjust clock time gradually by some small
> > percentage
> > +     of delta in each second one needs to check if this process has
> > +     been finished.  */
> > +  do
> > +    {
> > +      ret = adjtime (NULL, &odelta);
> > +      if (ret == -1)
> > +        FAIL_EXIT1 ("adjtime failed: %m\n");
> > +
> > +      ret = usleep (ADJTIME_LOOP_SLEEP);
> > +      if (ret != 0)
> > +        FAIL_EXIT1 ("usleep failed: %m\n");
> > +    }
> > +  while ( ! (odelta.tv_sec == 0 && odelta.tv_usec == 0));
> > +
> > +  tv_now = xclock_now (CLOCK_REALTIME);
> > +  tv_now_m = xclock_now (CLOCK_MONOTONIC);
> > +
> > +  /* Check if adjtime adjusted the system time.  */
> > +  struct timespec r = timespec_sub (tv_now, tv_then);
> > +  struct timespec r_m = timespec_sub (tv_now_m, tv_then_m);
> > +
> > +  struct timespec r_adjtime = timespec_sub (r, r_m);
> > +
> > +  TEST_COMPARE (support_timespec_check_in_range
> > +                ((struct timespec) { 1, 0 }, r_adjtime, 0.9, 1.1),
> > 1); +
> > +  return 0;
> > +}
> > +
> > +#include <support/test-driver.c>  
> 
> 
> 
> 
> Best regards,
> 
> Lukasz Majewski
> 
> --
> 
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> lukma@denx.de



Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
  

Patch

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index ddc1e748e6..30c8629386 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -113,7 +113,8 @@  tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
 	 tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux tst-sysvshm-linux \
 	 tst-timerfd tst-ppoll tst-futimens tst-utime tst-utimes \
 	 tst-clock_adjtime tst-adjtimex tst-ntp_adjtime tst-ntp_gettime \
-	 tst-ntp_gettimex tst-sigtimedwait tst-futimes tst-lutimes
+	 tst-ntp_gettimex tst-sigtimedwait tst-futimes tst-lutimes \
+	 tst-adjtime
 
 # Test for the symbol version of fcntl that was replaced in glibc 2.28.
 ifeq ($(have-GLIBC_2.27)$(build-shared),yesyes)
diff --git a/sysdeps/unix/sysv/linux/tst-adjtime.c b/sysdeps/unix/sysv/linux/tst-adjtime.c
new file mode 100644
index 0000000000..4b24fcb890
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-adjtime.c
@@ -0,0 +1,83 @@ 
+/* Test for adjtime.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <time.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/timerfd.h>
+#include <support/check.h>
+#include <support/xunistd.h>
+#include <support/timespec.h>
+
+#define TIMEOUT (60*10)
+#define ADJTIME_LOOP_SLEEP 10000
+
+static int
+do_test (void)
+{
+  struct timespec tv_then, tv_now, tv_then_m, tv_now_m;
+  struct timeval delta, odelta;
+  int ret;
+
+  /* Check if altering target time is allowed.  */
+  if (getenv (SETTIME_ENV_NAME) == NULL)
+    FAIL_UNSUPPORTED ("adjtime is executed only when "\
+                      SETTIME_ENV_NAME" is set\n");
+
+  tv_then = xclock_now (CLOCK_REALTIME);
+  tv_then_m = xclock_now (CLOCK_MONOTONIC);
+
+  /* Setup time value to adjust - 1 sec. */
+  delta.tv_sec = 1;
+  delta.tv_usec = 0;
+
+  ret = adjtime (&delta, NULL);
+  if (ret == -1)
+    FAIL_EXIT1 ("adjtime failed: %m\n");
+
+  /* As adjtime adjust clock time gradually by some small percentage
+     of delta in each second one needs to check if this process has
+     been finished.  */
+  do
+    {
+      ret = adjtime (NULL, &odelta);
+      if (ret == -1)
+        FAIL_EXIT1 ("adjtime failed: %m\n");
+
+      ret = usleep (ADJTIME_LOOP_SLEEP);
+      if (ret != 0)
+        FAIL_EXIT1 ("usleep failed: %m\n");
+    }
+  while ( ! (odelta.tv_sec == 0 && odelta.tv_usec == 0));
+
+  tv_now = xclock_now (CLOCK_REALTIME);
+  tv_now_m = xclock_now (CLOCK_MONOTONIC);
+
+  /* Check if adjtime adjusted the system time.  */
+  struct timespec r = timespec_sub (tv_now, tv_then);
+  struct timespec r_m = timespec_sub (tv_now_m, tv_then_m);
+
+  struct timespec r_adjtime = timespec_sub (r, r_m);
+
+  TEST_COMPARE (support_timespec_check_in_range
+                ((struct timespec) { 1, 0 }, r_adjtime, 0.9, 1.1), 1);
+
+  return 0;
+}
+
+#include <support/test-driver.c>