1 /*****************************************************************************
2  * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
3  * @file
4  * @author  Jim E. Brooks  http://www.palomino3d.org
5  * @brief   Test of ConfBin class.
6  *//*
7  * LEGAL:   COPYRIGHT (C) 2004 JIM E. BROOKS
8  *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
9  *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
10  *****************************************************************************/
11 
12 #define TESTING 1
13 #include "test.hh"
14 #include "base/module.hh"
15 #include "base/conf_bin.hh"
16 using namespace base;
17 
18 INTERN const char FNAME[]       = "/tmp/base_config_file_test.cfg";
19 INTERN const char PROGNAME[]    = "test";
20 
21 /*****************************************************************************
22  * Test.
23  *****************************************************************************/
24 bool
Test1(void)25 Test1( void )
26 {
27     // ------------------------------------------------------------------------
28     // First series of tests are for when no configuration file exists yet.
29     // ------------------------------------------------------------------------
30 
31     unlink( FNAME ); // ensure configuration file doesn't exist
32 
33     ConfBin config( PROGNAME, FNAME );
34 
35     int         right_highscore = 536000;
36     string      right_game      = "pacman";
37     double      right_offset    = 1.2345;
38     int         highscore;
39     string      game;
40     double      offset;
41 
42     // Test writing.
43     if ( ! config.Write( "highscore", right_highscore ) )
44     {
45         CDEBUG << "FAIL: Write(highscore) \n";
46         return Fail();
47     }
48 
49     if ( ! config.Write( "game", right_game ) )
50     {
51         CDEBUG << "FAIL: Write(game) \n";
52         return Fail();
53     }
54 
55     if ( ! config.Write( "offset", right_offset ) )
56     {
57         CDEBUG << "FAIL: Write(highscore) \n";
58         return Fail();
59     }
60 
61     // Test reading.
62     if ( config.Read( "highscore", highscore ) && highscore == right_highscore )
63         { CDEBUG << "(ok) highscore = " << highscore << std::endl; }
64     else
65         { CDEBUG << "FAIL: Read(highscore)\n"; return Fail(); }
66 
67     if ( config.Read( "game", game ) && game == right_game )
68         { CDEBUG << "(ok) game      = " << game << std::endl; }
69     else
70         { CDEBUG << "FAIL: Read(game)\n"; return Fail(); }
71 
72     if ( config.Read( "offset", offset ) && offset == right_offset )
73         { CDEBUG << "(ok) offset    = " << offset << std::endl; }
74     else
75         { CDEBUG << "FAIL: Read(offset)\n"; return Fail(); }
76 
77     return true;
78 }
79 
80 /*****************************************************************************
81  * Test.
82  *****************************************************************************/
83 bool
Test2(void)84 Test2( void )
85 {
86     // ------------------------------------------------------------------------
87     // Second series of tests are for when a configuration file DOES exist.
88     // ------------------------------------------------------------------------
89 
90     ConfBin config( PROGNAME, FNAME );
91 
92     int         right_highscore = 536000;
93     string      right_game      = "pacman";
94     double      right_offset    = 1.2345;
95     int         highscore;
96     string      game;
97     double      offset;
98 
99     // Test reading.
100     if ( config.Read( "highscore", highscore ) && highscore == right_highscore )
101         { CDEBUG << "(ok) highscore = " << highscore << std::endl; }
102     else
103         { CDEBUG << "FAIL: Read(highscore)\n"; return Fail(); }
104 
105     if ( config.Read( "game", game ) && game == right_game )
106         { CDEBUG << "(ok) game[]    = " << game << std::endl; }
107     else
108         { CDEBUG << "FAIL: Read(game)\n"; return Fail(); }
109 
110     if ( config.Read( "offset", offset ) && offset == right_offset )
111         { CDEBUG << "(ok) offset    = " << offset << std::endl; }
112     else
113         { CDEBUG << "FAIL: Read(offset)\n"; return Fail(); }
114 
115     return true;
116 }
117 
118 /*****************************************************************************
119  *
120  *****************************************************************************/
121 bool
Test3(void)122 Test3( void )
123 {
124     // ------------------------------------------------------------------------
125     // Test giving different values using the same key/type.
126     // ------------------------------------------------------------------------
127 
128     ConfBin config( PROGNAME, FNAME );
129 
130     CDEBUG << "Testing changing value of same key..." << std::endl;
131 
132     const char key_highscore[] = "highscore_changing";
133     int right_highscore = 1234;
134     int highscore;
135 
136     //
137     right_highscore = 0xabcd;
138     if ( ! config.Write( key_highscore, right_highscore ) )
139     {
140         CDEBUG << "FAIL: Write(highscore) \n";
141         return Fail();
142     }
143     if ( ! config.Read( key_highscore, highscore ) || highscore != right_highscore )
144         { CDEBUG << "FAIL: Read(highscore)\n"; return Fail(); }
145 
146     //
147     right_highscore = 0;
148     if ( ! config.Write( key_highscore, right_highscore ) )
149     {
150         CDEBUG << "FAIL: Write(highscore) \n";
151         return Fail();
152     }
153     if ( ! config.Read( key_highscore, highscore ) || highscore != right_highscore )
154         { CDEBUG << "FAIL: Read(highscore)"; return Fail(); }
155 
156     //
157     right_highscore = 123467;
158     if ( ! config.Write( key_highscore, right_highscore ) )
159     {
160         CDEBUG << "FAIL: Write(highscore) \n";
161         return Fail();
162     }
163     if ( ! config.Read( key_highscore, highscore ) || highscore != right_highscore )
164         { CDEBUG << "FAIL: Read(highscore)\n"; return Fail(); }
165 
166     CDEBUG << "ok." << std::endl;
167 
168     return true;
169 }
170 
171 /*****************************************************************************
172  * Test.
173  *****************************************************************************/
174 bool
Test4(void)175 Test4( void )
176 {
177     // ------------------------------------------------------------------------
178     // Delete test.
179     // ------------------------------------------------------------------------
180 
181     ConfBin config( PROGNAME, FNAME );
182 
183 //  int         right_highscore = 536000;
184     string      right_game      = "pacman";
185     double      right_offset    = 1.2345;
186     int         highscore;
187     string      game;
188     double      offset;
189 
190     // Test deleting
191     if ( config.Remove( "highscore" ) )
192         { CDEBUG << "(ok) deleted highscore \n"; }
193     else
194         { CDEBUG << "FAIL: Remove(highscore)\n"; return Fail(); }
195 
196 
197     // Test reading.
198     if ( config.Read( "highscore", highscore ) )        // deleted
199         { CDEBUG << "FAIL: highscore should be deleted\n"; return Fail(); }
200 
201     if ( config.Read( "game", game ) && game == right_game )
202         { CDEBUG << "(ok) game[]    = " << game << std::endl; }
203     else
204         { CDEBUG << "FAIL: Read(game)\n"; return Fail(); }
205 
206     if ( config.Read( "offset", offset ) && offset == right_offset )
207         { CDEBUG << "(ok) offset    = " << offset << std::endl; }
208     else
209         { CDEBUG << "FAIL: Read(offset)\n"; return Fail(); }
210 
211     return true;
212 }
213 
214 /*****************************************************************************
215  * Test.
216  *****************************************************************************/
217 bool
Test5(void)218 Test5( void )
219 {
220     // ------------------------------------------------------------------------
221     // Corner cases, bad args.
222     // ------------------------------------------------------------------------
223 
224     ConfBin config( PROGNAME, FNAME );
225 
226     string s;
227 
228     // Test a string containing whitespace.
229     const char ws_key[] = "_key_whitespace";
230     string ws_val = "\tthis string has whitespace\n";
231     config.Write( ws_key, ws_val );
232     if ( config.Read( ws_key, s ) && s == ws_val )
233     { CDEBUG << "(ok) reading string with whitespace" << std::endl; }
234     else
235     { CDEBUG << "FAIL: reading string with whitespace" << std::endl; return Fail(); }
236 
237     // Test a empty string value.
238     const char empty_string_key[] = "_key_empty_string";
239     config.Write( empty_string_key, "" );
240     s = "dummy";
241     if ( config.Read( empty_string_key, s ) && s == "" )
242     { CDEBUG << "(ok) reading empty string" << std::endl; }
243     else
244     { CDEBUG << "FAIL: reading empty string" << std::endl; return Fail(); }
245 
246     const char key_big[] =
247     "AAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCC"
248     "DDDDDDDDDDDDDDDDEEEEEEEEEEEEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
249     "GGGGGGGGGGGGGGGGGGGGGGGGGGGHHHHHHHHHHHHHHHHHHHHHHHHHHIIIIIIIIIIIIIIIIIIIIIII"
250     "KKKKKKKKKKKKKKKKKKKKLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLMMMMMMMMMMMMMMMMMMMMMMMM"
251     "NNNNNNNNNNNNNNNNNNOOOOOOOOOOOOOOOOOOOOOOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP";
252     string val_string_big =
253     "QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"
254     "SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"
255     "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"
256     "WWWWWWWWWWWWWWWWWWWWWWWXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYYYYYYYYYYYYYYYYYYYY";
257 
258     // NULL args aren't tested -- let 'em die.
259     // This won't succeed but it shouldn't cause a crash.
260     string str;
261     config.Write( key_big, val_string_big );
262     if ( config.Read( key_big, str ) )
263     { CDEBUG << "(ok) too big " << str << std::endl; }
264 
265     return true;
266 }
267 
268 /*****************************************************************************
269  * Test.
270  *****************************************************************************/
271 bool
Test6(void)272 Test6( void )
273 {
274     // ------------------------------------------------------------------------
275     // Test Access() and more interesting keys/values.
276     // ------------------------------------------------------------------------
277 
278     ConfBin config( PROGNAME, FNAME );
279 
280     int         right_int1      = -1;
281     int         right_int2      = 0x88889999;
282     int         right_int3      = 0;
283     string      right_str       = "ABCDzxcv123409~!@#$%&*\"*(){}[];',.//<>?";
284     double      right_float     = 123456.430000;
285 
286     int         val_int1        = 0xdead;
287     int         val_int2        = 0xdead;
288     int         val_int3        = 0xdead;
289     string      val_str         = "";
290     double      val_float       = 0;
291 
292     PERSISTENT const char key_int1[]    = "___int1____";
293     PERSISTENT const char key_int2[]    = "___int 2____";
294     PERSISTENT const char key_int3[]    = "___int3____";
295     PERSISTENT const char key_str[]     = "___String____";
296     PERSISTENT const char key_float[]   = "___Float#1____";
297 
298     int res;
299 
300     CDEBUG << "Testing Access()..." << std::endl;
301 
302     // Test writing by Access().
303     if ( ! config.Access( ConfBin::eAccess_WRITE, key_int1, right_int1 ) )
304         { CDEBUG << "FAIL: Access(WRITE,int1)\n"; return Fail(); }
305 
306     if ( ! config.Access( ConfBin::eAccess_WRITE, key_int2, right_int2 ) )
307         { CDEBUG << "FAIL: Access(WRITE,int2)\n"; return Fail(); }
308 
309     if ( ! config.Access( ConfBin::eAccess_WRITE, key_int3, right_int3 ) )
310         { CDEBUG << "FAIL: Access(WRITE,int3)\n"; return Fail(); }
311 
312     if ( ! config.Access( ConfBin::eAccess_WRITE, key_str, right_str ) )
313         { CDEBUG << "FAIL: Access(WRITE,str)\n"; return Fail(); }
314 
315     if ( ! config.Access( ConfBin::eAccess_WRITE, key_float, right_float ) )
316         { CDEBUG << "FAIL: Access(WRITE,float)\n"; return Fail(); }
317 
318     // Test reading by Access().
319     res = config.Access( ConfBin::eAccess_READ, key_int1, val_int1 );
320     if ( ! res || val_int1 != right_int1 )
321         { CDEBUG << "FAIL: Access(WRITE,int1)\n"; return Fail(); }
322 
323     res = config.Access( ConfBin::eAccess_READ, key_int2, val_int2 );
324     if ( ! res || val_int2 != right_int2 )
325         { CDEBUG << "FAIL: Access(WRITE,int2)\n"; return Fail(); }
326 
327     res = config.Access( ConfBin::eAccess_READ, key_int3, val_int3 );
328     if ( ! res || val_int3 != right_int3 )
329         { CDEBUG << "FAIL: Access(WRITE,int3)\n"; return Fail(); }
330 
331     res = config.Access( ConfBin::eAccess_READ, key_str, val_str );
332     if ( ! res || val_str != right_str )
333         { CDEBUG << "FAIL: Access(WRITE,str)\n"; return Fail(); }
334 
335     res = config.Access( ConfBin::eAccess_READ, key_float, val_float );
336     if ( ! res || val_float < right_float - 0.2 || val_float > right_float + 0.2 )
337         { CDEBUG << "FAIL: Access(WRITE,float)\n"; return Fail(); }
338 
339     CDEBUG << "ok." << std::endl;
340 
341     return true;
342 }
343 
344 /*****************************************************************************
345  * Test.
346  *****************************************************************************/
347 bool
Test7(void)348 Test7( void )
349 {
350     // ------------------------------------------------------------------------
351     // Corner cases, bad args.
352     // ------------------------------------------------------------------------
353 
354     try
355     {
356         int i;
357         CDEBUG << "--- THIS SHOULD PRINT ERRORS due to bad filename ---" << std::endl;
358         ConfBin config( PROGNAME, "/a/b/c/doesnt_exist" );
359         if ( config.IfValid() )                 { CDEBUG << "IfValid() is wrong \n"; return Fail(); }
360         if ( config.Write( "abc", (int)123 ) )  { CDEBUG << "Write() is wrong \n"; return Fail(); }
361         if ( config.Read( "abc", i ) )          { CDEBUG << "Read() is wrong \n"; return Fail(); }
362         if ( config.Remove( "abc" ) )           { CDEBUG << "Remove() is wrong \n"; return Fail(); }
363         CDEBUG << "---  ---\n" << std::endl;
364     }
365     catch (...)
366     {
367         return true;
368     }
369     return false;
370 }
371 
372 /*****************************************************************************
373  * Called if all other tests passed else no cleanup.
374  *****************************************************************************/
375 bool
Cleanup(void)376 Cleanup( void )
377 {
378     unlink( FNAME );
379     return true;
380 }
381 
382 /*****************************************************************************
383  * main.
384  *****************************************************************************/
385 int
main(int argc,char ** argv)386 main( int argc, char** argv )
387 {
388     RUN_TEST( "ConfBin", TEST_ERROR_MODE_CATCH,  // this test expects an exception
389               Test1()
390           and Test2()
391           and Test3()
392           and Test4()
393           and Test5()
394           and Test6()
395           and Test7()
396           and Cleanup() )
397 }
398