1 // ===========================================================================
2 //
3 //                            PUBLIC DOMAIN NOTICE
4 //               National Center for Biotechnology Information
5 //
6 //  This software/database is a "United States Government Work" under the
7 //  terms of the United States Copyright Act.  It was written as part of
8 //  the author's official duties as a United States Government employee and
9 //  thus cannot be copyrighted.  This software/database is freely available
10 //  to the public for use. The National Library of Medicine and the U.S.
11 //  Government have not placed any restriction on its use or reproduction.
12 //
13 //  Although all reasonable efforts have been taken to ensure the accuracy
14 //  and reliability of the software and data, the NLM and the U.S.
15 //  Government do not and cannot warrant the performance or results that
16 //  may be obtained by using this software or data. The NLM and the U.S.
17 //  Government disclaim all warranties, express or implied, including
18 //  warranties of performance, merchantability or fitness for any particular
19 //  purpose.
20 //
21 //  Please cite the author in any work or product based on this material.
22 //
23 // ===========================================================================
24 
25 #include <vdb/manager.h> // VDBManager
26 #include <vdb/vdb-priv.h>
27 
28 #include <ktst/unit_test.hpp> // TEST_CASE
29 #include <klib/text.h>
30 #include <klib/out.h>
31 #include <klib/namelist.h>
32 
33 #include <sysalloc.h>
34 #include <cstdlib>
35 #include <stdexcept>
36 
37 using namespace std;
38 
39 TEST_SUITE( T_VNamelist )
40 
41 
TEST_CASE(VNamelist_1)42 TEST_CASE( VNamelist_1 )
43 {
44     VNamelist * list;
45     rc_t rc = VNamelistMake ( &list, 10 );
46     if ( rc != 0 )
47         FAIL( "FAIL: VNamelistMake( 10 ) failed" );
48 
49     rc = VNamelistRelease ( list );
50     if ( rc != 0 )
51         FAIL( "FAIL: VNamelistRelease() failed" );
52 }
53 
54 struct on_part_ctx
55 {
56     const char ** v;
57     int idx;
58 };
59 
on_part(const String * part,void * data)60 static rc_t CC on_part( const String * part, void * data )
61 {
62     rc_t rc = 0;
63     struct on_part_ctx * ctx = ( struct on_part_ctx * ) data;
64     std::string p = std::string( part->addr, part->size );
65     std::string c = std::string( ctx->v[ ctx->idx ] );
66     if ( p != c ) rc = -1;
67     ctx->idx++;
68     return rc;
69 }
70 
71 
test_String(const char * to_test,const char ** v,int count)72 rc_t test_String( const char * to_test, const char ** v, int count )
73 {
74     String s;
75     struct on_part_ctx ctx;
76     ctx.v = v;
77     ctx.idx = 0;
78 
79     StringInitCString( &s, to_test );
80     rc_t rc = foreach_String_part( &s, ':', on_part, &ctx );
81     if ( rc == 0 && ctx.idx != count ) rc = -1;
82     return rc;
83 }
84 
85 
test_pchar(const char * to_test,const char ** v,int count)86 rc_t test_pchar( const char * to_test, const char ** v, int count )
87 {
88     struct on_part_ctx ctx;
89     ctx.v = v;
90     ctx.idx = 0;
91 
92     rc_t rc = foreach_Str_part( to_test, ':', on_part, &ctx );
93     if ( rc == 0 && ctx.idx != count ) rc = -1;
94     return rc;
95 }
96 
97 static const char * s1 = "string:with:colons";
98 static const char * t1[] = { "string", "with", "colons" };
99 static const int n1 = 3;
100 
101 static const char * s2 = "just a string";
102 static const char * t2[] = { "just a string" };
103 static const int n2 = 1;
104 
105 static const char * s3 = "with::multiple::colons";
106 static const char * t3[] = { "with", "", "multiple", "", "colons" };
107 static const int n3 = 5;
108 
109 static const char * s4 = "::leading:colons";
110 static const char * t4[] = { "", "", "leading", "colons" };
111 static const int n4 = 4;
112 
113 static const char * s5 = "trailing:colons::";
114 static const char * t5[] = { "trailing", "colons", "", "" };
115 static const int n5 = 4;
116 
TEST_CASE(StringSplit)117 TEST_CASE( StringSplit )
118 {
119     std::cout << "testing String-splitting by callback" << std::endl;
120 
121     rc_t rc = test_String( s1, t1, n1 );
122     if ( rc != 0 )
123         FAIL( "FAIL: foreach_String_part( #1 ) failed" );
124     rc = test_pchar( s1, t1, n1 );
125     if ( rc != 0 )
126         FAIL( "FAIL: foreach_Str_part( #1 ) failed" );
127 
128     rc = test_String( s2, t2, n2 );
129     if ( rc != 0 )
130         FAIL( "FAIL: foreach_String_part( #2 ) failed" );
131     rc = test_pchar( s2, t2, n2 );
132     if ( rc != 0 )
133         FAIL( "FAIL: foreach_Str_part( #2 ) failed" );
134 
135     rc = test_String( s3, t3, n3 );
136     if ( rc != 0 )
137         FAIL( "FAIL: foreach_String_part( #3) failed" );
138     rc = test_pchar( s3, t3, n3 );
139     if ( rc != 0 )
140         FAIL( "FAIL: foreach_Str_part( #3 ) failed" );
141 
142     rc = test_String( s4, t4, n4 );
143     if ( rc != 0 )
144         FAIL( "FAIL: foreach_String_part( #4 ) failed" );
145     rc = test_pchar( s4, t4, n4 );
146     if ( rc != 0 )
147         FAIL( "FAIL: foreach_Str_part( #4 ) failed" );
148 
149     rc = test_String( s5, t5, n5 );
150     if ( rc != 0 )
151         FAIL( "FAIL: foreach_String_part( #5 ) failed" );
152     rc = test_pchar( s5, t5, n5 );
153     if ( rc != 0 )
154         FAIL( "FAIL: foreach_Str_part( #5 ) failed" );
155 }
156 
157 
insert_String(VNamelist * list,const char * to_test)158 rc_t insert_String( VNamelist * list, const char * to_test )
159 {
160     String s;
161     StringInitCString( &s, to_test );
162     return VNamelistSplitString ( list, &s, ':' );
163 }
164 
165 
insert_pchar(VNamelist * list,const char * to_test)166 rc_t insert_pchar( VNamelist * list, const char * to_test )
167 {
168     return VNamelistSplitStr ( list, to_test, ':' );
169 }
170 
171 
check_list(const VNamelist * list,const char ** v,uint32_t count)172 rc_t check_list( const VNamelist * list, const char ** v, uint32_t count )
173 {
174     rc_t rc = 0;
175     uint32_t idx;
176     for ( idx = 0; rc == 0 && idx < count; ++idx )
177     {
178         const char * item;
179         rc = VNameListGet ( list, idx, &item );
180         if ( rc == 0 )
181         {
182             std::string s_item = std::string( item );
183             std::string s_cmp  = std::string( v[ idx ] );
184             if ( s_item.compare( s_cmp ) != 0 )
185                 rc = -1;
186         }
187         if ( rc == 0 )
188         {
189             uint32_t lc;
190             rc = VNameListCount ( list, &lc );
191             if ( rc == 0 && lc != count )
192                 rc = -1;
193         }
194     }
195     return rc;
196 }
197 
198 
test_split_string(const char * to_test,const char ** v,uint32_t count)199 rc_t test_split_string( const char * to_test, const char ** v, uint32_t count )
200 {
201     VNamelist * list;
202     rc_t rc = VNamelistMake ( &list, 10 );
203     if ( rc == 0 )
204     {
205         rc = insert_String( list, to_test );
206         if ( rc == 0 )
207             rc = check_list( list, v, count );
208         if ( rc == 0 )
209             rc = VNamelistRemoveAll( list );
210 
211         if ( rc == 0 )
212             rc = insert_pchar( list, to_test );
213         if ( rc == 0 )
214             rc = check_list( list, v, count );
215 
216         VNamelistRelease ( list );
217     }
218     return rc;
219 }
220 
TEST_CASE(SplitIntoVNamelist)221 TEST_CASE( SplitIntoVNamelist )
222 {
223     std::cout << "testing String-splitting into existing VNamelist " << std::endl;
224 
225     rc_t rc = test_split_string( s1, t1, n1 );
226     if ( rc != 0 )
227         FAIL( "FAIL: test_split_string( #1 )" );
228 
229     rc = test_split_string( s2, t2, n2 );
230     if ( rc != 0 )
231         FAIL( "FAIL: test_split_string( #2 )" );
232 
233     rc = test_split_string( s3, t3, n3 );
234     if ( rc != 0 )
235         FAIL( "FAIL: test_split_string( #3 )" );
236 
237     rc = test_split_string( s4, t4, n4 );
238     if ( rc != 0 )
239         FAIL( "FAIL: test_split_string( #4 )" );
240 
241     rc = test_split_string( s5, t5, n5 );
242     if ( rc != 0 )
243         FAIL( "FAIL: test_split_string( #5 )" );
244 
245 }
246 
247 
test_make_from_string(const char * to_test,const char ** v,uint32_t count)248 rc_t test_make_from_string( const char * to_test, const char ** v, uint32_t count )
249 {
250     String s;
251     StringInitCString( &s, to_test );
252 
253     VNamelist * list;
254     rc_t rc = VNamelistFromString( &list, &s, ':' );
255     if ( rc == 0 )
256     {
257         rc = check_list( list, v, count );
258         VNamelistRelease ( list );
259     }
260 
261     if ( rc == 0 )
262     {
263         rc = VNamelistFromStr( &list, to_test, ':' );
264         if ( rc == 0 )
265         {
266             rc = check_list( list, v, count );
267             VNamelistRelease ( list );
268         }
269     }
270     return rc;
271 }
272 
273 
TEST_CASE(MakeVNamelistFromString)274 TEST_CASE( MakeVNamelistFromString )
275 {
276     std::cout << "testing String-splitting into new VNamelist " << std::endl;
277 
278     rc_t rc = test_make_from_string( s1, t1, n1 );
279     if ( rc != 0 )
280         FAIL( "FAIL: test_make_from_string( #1 )" );
281 
282     rc = test_make_from_string( s2, t2, n2 );
283     if ( rc != 0 )
284         FAIL( "FAIL: test_make_from_string( #2 )" );
285 
286     rc = test_make_from_string( s3, t3, n3 );
287     if ( rc != 0 )
288         FAIL( "FAIL: test_make_from_string( #3 )" );
289 
290     rc = test_make_from_string( s4, t4, n4 );
291     if ( rc != 0 )
292         FAIL( "FAIL: test_make_from_string( #4 )" );
293 
294     rc = test_make_from_string( s5, t5, n5 );
295     if ( rc != 0 )
296         FAIL( "FAIL: test_make_from_string( #5 )" );
297 }
298 
split_join_and_check(const char * to_test)299 rc_t split_join_and_check( const char * to_test )
300 {
301     VNamelist * list;
302     rc_t rc = VNamelistFromStr( &list, to_test, ':' );
303     if ( rc == 0 )
304     {
305         const String * joined;
306         rc = VNamelistJoin( list, ':', &joined );
307         if ( rc != 0 )
308             FAIL( "FAIL: VNamelistJoin()" );
309         else
310         {
311             String S2;
312             StringInitCString( &S2, to_test );
313             if ( !StringEqual( joined, &S2 ) )
314                 rc = -1;
315             StringWhack ( joined );
316         }
317         VNamelistRelease ( list );
318     }
319     return rc;
320 }
321 
TEST_CASE(VNamelistJoining)322 TEST_CASE( VNamelistJoining )
323 {
324     std::cout << "testing joining VNamelist into one String" << std::endl;
325 
326     rc_t rc = split_join_and_check( s1 );
327     if ( rc != 0 )
328         FAIL( "FAIL: split_join_and_check( #1 )" );
329 
330     rc = split_join_and_check( s2 );
331     if ( rc != 0 )
332         FAIL( "FAIL: split_join_and_check( #2 )" );
333 
334     rc = split_join_and_check( s3 );
335     if ( rc != 0 )
336         FAIL( "FAIL: split_join_and_check( #3 )" );
337 
338     rc = split_join_and_check( s4 );
339     if ( rc != 0 )
340         FAIL( "FAIL: split_join_and_check( #4 )" );
341 
342     rc = split_join_and_check( s5 );
343     if ( rc != 0 )
344         FAIL( "FAIL: split_join_and_check( #5 )" );
345 }
346 
347 //////////////////////////////////////////// Main
348 extern "C"
349 {
350 
351 #include <kapp/args.h>
352 
KAppVersion(void)353 ver_t CC KAppVersion ( void ) { return 0x1000000; }
UsageSummary(const char * progname)354 rc_t CC UsageSummary ( const char * progname ) { return 0; }
Usage(const Args * args)355 rc_t CC Usage ( const Args * args ) { return 0; }
356 const char UsageDefaultName[] = "test-VDB-3060";
357 
KMain(int argc,char * argv[])358 rc_t CC KMain ( int argc, char *argv [] )
359 {
360     rc_t rc = T_VNamelist( argc, argv );
361     return rc;
362 }
363 
364 }
365