LCOV - code coverage report
Current view: top level - libs/rational/tests/src - test_librational_0002.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 143 143
Test Date: 2026-07-12 01:01:34 Functions: 100.0 % 6 6
Branches: 50.0 % 8 4

             Branch data     Line data    Source code
       1                 :             : #include "test_librational_all.h"
       2                 :             : #include <errno.h>
       3                 :             : #include <limits.h>
       4                 :             : 
       5                 :             : /* The expected stdout pattern is strict and covers the whole demonstration output.
       6                 :             :  * Non-decimal negative output depends on the platform width of int, so
       7                 :             :  * the test_librational_0002 suite uses a static assertion to keep these expectations
       8                 :             :  * tied to the supported 32-bit int targets */
       9                 :             : static const char expected_itoa_stdout_pattern[] =
      10                 :             :         "\\A"
      11                 :             :         "=== Testing extreme values ===\n"
      12                 :             :         "Value: 2147483647 \\(decimal\\)\n"
      13                 :             :         "Base 10 result: 2147483647, 2147483647\n"
      14                 :             :         "-------------------\n"
      15                 :             :         "Value: -2147483648 \\(decimal\\)\n"
      16                 :             :         "Base 10 result: -2147483648, -2147483648\n"
      17                 :             :         "-------------------\n"
      18                 :             :         "Value: -2147483648 \\(decimal\\)\n"
      19                 :             :         "Base 16 result: 80000000, Should show in hex\n"
      20                 :             :         "-------------------\n"
      21                 :             :         "\n"
      22                 :             :         "=== Testing regular values ===\n"
      23                 :             :         "Value: 255 \\(decimal\\)\n"
      24                 :             :         "Base 16 result: FF, FF\n"
      25                 :             :         "-------------------\n"
      26                 :             :         "Value: 255 \\(decimal\\)\n"
      27                 :             :         "Base  2 result: 11111111, 11111111\n"
      28                 :             :         "-------------------\n"
      29                 :             :         "Value: -255 \\(decimal\\)\n"
      30                 :             :         "Base 10 result: -255, -255\n"
      31                 :             :         "-------------------\n"
      32                 :             :         "\n"
      33                 :             :         "=== Testing zero ===\n"
      34                 :             :         "Value: 0 \\(decimal\\)\n"
      35                 :             :         "Base 10 result: 0, 0\n"
      36                 :             :         "-------------------\n"
      37                 :             :         "Value: 0 \\(decimal\\)\n"
      38                 :             :         "Base 16 result: 0, 0\n"
      39                 :             :         "-------------------\n"
      40                 :             :         "Value: 0 \\(decimal\\)\n"
      41                 :             :         "Base  2 result: 0, 0\n"
      42                 :             :         "-------------------\n"
      43                 :             :         "\n"
      44                 :             :         "=== Testing different bases ===\n"
      45                 :             :         "Value: 12345 \\(decimal\\)\n"
      46                 :             :         "Base 36 result: 9IX, Maximum supported base\n"
      47                 :             :         "-------------------\n"
      48                 :             :         "Value: 12345 \\(decimal\\)\n"
      49                 :             :         "Base 16 result: 3039, Common hex value\n"
      50                 :             :         "-------------------\n"
      51                 :             :         "Value: 12345 \\(decimal\\)\n"
      52                 :             :         "Base  8 result: 30071, Octal\n"
      53                 :             :         "-------------------\n"
      54                 :             :         "\n"
      55                 :             :         "=== Testing negative values ===\n"
      56                 :             :         "Value: -12345 \\(decimal\\)\n"
      57                 :             :         "Base 10 result: -12345, Only base 10 shows negative sign\n"
      58                 :             :         "-------------------\n"
      59                 :             :         "Value: -12345 \\(decimal\\)\n"
      60                 :             :         "Base 16 result: FFFFCFC7, Should show unsigned hex\n"
      61                 :             :         "-------------------\n"
      62                 :             :         "Value: -1 \\(decimal\\)\n"
      63                 :             :         "Base  2 result: 11111111111111111111111111111111, All bits set\n"
      64                 :             :         "-------------------\n"
      65                 :             :         "\n"
      66                 :             :         "=== Few more examples ===\n"
      67                 :             :         "12345\n"
      68                 :             :         "FF\n"
      69                 :             :         "1111\n"
      70                 :             :         "-789\n"
      71                 :             :         "0\n"
      72                 :             :         "Number: 1567\n"
      73                 :             :         "Base: 10\tConverted String: 1567\n"
      74                 :             :         "Base: 2\t\tConverted String: 11000011111\n"
      75                 :             :         "Base: 8\t\tConverted String: 3037\n"
      76                 :             :         "Base: 16\tConverted String: 61F\n"
      77                 :             :         "\n"
      78                 :             :         "=== Invalid base handling ===\n"
      79                 :             :         "Base 0 result: '', errno: 22\n"
      80                 :             :         "Base 1 result: '', errno: 22\n"
      81                 :             :         "Base 37 result: '', errno: 22\n"
      82                 :             :         "\n"
      83                 :             :         "=== NULL buffer handling ===\n"
      84                 :             :         "NULL buffer result: NULL, errno: 22\\Z";
      85                 :             : 
      86                 :          15 : static void test_conversion(
      87                 :             :         int          value,
      88                 :             :         unsigned int base,
      89                 :             :         const char   *reference_text)
      90                 :             : {
      91                 :             :         char buffer[66];  /* 64 bits + sign + null terminator */
      92                 :          15 :         itoa(value,buffer,base);
      93                 :             : 
      94                 :             :         /* Print the converted value next to reference text for the strict stdout pattern */
      95                 :          15 :         printf("Value: %d (decimal)\n",value);
      96                 :          15 :         printf("Base %2u result: %s, %s\n",base,buffer,reference_text);
      97                 :          15 :         printf("-------------------\n");
      98                 :          15 : }
      99                 :             : 
     100                 :             : /**
     101                 :             :  * @brief Test program for itoa function
     102                 :             :  *
     103                 :             :  * @note Tests edge cases and different bases with special focus on
     104                 :             :  *       negative numbers and MIN/MAX integer values
     105                 :             :  */
     106                 :           1 : static void test_itoa(void)
     107                 :             : {
     108                 :             :         /* Test extreme values */
     109                 :           1 :         printf("=== Testing extreme values ===\n");
     110                 :           1 :         test_conversion(INT_MAX,10,"2147483647");
     111                 :           1 :         test_conversion(INT_MIN,10,"-2147483648");
     112                 :           1 :         test_conversion(INT_MIN,16,"Should show in hex");
     113                 :             : 
     114                 :             :         /* Test regular cases */
     115                 :           1 :         printf("\n=== Testing regular values ===\n");
     116                 :           1 :         test_conversion(255,16,"FF");
     117                 :           1 :         test_conversion(255,2,"11111111");
     118                 :           1 :         test_conversion(-255,10,"-255");
     119                 :             : 
     120                 :             :         /* Test zero handling */
     121                 :           1 :         printf("\n=== Testing zero ===\n");
     122                 :           1 :         test_conversion(0,10,"0");
     123                 :           1 :         test_conversion(0,16,"0");
     124                 :           1 :         test_conversion(0,2,"0");
     125                 :             : 
     126                 :             :         /* Test larger bases */
     127                 :           1 :         printf("\n=== Testing different bases ===\n");
     128                 :           1 :         test_conversion(12345,36,"Maximum supported base");
     129                 :           1 :         test_conversion(12345,16,"Common hex value");
     130                 :           1 :         test_conversion(12345,8,"Octal");
     131                 :             : 
     132                 :             :         /* Test negative values in different bases */
     133                 :           1 :         printf("\n=== Testing negative values ===\n");
     134                 :           1 :         test_conversion(-12345,10,"Only base 10 shows negative sign");
     135                 :           1 :         test_conversion(-12345,16,"Should show unsigned hex");
     136                 :           1 :         test_conversion(-1,2,"All bits set");
     137                 :             : 
     138                 :           1 :         printf("\n=== Few more examples ===\n");
     139                 :             :         char buffer[33];  /* Buffer for 32-bit integer */
     140                 :             : 
     141                 :             :         /* Decimal conversion */
     142                 :           1 :         itoa(12345,buffer,10);
     143                 :           1 :         puts(buffer);
     144                 :             : 
     145                 :             :         /* Hexadecimal conversion */
     146                 :           1 :         itoa(255,buffer,16);
     147                 :           1 :         puts(buffer);
     148                 :             : 
     149                 :             :         /* Binary conversion */
     150                 :           1 :         itoa(15,buffer,2);
     151                 :           1 :         puts(buffer);
     152                 :             : 
     153                 :             :         /* Negative number */
     154                 :           1 :         itoa(-789,buffer,10);
     155                 :           1 :         puts(buffer);
     156                 :             : 
     157                 :             :         /* Zero case */
     158                 :           1 :         itoa(0,buffer,10);
     159                 :           1 :         puts(buffer);
     160                 :             : 
     161                 :             :         char str[100];
     162                 :           1 :         printf("Number: %d\nBase: %d\tConverted String: %s\n",1567,10,itoa(1567,str,10));
     163                 :           1 :         printf("Base: %d\t\tConverted String: %s\n",2,itoa(1567,str,2));
     164                 :           1 :         printf("Base: %d\t\tConverted String: %s\n",8,itoa(1567,str,8));
     165                 :           1 :         printf("Base: %d\tConverted String: %s\n",16,itoa(1567,str,16));
     166                 :             : 
     167                 :           1 :         printf("\n=== Invalid base handling ===\n");
     168                 :             :         char errbuf[4];
     169                 :           1 :         char *ret = NULL;
     170                 :             : 
     171                 :           1 :         errno = 0;
     172                 :           1 :         ret = itoa(123,errbuf,0);
     173         [ +  - ]:           1 :         printf("Base 0 result: '%s', errno: %d\n",ret ? ret : "NULL",errno);
     174                 :             : 
     175                 :           1 :         errno = 0;
     176                 :           1 :         ret = itoa(123,errbuf,1);
     177         [ +  - ]:           1 :         printf("Base 1 result: '%s', errno: %d\n",ret ? ret : "NULL",errno);
     178                 :             : 
     179                 :           1 :         errno = 0;
     180                 :           1 :         ret = itoa(123,errbuf,37);
     181         [ +  - ]:           1 :         printf("Base 37 result: '%s', errno: %d\n",ret ? ret : "NULL",errno);
     182                 :             : 
     183                 :           1 :         printf("\n=== NULL buffer handling ===\n");
     184                 :           1 :         errno = 0;
     185                 :           1 :         ret = itoa(123,NULL,10);
     186         [ -  + ]:           1 :         printf("NULL buffer result: %s, errno: %d\n",ret ? "non-NULL" : "NULL",errno);
     187                 :           1 : }
     188                 :             : 
     189                 :           1 : static Return capture_librational_itoa_output(void)
     190                 :             : {
     191                 :           1 :         INITTEST;
     192                 :             : 
     193                 :           1 :         test_itoa();
     194                 :             : 
     195                 :           1 :         deliver(status);
     196                 :             : }
     197                 :             : 
     198                 :             : /**
     199                 :             :  * @brief Check that the itoa() demonstration output remains unchanged
     200                 :             :  *
     201                 :             :  * @return Return describing success or failure
     202                 :             :  */
     203                 :           1 : static Return test_librational_0002_1(void)
     204                 :             : {
     205                 :           1 :         INITTEST;
     206                 :             : 
     207                 :           1 :         ASSERT(SUCCESS == match_function_output(
     208                 :             :                 expected_itoa_stdout_pattern,
     209                 :             :                 NULL,
     210                 :             :                 capture_librational_itoa_output));
     211                 :             : 
     212                 :           1 :         RETURN_STATUS;
     213                 :             : }
     214                 :             : 
     215                 :             : /**
     216                 :             :  * @brief Check itoa() conversions and error paths directly
     217                 :             :  *
     218                 :             :  * @details This block exercises the key textual invariants without relying
     219                 :             :  * on demonstration text: INT_MIN and INT_MAX in base 10 (which exercise
     220                 :             :  * the UB-avoidance path documented in rational_itoa.c), zero handling
     221                 :             :  * across multiple bases, the unsigned bit-pattern representation of
     222                 :             :  * negative values in bases other than 10, the use of letters A-Z by the
     223                 :             :  * maximum supported base 36, and the documented error paths
     224                 :             :  *
     225                 :             :  * @return Return describing success or failure
     226                 :             :  */
     227                 :           1 : static Return test_librational_0002_2(void)
     228                 :             : {
     229                 :           1 :         INITTEST;
     230                 :             : 
     231                 :             :         char ibuf[64];  /* Large enough to hold a 32-bit value printed in base 2 (32 chars + terminator) */
     232                 :           1 :         char *iret = NULL;
     233                 :             : 
     234                 :             :         /* Extreme values in base 10. INT_MIN exercises the UB-avoidance path inside itoa() */
     235                 :           1 :         iret = itoa(INT_MAX,ibuf,10);
     236                 :           1 :         ASSERT(iret == ibuf);
     237                 :           1 :         ASSERT(0 == strcmp(ibuf,"2147483647"));
     238                 :             : 
     239                 :           1 :         iret = itoa(INT_MIN,ibuf,10);
     240                 :           1 :         ASSERT(iret == ibuf);
     241                 :           1 :         ASSERT(0 == strcmp(ibuf,"-2147483648"));
     242                 :             : 
     243                 :           1 :         iret = itoa(INT_MIN,ibuf,16);
     244                 :           1 :         ASSERT(iret == ibuf);
     245                 :           1 :         ASSERT(0 == strcmp(ibuf,"80000000"));
     246                 :             : 
     247                 :             :         /* Zero must format as "0" regardless of base */
     248                 :           1 :         iret = itoa(0,ibuf,10);
     249                 :           1 :         ASSERT(iret == ibuf);
     250                 :           1 :         ASSERT(0 == strcmp(ibuf,"0"));
     251                 :             : 
     252                 :           1 :         iret = itoa(0,ibuf,16);
     253                 :           1 :         ASSERT(iret == ibuf);
     254                 :           1 :         ASSERT(0 == strcmp(ibuf,"0"));
     255                 :             : 
     256                 :           1 :         iret = itoa(0,ibuf,2);
     257                 :           1 :         ASSERT(iret == ibuf);
     258                 :           1 :         ASSERT(0 == strcmp(ibuf,"0"));
     259                 :             : 
     260                 :             :         /* Negative values in bases other than 10 must be printed as the unsigned bit pattern */
     261                 :           1 :         iret = itoa(-1,ibuf,16);
     262                 :           1 :         ASSERT(iret == ibuf);
     263                 :           1 :         ASSERT(0 == strcmp(ibuf,"FFFFFFFF"));
     264                 :             : 
     265                 :           1 :         iret = itoa(-1,ibuf,2);
     266                 :           1 :         ASSERT(iret == ibuf);
     267                 :           1 :         ASSERT(0 == strcmp(ibuf,"11111111111111111111111111111111"));
     268                 :             : 
     269                 :           1 :         iret = itoa(-12345,ibuf,16);
     270                 :           1 :         ASSERT(iret == ibuf);
     271                 :           1 :         ASSERT(0 == strcmp(ibuf,"FFFFCFC7"));
     272                 :             : 
     273                 :             :         /* Common non-decimal bases must use the expected digits for positive values */
     274                 :           1 :         iret = itoa(255,ibuf,16);
     275                 :           1 :         ASSERT(iret == ibuf);
     276                 :           1 :         ASSERT(0 == strcmp(ibuf,"FF"));
     277                 :             : 
     278                 :           1 :         iret = itoa(255,ibuf,2);
     279                 :           1 :         ASSERT(iret == ibuf);
     280                 :           1 :         ASSERT(0 == strcmp(ibuf,"11111111"));
     281                 :             : 
     282                 :           1 :         iret = itoa(12345,ibuf,16);
     283                 :           1 :         ASSERT(iret == ibuf);
     284                 :           1 :         ASSERT(0 == strcmp(ibuf,"3039"));
     285                 :             : 
     286                 :           1 :         iret = itoa(12345,ibuf,8);
     287                 :           1 :         ASSERT(iret == ibuf);
     288                 :           1 :         ASSERT(0 == strcmp(ibuf,"30071"));
     289                 :             : 
     290                 :             :         /* Base 36 is the maximum supported base and must use letters A-Z for digits >= 10 */
     291                 :           1 :         iret = itoa(35,ibuf,36);
     292                 :           1 :         ASSERT(iret == ibuf);
     293                 :           1 :         ASSERT(0 == strcmp(ibuf,"Z"));
     294                 :             : 
     295                 :           1 :         iret = itoa(12345,ibuf,36);
     296                 :           1 :         ASSERT(iret == ibuf);
     297                 :           1 :         ASSERT(0 == strcmp(ibuf,"9IX"));
     298                 :             : 
     299                 :             :         /* Error paths: invalid bases and NULL output buffer.
     300                 :             :          * buffer[0] is pre-set to a non-NUL sentinel before each call so the ASSERT
     301                 :             :          * below verifies that itoa() actually wrote the terminator on the error path,
     302                 :             :          * rather than just leaving the prior buffer contents intact */
     303                 :             :         char buffer[8];
     304                 :           1 :         char *result = NULL;
     305                 :             : 
     306                 :           1 :         errno = 0;
     307                 :           1 :         buffer[0] = 'X';
     308                 :           1 :         result = itoa(123,buffer,0);
     309                 :           1 :         ASSERT(result == buffer);
     310                 :           1 :         ASSERT(errno == EINVAL);
     311                 :           1 :         ASSERT(buffer[0] == '\0');
     312                 :             : 
     313                 :           1 :         errno = 0;
     314                 :           1 :         buffer[0] = 'Y';
     315                 :           1 :         result = itoa(123,buffer,1);
     316                 :           1 :         ASSERT(result == buffer);
     317                 :           1 :         ASSERT(errno == EINVAL);
     318                 :           1 :         ASSERT(buffer[0] == '\0');
     319                 :             : 
     320                 :           1 :         errno = 0;
     321                 :           1 :         buffer[0] = 'Z';
     322                 :           1 :         result = itoa(123,buffer,37);
     323                 :           1 :         ASSERT(result == buffer);
     324                 :           1 :         ASSERT(errno == EINVAL);
     325                 :           1 :         ASSERT(buffer[0] == '\0');
     326                 :             : 
     327                 :           1 :         errno = 0;
     328                 :           1 :         result = itoa(123,NULL,10);
     329                 :           1 :         ASSERT(result == NULL);
     330                 :           1 :         ASSERT(errno == EINVAL);
     331                 :             : 
     332                 :           1 :         RETURN_STATUS;
     333                 :             : }
     334                 :             : 
     335                 :             : /**
     336                 :             :  * @brief Run librational itoa conversion tests
     337                 :             :  *
     338                 :             :  * @details The suite runs in two independent blocks. The first captures
     339                 :             :  * the stdout produced by test_itoa() and matches it against a strict
     340                 :             :  * full-output regex. The second uses direct ASSERT checks for boundary
     341                 :             :  * values, supported bases, negative values, and error paths
     342                 :             :  *
     343                 :             :  * @return Return describing success or failure
     344                 :             :  */
     345                 :           1 : Return test_librational_0002(void)
     346                 :             : {
     347                 :           1 :         INITTEST;
     348                 :             : 
     349                 :             :         /* The hex and binary representations of negative ints below assume 32-bit int.
     350                 :             :          * The supported targets (Linux x86_64) satisfy this; the static assertion
     351                 :             :          * prevents silent breakage on any future port to a target with a wider int */
     352                 :             :         _Static_assert(sizeof(int) * CHAR_BIT == 32,"test_librational_0002 expects a 32-bit int for stable hex and binary expectations");
     353                 :             : 
     354                 :           1 :         TEST(test_librational_0002_1,"itoa() demonstration output matches the strict full pattern");
     355                 :           1 :         TEST(test_librational_0002_2,"itoa() converts boundaries, bases, negatives and error paths");
     356                 :             : 
     357                 :           1 :         RETURN_STATUS;
     358                 :             : }
        

Generated by: LCOV version 2.0-1