[v3] tst: Provide test for timerfd related functions

Message ID 20210114154027.3240-1-lukma@denx.de
State Committed
Delegated to: Adhemerval Zanella Netto
Headers
Series [v3] tst: Provide test for timerfd related functions |

Commit Message

Lukasz Majewski Jan. 14, 2021, 3:40 p.m. UTC
  This change adds new test to assess functionality of timerfd_*
functions.
It creates new timer (operates on its file descriptor) and checks
if time before and after sleep is between expected values.

---
Changes for v2:
- Provide extra space before opening '(' in function calls and
  definitions
- Use the xclose instead of close
- Remove the abs(diff) call
- Refactor the code to replace tabs with spaces

Changes for v3:
- Use FAIL_EXIT where possible
- Remove not needed {}
---
 sysdeps/unix/sysv/linux/Makefile      |  3 +-
 sysdeps/unix/sysv/linux/tst-timerfd.c | 82 +++++++++++++++++++++++++++
 2 files changed, 84 insertions(+), 1 deletion(-)
 create mode 100644 sysdeps/unix/sysv/linux/tst-timerfd.c
  

Comments

Lukasz Majewski Feb. 3, 2021, 2:13 p.m. UTC | #1
Hi Florian,

> This change adds new test to assess functionality of timerfd_*
> functions.
> It creates new timer (operates on its file descriptor) and checks
> if time before and after sleep is between expected values.
> 
> ---
> Changes for v2:
> - Provide extra space before opening '(' in function calls and
>   definitions
> - Use the xclose instead of close
> - Remove the abs(diff) call
> - Refactor the code to replace tabs with spaces
> 
> Changes for v3:
> - Use FAIL_EXIT where possible
> - Remove not needed {}

Do you have any more comments regarding this patch? 

Is it eligible for pulling it to -master ?

