LCOV - code coverage report
Current view: top level - test - test_duration.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 175 175 100.0 %
Date: 2026-07-14 21:28:07 Functions: 7 7 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 33 54 61.1 %

           Branch data     Line data    Source code
       1                 :            : // Copyright 2011-2025 David Robillard <d@drobilla.net>
       2                 :            : // SPDX-License-Identifier: ISC
       3                 :            : 
       4                 :            : #undef NDEBUG
       5                 :            : 
       6                 :            : #include "int_test_utils.h"
       7                 :            : #include "num_test_utils.h"
       8                 :            : #include "write_test_utils.h"
       9                 :            : 
      10                 :            : #include <exess/exess.h>
      11                 :            : 
      12                 :            : #include <assert.h>
      13                 :            : #include <stdbool.h>
      14                 :            : #include <stdint.h>
      15                 :            : #include <stdio.h>
      16                 :            : #include <string.h>
      17                 :            : 
      18                 :            : static const ExessDuration zero       = {0, 0, 0};
      19                 :            : static const ExessDuration lowest     = {-INT32_MAX, -INT32_MAX, -999999999};
      20                 :            : static const ExessDuration highest    = {INT32_MAX, INT32_MAX, 999999999};
      21                 :            : static const ExessDuration longest    = {-2119579475, -1093803875, -999999999};
      22                 :            : static const ExessDuration longest_ym = {-2119579475, 0, 0};
      23                 :            : static const ExessDuration longest_dt = {0, -1093803875, -999999999};
      24                 :            : static const ExessDuration year       = {12, 0, 0};
      25                 :            : static const ExessDuration month      = {1, 0, 0};
      26                 :            : static const ExessDuration day        = {0, 24 * 60 * 60, 0};
      27                 :            : static const ExessDuration hour       = {0, 60 * 60, 0};
      28                 :            : static const ExessDuration minute     = {0, 60, 0};
      29                 :            : static const ExessDuration second     = {0, 1, 0};
      30                 :            : static const ExessDuration nanosecond = {0, 0, 1};
      31                 :            : 
      32                 :            : static const ExessDuration n_year       = {-12, 0, 0};
      33                 :            : static const ExessDuration n_month      = {-1, 0, 0};
      34                 :            : static const ExessDuration n_day        = {0, -24 * 60 * 60, 0};
      35                 :            : static const ExessDuration n_hour       = {0, -60 * 60, 0};
      36                 :            : static const ExessDuration n_minute     = {0, -60, 0};
      37                 :            : static const ExessDuration n_second     = {0, -1, 0};
      38                 :            : static const ExessDuration n_nanosecond = {0, 0, -1};
      39                 :            : 
      40                 :            : static const ExessDuration garbage1 = {1, 1, -1};
      41                 :            : static const ExessDuration garbage2 = {1, -1, 1};
      42                 :            : static const ExessDuration garbage3 = {1, -1, -1};
      43                 :            : static const ExessDuration garbage4 = {-1, 1, 1};
      44                 :            : static const ExessDuration garbage5 = {-1, 1, -1};
      45                 :            : static const ExessDuration garbage6 = {-1, -1, 1};
      46                 :            : static const ExessDuration garbage7 = {INT32_MIN, 0, -999999999};
      47                 :            : static const ExessDuration garbage8 = {0, INT32_MIN, -999999999};
      48                 :            : static const ExessDuration garbage9 = {INT32_MIN, INT32_MIN, -999999999};
      49                 :            : 
      50                 :            : static void
      51                 :         69 : check_read(const char* const string,
      52                 :            :            const ExessStatus expected_status,
      53                 :            :            const size_t      expected_count,
      54                 :            :            const int32_t     expected_years,
      55                 :            :            const int32_t     expected_months,
      56                 :            :            const int32_t     expected_days,
      57                 :            :            const int32_t     expected_hours,
      58                 :            :            const int32_t     expected_minutes,
      59                 :            :            const int32_t     expected_seconds,
      60                 :            :            const int32_t     expected_nanoseconds,
      61                 :            :            const bool        expected_is_negative)
      62                 :            : {
      63                 :         69 :   ExessDuration     value = {0, 0, 0};
      64                 :         69 :   const ExessResult r     = exess_read_duration(string, &value);
      65                 :            : 
      66         [ -  + ]:         69 :   assert(r.status == expected_status);
      67         [ -  + ]:         69 :   assert(r.count == expected_count);
      68                 :            : 
      69   [ +  +  -  + ]:         69 :   assert(value.months ==
      70                 :            :          ((expected_is_negative ? -1 : 1) * 12 * expected_years) +
      71                 :            :            expected_months);
      72                 :            : 
      73   [ +  +  -  + ]:         69 :   assert(value.seconds ==
      74                 :            :          (expected_is_negative ? -1 : 1) *
      75                 :            :            ((expected_seconds + (60 * expected_minutes) +
      76                 :            :              (60 * 60 * expected_hours) + (24 * 60 * 60 * expected_days))));
      77                 :            : 
      78         [ -  + ]:         69 :   assert(value.nanoseconds == expected_nanoseconds);
      79                 :         69 : }
      80                 :            : 
      81                 :            : static void
      82                 :          1 : test_read_duration(void)
      83                 :            : {
      84                 :            :   // No input
      85                 :          1 :   check_read("", EXESS_EXPECTED_DURATION, 0, 0, 0, 0, 0, 0, 0, 0, false);
      86                 :          1 :   check_read("\t\n\r ", EXESS_EXPECTED_DURATION, 4, 0, 0, 0, 0, 0, 0, 0, false);
      87                 :            : 
      88                 :            :   // Good values
      89                 :            : 
      90                 :          1 :   check_read(
      91                 :            :     "P2Y6M5DT12H35M30S", EXESS_SUCCESS, 17, 2, 6, 5, 12, 35, 30, 0, false);
      92                 :            : 
      93                 :          1 :   check_read("P1DT2H", EXESS_SUCCESS, 6, 0, 0, 1, 2, 0, 0, 0, false);
      94                 :          1 :   check_read("P20M", EXESS_SUCCESS, 4, 0, 20, 0, 0, 0, 0, 0, false);
      95                 :          1 :   check_read("PT20M", EXESS_SUCCESS, 5, 0, 0, 0, 0, 20, 0, 0, false);
      96                 :          1 :   check_read("P0Y20M0D", EXESS_SUCCESS, 8, 0, 20, 0, 0, 0, 0, 0, false);
      97                 :          1 :   check_read("P0Y", EXESS_SUCCESS, 3, 0, 0, 0, 0, 0, 0, 0, false);
      98                 :          1 :   check_read("-P60D", EXESS_SUCCESS, 5, 0, 0, 60, 0, 0, 0, 0, true);
      99                 :          1 :   check_read(
     100                 :            :     "PT1M30.5S", EXESS_SUCCESS, 9, 0, 0, 0, 0, 1, 30, 500000000, false);
     101                 :            : 
     102                 :            :   // Leading and trailing whitespace
     103                 :          1 :   check_read("\t\n\r P1Y", EXESS_SUCCESS, 7, 1, 0, 0, 0, 0, 0, 0, false);
     104                 :          1 :   check_read("P1MT2H\t\n\r ", EXESS_SUCCESS, 6, 0, 1, 0, 2, 0, 0, 0, false);
     105                 :          1 :   check_read("\t\n\r P1Y", EXESS_SUCCESS, 7, 1, 0, 0, 0, 0, 0, 0, false);
     106                 :          1 :   check_read("P1YT2H\t\n\r ", EXESS_SUCCESS, 6, 1, 0, 0, 2, 0, 0, 0, false);
     107                 :            : 
     108                 :            :   // Non-canonical form
     109                 :          1 :   check_read("P06D", EXESS_SUCCESS, 4, 0, 0, 6, 0, 0, 0, 0, false);
     110                 :          1 :   check_read("PT7.0S", EXESS_SUCCESS, 6, 0, 0, 0, 0, 0, 7, 0, false);
     111                 :          1 :   check_read(
     112                 :            :     "P0Y0M01DT06H00M00S", EXESS_SUCCESS, 18, 0, 0, 1, 6, 0, 0, 0, false);
     113                 :            : 
     114                 :            :   // Maximum field values
     115                 :          1 :   check_read(
     116                 :            :     "P178956970Y", EXESS_SUCCESS, 11, 178956970, 0, 0, 0, 0, 0, 0, false);
     117                 :          1 :   check_read(
     118                 :            :     "P2147483646M", EXESS_SUCCESS, 12, 0, 2147483646, 0, 0, 0, 0, 0, false);
     119                 :          1 :   check_read("P24855D", EXESS_SUCCESS, 7, 0, 0, 24855, 0, 0, 0, 0, false);
     120                 :          1 :   check_read("PT596523H", EXESS_SUCCESS, 9, 0, 0, 0, 596523, 0, 0, 0, false);
     121                 :          1 :   check_read(
     122                 :            :     "PT35791394M", EXESS_SUCCESS, 11, 0, 0, 0, 0, 35791394, 0, 0, false);
     123                 :          1 :   check_read(
     124                 :            :     "PT2147483646S", EXESS_SUCCESS, 13, 0, 0, 0, 0, 0, 2147483646, 0, false);
     125                 :          1 :   check_read(
     126                 :            :     "PT0.999999999S", EXESS_SUCCESS, 14, 0, 0, 0, 0, 0, 0, 999999999, false);
     127                 :            : 
     128                 :            :   // Out of range fields
     129                 :          1 :   check_read("P178956971Y", EXESS_OUT_OF_RANGE, 11, 0, 0, 0, 0, 0, 0, 0, false);
     130                 :          1 :   check_read(
     131                 :            :     "P2147483647M", EXESS_OUT_OF_RANGE, 12, 0, 0, 0, 0, 0, 0, 0, false);
     132                 :          1 :   check_read("P24856D", EXESS_OUT_OF_RANGE, 7, 0, 0, 0, 0, 0, 0, 0, false);
     133                 :          1 :   check_read("PT596524H", EXESS_OUT_OF_RANGE, 9, 0, 0, 0, 0, 0, 0, 0, false);
     134                 :          1 :   check_read("PT35791395M", EXESS_OUT_OF_RANGE, 11, 0, 0, 0, 0, 0, 0, 0, false);
     135                 :          1 :   check_read(
     136                 :            :     "PT2147483647S", EXESS_OUT_OF_RANGE, 13, 0, 0, 0, 0, 0, 0, 0, false);
     137                 :          1 :   check_read("PT0.1000000000S",
     138                 :            :              EXESS_EXPECTED_SECOND_TAG,
     139                 :            :              13,
     140                 :            :              0,
     141                 :            :              0,
     142                 :            :              0,
     143                 :            :              0,
     144                 :            :              0,
     145                 :            :              0,
     146                 :            :              0,
     147                 :            :              false);
     148                 :            : 
     149                 :            :   // Repeated fields
     150                 :          1 :   check_read("P1Y2Y", EXESS_BAD_ORDER, 5, 1, 0, 0, 0, 0, 0, 0, false);
     151                 :          1 :   check_read("P1M2M", EXESS_BAD_ORDER, 5, 0, 1, 0, 0, 0, 0, 0, false);
     152                 :          1 :   check_read("PT1H2H", EXESS_BAD_ORDER, 6, 0, 0, 0, 1, 0, 0, 0, false);
     153                 :          1 :   check_read("PT1M2M", EXESS_BAD_ORDER, 6, 0, 0, 0, 0, 1, 0, 0, false);
     154                 :            : 
     155                 :            :   // Trailing garbage
     156                 :          1 :   check_read("P1YM5D", EXESS_SUCCESS, 3, 1, 0, 0, 0, 0, 0, 0, false);
     157                 :          1 :   check_read("PT1S2", EXESS_SUCCESS, 4, 0, 0, 0, 0, 0, 1, 0, false);
     158                 :            : 
     159                 :            :   // Out of range fields
     160                 :          1 :   check_read("P18446744073709551616Y",
     161                 :            :              EXESS_OUT_OF_RANGE,
     162                 :            :              20,
     163                 :            :              0,
     164                 :            :              0,
     165                 :            :              0,
     166                 :            :              0,
     167                 :            :              0,
     168                 :            :              0,
     169                 :            :              0,
     170                 :            :              false);
     171                 :          1 :   check_read("PT18446744073709551616H",
     172                 :            :              EXESS_OUT_OF_RANGE,
     173                 :            :              21,
     174                 :            :              0,
     175                 :            :              0,
     176                 :            :              0,
     177                 :            :              0,
     178                 :            :              0,
     179                 :            :              0,
     180                 :            :              0,
     181                 :            :              false);
     182                 :            : 
     183                 :            :   // Garbage
     184                 :          1 :   check_read("P-20M", EXESS_EXPECTED_DIGIT, 1, 0, 0, 0, 0, 0, 0, 0, false);
     185                 :          1 :   check_read("P20MT", EXESS_EXPECTED_DIGIT, 5, 0, 20, 0, 0, 0, 0, 0, false);
     186                 :          1 :   check_read("P15.5Y", EXESS_EXPECTED_DATE_TAG, 3, 0, 0, 0, 0, 0, 0, 0, false);
     187                 :          1 :   check_read("P1.5Y", EXESS_EXPECTED_DATE_TAG, 2, 0, 0, 0, 0, 0, 0, 0, false);
     188                 :          1 :   check_read("P1.5M", EXESS_EXPECTED_DATE_TAG, 2, 0, 0, 0, 0, 0, 0, 0, false);
     189                 :          1 :   check_read("P1.5D", EXESS_EXPECTED_DATE_TAG, 2, 0, 0, 0, 0, 0, 0, 0, false);
     190                 :          1 :   check_read(
     191                 :            :     "PT1.5H", EXESS_EXPECTED_SECOND_TAG, 5, 0, 0, 0, 0, 0, 0, 0, false);
     192                 :          1 :   check_read(
     193                 :            :     "PT1.5M", EXESS_EXPECTED_SECOND_TAG, 5, 0, 0, 0, 0, 0, 0, 0, false);
     194                 :          1 :   check_read("P1D2H", EXESS_SUCCESS, 3, 0, 0, 1, 0, 0, 0, 0, false);
     195                 :          1 :   check_read("1Y2M", EXESS_EXPECTED_DURATION, 0, 0, 0, 0, 0, 0, 0, 0, false);
     196                 :          1 :   check_read("P2M1Y", EXESS_BAD_ORDER, 5, 0, 2, 0, 0, 0, 0, 0, false);
     197                 :          1 :   check_read("P2D1Y", EXESS_SUCCESS, 3, 0, 0, 2, 0, 0, 0, 0, false);
     198                 :          1 :   check_read("P", EXESS_EXPECTED_DIGIT, 1, 0, 0, 0, 0, 0, 0, 0, false);
     199                 :          1 :   check_read(
     200                 :            :     "PT15.5H", EXESS_EXPECTED_SECOND_TAG, 6, 0, 0, 0, 0, 0, 0, 0, false);
     201                 :          1 :   check_read("PT2M1H", EXESS_BAD_ORDER, 6, 0, 0, 0, 0, 2, 0, 0, false);
     202                 :          1 :   check_read("PT15.S", EXESS_EXPECTED_DIGIT, 5, 0, 0, 0, 0, 0, 0, 0, false);
     203                 :          1 :   check_read("P1Q", EXESS_EXPECTED_DATE_TAG, 2, 0, 0, 0, 0, 0, 0, 0, false);
     204                 :          1 :   check_read("PT1Q", EXESS_EXPECTED_TIME_TAG, 3, 0, 0, 0, 0, 0, 0, 0, false);
     205                 :          1 :   check_read("P-1Y", EXESS_EXPECTED_DIGIT, 1, 0, 0, 0, 0, 0, 0, 0, false);
     206                 :          1 :   check_read("P-1M", EXESS_EXPECTED_DIGIT, 1, 0, 0, 0, 0, 0, 0, 0, false);
     207                 :          1 :   check_read("P-1D", EXESS_EXPECTED_DIGIT, 1, 0, 0, 0, 0, 0, 0, 0, false);
     208                 :          1 :   check_read("PT-1H", EXESS_EXPECTED_DIGIT, 2, 0, 0, 0, 0, 0, 0, 0, false);
     209                 :          1 :   check_read("PT-1M", EXESS_EXPECTED_DIGIT, 2, 0, 0, 0, 0, 0, 0, 0, false);
     210                 :          1 :   check_read("PT-1S", EXESS_EXPECTED_DIGIT, 2, 0, 0, 0, 0, 0, 0, 0, false);
     211                 :          1 :   check_read(
     212                 :            :     "P4294967296Y", EXESS_OUT_OF_RANGE, 12, 0, 0, 0, 0, 0, 0, 0, false);
     213                 :          1 :   check_read(
     214                 :            :     "P4294967296M", EXESS_OUT_OF_RANGE, 12, 0, 0, 0, 0, 0, 0, 0, false);
     215                 :          1 :   check_read(
     216                 :            :     "P4294967296D", EXESS_OUT_OF_RANGE, 12, 0, 0, 0, 0, 0, 0, 0, false);
     217                 :          1 :   check_read(
     218                 :            :     "PT4294967296H", EXESS_OUT_OF_RANGE, 13, 0, 0, 0, 0, 0, 0, 0, false);
     219                 :          1 :   check_read(
     220                 :            :     "PT4294967296M", EXESS_OUT_OF_RANGE, 13, 0, 0, 0, 0, 0, 0, 0, false);
     221                 :          1 :   check_read("", EXESS_EXPECTED_DURATION, 0, 0, 0, 0, 0, 0, 0, 0, false);
     222                 :          1 : }
     223                 :            : 
     224                 :            : static void
     225                 :         43 : check_write(const ExessDuration value,
     226                 :            :             const ExessStatus   expected_status,
     227                 :            :             const size_t        buf_size,
     228                 :            :             const char* const   expected_string)
     229                 :            : {
     230                 :         43 :   char buf[EXESS_MAX_DURATION_LENGTH + 1] = {42};
     231                 :         43 :   init_out_buf(sizeof(buf), buf);
     232                 :            : 
     233         [ -  + ]:         43 :   assert(buf_size <= sizeof(buf));
     234                 :            : 
     235                 :         43 :   const ExessResult r = exess_write_duration(value, buf_size, buf);
     236         [ -  + ]:         43 :   assert(r.status == expected_status);
     237         [ +  + ]:         43 :   if (!r.status) {
     238         [ -  + ]:         20 :     assert(!strcmp(buf, expected_string));
     239         [ -  + ]:         20 :     assert(r.count == strlen(buf));
     240         [ -  + ]:         20 :     assert(exess_write_duration(value, 0, NULL).count == r.count);
     241                 :            :   }
     242                 :         43 : }
     243                 :            : 
     244                 :            : static void
     245                 :          1 : test_write_duration(void)
     246                 :            : {
     247                 :          1 :   check_write(zero, EXESS_SUCCESS, 4, "P0Y");
     248                 :            : 
     249                 :          1 :   check_write(
     250                 :            :     lowest, EXESS_SUCCESS, 39, "-P178956970Y7M24855DT3H14M7.999999999S");
     251                 :            : 
     252                 :          1 :   check_write(
     253                 :            :     highest, EXESS_SUCCESS, 38, "P178956970Y7M24855DT3H14M7.999999999S");
     254                 :            : 
     255                 :          1 :   check_write(
     256                 :            :     longest, EXESS_SUCCESS, 42, "-P176631622Y11M12659DT18H24M35.999999999S");
     257                 :            : 
     258                 :          1 :   check_write(longest_ym, EXESS_SUCCESS, 16, "-P176631622Y11M");
     259                 :          1 :   check_write(longest_dt, EXESS_SUCCESS, 29, "-P12659DT18H24M35.999999999S");
     260                 :            : 
     261                 :          1 :   check_write(year, EXESS_SUCCESS, 4, "P1Y");
     262                 :          1 :   check_write(month, EXESS_SUCCESS, 4, "P1M");
     263                 :          1 :   check_write(day, EXESS_SUCCESS, 4, "P1D");
     264                 :          1 :   check_write(hour, EXESS_SUCCESS, 5, "PT1H");
     265                 :          1 :   check_write(minute, EXESS_SUCCESS, 5, "PT1M");
     266                 :          1 :   check_write(second, EXESS_SUCCESS, 5, "PT1S");
     267                 :          1 :   check_write(nanosecond, EXESS_SUCCESS, 15, "PT0.000000001S");
     268                 :            : 
     269                 :          1 :   check_write(n_year, EXESS_SUCCESS, 5, "-P1Y");
     270                 :          1 :   check_write(n_month, EXESS_SUCCESS, 5, "-P1M");
     271                 :          1 :   check_write(n_day, EXESS_SUCCESS, 5, "-P1D");
     272                 :          1 :   check_write(n_hour, EXESS_SUCCESS, 6, "-PT1H");
     273                 :          1 :   check_write(n_minute, EXESS_SUCCESS, 6, "-PT1M");
     274                 :          1 :   check_write(n_second, EXESS_SUCCESS, 6, "-PT1S");
     275                 :          1 :   check_write(n_nanosecond, EXESS_SUCCESS, 16, "-PT0.000000001S");
     276                 :            : 
     277                 :          1 :   check_write(garbage1, EXESS_BAD_VALUE, 42, "");
     278                 :          1 :   check_write(garbage2, EXESS_BAD_VALUE, 42, "");
     279                 :          1 :   check_write(garbage3, EXESS_BAD_VALUE, 42, "");
     280                 :          1 :   check_write(garbage4, EXESS_BAD_VALUE, 42, "");
     281                 :          1 :   check_write(garbage5, EXESS_BAD_VALUE, 42, "");
     282                 :          1 :   check_write(garbage6, EXESS_BAD_VALUE, 42, "");
     283                 :          1 :   check_write(garbage7, EXESS_OUT_OF_RANGE, 42, "");
     284                 :          1 :   check_write(garbage8, EXESS_OUT_OF_RANGE, 42, "");
     285                 :          1 :   check_write(garbage9, EXESS_OUT_OF_RANGE, 42, "");
     286                 :            : 
     287                 :          1 :   check_write(zero, EXESS_NO_SPACE, 3, "");
     288                 :          1 :   check_write(lowest, EXESS_NO_SPACE, 24, "");
     289                 :          1 :   check_write(highest, EXESS_NO_SPACE, 4, "");
     290                 :          1 :   check_write(highest, EXESS_NO_SPACE, 10, "");
     291                 :          1 :   check_write(highest, EXESS_NO_SPACE, 13, "");
     292                 :          1 :   check_write(highest, EXESS_NO_SPACE, 16, "");
     293                 :          1 :   check_write(highest, EXESS_NO_SPACE, 20, "");
     294                 :          1 :   check_write(highest, EXESS_NO_SPACE, 23, "");
     295                 :          1 :   check_write(year, EXESS_NO_SPACE, 3, "");
     296                 :          1 :   check_write(month, EXESS_NO_SPACE, 3, "");
     297                 :          1 :   check_write(day, EXESS_NO_SPACE, 3, "");
     298                 :          1 :   check_write(hour, EXESS_NO_SPACE, 4, "");
     299                 :          1 :   check_write(minute, EXESS_NO_SPACE, 4, "");
     300                 :          1 :   check_write(second, EXESS_NO_SPACE, 4, "");
     301                 :            : 
     302                 :            :   // Check that nothing is written when there isn't enough space
     303                 :          1 :   char              c = 42;
     304                 :          1 :   const ExessResult r = exess_write_duration(zero, 0, &c);
     305         [ -  + ]:          1 :   assert(c == 42);
     306         [ -  + ]:          1 :   assert(r.status == EXESS_NO_SPACE);
     307         [ -  + ]:          1 :   assert(r.count == 3);
     308                 :          1 : }
     309                 :            : 
     310                 :            : static void
     311                 :       1024 : check_round_trip(const ExessDuration value)
     312                 :            : {
     313                 :       1024 :   ExessDuration parsed_value                       = {0, 0, 0};
     314                 :       1024 :   char          buf[EXESS_MAX_DURATION_LENGTH + 1] = {42};
     315                 :       1024 :   init_out_buf(sizeof(buf), buf);
     316                 :            : 
     317         [ -  + ]:       1024 :   assert(exess_write_duration(value, 0, NULL).count <=
     318                 :            :          EXESS_MAX_DURATION_LENGTH);
     319                 :            : 
     320         [ -  + ]:       1024 :   assert(!exess_write_duration(value, sizeof(buf), buf).status);
     321         [ -  + ]:       1024 :   assert(!exess_read_duration(buf, &parsed_value).status);
     322         [ -  + ]:       1024 :   assert(parsed_value.months == value.months);
     323         [ -  + ]:       1024 :   assert(parsed_value.seconds == value.seconds);
     324         [ -  + ]:       1024 :   assert(parsed_value.nanoseconds == value.nanoseconds);
     325                 :       1024 : }
     326                 :            : 
     327                 :            : static void
     328                 :          1 : test_round_trip(const ExessNumTestOptions opts)
     329                 :            : {
     330                 :          1 :   fprintf(stderr, "Testing xsd:duration randomly with seed %u\n", opts.seed);
     331                 :            : 
     332                 :          1 :   uint32_t rng = opts.seed;
     333         [ +  + ]:       1025 :   for (size_t i = 0; i < opts.n_tests; ++i) {
     334                 :       1024 :     rng = lcg32(rng);
     335                 :            : 
     336                 :       1024 :     const int32_t months = (int32_t)rng;
     337                 :            : 
     338                 :       1024 :     rng = lcg32(rng);
     339                 :            : 
     340         [ +  + ]:       1024 :     const int32_t seconds = (months < 0 ? -1 : 1) * (int32_t)(rng % INT32_MAX);
     341                 :            : 
     342                 :       1024 :     rng = lcg32(rng);
     343                 :            : 
     344                 :       1024 :     const int32_t nanoseconds =
     345         [ +  + ]:       1024 :       (months < 0 ? -1 : 1) * (int32_t)(rng % 1000000000);
     346                 :            : 
     347                 :       1024 :     const ExessDuration value = {months, seconds, nanoseconds};
     348                 :       1024 :     check_round_trip(value);
     349                 :            : 
     350                 :       1024 :     print_num_test_progress(i, opts.n_tests);
     351                 :            :   }
     352                 :          1 : }
     353                 :            : 
     354                 :            : int
     355                 :          1 : main(int argc, char** argv)
     356                 :            : {
     357                 :            :   ExessNumTestOptions opts =
     358                 :          1 :     parse_num_test_options(argc, argv, 16384U, 0U, INT32_MAX);
     359                 :            : 
     360         [ +  - ]:          1 :   opts.n_tests = (opts.n_tests >= 4096U) ? (opts.n_tests / 16U) : 256U;
     361                 :            : 
     362         [ +  - ]:          1 :   if (!opts.error) {
     363                 :          1 :     test_read_duration();
     364                 :          1 :     test_write_duration();
     365                 :          1 :     test_round_trip(opts);
     366                 :            :   }
     367                 :            : 
     368                 :          1 :   return (int)opts.error;
     369                 :            : }

Generated by: LCOV version 1.16