2222
2323#define C (expr ) if (!(expr)) { return __LINE__; }
2424
25+ #define TEST (test ) { ret = test; if (ret != 0) { return ret; }}
26+
2527#define SINK (char*)0xE40000
2628
2729/* pass NULL into functions without triggering -Wnonnull */
@@ -54,6 +56,9 @@ void *T_memrchr(const void *s, int c, size_t n)
5456char * T_stpcpy (char * __restrict dest , const char * __restrict src )
5557 __attribute__((nonnull (1 , 2 )));
5658
59+ size_t T_strlcat (void * __restrict dest , const void * __restrict src , size_t n )
60+ __attribute__((nonnull (1 , 2 )));
61+
5762size_t T_strlen (const char * s )
5863 __attribute__((nonnull (1 )));
5964
@@ -75,6 +80,7 @@ void T_bzero(void* s, size_t n);
7580#define T_mempcpy mempcpy
7681#define T_memrchr memrchr
7782#define T_stpcpy stpcpy
83+ #define T_strlcat strlcat
7884#define T_strlen strlen
7985#define T_strcmp strcmp
8086#define T_strncmp strncmp
@@ -159,7 +165,7 @@ int boot_sprintf_tests(void) {
159165 printf ("E: %d != %d\n" , len_3 , pos_3 );
160166 return __LINE__ ;
161167 }
162-
168+
163169 // large string test
164170 static char const * const s = "Hello" ;
165171 int len_4 = boot_snprintf (SINK , 300 ,
@@ -271,7 +277,7 @@ int nano_tests(void) {
271277 printf ("E: %d != %d\n" , len_3s , pos_3 );
272278 return __LINE__ ;
273279 }
274-
280+
275281 // https://en.cppreference.com/w/c/io/fprintf
276282 static char const * const s = "Hello" ;
277283 int len_4 = snprintf (SINK , 300 ,
@@ -360,7 +366,7 @@ int memccpy_tests(void) {
360366 return __LINE__ ;
361367 }
362368 file = fopen (file_name , "wb" );
363-
369+
364370 // Check if the file was opened successfully
365371 if (file == NULL ) {
366372 perror ("Error opening file" );
@@ -371,32 +377,32 @@ int memccpy_tests(void) {
371377 const char terminal [] = {':' , ' ' , ',' , '.' , '!' };
372378 char dest [sizeof src ];
373379 const char alt = '@' ;
374-
380+
375381 for (size_t i = 0 ; i != sizeof terminal ; ++ i )
376382 {
377383 void * to = T_memccpy (dest , src , terminal [i ], sizeof dest );
378-
384+
379385 fprintf (file ,"Terminal '%c' (%s):\t\"" , terminal [i ], to ? "found" : "absent" );
380-
386+
381387 // if `terminal` character was not found - print the whole `dest`
382388 to = to ? to : dest + sizeof dest ;
383-
389+
384390 for (char * from = dest ; from != to ; ++ from ) {
385391 fputc (isprint (* from ) ? * from : alt , file );
386392 }
387-
393+
388394 fputs ("\"\n" , file );
389395 }
390-
391-
396+
397+
392398 fprintf (file , "%c%s" , '\n' , "Separate star names from distances (ly):\n" );
393399 const char * star_distance [] = {
394400 "Arcturus : 37" , "Vega : 25" , "Capella : 43" , "Rigel : 860" , "Procyon : 11"
395401 };
396402 char names_only [64 ];
397403 char * first = names_only ;
398404 char * last = names_only + sizeof names_only ;
399-
405+
400406 for (size_t t = 0 ; t != (sizeof star_distance ) / (sizeof star_distance [0 ]); ++ t )
401407 {
402408 if (first ) {
@@ -597,6 +603,57 @@ int memmove_test(void) {
597603 return 0 ;
598604}
599605
606+ static bool strcmp_exact (const char * x , const char * y ) {
607+ if (strlen (x ) != strlen (y )) {
608+ return false;
609+ }
610+ if (strcmp (x , y ) != 0 ) {
611+ return false;
612+ }
613+ return true;
614+ }
615+
616+ int strlcat_test (void )
617+ {
618+ const char * src1 = "Foo" ;
619+ const char * src2 = "Bar" ;
620+ char dst [10 ];
621+
622+ strcpy (dst , src1 ); C (T_strlcat (dst , src2 , 0 ) == 3 ); C (strcmp_exact (dst , "Foo" ));
623+ strcpy (dst , src1 ); C (T_strlcat (dst , src2 , 1 ) == 4 ); C (strcmp_exact (dst , "Foo" ));
624+ strcpy (dst , src1 ); C (T_strlcat (dst , src2 , 2 ) == 5 ); C (strcmp_exact (dst , "Foo" ));
625+ strcpy (dst , src1 ); C (T_strlcat (dst , src2 , 3 ) == 6 ); C (strcmp_exact (dst , "Foo" ));
626+ strcpy (dst , src1 ); C (T_strlcat (dst , src2 , 4 ) == 6 ); C (strcmp_exact (dst , "Foo" ));
627+ strcpy (dst , src1 ); C (T_strlcat (dst , src2 , 5 ) == 6 ); C (strcmp_exact (dst , "FooB" ));
628+ strcpy (dst , src1 ); C (T_strlcat (dst , src2 , 6 ) == 6 ); C (strcmp_exact (dst , "FooBa" ));
629+ strcpy (dst , src1 ); C (T_strlcat (dst , src2 , 7 ) == 6 ); C (strcmp_exact (dst , "FooBar" ));
630+ strcpy (dst , src1 ); C (T_strlcat (dst , src2 , 8 ) == 6 ); C (strcmp_exact (dst , "FooBar" ));
631+ strcpy (dst , src1 ); C (T_strlcat (dst , src2 , 9 ) == 6 ); C (strcmp_exact (dst , "FooBar" ));
632+
633+ strcpy (dst , src1 ); C (T_strlcat (dst , SINK , 0 ) == 0 ); C (strcmp_exact (dst , src1 ));
634+ strcpy (dst , src1 ); C (T_strlcat (dst , SINK , 1 ) == 1 ); C (strcmp_exact (dst , src1 ));
635+ strcpy (dst , src1 ); C (T_strlcat (dst , SINK , 2 ) == 2 ); C (strcmp_exact (dst , src1 ));
636+ strcpy (dst , src1 ); C (T_strlcat (dst , SINK , 3 ) == 3 ); C (strcmp_exact (dst , src1 ));
637+ strcpy (dst , src1 ); C (T_strlcat (dst , SINK , 4 ) == 3 ); C (strcmp_exact (dst , src1 ));
638+ strcpy (dst , src1 ); C (T_strlcat (dst , SINK , 5 ) == 3 ); C (strcmp_exact (dst , src1 ));
639+
640+ C (T_strlcat (NULL_ptr , SINK , 0 ) == 0 );
641+ C (T_strlcat (NULL_ptr , src1 , 0 ) == 3 );
642+
643+ dst [0 ] = '\0' ; C (T_strlcat (dst , SINK , 0 ) == 0 ); C (dst [0 ] == '\0' );
644+ dst [0 ] = '\0' ; C (T_strlcat (dst , SINK , 1 ) == 0 ); C (dst [0 ] == '\0' );
645+ dst [0 ] = '\0' ; C (T_strlcat (dst , SINK , 2 ) == 0 ); C (dst [0 ] == '\0' );
646+
647+ dst [0 ] = '\0' ; C (T_strlcat (dst , src1 , 0 ) == 3 ); C (strcmp_exact (dst , "" ));
648+ dst [0 ] = '\0' ; C (T_strlcat (dst , src1 , 1 ) == 3 ); C (strcmp_exact (dst , "" ));
649+ dst [0 ] = '\0' ; C (T_strlcat (dst , src1 , 2 ) == 3 ); C (strcmp_exact (dst , "F" ));
650+ dst [0 ] = '\0' ; C (T_strlcat (dst , src1 , 3 ) == 3 ); C (strcmp_exact (dst , "Fo" ));
651+ dst [0 ] = '\0' ; C (T_strlcat (dst , src1 , 4 ) == 3 ); C (strcmp_exact (dst , "Foo" ));
652+ dst [0 ] = '\0' ; C (T_strlcat (dst , src1 , 5 ) == 3 ); C (strcmp_exact (dst , "Foo" ));
653+
654+ return 0 ;
655+ }
656+
600657int run_tests (void ) {
601658 int ret = 0 ;
602659 /* boot_asprintf */
@@ -618,25 +675,12 @@ int run_tests(void) {
618675 }
619676 if (ret != 0 ) { return ret ; }
620677
621- /* mempcpy */
622- ret = mempcpy_test ();
623- if (ret != 0 ) { return ret ; }
624-
625- /* bzero */
626- ret = bzero_test ();
627- if (ret != 0 ) { return ret ; }
628-
629- /* strncmp */
630- ret = strncmp_test ();
631- if (ret != 0 ) { return ret ; }
632-
633- /* memrchr */
634- ret = memrchr_test ();
635- if (ret != 0 ) { return ret ; }
636-
637- /* memrchr */
638- ret = memmove_test ();
639- if (ret != 0 ) { return ret ; }
678+ TEST (mempcpy_test ());
679+ TEST (bzero_test ());
680+ TEST (strncmp_test ());
681+ TEST (memrchr_test ());
682+ TEST (memmove_test ());
683+ TEST (strlcat_test ());
640684
641685 return 0 ;
642686}
@@ -675,7 +719,7 @@ int main(void)
675719 printf ("All tests %s" , "passed" );
676720 #endif
677721 }
678-
722+
679723 while (!os_GetCSC ());
680724
681725 return 0 ;
0 commit comments