(root)/
findutils-4.9.0/
gnulib-tests/
test-timespec.c
       1  /* Test timespec functions.
       2     Copyright 2015-2022 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 <stdbool.h>
      27  #include <limits.h>
      28  
      29  static struct { int s; int ns; } const prototype[] =
      30    {
      31      { INT_MIN, 0 },
      32      { INT_MIN, 1 },
      33      { INT_MIN, TIMESPEC_HZ - 1 },
      34      { INT_MIN + 1, 0 },
      35      { INT_MIN + 1, 1 },
      36      { INT_MIN + 1, TIMESPEC_HZ - 1 },
      37      { -1, 0 },
      38      { -1, 1 },
      39      { -1, TIMESPEC_HZ - 1 },
      40      { 0, 0 },
      41      { 0, 1 },
      42      { 0, TIMESPEC_HZ - 1 },
      43      { 1, 0 },
      44      { 1, 1 },
      45      { 1, TIMESPEC_HZ - 1 },
      46      { 1234567890, 0 },
      47      { 1234567890, 1 },
      48      { 1234567890, TIMESPEC_HZ - 1 },
      49      { INT_MAX - 1, 0 },
      50      { INT_MAX - 1, 1 },
      51      { INT_MAX - 1, TIMESPEC_HZ - 1 },
      52      { INT_MAX, 0 },
      53      { INT_MAX, 1 },
      54      { INT_MAX, TIMESPEC_HZ - 1 },
      55      { INT_MAX, 2 * TIMESPEC_HZ }
      56    };
      57  enum { nprototypes = sizeof prototype / sizeof *prototype };
      58  
      59  static bool
      60  valid (struct timespec a)
      61  {
      62    return 0 <= a.tv_nsec && a.tv_nsec < TIMESPEC_HZ;
      63  }
      64  
      65  static int
      66  sign (int i)
      67  {
      68    return i < 0 ? -1 : 0 < i;
      69  }
      70  
      71  static int
      72  cmp (struct timespec a, struct timespec b)
      73  {
      74    return sign (timespec_cmp (a, b));
      75  }
      76  
      77  static bool
      78  eq (struct timespec a, struct timespec b)
      79  {
      80    return timespec_cmp (a, b) == 0;
      81  }
      82  
      83  static bool
      84  extremal (struct timespec a)
      85  {
      86    return ((a.tv_sec == TYPE_MINIMUM (time_t) && a.tv_nsec == 0)
      87            || (a.tv_sec == TYPE_MAXIMUM (time_t)
      88                && a.tv_nsec == TIMESPEC_HZ - 1));
      89  }
      90  
      91  int
      92  main (void)
      93  {
      94    int i, j, k;
      95    struct timespec test[nprototypes + 1];
      96    int ntests;
      97    int computed_hz = 1;
      98    struct timespec prevroundtrip;
      99  
     100    test[0] = make_timespec (TYPE_MINIMUM (time_t), -1);
     101    ntests = 1;
     102    for (i = 0; i < nprototypes; i++)
     103      {
     104        int s = prototype[i].s;
     105        if (TYPE_SIGNED (time_t) || 0 <= s)
     106          {
     107            time_t t = (s <= INT_MIN + 1 ? s - INT_MIN + TYPE_MINIMUM (time_t)
     108                        : INT_MAX - 1 <= s ? s - INT_MAX + TYPE_MAXIMUM (time_t)
     109                        : s);
     110            test[ntests++] = make_timespec (t, prototype[i].ns);
     111          }
     112      }
     113  
     114    for (i = 0; i < LOG10_TIMESPEC_HZ; i++)
     115      computed_hz *= 10;
     116    ASSERT (computed_hz == TIMESPEC_HZ);
     117  
     118    for (i = 0; i < ntests; i++)
     119      {
     120        struct timespec a = test[i];
     121  
     122        struct timespec roundtrip = dtotimespec (timespectod (a));
     123        if (i != 0)
     124          ASSERT (cmp (prevroundtrip, roundtrip) <= 0);
     125        prevroundtrip = roundtrip;
     126  
     127        ASSERT (sign (timespec_sign (a)) == cmp (a, make_timespec (0, 0)));
     128  
     129        if (valid (a))
     130          for (j = 0; j < ntests; j++)
     131            {
     132              struct timespec b = test[j];
     133              if (valid (b))
     134                {
     135                  struct timespec sum = timespec_add (a, b);
     136                  struct timespec diff = timespec_sub (a, b);
     137                  struct timespec rdiff = timespec_sub (b, a);
     138                  ASSERT (cmp (a, b) == sign (i - j));
     139                  ASSERT (eq (sum, timespec_add (b, a)));
     140                  if (! extremal (sum))
     141                    {
     142                      ASSERT (eq (a, timespec_sub (sum, b)));
     143                      ASSERT (eq (b, timespec_sub (sum, a)));
     144  
     145                      for (k = 0; k < ntests; k++)
     146                        {
     147                          struct timespec c = test[k];
     148                          if (valid (c))
     149                            {
     150                              struct timespec sumbc = timespec_add (b, c);
     151                              if (! extremal (sumbc))
     152                                ASSERT (eq (timespec_add (a, sumbc),
     153                                            timespec_add (sum, c)));
     154                            }
     155                        }
     156                    }
     157                  if (! extremal (diff))
     158                    ASSERT (eq (a, timespec_add (diff, b)));
     159                  if (! extremal (rdiff))
     160                    ASSERT (eq (b, timespec_add (rdiff, a)));
     161  
     162                }
     163            }
     164      }
     165  
     166    return 0;
     167  }