Re: [PATCH] getrusage: Add smoke test for getrusage
Adhemerval Zanella Netto <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.alpha |
|---|---|
| Organization | Linaro |
| Message-ID | <[email protected]> |
On 27/06/26 09:48, Ondrej Marek wrote: > Add smoke test verifying that getrusage returns non-negative user time and fails with invalid who value. > > Co-authored-by: Frantisek Cech <[email protected]> > Signed-off-by: Ondrej Marek <[email protected]> > --- > v2: > - use volatile variables to prevent compiler from optimizing away the loop > - RUSAGE_CHILDREN test forks new processes > - use both fields of timeval struct for elapsed time comparison > resource/Makefile | 1 + > resource/tst-getrusage.c | 139 +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 140 insertions(+) > create mode 100644 resource/tst-getrusage.c > > diff --git a/resource/Makefile b/resource/Makefile > index 589b73f44f..dac48434dd 100644 > --- a/resource/Makefile > +++ b/resource/Makefile > @@ -28,6 +28,7 @@ routines := getrlimit setrlimit getrlimit64 setrlimit64 getrusage ulimit \ > tests := \ > bug-ulimit1 \ > tst-getrlimit \ > + tst-getrusage \ > # tests > > > diff --git a/resource/tst-getrusage.c b/resource/tst-getrusage.c > new file mode 100644 > index 0000000000..c50456b9bc > --- /dev/null > +++ b/resource/tst-getrusage.c > @@ -0,0 +1,139 @@ > +/* Test of the getrusage function. > + Copyright (C) 2005-2026 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 <errno.h> > +#include <stdio.h> > +#include <sys/resource.h> > +#include <stdint.h> > +#include <support/check.h> > +#include <sys/types.h> > +#include <unistd.h> > +#include <sys/wait.h> > + > +static int > +get_child_elapsed_time (long *result) > +{ > + pid_t pid; > + pid = fork (); Use xfork here. > + > + if (pid == -1) > + { > + perror ("Fork failed"); > + return 1; > + } > + else if (pid > 0) > + { > + int status; > + if (waitpid (pid, &status, 0) == -1) > + { > + perror ("waitpid"); > + return 1; > + } And xwaitpid. > + > + if (!WIFEXITED (status)) > + { > + puts ("An error occured in the child process\n"); > + return 1; > + } And TEST_VERIFY_EXIT (WIFEXITED (status)); > + > + struct rusage rusage = { 0 }; > + > + int ret_val = getrusage (RUSAGE_CHILDREN, &rusage); > + TEST_VERIFY_EXIT (ret_val == 0); > + long elapsed_time = (rusage.ru_utime.tv_sec * 1000000L) + rusage.ru_utime.tv_usec; > + TEST_VERIFY_EXIT (elapsed_time >= 0); > + > + *result = elapsed_time; > + return 0; > + } > + else > + { > + /* Simulate some work */ > + volatile unsigned long long sink = 0; > + > + for (unsigned long long i = 0; i < 1000000000ULL; i++) { > + sink += i; > + } We have the macro DO_NOT_OPTIMIZE_OUT (benchtests/bench-util.h), which are used for similar constructs. Maybe move this to somewhere in include and do: uint64_t sink = 0; for (uint64_t i = 0; i < UINT64_C(1000000000); i++) { sink += i; DO_NOT_OPTIMIZE_OUT (sink); } > + > + _exit(0); > + } > +} > + > +static void > +test_getrusage_children (void) > +{ > + long elapsed_time_before; > + long elapsed_time_after; > + > + int ret_val = get_child_elapsed_time (&elapsed_time_before); > + TEST_VERIFY_EXIT (ret_val == 0); > + int ret_val2 = get_child_elapsed_time (&elapsed_time_after); > + TEST_VERIFY_EXIT (ret_val2 == 0); > + TEST_VERIFY_EXIT (elapsed_time_after >= elapsed_time_before); > +} > + > +static void > +test_getrusage (int who) > +{ > + struct rusage before_usage = { 0 }; > + struct rusage after_usage = { 0 }; > + > + int ret_val = getrusage (who, &before_usage); > + TEST_VERIFY_EXIT (ret_val == 0); > + long elapsed_time_before = (before_usage.ru_utime.tv_sec * 1000000L) + before_usage.ru_utime.tv_usec; Line too long, use clang-format with the .clang-format we now have. > + TEST_VERIFY_EXIT (elapsed_time_before >= 0); > + > + /* Simulate some work */ > + volatile unsigned long long sink = 0; > + > + for (unsigned long long i = 0; i < 1000000000ULL; i++) > + { > + sink += i; > + } > + > + int ret_val2 = getrusage (who, &after_usage); > + TEST_VERIFY_EXIT (ret_val2 == 0); > + > + long elapsed_time_after = (after_usage.ru_utime.tv_sec * 1000000L) + after_usage.ru_utime.tv_usec; > + TEST_VERIFY_EXIT (elapsed_time_after >= elapsed_time_before); > +} > + > +static int > +do_test (void) > +{ > + int whos[] = { RUSAGE_SELF, RUSAGE_THREAD }; > + for (int i = 0; i < sizeof (whos) / sizeof (int); i++) Use array_length (...). > + { > + int who = whos[i]; > + test_getrusage (who); > + } > + > + /* RUSAGE_CHILDREN test case with forking children */ > + test_getrusage_children (); > + > + /* Invalid who value test case */ > + struct rusage usage_struct = { 0 }; > + int invalid_who = 999; > + int ret_val = getrusage (invalid_who, &usage_struct); > + TEST_VERIFY (ret_val == -1); > + > + puts ("Everything OK\n"); > + return 0; > +} > + > +#include <support/test-driver.c> The rest looks ok.