source: box/trunk/test/common/testcommon.cpp @ 2943

Revision 2943, 25.4 KB checked in by chris, 13 months ago (diff)

Log the expected and actual values when comparison failed.

  • Property svn:eol-style set to native
Line 
1// --------------------------------------------------------------------------
2//
3// File
4//              Name:    testcommon.cpp
5//              Purpose: Tests for the code in lib/common
6//              Created: 2003/07/23
7//
8// --------------------------------------------------------------------------
9
10#include "Box.h"
11
12#include <errno.h>
13#include <stdio.h>
14#include <time.h>
15
16#include "Test.h"
17#include "Configuration.h"
18#include "FdGetLine.h"
19#include "Guards.h"
20#include "FileStream.h"
21#include "InvisibleTempFileStream.h"
22#include "IOStreamGetLine.h"
23#include "NamedLock.h"
24#include "ReadGatherStream.h"
25#include "MemBlockStream.h"
26#include "ExcludeList.h"
27#include "CommonException.h"
28#include "Conversion.h"
29#include "autogen_ConversionException.h"
30#include "CollectInBufferStream.h"
31#include "Archive.h"
32#include "Timer.h"
33#include "Logging.h"
34#include "ZeroStream.h"
35#include "PartialReadStream.h"
36
37#include "MemLeakFindOn.h"
38
39using namespace BoxConvert;
40
41void test_conversions()
42{
43        TEST_THAT((Convert<int32_t, const std::string &>(std::string("32"))) == 32);
44        TEST_THAT((Convert<int32_t, const char *>("42")) == 42);
45        TEST_THAT((Convert<int32_t, const char *>("-42")) == -42);
46        TEST_CHECK_THROWS((Convert<int8_t, const char *>("500")), ConversionException, IntOverflowInConvertFromString);
47        TEST_CHECK_THROWS((Convert<int8_t, const char *>("pants")), ConversionException, BadStringRepresentationOfInt);
48        TEST_CHECK_THROWS((Convert<int8_t, const char *>("")), ConversionException, CannotConvertEmptyStringToInt);
49       
50        std::string a(Convert<std::string, int32_t>(63));
51        TEST_THAT(a == "63");
52        std::string b(Convert<std::string, int32_t>(-3473463));
53        TEST_THAT(b == "-3473463");
54        std::string c(Convert<std::string, int16_t>(344));
55        TEST_THAT(c == "344");
56}
57
58ConfigurationVerifyKey verifykeys1_1_1[] =
59{
60        ConfigurationVerifyKey("bing", ConfigTest_Exists),
61        ConfigurationVerifyKey("carrots", ConfigTest_Exists | ConfigTest_IsInt),
62        ConfigurationVerifyKey("terrible", ConfigTest_Exists | ConfigTest_LastEntry)
63};
64
65ConfigurationVerifyKey verifykeys1_1_2[] =
66{
67        ConfigurationVerifyKey("fish", ConfigTest_Exists | ConfigTest_IsInt),
68        ConfigurationVerifyKey("string", ConfigTest_Exists | ConfigTest_LastEntry)
69};
70
71
72ConfigurationVerify verifysub1_1[] = 
73{
74        {
75                "*",
76                0,
77                verifykeys1_1_1,
78                ConfigTest_Exists,
79                0
80        },
81        {
82                "otherthing",
83                0,
84                verifykeys1_1_2,
85                ConfigTest_Exists | ConfigTest_LastEntry,
86                0
87        }
88};
89
90ConfigurationVerifyKey verifykeys1_1[] =
91{
92        ConfigurationVerifyKey("value", ConfigTest_Exists | ConfigTest_IsInt),
93        ConfigurationVerifyKey("string1", ConfigTest_Exists),
94        ConfigurationVerifyKey("string2", ConfigTest_Exists | ConfigTest_LastEntry)
95};
96
97ConfigurationVerifyKey verifykeys1_2[] = 
98{
99        ConfigurationVerifyKey("carrots", ConfigTest_Exists | ConfigTest_IsInt),
100        ConfigurationVerifyKey("string", ConfigTest_Exists | ConfigTest_LastEntry)
101};
102
103ConfigurationVerify verifysub1[] = 
104{
105        {
106                "test1",
107                verifysub1_1,
108                verifykeys1_1,
109                ConfigTest_Exists,
110                0
111        },
112        {
113                "ping",
114                0,
115                verifykeys1_2,
116                ConfigTest_Exists | ConfigTest_LastEntry,
117                0
118        }
119};
120
121ConfigurationVerifyKey verifykeys1[] =
122{
123                ConfigurationVerifyKey("notExpected", 0),
124                ConfigurationVerifyKey("HasDefaultValue", 0, "Lovely default value"),
125                ConfigurationVerifyKey("MultiValue", ConfigTest_MultiValueAllowed),
126                ConfigurationVerifyKey("BoolTrue1", ConfigTest_IsBool),
127                ConfigurationVerifyKey("BoolTrue2", ConfigTest_IsBool),
128                ConfigurationVerifyKey("BoolFalse1", ConfigTest_IsBool),
129                ConfigurationVerifyKey("BoolFalse2", ConfigTest_IsBool),
130                ConfigurationVerifyKey("TOPlevel", 
131                        ConfigTest_LastEntry | ConfigTest_Exists)
132};
133
134ConfigurationVerify verify =
135{
136        "root",
137        verifysub1,
138        verifykeys1,
139        ConfigTest_Exists | ConfigTest_LastEntry,
140        0
141};
142
143class TestLogger : public Logger
144{
145        private:
146        bool mTriggered;
147        Log::Level mTargetLevel;
148
149        public:
150        TestLogger(Log::Level targetLevel) 
151        : mTriggered(false), mTargetLevel(targetLevel)
152        { 
153                Logging::Add(this);
154        }
155        ~TestLogger() 
156        {
157                Logging::Remove(this);
158        }
159
160        bool IsTriggered() { return mTriggered; }
161        void Reset()       { mTriggered = false; }
162
163        virtual bool Log(Log::Level level, const std::string& rFile,
164                int line, std::string& rMessage)
165        {
166                if (level == mTargetLevel)
167                {
168                        mTriggered = true;
169                }
170                return true;
171        }
172
173        virtual const char* GetType() { return "Test"; }
174        virtual void SetProgramName(const std::string& rProgramName) { }
175};
176
177int test(int argc, const char *argv[])
178{
179        // Test PartialReadStream and ReadGatherStream handling of files
180        // over 2GB (refs #2)
181        {
182                char buffer[8];
183
184                ZeroStream zero(0x80000003);
185                zero.Seek(0x7ffffffe, IOStream::SeekType_Absolute);
186                TEST_THAT(zero.GetPosition() == 0x7ffffffe);
187                TEST_THAT(zero.Read(buffer, 8) == 5);
188                TEST_THAT(zero.GetPosition() == 0x80000003);
189                TEST_THAT(zero.Read(buffer, 8) == 0);
190                zero.Seek(0, IOStream::SeekType_Absolute);
191                TEST_THAT(zero.GetPosition() == 0);
192
193                char* buffer2 = new char [0x1000000];
194                TEST_THAT(buffer2 != NULL);
195
196                PartialReadStream part(zero, 0x80000002);
197                for (int i = 0; i < 0x80; i++)
198                {
199                        int read = part.Read(buffer2, 0x1000000);
200                        TEST_THAT(read == 0x1000000);
201                }
202                TEST_THAT(part.Read(buffer, 8) == 2);
203                TEST_THAT(part.Read(buffer, 8) == 0);
204
205                delete [] buffer2;
206
207                ReadGatherStream gather(false);
208                zero.Seek(0, IOStream::SeekType_Absolute);
209                int component = gather.AddComponent(&zero);
210                gather.AddBlock(component, 0x80000002);
211                TEST_THAT(gather.Read(buffer, 8) == 8);
212        }
213
214        // Test self-deleting temporary file streams
215        {
216                std::string tempfile("testfiles/tempfile");
217                TEST_CHECK_THROWS(InvisibleTempFileStream fs(tempfile.c_str()), 
218                        CommonException, OSFileOpenError);
219                InvisibleTempFileStream fs(tempfile.c_str(), O_CREAT);
220
221        #ifdef WIN32
222                // file is still visible under Windows
223                TEST_THAT(TestFileExists(tempfile.c_str()));
224
225                // opening it again should work
226                InvisibleTempFileStream fs2(tempfile.c_str());
227                TEST_THAT(TestFileExists(tempfile.c_str()));
228
229                // opening it to create should work
230                InvisibleTempFileStream fs3(tempfile.c_str(), O_CREAT);
231                TEST_THAT(TestFileExists(tempfile.c_str()));
232
233                // opening it to create exclusively should fail
234                TEST_CHECK_THROWS(InvisibleTempFileStream fs4(tempfile.c_str(), 
235                        O_CREAT | O_EXCL), CommonException, OSFileOpenError);
236
237                fs2.Close();
238        #else
239                // file is not visible under Unix
240                TEST_THAT(!TestFileExists(tempfile.c_str()));
241
242                // opening it again should fail
243                TEST_CHECK_THROWS(InvisibleTempFileStream fs2(tempfile.c_str()),
244                        CommonException, OSFileOpenError);
245
246                // opening it to create should work
247                InvisibleTempFileStream fs3(tempfile.c_str(), O_CREAT);
248                TEST_THAT(!TestFileExists(tempfile.c_str()));
249
250                // opening it to create exclusively should work
251                InvisibleTempFileStream fs4(tempfile.c_str(), O_CREAT | O_EXCL);
252                TEST_THAT(!TestFileExists(tempfile.c_str()));
253
254                fs4.Close();
255        #endif
256
257                fs.Close();
258                fs3.Close();
259
260                // now that it's closed, it should be invisible on all platforms
261                TEST_THAT(!TestFileExists(tempfile.c_str()));
262        }
263
264        // Test that memory leak detection doesn't crash
265        {
266                char *test = new char[1024];
267                delete [] test;
268                MemBlockStream *s = new MemBlockStream(test,12);
269                delete s;
270        }
271
272#ifdef BOX_MEMORY_LEAK_TESTING
273        {
274                Timers::Cleanup();
275
276                TEST_THAT(memleakfinder_numleaks() == 0);
277                void *block = ::malloc(12);
278                TEST_THAT(memleakfinder_numleaks() == 1);
279                void *b2 = ::realloc(block, 128*1024);
280                TEST_THAT(memleakfinder_numleaks() == 1);
281                ::free(b2);
282                TEST_THAT(memleakfinder_numleaks() == 0);
283                char *test = new char[1024];
284                TEST_THAT(memleakfinder_numleaks() == 1);
285                MemBlockStream *s = new MemBlockStream(test,12);
286                TEST_THAT(memleakfinder_numleaks() == 2);
287                delete s;
288                TEST_THAT(memleakfinder_numleaks() == 1);
289                delete [] test;
290                TEST_THAT(memleakfinder_numleaks() == 0);
291
292                Timers::Init();
293        }
294#endif // BOX_MEMORY_LEAK_TESTING
295
296        // test main() initialises timers for us, so uninitialise them
297        Timers::Cleanup();
298       
299        // Check that using timer methods without initialisation
300        // throws an assertion failure. Can only do this in debug mode
301        #ifndef BOX_RELEASE_BUILD
302                TEST_CHECK_THROWS(Timers::Add(*(Timer*)NULL), 
303                        CommonException, AssertFailed);
304                TEST_CHECK_THROWS(Timers::Remove(*(Timer*)NULL), 
305                        CommonException, AssertFailed);
306        #endif
307
308        // TEST_CHECK_THROWS(Timers::Signal(), CommonException, AssertFailed);
309        #ifndef BOX_RELEASE_BUILD
310                TEST_CHECK_THROWS(Timers::Cleanup(), CommonException,
311                        AssertFailed);
312        #endif
313       
314        // Check that we can initialise the timers
315        Timers::Init();
316       
317        // Check that double initialisation throws an exception
318        #ifndef BOX_RELEASE_BUILD
319                TEST_CHECK_THROWS(Timers::Init(), CommonException,
320                        AssertFailed);
321        #endif
322
323        // Check that we can clean up the timers
324        Timers::Cleanup();
325       
326        // Check that double cleanup throws an exception
327        #ifndef BOX_RELEASE_BUILD
328                TEST_CHECK_THROWS(Timers::Cleanup(), CommonException,
329                        AssertFailed);
330        #endif
331
332        Timers::Init();
333
334        Timer t0(0, "t0"); // should never expire
335        Timer t1(1, "t1");
336        Timer t2(2, "t2");
337        Timer t3(3, "t3");
338       
339        TEST_THAT(!t0.HasExpired());
340        TEST_THAT(!t1.HasExpired());
341        TEST_THAT(!t2.HasExpired());
342        TEST_THAT(!t3.HasExpired());
343       
344        safe_sleep(1);
345        TEST_THAT(!t0.HasExpired());
346        TEST_THAT(t1.HasExpired());
347        TEST_THAT(!t2.HasExpired());
348        TEST_THAT(!t3.HasExpired());
349       
350        safe_sleep(1);
351        TEST_THAT(!t0.HasExpired());
352        TEST_THAT(t1.HasExpired());
353        TEST_THAT(t2.HasExpired());
354        TEST_THAT(!t3.HasExpired());
355       
356        t1 = Timer(1, "t1a");
357        t2 = Timer(2, "t2a");
358        TEST_THAT(!t0.HasExpired());
359        TEST_THAT(!t1.HasExpired());
360        TEST_THAT(!t2.HasExpired());
361       
362        safe_sleep(1);
363        TEST_THAT(!t0.HasExpired());
364        TEST_THAT(t1.HasExpired());
365        TEST_THAT(!t2.HasExpired());
366        TEST_THAT(t3.HasExpired());
367
368        // Leave timers initialised for rest of test.
369        // Test main() will cleanup after test finishes.
370
371        static const char *testfilelines[] =
372        {
373                "First line",
374                "Second line",
375                "Third",
376                "",
377                "",
378                "",
379                "sdf hjjk",
380                "",
381                "test",
382                "test#not comment",
383                "test#not comment",
384                "",
385                "nice line",
386                "fish",
387                "",
388                "ping",
389                "",
390                "",
391                "Nothing",
392                "Nothing",
393                0
394        };
395
396        // First, test the FdGetLine class -- rather important this works!
397        {
398                FileHandleGuard<O_RDONLY> file("testfiles"
399                        DIRECTORY_SEPARATOR "fdgetlinetest.txt");
400                FdGetLine getline(file);
401               
402                int l = 0;
403                while(testfilelines[l] != 0)
404                {
405                        TEST_THAT(!getline.IsEOF());
406                        std::string line = getline.GetLine(true);
407                        printf("expected |%s| got |%s|\n", testfilelines[l],
408                                line.c_str());
409                        TEST_LINE(strcmp(testfilelines[l], line.c_str()) == 0,
410                                line);
411                        l++;
412                }
413                TEST_THAT(getline.IsEOF());
414                TEST_CHECK_THROWS(getline.GetLine(true), CommonException, GetLineEOF);
415        }
416        // and again without pre-processing
417        {
418                FileHandleGuard<O_RDONLY> file("testfiles"
419                        DIRECTORY_SEPARATOR "fdgetlinetest.txt");
420                FILE *file2 = fopen("testfiles" DIRECTORY_SEPARATOR
421                        "fdgetlinetest.txt", "r");
422                TEST_THAT_ABORTONFAIL(file2 != 0);
423                FdGetLine getline(file);
424                char ll[512];
425               
426                while(!feof(file2))
427                {
428                        fgets(ll, sizeof(ll), file2);
429                        int e = strlen(ll);
430                        while(e > 0 && (ll[e-1] == '\n' || ll[e-1] == '\r'))
431                        {
432                                e--;
433                        }
434                        ll[e] = '\0';
435               
436                        TEST_THAT(!getline.IsEOF());
437                        std::string line = getline.GetLine(false);
438                        //printf("expected |%s| got |%s|\n", ll, line.c_str());
439                        TEST_THAT(strcmp(ll, line.c_str()) == 0);
440                }
441                TEST_THAT(getline.IsEOF());
442                TEST_CHECK_THROWS(getline.GetLine(true), CommonException, GetLineEOF);
443               
444                fclose(file2);
445        }
446       
447        // Then the IOStream version of get line, seeing as we're here...
448        {
449                FileStream file("testfiles" DIRECTORY_SEPARATOR
450                        "fdgetlinetest.txt", O_RDONLY);
451                IOStreamGetLine getline(file);
452               
453                int l = 0;
454                while(testfilelines[l] != 0)
455                {
456                        TEST_THAT(!getline.IsEOF());
457                        std::string line;
458                        while(!getline.GetLine(line, true))
459                                ;
460                        printf("expected |%s| got |%s|\n", testfilelines[l],
461                                line.c_str());
462                        TEST_LINE(strcmp(testfilelines[l], line.c_str()) == 0,
463                                line);
464                        l++;
465                }
466                TEST_THAT(getline.IsEOF());
467                std::string dummy;
468                TEST_CHECK_THROWS(getline.GetLine(dummy, true), CommonException, GetLineEOF);
469        }
470        // and again without pre-processing
471        {
472                FileStream file("testfiles" DIRECTORY_SEPARATOR
473                        "fdgetlinetest.txt", O_RDONLY);
474                IOStreamGetLine getline(file);
475
476                FILE *file2 = fopen("testfiles" DIRECTORY_SEPARATOR
477                        "fdgetlinetest.txt", "r");
478                TEST_THAT_ABORTONFAIL(file2 != 0);
479                char ll[512];
480               
481                while(!feof(file2))
482                {
483                        fgets(ll, sizeof(ll), file2);
484                        int e = strlen(ll);
485                        while(e > 0 && (ll[e-1] == '\n' || ll[e-1] == '\r'))
486                        {
487                                e--;
488                        }
489                        ll[e] = '\0';
490               
491                        TEST_THAT(!getline.IsEOF());
492                        std::string line;
493                        while(!getline.GetLine(line, false))
494                                ;
495                        //printf("expected |%s| got |%s|\n", ll, line.c_str());
496                        TEST_THAT(strcmp(ll, line.c_str()) == 0);
497                }
498                TEST_THAT(getline.IsEOF());
499                std::string dummy;
500                TEST_CHECK_THROWS(getline.GetLine(dummy, true), CommonException, GetLineEOF);
501               
502                fclose(file2);
503        }
504       
505        // Doesn't exist
506        {
507                std::string errMsg;
508                TEST_CHECK_THROWS(std::auto_ptr<Configuration> pconfig(
509                        Configuration::LoadAndVerify(
510                                "testfiles" DIRECTORY_SEPARATOR "DOESNTEXIST", 
511                                &verify, errMsg)), 
512                        CommonException, OSFileOpenError);
513        }
514
515        // Basic configuration test
516        {
517                std::string errMsg;
518                std::auto_ptr<Configuration> pconfig(
519                        Configuration::LoadAndVerify(
520                                "testfiles" DIRECTORY_SEPARATOR "config1.txt", 
521                                &verify, errMsg));
522                if(!errMsg.empty())
523                {
524                        printf("UNEXPECTED error msg is:\n------\n%s------\n", errMsg.c_str());
525                }
526                TEST_THAT_ABORTONFAIL(pconfig.get() != 0);
527                TEST_THAT(errMsg.empty());
528                TEST_THAT(pconfig->KeyExists("TOPlevel"));
529                TEST_THAT(pconfig->GetKeyValue("TOPlevel") == "value");
530                TEST_THAT(pconfig->KeyExists("MultiValue"));
531                TEST_THAT(pconfig->GetKeyValue("MultiValue") == "single");
532                TEST_THAT(!pconfig->KeyExists("not exist"));
533                TEST_THAT(pconfig->KeyExists("HasDefaultValue"));
534                TEST_THAT(pconfig->GetKeyValue("HasDefaultValue") == "Lovely default value");
535                TEST_CHECK_THROWS(pconfig->GetKeyValue("not exist"), CommonException, ConfigNoKey);
536                // list of keys
537                std::vector<std::string> keylist(pconfig->GetKeyNames());
538                TEST_THAT(keylist.size() == 3);
539                // will be sorted alphanumerically
540                TEST_THAT(keylist[2] == "TOPlevel" && keylist[1] == "MultiValue" && keylist[0] == "HasDefaultValue");
541                // list of sub configurations
542                std::vector<std::string> sublist(pconfig->GetSubConfigurationNames());
543                TEST_THAT(sublist.size() == 2);
544                TEST_THAT(sublist[0] == "test1");
545                TEST_THAT(sublist[1] == "ping");
546                TEST_THAT(pconfig->SubConfigurationExists("test1"));
547                TEST_THAT(pconfig->SubConfigurationExists("ping"));
548                TEST_CHECK_THROWS(pconfig->GetSubConfiguration("nosubconfig"), CommonException, ConfigNoSubConfig);
549                // Get a sub configuration
550                const Configuration &sub1 = pconfig->GetSubConfiguration("test1");
551                TEST_THAT(sub1.GetKeyValueInt("value") == 12);
552                std::vector<std::string> sublist2(sub1.GetSubConfigurationNames());
553                TEST_THAT(sublist2.size() == 4);
554                // And the sub-sub configs
555                const Configuration &sub1_1 = sub1.GetSubConfiguration("subconfig");
556                TEST_THAT(sub1_1.GetKeyValueInt("carrots") == 0x2356);
557                const Configuration &sub1_2 = sub1.GetSubConfiguration("subconfig2");
558                TEST_THAT(sub1_2.GetKeyValueInt("carrots") == -243895);
559                const Configuration &sub1_3 = sub1.GetSubConfiguration("subconfig3");
560                TEST_THAT(sub1_3.GetKeyValueInt("carrots") == 050);
561                TEST_THAT(sub1_3.GetKeyValue("terrible") == "absolutely");
562        }       
563
564        static const char *file[] =
565        {
566                "testfiles" DIRECTORY_SEPARATOR "config2.txt", 
567                        // Value missing from root
568                "testfiles" DIRECTORY_SEPARATOR "config3.txt", 
569                        // Unexpected {
570                "testfiles" DIRECTORY_SEPARATOR "config4.txt", 
571                        // Missing }
572                "testfiles" DIRECTORY_SEPARATOR "config5.txt", 
573                        // { expected, but wasn't there
574                "testfiles" DIRECTORY_SEPARATOR "config6.txt", 
575                        // Duplicate key
576                "testfiles" DIRECTORY_SEPARATOR "config7.txt", 
577                        // Invalid key (no name)
578                "testfiles" DIRECTORY_SEPARATOR "config8.txt", 
579                        // Not all sub blocks terminated
580                "testfiles" DIRECTORY_SEPARATOR "config9.txt", 
581                        // Not valid integer
582                "testfiles" DIRECTORY_SEPARATOR "config9b.txt", 
583                        // Not valid integer
584                "testfiles" DIRECTORY_SEPARATOR "config9c.txt", 
585                        // Not valid integer
586                "testfiles" DIRECTORY_SEPARATOR "config9d.txt", 
587                        // Not valid integer
588                "testfiles" DIRECTORY_SEPARATOR "config10.txt", 
589                        // Missing key (in subblock)
590                "testfiles" DIRECTORY_SEPARATOR "config11.txt", 
591                        // Unknown key
592                "testfiles" DIRECTORY_SEPARATOR "config12.txt", 
593                        // Missing block
594                "testfiles" DIRECTORY_SEPARATOR "config13.txt", 
595                        // Subconfig (wildcarded) should exist, but missing (ie nothing present)
596                "testfiles" DIRECTORY_SEPARATOR "config16.txt", 
597                        // bad boolean value
598                0
599        };
600
601        for(int l = 0; file[l] != 0; ++l)       
602        {
603                std::string errMsg;
604                std::auto_ptr<Configuration> pconfig(Configuration::LoadAndVerify(file[l], &verify, errMsg));
605                TEST_THAT(pconfig.get() == 0);
606                TEST_THAT(!errMsg.empty());
607                printf("(%s) Error msg is:\n------\n%s------\n", file[l], errMsg.c_str());
608        }
609       
610        // Check that multivalues happen as expected
611        // (single value in a multivalue already checked)
612        {
613                std::string errMsg;
614                std::auto_ptr<Configuration> pconfig(
615                        Configuration::LoadAndVerify(
616                                "testfiles" DIRECTORY_SEPARATOR "config14.txt",
617                        &verify, errMsg));
618                TEST_THAT(pconfig.get() != 0);
619                TEST_THAT(errMsg.empty());
620                TEST_THAT(pconfig->KeyExists("MultiValue"));
621                // values are separated by a specific character
622                std::string expectedvalue("value1");
623                expectedvalue += Configuration::MultiValueSeparator;
624                expectedvalue += "secondvalue";
625                TEST_THAT(pconfig->GetKeyValue("MultiValue") == expectedvalue);
626        }
627
628        // Check boolean values
629        {
630                std::string errMsg;
631                std::auto_ptr<Configuration> pconfig(
632                        Configuration::LoadAndVerify(
633                                "testfiles" DIRECTORY_SEPARATOR "config15.txt",
634                        &verify, errMsg));
635                TEST_THAT(pconfig.get() != 0);
636                TEST_THAT(errMsg.empty());
637                TEST_THAT(pconfig->GetKeyValueBool("BoolTrue1") == true);
638                TEST_THAT(pconfig->GetKeyValueBool("BoolTrue2") == true);
639                TEST_THAT(pconfig->GetKeyValueBool("BoolFalse1") == false);
640                TEST_THAT(pconfig->GetKeyValueBool("BoolFalse2") == false);
641        }
642       
643        // Test named locks
644        {
645                NamedLock lock1;
646                // Try and get a lock on a name in a directory which doesn't exist
647                TEST_CHECK_THROWS(lock1.TryAndGetLock(
648                                "testfiles" 
649                                DIRECTORY_SEPARATOR "non-exist"
650                                DIRECTORY_SEPARATOR "lock"), 
651                        CommonException, OSFileError);
652
653                // And a more resonable request
654                TEST_THAT(lock1.TryAndGetLock(
655                        "testfiles" DIRECTORY_SEPARATOR "lock1") == true);
656
657                // Try to lock something using the same lock
658                TEST_CHECK_THROWS(
659                        lock1.TryAndGetLock(
660                                "testfiles" 
661                                DIRECTORY_SEPARATOR "non-exist"
662                                DIRECTORY_SEPARATOR "lock2"), 
663                        CommonException, NamedLockAlreadyLockingSomething);             
664#if defined(HAVE_FLOCK) || HAVE_DECL_O_EXLOCK
665                // And again on that name
666                NamedLock lock2;
667                TEST_THAT(lock2.TryAndGetLock(
668                        "testfiles" DIRECTORY_SEPARATOR "lock1") == false);
669#endif
670        }
671        {
672                // Check that it unlocked when it went out of scope
673                NamedLock lock3;
674                TEST_THAT(lock3.TryAndGetLock(
675                        "testfiles" DIRECTORY_SEPARATOR "lock1") == true);
676        }
677        {
678                // And unlocking works
679                NamedLock lock4;
680                TEST_CHECK_THROWS(lock4.ReleaseLock(), CommonException, 
681                        NamedLockNotHeld);
682                TEST_THAT(lock4.TryAndGetLock(
683                        "testfiles" DIRECTORY_SEPARATOR "lock4") == true);
684                lock4.ReleaseLock();
685                NamedLock lock5;
686                TEST_THAT(lock5.TryAndGetLock(
687                        "testfiles" DIRECTORY_SEPARATOR "lock4") == true);
688                // And can reuse it
689                TEST_THAT(lock4.TryAndGetLock(
690                        "testfiles" DIRECTORY_SEPARATOR "lock5") == true);
691        }
692
693        // Test the ReadGatherStream
694        {
695                #define GATHER_DATA1 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
696                #define GATHER_DATA2 "ZYZWVUTSRQPOMNOLKJIHGFEDCBA9876543210zyxwvutsrqpomno"
697
698                // Make two streams
699                MemBlockStream s1(GATHER_DATA1, sizeof(GATHER_DATA1));
700                MemBlockStream s2(GATHER_DATA2, sizeof(GATHER_DATA2));
701
702                // And a gather stream
703                ReadGatherStream gather(false /* no deletion */);
704               
705                // Add the streams
706                int s1_c = gather.AddComponent(&s1);
707                int s2_c = gather.AddComponent(&s2);
708                TEST_THAT(s1_c == 0);
709                TEST_THAT(s2_c == 1);
710               
711                // Set up some blocks
712                gather.AddBlock(s1_c, 11);
713                gather.AddBlock(s1_c, 2);
714                gather.AddBlock(s1_c, 8, true, 2);
715                gather.AddBlock(s2_c, 20);
716                gather.AddBlock(s1_c, 20);
717                gather.AddBlock(s2_c, 25);
718                gather.AddBlock(s1_c, 10, true, 0);
719                #define GATHER_RESULT "0123456789abc23456789ZYZWVUTSRQPOMNOLKJIHabcdefghijklmnopqrstGFEDCBA9876543210zyxwvuts0123456789"
720
721                // Read them in...
722                char buffer[1024];
723                unsigned int r = 0;
724                while(r < sizeof(GATHER_RESULT) - 1)
725                {
726                        int s = gather.Read(buffer + r, 7);
727                        r += s;
728                       
729                        TEST_THAT(gather.GetPosition() == r);
730                        if(r < sizeof(GATHER_RESULT) - 1)
731                        {
732                                TEST_THAT(gather.StreamDataLeft());
733                                TEST_THAT(static_cast<size_t>(gather.BytesLeftToRead()) == sizeof(GATHER_RESULT) - 1 - r);
734                        }
735                        else
736                        {
737                                TEST_THAT(!gather.StreamDataLeft());
738                                TEST_THAT(gather.BytesLeftToRead() == 0);
739                        }
740                }
741                TEST_THAT(r == sizeof(GATHER_RESULT) - 1);
742                TEST_THAT(::memcmp(buffer, GATHER_RESULT, sizeof(GATHER_RESULT) - 1) == 0);
743        }
744       
745        // Test ExcludeList
746        {
747                ExcludeList elist;
748                // Check assumption
749                TEST_THAT(Configuration::MultiValueSeparator == '\x01');
750                // Add definite entries
751                elist.AddDefiniteEntries(std::string("\x01"));
752                elist.AddDefiniteEntries(std::string(""));
753                elist.AddDefiniteEntries(std::string("Definite1\x01/dir/DefNumberTwo\x01\x01ThingDefThree"));
754                elist.AddDefiniteEntries(std::string("AnotherDef"));
755                TEST_THAT(elist.SizeOfDefiniteList() == 4);
756
757                // Add regex entries
758                #ifdef HAVE_REGEX_SUPPORT
759                        elist.AddRegexEntries(std::string("[a-d]+\\.reg$" "\x01" "EXCLUDE" "\x01" "^exclude$"));
760                        elist.AddRegexEntries(std::string(""));
761                        TEST_CHECK_THROWS(elist.AddRegexEntries(std::string("[:not_valid")), CommonException, BadRegularExpression);
762                        TEST_THAT(elist.SizeOfRegexList() == 3);
763                #else
764                        TEST_CHECK_THROWS(elist.AddRegexEntries(std::string("[a-d]+\\.reg$" "\x01" "EXCLUDE" "\x01" "^exclude$")), CommonException, RegexNotSupportedOnThisPlatform);
765                        TEST_THAT(elist.SizeOfRegexList() == 0);
766                #endif
767
768                #ifdef WIN32
769                #define CASE_SENSITIVE false
770                #else
771                #define CASE_SENSITIVE true
772                #endif
773
774                // Try some matches!
775                TEST_THAT(elist.IsExcluded(std::string("Definite1")) == true);
776                TEST_THAT(elist.IsExcluded(std::string("/dir/DefNumberTwo")) == true);
777                TEST_THAT(elist.IsExcluded(std::string("ThingDefThree")) == true);
778                TEST_THAT(elist.IsExcluded(std::string("AnotherDef")) == true);
779                TEST_THAT(elist.IsExcluded(std::string("dir/DefNumberTwo")) == false);
780
781                // Try some case insensitive matches,
782                // that should pass on Win32 and fail elsewhere
783                TEST_THAT(elist.IsExcluded("DEFINITe1") 
784                        == !CASE_SENSITIVE);
785                TEST_THAT(elist.IsExcluded("/Dir/DefNumberTwo") 
786                        == !CASE_SENSITIVE);
787                TEST_THAT(elist.IsExcluded("thingdefthree") 
788                        == !CASE_SENSITIVE);
789
790                #ifdef HAVE_REGEX_SUPPORT
791                        TEST_THAT(elist.IsExcluded(std::string("b.reg")) == true);
792                        TEST_THAT(elist.IsExcluded(std::string("B.reg")) == !CASE_SENSITIVE);
793                        TEST_THAT(elist.IsExcluded(std::string("b.Reg")) == !CASE_SENSITIVE);
794                        TEST_THAT(elist.IsExcluded(std::string("e.reg")) == false);
795                        TEST_THAT(elist.IsExcluded(std::string("e.Reg")) == false);
796                        TEST_THAT(elist.IsExcluded(std::string("DEfinite1")) == !CASE_SENSITIVE);
797                        TEST_THAT(elist.IsExcluded(std::string("DEXCLUDEfinite1")) == true);
798                        TEST_THAT(elist.IsExcluded(std::string("DEfinitexclude1")) == !CASE_SENSITIVE);
799                        TEST_THAT(elist.IsExcluded(std::string("exclude")) == true);
800                        TEST_THAT(elist.IsExcluded(std::string("ExcludE")) == !CASE_SENSITIVE);
801                #endif
802
803                #undef CASE_SENSITIVE
804
805                TestLogger logger(Log::WARNING);
806                TEST_THAT(!logger.IsTriggered());
807                elist.AddDefiniteEntries(std::string("/foo"));
808                TEST_THAT(!logger.IsTriggered());
809                elist.AddDefiniteEntries(std::string("/foo/"));
810                TEST_THAT(logger.IsTriggered());
811                logger.Reset();
812                elist.AddDefiniteEntries(std::string("/foo" 
813                        DIRECTORY_SEPARATOR));
814                TEST_THAT(logger.IsTriggered());
815                logger.Reset();
816                elist.AddDefiniteEntries(std::string("/foo" 
817                        DIRECTORY_SEPARATOR "bar\x01/foo"));
818                TEST_THAT(!logger.IsTriggered());
819                elist.AddDefiniteEntries(std::string("/foo" 
820                        DIRECTORY_SEPARATOR "bar\x01/foo" 
821                        DIRECTORY_SEPARATOR));
822                TEST_THAT(logger.IsTriggered());
823        }
824
825        test_conversions();
826
827        // test that we can use Archive and CollectInBufferStream
828        // to read and write arbitrary types to a memory buffer
829
830        {
831                CollectInBufferStream buffer;
832                ASSERT(buffer.GetPosition() == 0);
833
834                {
835                        Archive archive(buffer, 0);
836                        ASSERT(buffer.GetPosition() == 0);
837
838                        archive.Write((bool) true);
839                        archive.Write((bool) false);
840                        archive.Write((int) 0x12345678);
841                        archive.Write((int) 0x87654321);
842                        archive.Write((int64_t)  0x0badfeedcafebabeLL);
843                        archive.Write((uint64_t) 0xfeedfacedeadf00dLL);
844                        archive.Write((uint8_t)  0x01);
845                        archive.Write((uint8_t)  0xfe);
846                        archive.Write(std::string("hello world!"));
847                        archive.Write(std::string("goodbye cruel world!"));
848                }
849
850                CollectInBufferStream buf2;
851                buf2.Write(buffer.GetBuffer(), buffer.GetSize());
852                TEST_THAT(buf2.GetPosition() == buffer.GetSize());
853
854                buf2.SetForReading();
855                TEST_THAT(buf2.GetPosition() == 0);
856
857                {
858                        Archive archive(buf2, 0);
859                        TEST_THAT(buf2.GetPosition() == 0);
860
861                        bool b;
862                        archive.Read(b); TEST_THAT(b == true);
863                        archive.Read(b); TEST_THAT(b == false);
864
865                        int i;
866                        archive.Read(i); TEST_THAT(i == 0x12345678);
867                        archive.Read(i); TEST_THAT((unsigned int)i == 0x87654321);
868
869                        uint64_t i64;
870                        archive.Read(i64); TEST_THAT(i64 == 0x0badfeedcafebabeLL);
871                        archive.Read(i64); TEST_THAT(i64 == 0xfeedfacedeadf00dLL);
872
873                        uint8_t i8;
874                        archive.Read(i8); TEST_THAT(i8 == 0x01);
875                        archive.Read(i8); TEST_THAT(i8 == 0xfe);
876
877                        std::string s;
878                        archive.Read(s); TEST_THAT(s == "hello world!");
879                        archive.Read(s); TEST_THAT(s == "goodbye cruel world!");
880
881                        TEST_THAT(!buf2.StreamDataLeft());
882                }
883        }
884
885        return 0;
886}
Note: See TracBrowser for help on using the repository browser.