@@ -24,6 +24,7 @@ DEALINGS IN THE SOFTWARE. */
2424
2525#include <config.h>
2626
27+ #include <stddef.h>
2728#include <stdlib.h>
2829#include <stdio.h>
2930#include <limits.h>
@@ -33,6 +34,9 @@ DEALINGS IN THE SOFTWARE. */
3334
3435#include "../htslib/kstring.h"
3536
37+ // Include kstring.c here so we can unit test internal functions.
38+ #include "../kstring.c"
39+
3640static inline void clamp (int64_t * val , int64_t min , int64_t max ) {
3741 if (* val < min ) * val = min ;
3842 if (* val > max ) * val = max ;
@@ -579,6 +583,129 @@ static int test_kinsertstr(void) {
579583 return 0 ;
580584}
581585
586+ static int test_kmemmem (void ) {
587+ typedef struct {
588+ const char * str ;
589+ int slen ;
590+ const char * pat ;
591+ int plen ;
592+ ptrdiff_t location ; // location of pat in str, or -1 if not present
593+ } kmemmem_dat ;
594+
595+ kmemmem_dat tests [] = {
596+ { "f\0\0f\0\0f\0\0bar\0\0f\0\0f" , 18 , "f\0\0" , 3 , 0 },
597+ { "f\0\0f\0\0f\0\0bar\0\0f\0\0f" , 18 , "\0\0f" , 3 , 1 },
598+ { "\0\0f\0\0f\0\0fbar\0\0f\0\0f" , 18 , "\0\0f" , 3 , 0 },
599+ { "\0\0f\0\0f\0\0fbar\0\0f\0\0f" , 18 , "f\0\0" , 3 , 2 },
600+ { "f\0\0f\0\0f\0\0bar\0\0f\0\0f" , 18 , "bar" , 3 , 9 },
601+ { "f\0\0f\0\0f\0\0baz\0\0f\0\0f" , 18 , "bar" , 3 , -1 },
602+ { "f\0\0f\0\0f\0\0bar\0\0f\0\0f" , 18 , "" , 0 , 0 },
603+ { "f\0\0f\0\0f\0\0bar\0\0f\0\0f" , 18 , "\0\0b" , 3 , 7 },
604+ { "f\0\0f\0\0f\0\0bar\0\0f\0\0f" , 18 , "r\0\0" , 3 , 11 },
605+ { "bar" , 3 , "f\0\0f\0\0f\0\0bar\0\0f\0\0f" , 18 , -1 },
606+ { "" , 0 , "bar" , 3 , -1 },
607+ { "" , 0 , "" , 0 , 0 },
608+ };
609+
610+ size_t i ;
611+ int pass = 1 ;
612+
613+ for (i = 0 ; i < sizeof (tests ) / sizeof (tests [0 ]); i ++ ) {
614+ char * found = kmemmem (tests [i ].str , tests [i ].slen ,
615+ tests [i ].pat , tests [i ].plen , NULL );
616+ ptrdiff_t loc = found ? found - tests [i ].str : -1 ;
617+ if (loc != tests [i ].location ) {
618+ pass = 0 ;
619+ fprintf (stderr ,
620+ "kmemmem() test %zd failed - got %lld expected %lld\n" ,
621+ i , (long long ) loc , (long long ) tests [i ].location );
622+ }
623+
624+ found = karp_rabin (tests [i ].str , tests [i ].slen ,
625+ tests [i ].pat , tests [i ].plen );
626+ loc = found ? found - tests [i ].str : -1 ;
627+ if (loc != tests [i ].location ) {
628+ pass = 0 ;
629+ fprintf (stderr ,
630+ "karp_rabin() test %zd failed - got %lld expected %lld\n" ,
631+ i , (long long ) loc , (long long ) tests [i ].location );
632+ }
633+ }
634+
635+ return pass ? 0 : -1 ;
636+ }
637+
638+ static int test_kstrstr (void ) {
639+ typedef struct {
640+ const char * str ;
641+ const char * pat ;
642+ ptrdiff_t location ; // location of pat in str, or -1 if not present
643+ } kstrstr_dat ;
644+
645+ kstrstr_dat tests [] = {
646+ { "foofoofoobaroofoof" , "bar" , 9 },
647+ { "foofoofoobazoofoof" , "bar" , -1 },
648+ { "foofoofoobaroofoof" , "" , 0 },
649+ { "foofoofoobaroofoof" , "oob" , 7 },
650+ { "foofoofoobaroofoof" , "roo" , 11 },
651+ { "bar" , "foofoofoobaroofoof" , -1 },
652+ { "" , "bar" , -1 },
653+ { "" , "" , 0 },
654+ };
655+
656+ size_t i ;
657+ int pass = 1 ;
658+
659+ for (i = 0 ; i < sizeof (tests ) / sizeof (tests [0 ]); i ++ ) {
660+ char * found = kstrstr (tests [i ].str , tests [i ].pat , NULL );
661+ ptrdiff_t loc = found ? found - tests [i ].str : -1 ;
662+ if (loc != tests [i ].location ) {
663+ pass = 0 ;
664+ fprintf (stderr ,
665+ "kstrstr() test %zd failed - got %lld expected %lld\n" ,
666+ i , (long long ) loc , (long long ) tests [i ].location );
667+ }
668+ }
669+
670+ return pass ? 0 : -1 ;
671+ }
672+
673+ static int test_kstrnstr (void ) {
674+ typedef struct {
675+ const char * str ;
676+ const char * pat ;
677+ int n ;
678+ ptrdiff_t location ; // location of pat in str, or -1 if not present
679+ } kstrnstr_dat ;
680+
681+ kstrnstr_dat tests [] = {
682+ { "foofoofoobaroofoof" , "bar" , 18 , 9 },
683+ { "foofoofoobazoofoof" , "bar" , 18 , -1 },
684+ { "foofoofoobaroofoof" , "bar" , 9 , -1 },
685+ { "foofoofoobaroofoof" , "" , 18 , 0 },
686+ { "bar" , "foofoofoobaroofoof" , 18 , -1 },
687+ { "foofoof\0obaroofoof" , "bar" , 18 , -1 },
688+ { "" , "bar" , 3 , -1 },
689+ { "" , "" , 0 , 0 },
690+ };
691+
692+ size_t i ;
693+ int pass = 1 ;
694+
695+ for (i = 0 ; i < sizeof (tests ) / sizeof (tests [0 ]); i ++ ) {
696+ char * found = kstrnstr (tests [i ].str , tests [i ].pat , tests [i ].n , NULL );
697+ ptrdiff_t loc = found ? found - tests [i ].str : -1 ;
698+ if (loc != tests [i ].location ) {
699+ pass = 0 ;
700+ fprintf (stderr ,
701+ "kstrnstr() test %zd failed - got %lld expected %lld\n" ,
702+ i , (long long ) loc , (long long ) tests [i ].location );
703+ }
704+ }
705+
706+ return pass ? 0 : -1 ;
707+ }
708+
582709int main (int argc , char * * argv ) {
583710 int opt , res = EXIT_SUCCESS ;
584711 int64_t start = 0 ;
@@ -634,5 +761,14 @@ int main(int argc, char **argv) {
634761 if (!test || strcmp (test , "kinsertstr" ) == 0 )
635762 if (test_kinsertstr () != 0 ) res = EXIT_FAILURE ;
636763
764+ if (!test || strcmp (test , "kmemmem" ) == 0 )
765+ if (test_kmemmem () != 0 ) res = EXIT_FAILURE ;
766+
767+ if (!test || strcmp (test , "kstrstr" ) == 0 )
768+ if (test_kstrstr () != 0 ) res = EXIT_FAILURE ;
769+
770+ if (!test || strcmp (test , "kstrnstr" ) == 0 )
771+ if (test_kstrnstr () != 0 ) res = EXIT_FAILURE ;
772+
637773 return res ;
638774}
0 commit comments