> ---
>  sysdeps/unix/sysv/linux/Makefile      |  3 +-
>  sysdeps/unix/sysv/linux/tst-timerfd.c | 82
> +++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1
> deletion(-) create mode 100644 sysdeps/unix/sysv/linux/tst-timerfd.c
> 
> diff --git a/sysdeps/unix/sysv/linux/Makefile
> b/sysdeps/unix/sysv/linux/Makefile index 6df4779126..7503b356c8 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -107,7 +107,8 @@ tests += tst-clone tst-clone2 tst-clone3
> tst-fanotify tst-personality \ tst-quota tst-sync_file_range
> tst-sysconf-iov_max tst-ttyname \ test-errno-linux tst-memfd_create
> tst-mlock2 tst-pkey \ tst-rlimit-infinity tst-ofdlocks tst-gettid
> tst-gettid-kill \
> -	 tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux
> tst-sysvshm-linux
> +	 tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux
> tst-sysvshm-linux \
> +	 tst-timerfd
>  tests-internal += tst-ofdlocks-compat tst-sigcontext-get_pc
>  
>  CFLAGS-tst-sigcontext-get_pc.c = -fasynchronous-unwind-tables
> diff --git a/sysdeps/unix/sysv/linux/tst-timerfd.c
> b/sysdeps/unix/sysv/linux/tst-timerfd.c new file mode 100644
> index 0000000000..130650fca2
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/tst-timerfd.c
> @@ -0,0 +1,82 @@
> +/* Test for timerfd related functions
> +   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 <support/check.h>
> +#include <support/xunistd.h>
> +#include <sys/time.h>
> +#include <sys/timerfd.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +
> +static int
> +do_test (void)
> +{
> +  struct itimerspec settings = { { 2, 0 }, { 2, 0 } };
> +  struct itimerspec val1, val2;
> +  int fd, ret;
> +
> +  fd = timerfd_create (CLOCK_REALTIME, 0);
> +  if (fd < 0)
> +      FAIL_EXIT1 ("*** timerfd_create failed: %m");
> +
> +  /* Set the timer.  */
> +  ret = timerfd_settime (fd, 0, &settings, NULL);
> +  if (ret != 0)
> +    {
> +      xclose (fd);
> +      FAIL_EXIT1 ("*** timerfd_settime failed: %m\n");
> +    }
> +
> +  /* Read the timer just before sleep.  */
> +  ret = timerfd_gettime (fd, &val1);
> +  if (ret != 0)
> +    {
> +      xclose (fd);
> +      FAIL_EXIT1 ("*** timerfd_gettime failed: %m\n");
> +    }
> +
> +  /* Sleep for 1 second.  */
> +  ret = usleep (1000000);
> +  if (ret != 0)
> +    {
> +      xclose (fd);
> +      FAIL_EXIT1 ("*** usleep failed: %m\n");
> +    }
> +
> +  /* Read the timer just after sleep.  */
> +  ret = timerfd_gettime (fd, &val2);
> +  xclose (fd);
> +  if (ret != 0)
> +    FAIL_EXIT1 ("*** timerfd_gettime failed: %m\n");
> +
> +  /* Check difference between timerfd_gettime calls.  */
> +  long long int diff = val2.it_value.tv_sec - val1.it_value.tv_sec;
> +  diff *= 1000000000;
> +  diff += val2.it_value.tv_nsec - val1.it_value.tv_nsec;
> +  /* Subtrack time we have been sleeping (1s).  */
> +  diff -= 1000000000;
> +
> +  if (diff > 100000000)
> +    FAIL_EXIT1 ("*** The diff between timerfd calls (%lld) is
> wrong!\n", diff); +
> +  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
  
Adhemerval Zanella Feb. 3, 2021, 8:49 p.m. UTC | #2
On 14/01/2021 12:40, Lukasz Majewski wrote:
> This change adds new test to assess functionality of timerfd_*
> functions.
> It creates new timer (operates on its file descriptor) and checks
> if time before and after sleep is between expected values.
> 
> ---
> Changes for v2:
> - Provide extra space before opening '(' in function calls and
>   definitions
> - Use the xclose instead of close
> - Remove the abs(diff) call
> - Refactor the code to replace tabs with spaces
> 
> Changes for v3:
> - Use FAIL_EXIT where possible
> - Remove not needed {}

Ok with the fixed below.

> ---
>  sysdeps/unix/sysv/linux/Makefile      |  3 +-
>  sysdeps/unix/sysv/linux/tst-timerfd.c | 82 +++++++++++++++++++++++++++
>  2 files changed, 84 insertions(+), 1 deletion(-)
>  create mode 100644 sysdeps/unix/sysv/linux/tst-timerfd.c
> 
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 6df4779126..7503b356c8 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -107,7 +107,8 @@ tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
>  	 tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
>  	 test-errno-linux tst-memfd_create tst-mlock2 tst-pkey \
>  	 tst-rlimit-infinity tst-ofdlocks tst-gettid tst-gettid-kill \
> -	 tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux tst-sysvshm-linux
> +	 tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux tst-sysvshm-linux \
> +	 tst-timerfd
>  tests-internal += tst-ofdlocks-compat tst-sigcontext-get_pc
>  
>  CFLAGS-tst-sigcontext-get_pc.c = -fasynchronous-unwind-tables

Ok.

> diff --git a/sysdeps/unix/sysv/linux/tst-timerfd.c b/sysdeps/unix/sysv/linux/tst-timerfd.c
> new file mode 100644
> index 0000000000..130650fca2
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/tst-timerfd.c
> @@ -0,0 +1,82 @@
> +/* Test for timerfd related functions
> +   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 <support/check.h>
> +#include <support/xunistd.h>
> +#include <sys/time.h>
> +#include <sys/timerfd.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +
> +static int
> +do_test (void)
> +{
> +  struct itimerspec settings = { { 2, 0 }, { 2, 0 } };
> +  struct itimerspec val1, val2;
> +  int fd, ret;
> +
> +  fd = timerfd_create (CLOCK_REALTIME, 0);
> +  if (fd < 0)
> +      FAIL_EXIT1 ("*** timerfd_create failed: %m");
> +
> +  /* Set the timer.  */
> +  ret = timerfd_settime (fd, 0, &settings, NULL);
> +  if (ret != 0)
> +    {
> +      xclose (fd);

No need to close the file descriptor (the tests will exit anyway).
Same for the following xclose.

> +      FAIL_EXIT1 ("*** timerfd_settime failed: %m\n");
> +    }
> +
> +  /* Read the timer just before sleep.  */
> +  ret = timerfd_gettime (fd, &val1);
> +  if (ret != 0)
> +    {
> +      xclose (fd);
> +      FAIL_EXIT1 ("*** timerfd_gettime failed: %m\n");
> +    }> +
> +  /* Sleep for 1 second.  */
> +  ret = usleep (1000000);
> +  if (ret != 0)
> +    {
> +      xclose (fd);
> +      FAIL_EXIT1 ("*** usleep failed: %m\n");
> +    }
> +
> +  /* Read the timer just after sleep.  */
> +  ret = timerfd_gettime (fd, &val2);
> +  xclose (fd);
> +  if (ret != 0)
> +    FAIL_EXIT1 ("*** timerfd_gettime failed: %m\n");
> +
> +  /* Check difference between timerfd_gettime calls.  */
> +  long long int diff = val2.it_value.tv_sec - val1.it_value.tv_sec;
> +  diff *= 1000000000;
> +  diff += val2.it_value.tv_nsec - val1.it_value.tv_nsec;
> +  /* Subtrack time we have been sleeping (1s).  */
> +  diff -= 1000000000;
> +
> +  if (diff > 100000000)
> +    FAIL_EXIT1 ("*** The diff between timerfd calls (%lld) is wrong!\n", diff);

We have libsupport timespec helper functions to check for it:

  struct timespec r = timespec_sub (val2.it_value, val1.it_value);
  TEST_COMPARE (support_timespec_check_in_range ((struct timespec) { 1, 0 },
                                                 r, 1.0, 1.5), 0);

It assumes that the interval between timefd_gettime will be between 1s and
1.5s.  I think it should be a fair assumption, even for a high loaded
system.

> +
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>
>
  
Lukasz Majewski Feb. 4, 2021, 4:39 p.m. UTC | #3
Hi Adhemerval,

> On 14/01/2021 12:40, Lukasz Majewski wrote:
> > This change adds new test to assess functionality of timerfd_*
> > functions.
> > It creates new timer (operates on its file descriptor) and checks
> > if time before and after sleep is between expected values.
> > 
> > ---
> > Changes for v2:
> > - Provide extra space before opening '(' in function calls and
> >   definitions
> > - Use the xclose instead of close
> > - Remove the abs(diff) call
> > - Refactor the code to replace tabs with spaces
> > 
> > Changes for v3:
> > - Use FAIL_EXIT where possible
> > - Remove not needed {}  
> 
> Ok with the fixed below.
> 
> > ---
> >  sysdeps/unix/sysv/linux/Makefile      |  3 +-
> >  sysdeps/unix/sysv/linux/tst-timerfd.c | 82
> > +++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1
> > deletion(-) create mode 100644 sysdeps/unix/sysv/linux/tst-timerfd.c
> > 
> > diff --git a/sysdeps/unix/sysv/linux/Makefile
> > b/sysdeps/unix/sysv/linux/Makefile index 6df4779126..7503b356c8
> > 100644 --- a/sysdeps/unix/sysv/linux/Makefile
> > +++ b/sysdeps/unix/sysv/linux/Makefile
> > @@ -107,7 +107,8 @@ tests += tst-clone tst-clone2 tst-clone3
> > tst-fanotify tst-personality \ tst-quota tst-sync_file_range
> > tst-sysconf-iov_max tst-ttyname \ test-errno-linux tst-memfd_create
> > tst-mlock2 tst-pkey \ tst-rlimit-infinity tst-ofdlocks tst-gettid
> > tst-gettid-kill \
> > -	 tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux
> > tst-sysvshm-linux
> > +	 tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux
> > tst-sysvshm-linux \
> > +	 tst-timerfd
> >  tests-internal += tst-ofdlocks-compat tst-sigcontext-get_pc
> >  
> >  CFLAGS-tst-sigcontext-get_pc.c = -fasynchronous-unwind-tables  
> 
> Ok.
> 
> > diff --git a/sysdeps/unix/sysv/linux/tst-timerfd.c
> > b/sysdeps/unix/sysv/linux/tst-timerfd.c new file mode 100644
> > index 0000000000..130650fca2
> > --- /dev/null
> > +++ b/sysdeps/unix/sysv/linux/tst-timerfd.c
> > @@ -0,0 +1,82 @@
> > +/* Test for timerfd related functions
> > +   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 <support/check.h>
> > +#include <support/xunistd.h>
> > +#include <sys/time.h>
> > +#include <sys/timerfd.h>
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <unistd.h>
> > +
> > +static int
> > +do_test (void)
> > +{
> > +  struct itimerspec settings = { { 2, 0 }, { 2, 0 } };
> > +  struct itimerspec val1, val2;
> > +  int fd, ret;
> > +
> > +  fd = timerfd_create (CLOCK_REALTIME, 0);
> > +  if (fd < 0)
> > +      FAIL_EXIT1 ("*** timerfd_create failed: %m");
> > +
> > +  /* Set the timer.  */
> > +  ret = timerfd_settime (fd, 0, &settings, NULL);
> > +  if (ret != 0)
> > +    {
> > +      xclose (fd);  
> 
> No need to close the file descriptor (the tests will exit anyway).
> Same for the following xclose.

Ok, removed.

> 
> > +      FAIL_EXIT1 ("*** timerfd_settime failed: %m\n");
> > +    }
> > +
> > +  /* Read the timer just before sleep.  */
> > +  ret = timerfd_gettime (fd, &val1);
> > +  if (ret != 0)
> > +    {
> > +      xclose (fd);
> > +      FAIL_EXIT1 ("*** timerfd_gettime failed: %m\n");
> > +    }> +
> > +  /* Sleep for 1 second.  */
> > +  ret = usleep (1000000);
> > +  if (ret != 0)
> > +    {
> > +      xclose (fd);
> > +      FAIL_EXIT1 ("*** usleep failed: %m\n");
> > +    }
> > +
> > +  /* Read the timer just after sleep.  */
> > +  ret = timerfd_gettime (fd, &val2);
> > +  xclose (fd);
> > +  if (ret != 0)
> > +    FAIL_EXIT1 ("*** timerfd_gettime failed: %m\n");
> > +
> > +  /* Check difference between timerfd_gettime calls.  */
> > +  long long int diff = val2.it_value.tv_sec - val1.it_value.tv_sec;
> > +  diff *= 1000000000;
> > +  diff += val2.it_value.tv_nsec - val1.it_value.tv_nsec;
> > +  /* Subtrack time we have been sleeping (1s).  */
> > +  diff -= 1000000000;
> > +
> > +  if (diff > 100000000)
> > +    FAIL_EXIT1 ("*** The diff between timerfd calls (%lld) is
> > wrong!\n", diff);  
> 
> We have libsupport timespec helper functions to check for it:
> 
>   struct timespec r = timespec_sub (val2.it_value, val1.it_value);
>   TEST_COMPARE (support_timespec_check_in_range ((struct timespec) {
> 1, 0 }, r, 1.0, 1.5), 0);
> 
> It assumes that the interval between timefd_gettime will be between
> 1s and 1.5s.  I think it should be a fair assumption, even for a high
> loaded system.

Ok. I've fixed it.

> 
> > +
> > +  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
  

Patch

diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 6df4779126..7503b356c8 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -107,7 +107,8 @@  tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
 	 tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
 	 test-errno-linux tst-memfd_create tst-mlock2 tst-pkey \
 	 tst-rlimit-infinity tst-ofdlocks tst-gettid tst-gettid-kill \
-	 tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux tst-sysvshm-linux
+	 tst-tgkill tst-sysvsem-linux tst-sysvmsg-linux tst-sysvshm-linux \
+	 tst-timerfd
 tests-internal += tst-ofdlocks-compat tst-sigcontext-get_pc
 
 CFLAGS-tst-sigcontext-get_pc.c = -fasynchronous-unwind-tables
diff --git a/sysdeps/unix/sysv/linux/tst-timerfd.c b/sysdeps/unix/sysv/linux/tst-timerfd.c
new file mode 100644
index 0000000000..130650fca2
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-timerfd.c
@@ -0,0 +1,82 @@ 
+/* Test for timerfd related functions
+   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 <support/check.h>
+#include <support/xunistd.h>
+#include <sys/time.h>
+#include <sys/timerfd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static int
+do_test (void)
+{
+  struct itimerspec settings = { { 2, 0 }, { 2, 0 } };
+  struct itimerspec val1, val2;
+  int fd, ret;
+
+  fd = timerfd_create (CLOCK_REALTIME, 0);
+  if (fd < 0)
+      FAIL_EXIT1 ("*** timerfd_create failed: %m");
+
+  /* Set the timer.  */
+  ret = timerfd_settime (fd, 0, &settings, NULL);
+  if (ret != 0)
+    {
+      xclose (fd);
+      FAIL_EXIT1 ("*** timerfd_settime failed: %m\n");
+    }
+
+  /* Read the timer just before sleep.  */
+  ret = timerfd_gettime (fd, &val1);
+  if (ret != 0)
+    {
+      xclose (fd);
+      FAIL_EXIT1 ("*** timerfd_gettime failed: %m\n");
+    }
+
+  /* Sleep for 1 second.  */
+  ret = usleep (1000000);
+  if (ret != 0)
+    {
+      xclose (fd);
+      FAIL_EXIT1 ("*** usleep failed: %m\n");
+    }
+
+  /* Read the timer just after sleep.  */
+  ret = timerfd_gettime (fd, &val2);
+  xclose (fd);
+  if (ret != 0)
+    FAIL_EXIT1 ("*** timerfd_gettime failed: %m\n");
+
+  /* Check difference between timerfd_gettime calls.  */
+  long long int diff = val2.it_value.tv_sec - val1.it_value.tv_sec;
+  diff *= 1000000000;
+  diff += val2.it_value.tv_nsec - val1.it_value.tv_nsec;
+  /* Subtrack time we have been sleeping (1s).  */
+  diff -= 1000000000;
+
+  if (diff > 100000000)
+    FAIL_EXIT1 ("*** The diff between timerfd calls (%lld) is wrong!\n", diff);
+
+  return 0;
+}
+
+#include <support/test-driver.c>