(root)/
coreutils-9.4/
gnulib-tests/
test-timespec.c
       1  /* Test timespec functions.
       2     Copyright 2015-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Written by Paul Eggert.  */
      18  
      19  #include <config.h>
      20  
      21  #include "timespec.h"
      22  
      23  #include "intprops.h"
      24  #include "macros.h"
      25  
      26  #include <limits.h>
      27  
      28  static struct { int s; int ns; } const prototype[] =
      29    {
      30      { INT_MIN, 0 },
      31      { INT_MIN, 1 },
      32      { INT_MIN, TIMESPEC_HZ - 1 },
      33      { INT_MIN + 1, 0 },
      34      { INT_MIN + 1, 1 },
      35      { INT_MIN + 1, TIMESPEC_HZ - 1 },
      36      { -1, 0 },
      37      { -1, 1 },
      38      { -1, TIMESPEC_HZ - 1 },
      39      { 0, 0 },
      40      { 0, 1 },
      41      { 0, TIMESPEC_HZ - 1 },
      42      { 1, 0 },
      43      { 1, 1 },
      44      { 1, TIMESPEC_HZ - 1 },
      45      { 1234567890, 0 },
      46      { 1234567890, 1 },
      47      { 1234567890, TIMESPEC_HZ - 1 },
      48      { INT_MAX - 1, 0 },
      49      { INT_MAX - 1, 1 },
      50      { INT_MAX - 1, TIMESPEC_HZ - 1 },
      51      { INT_MAX, 0 },
      52      { INT_MAX, 1 },
      53      { INT_MAX, TIMESPEC_HZ - 1 },
      54      { INT_MAX, 2 * TIMESPEC_HZ }
      55    };
      56  enum { nprototypes = sizeof prototype / sizeof *prototype };
      57  
      58  static bool
      59  valid (struct timespec a)
      60  {
      61    return 0 <= a.tv_nsec && a.tv_nsec < TIMESPEC_HZ;
      62  }
      63  
      64  static int
      65  sign (int i)
      66  {
      67    return i < 0 ? -1 : 0 < i;
      68  }
      69  
      70  static int
      71  cmp (struct timespec a, struct timespec b)
      72  {
      73    return sign (timespec_cmp (a, b));
      74  }
      75  
      76  static bool
      77  eq (struct timespec a, struct timespec b)
      78  {
      79    return timespec_cmp (a, b) == 0;
      80  }
      81  
      82  static bool
      83  extremal (struct timespec a)
      84  {
      85    return ((a.tv_sec == TYPE_MINIMUM (time_t) && a.tv_nsec == 0)
      86            || (a.tv_sec == TYPE_MAXIMUM (time_t)
      87                && a.tv_nsec == TIMESPEC_HZ - 1));
      88  }
      89  
      90  int
      91  main (void)
      92  {
      93    int i, j, k;
      94    struct timespec test[nprototypes + 1];
      95    int ntests;
      96    int computed_hz = 1;
      97    struct timespec prevroundtrip;
      98  
      99    test[0] = make_timespec (TYPE_MINIMUM (time_t), -1);
     100    ntests = 1;
     101    for (i = 0; i < nprototypes; i++)
     102      {
     103        int s = prototype[i].s;
     104        if (TYPE_SIGNED (time_t) || 0 <= s)
     105          {
     106            time_t t = (s <= INT_MIN + 1 ? s - INT_MIN + TYPE_MINIMUM (time_t)
     107                        : INT_MAX - 1 <= s ? s - INT_MAX + TYPE_MAXIMUM (time_t)
     108                        : s);
     109            test[ntests++] = make_timespec (t, prototype[i].ns);
     110          }
     111      }
     112  
     113    for (i = 0; i < LOG10_TIMESPEC_HZ; i++)
     114      computed_hz *= 10;
     115    ASSERT (computed_hz == TIMESPEC_HZ);
     116  
     117    for (i = 0; i < ntests; i++)
     118      {
     119        struct timespec a = test[i];
     120  
     121        struct timespec roundtrip = dtotimespec (timespectod (a));
     122        if (i != 0)
     123          ASSERT (cmp (prevroundtrip, roundtrip) <= 0);
     124        prevroundtrip = roundtrip;
     125  
     126        ASSERT (sign (timespec_sign (a)) == cmp (a, make_timespec (0, 0)));
     127  
     128        if (valid (a))
     129          for (j = 0; j < ntests; j++)
     130            {
     131              struct timespec b = test[j];
     132              if (valid (b))
     133                {
     134                  struct timespec sum = timespec_add (a, b);
     135                  struct timespec diff = timespec_sub (a, b);
     136                  struct timespec rdiff = timespec_sub (b, a);
     137                  ASSERT (cmp (a, b) == sign (i - j));
     138                  ASSERT (eq (sum, timespec_add (b, a)));
     139                  if (! extremal (sum))
     140                    {
     141                      ASSERT (eq (a, timespec_sub (sum, b)));
     142                      ASSERT (eq (b, timespec_sub (sum, a)));
     143  
     144                      for (k = 0; k < ntests; k++)
     145                        {
     146                          struct timespec c = test[k];
     147                          if (valid (c))
     148                            {
     149                              struct timespec sumbc = timespec_add (b, c);
     150                              if (! extremal (sumbc))
     151                                ASSERT (eq (timespec_add (a, sumbc),
     152                                            timespec_add (sum, c)));
     153                            }
     154                        }
     155                    }
     156                  if (! extremal (diff))
     157                    ASSERT (eq (a, timespec_add (diff, b)));
     158                  if (! extremal (rdiff))
     159                    ASSERT (eq (b, timespec_add (rdiff, a)));
     160  
     161                }
     162            }
     163      }
     164  
     165    return 0;
     166  }