summaryrefslogtreecommitdiff
path: root/test/common
diff options
context:
space:
mode:
Diffstat (limited to 'test/common')
-rwxr-xr-xtest/common/testcommon.cpp515
-rwxr-xr-xtest/common/testfiles/config1.txt40
-rwxr-xr-xtest/common/testfiles/config10.txt37
-rwxr-xr-xtest/common/testfiles/config11.txt39
-rwxr-xr-xtest/common/testfiles/config12.txt33
-rwxr-xr-xtest/common/testfiles/config13.txt15
-rwxr-xr-xtest/common/testfiles/config14.txt41
-rwxr-xr-xtest/common/testfiles/config15.txt45
-rwxr-xr-xtest/common/testfiles/config16.txt42
-rwxr-xr-xtest/common/testfiles/config2.txt39
-rwxr-xr-xtest/common/testfiles/config3.txt39
-rwxr-xr-xtest/common/testfiles/config4.txt40
-rwxr-xr-xtest/common/testfiles/config5.txt37
-rwxr-xr-xtest/common/testfiles/config6.txt39
-rwxr-xr-xtest/common/testfiles/config7.txt39
-rwxr-xr-xtest/common/testfiles/config8.txt37
-rwxr-xr-xtest/common/testfiles/config9.txt38
-rwxr-xr-xtest/common/testfiles/config9b.txt38
-rwxr-xr-xtest/common/testfiles/config9c.txt38
-rwxr-xr-xtest/common/testfiles/config9d.txt38
-rwxr-xr-xtest/common/testfiles/fdgetlinetest.txt20
21 files changed, 1249 insertions, 0 deletions
diff --git a/test/common/testcommon.cpp b/test/common/testcommon.cpp
new file mode 100755
index 00000000..c6d0e52f
--- /dev/null
+++ b/test/common/testcommon.cpp
@@ -0,0 +1,515 @@
+// --------------------------------------------------------------------------
+//
+// File
+// Name: testcommon.cpp
+// Purpose: Tests for the code in lib/common
+// Created: 2003/07/23
+//
+// --------------------------------------------------------------------------
+
+#include "Box.h"
+
+#include <stdio.h>
+
+#include "Test.h"
+#include "Configuration.h"
+#include "FdGetLine.h"
+#include "Guards.h"
+#include "FileStream.h"
+#include "IOStreamGetLine.h"
+#include "NamedLock.h"
+#include "ReadGatherStream.h"
+#include "MemBlockStream.h"
+#include "ExcludeList.h"
+#include "CommonException.h"
+#include "Conversion.h"
+#include "autogen_ConversionException.h"
+
+#include "MemLeakFindOn.h"
+
+using namespace BoxConvert;
+
+void test_conversions()
+{
+ TEST_THAT((Convert<int32_t, const std::string &>(std::string("32"))) == 32);
+ TEST_THAT((Convert<int32_t, const char *>("42")) == 42);
+ TEST_THAT((Convert<int32_t, const char *>("-42")) == -42);
+ TEST_CHECK_THROWS((Convert<int8_t, const char *>("500")), ConversionException, IntOverflowInConvertFromString);
+ TEST_CHECK_THROWS((Convert<int8_t, const char *>("pants")), ConversionException, BadStringRepresentationOfInt);
+ TEST_CHECK_THROWS((Convert<int8_t, const char *>("")), ConversionException, CannotConvertEmptyStringToInt);
+
+ std::string a(Convert<std::string, int32_t>(63));
+ TEST_THAT(a == "63");
+ std::string b(Convert<std::string, int32_t>(-3473463));
+ TEST_THAT(b == "-3473463");
+ std::string c(Convert<std::string, int16_t>(344));
+ TEST_THAT(c == "344");
+}
+
+ConfigurationVerifyKey verifykeys1_1_1[] =
+{
+ {"bing", 0, ConfigTest_Exists, 0},
+ {"carrots", 0, ConfigTest_Exists | ConfigTest_IsInt, 0},
+ {"terrible", 0, ConfigTest_Exists | ConfigTest_LastEntry, 0}
+};
+
+ConfigurationVerifyKey verifykeys1_1_2[] =
+{
+ {"fish", 0, ConfigTest_Exists | ConfigTest_IsInt, 0},
+ {"string", 0, ConfigTest_Exists | ConfigTest_LastEntry, 0}
+};
+
+
+ConfigurationVerify verifysub1_1[] =
+{
+ {
+ "*",
+ 0,
+ verifykeys1_1_1,
+ ConfigTest_Exists,
+ 0
+ },
+ {
+ "otherthing",
+ 0,
+ verifykeys1_1_2,
+ ConfigTest_Exists | ConfigTest_LastEntry,
+ 0
+ }
+};
+
+ConfigurationVerifyKey verifykeys1_1[] =
+{
+ {"value", 0, ConfigTest_Exists | ConfigTest_IsInt, 0},
+ {"string1", 0, ConfigTest_Exists, 0},
+ {"string2", 0, ConfigTest_Exists | ConfigTest_LastEntry, 0}
+};
+
+ConfigurationVerifyKey verifykeys1_2[] =
+{
+ {"carrots", 0, ConfigTest_Exists | ConfigTest_IsInt, 0},
+ {"string", 0, ConfigTest_Exists | ConfigTest_LastEntry, 0}
+};
+
+ConfigurationVerify verifysub1[] =
+{
+ {
+ "test1",
+ verifysub1_1,
+ verifykeys1_1,
+ ConfigTest_Exists,
+ 0
+ },
+ {
+ "ping",
+ 0,
+ verifykeys1_2,
+ ConfigTest_Exists | ConfigTest_LastEntry,
+ 0
+ }
+};
+
+ConfigurationVerifyKey verifykeys1[] =
+{
+ {"notExpected", 0, 0, 0},
+ {"HasDefaultValue", "Lovely default value", 0, 0},
+ {"MultiValue", 0, ConfigTest_MultiValueAllowed, 0},
+ {"BoolTrue1", 0, ConfigTest_IsBool, 0},
+ {"BoolTrue2", 0, ConfigTest_IsBool, 0},
+ {"BoolFalse1", 0, ConfigTest_IsBool, 0},
+ {"BoolFalse2", 0, ConfigTest_IsBool, 0},
+ {"TOPlevel", 0, ConfigTest_LastEntry | ConfigTest_Exists, 0}
+};
+
+ConfigurationVerify verify =
+{
+ "root",
+ verifysub1,
+ verifykeys1,
+ ConfigTest_Exists | ConfigTest_LastEntry,
+ 0
+};
+
+int test(int argc, const char *argv[])
+{
+ // Test memory leak detection
+#ifdef BOX_MEMORY_LEAK_TESTING
+ {
+ TEST_THAT(memleakfinder_numleaks() == 0);
+ void *block = ::malloc(12);
+ TEST_THAT(memleakfinder_numleaks() == 1);
+ void *b2 = ::realloc(block, 128*1024);
+ TEST_THAT(block != b2);
+ TEST_THAT(memleakfinder_numleaks() == 1);
+ ::free(b2);
+ TEST_THAT(memleakfinder_numleaks() == 0);
+ char *test = new char[1024];
+ TEST_THAT(memleakfinder_numleaks() == 1);
+ MemBlockStream *s = new MemBlockStream(test,12);
+ TEST_THAT(memleakfinder_numleaks() == 2);
+ delete s;
+ TEST_THAT(memleakfinder_numleaks() == 1);
+ delete [] test;
+ TEST_THAT(memleakfinder_numleaks() == 0);
+ }
+#endif // BOX_MEMORY_LEAK_TESTING
+
+
+ static char *testfilelines[] =
+ {
+ "First line",
+ "Second line",
+ "Third",
+ "",
+ "",
+ "",
+ "sdf hjjk",
+ "",
+ "test",
+ "test#not comment",
+ "test#not comment",
+ "",
+ "nice line",
+ "fish",
+ "",
+ "ping",
+ "",
+ "",
+ "Nothing",
+ "Nothing",
+ 0
+ };
+
+ // First, test the FdGetLine class -- rather important this works!
+ {
+ FileHandleGuard<O_RDONLY> file("testfiles/fdgetlinetest.txt");
+ FdGetLine getline(file);
+
+ int l = 0;
+ while(testfilelines[l] != 0)
+ {
+ TEST_THAT(!getline.IsEOF());
+ std::string line = getline.GetLine(true);
+ //printf("expected |%s| got |%s|\n", lines[l], line.c_str());
+ TEST_THAT(strcmp(testfilelines[l], line.c_str()) == 0);
+ l++;
+ }
+ TEST_THAT(getline.IsEOF());
+ TEST_CHECK_THROWS(getline.GetLine(true), CommonException, GetLineEOF);
+ }
+ // and again without pre-processing
+ {
+ FileHandleGuard<O_RDONLY> file("testfiles/fdgetlinetest.txt");
+ FILE *file2 = fopen("testfiles/fdgetlinetest.txt", "r");
+ TEST_THAT_ABORTONFAIL(file2 != 0);
+ FdGetLine getline(file);
+ char ll[512];
+
+ while(!feof(file2))
+ {
+ fgets(ll, sizeof(ll), file2);
+ int e = strlen(ll);
+ while(e > 0 && (ll[e-1] == '\n' || ll[e-1] == '\r'))
+ {
+ e--;
+ }
+ ll[e] = '\0';
+
+ TEST_THAT(!getline.IsEOF());
+ std::string line = getline.GetLine(false);
+ //printf("expected |%s| got |%s|\n", ll, line.c_str());
+ TEST_THAT(strcmp(ll, line.c_str()) == 0);
+ }
+ TEST_THAT(getline.IsEOF());
+ TEST_CHECK_THROWS(getline.GetLine(true), CommonException, GetLineEOF);
+
+ fclose(file2);
+ }
+
+ // Then the IOStream version of get line, seeing as we're here...
+ {
+ FileStream file("testfiles/fdgetlinetest.txt", O_RDONLY);
+ IOStreamGetLine getline(file);
+
+ int l = 0;
+ while(testfilelines[l] != 0)
+ {
+ TEST_THAT(!getline.IsEOF());
+ std::string line;
+ while(!getline.GetLine(line, true))
+ ;
+ //printf("expected |%s| got |%s|\n", lines[l], line.c_str());
+ TEST_THAT(strcmp(testfilelines[l], line.c_str()) == 0);
+ l++;
+ }
+ TEST_THAT(getline.IsEOF());
+ std::string dummy;
+ TEST_CHECK_THROWS(getline.GetLine(dummy, true), CommonException, GetLineEOF);
+ }
+ // and again without pre-processing
+ {
+ FileStream file("testfiles/fdgetlinetest.txt", O_RDONLY);
+ IOStreamGetLine getline(file);
+
+ FILE *file2 = fopen("testfiles/fdgetlinetest.txt", "r");
+ TEST_THAT_ABORTONFAIL(file2 != 0);
+ char ll[512];
+
+ while(!feof(file2))
+ {
+ fgets(ll, sizeof(ll), file2);
+ int e = strlen(ll);
+ while(e > 0 && (ll[e-1] == '\n' || ll[e-1] == '\r'))
+ {
+ e--;
+ }
+ ll[e] = '\0';
+
+ TEST_THAT(!getline.IsEOF());
+ std::string line;
+ while(!getline.GetLine(line, false))
+ ;
+ //printf("expected |%s| got |%s|\n", ll, line.c_str());
+ TEST_THAT(strcmp(ll, line.c_str()) == 0);
+ }
+ TEST_THAT(getline.IsEOF());
+ std::string dummy;
+ TEST_CHECK_THROWS(getline.GetLine(dummy, true), CommonException, GetLineEOF);
+
+ fclose(file2);
+ }
+
+ // Doesn't exist
+ {
+ std::string errMsg;
+ TEST_CHECK_THROWS(std::auto_ptr<Configuration> pconfig(Configuration::LoadAndVerify("testfiles/DOESNTEXIST", &verify, errMsg)), CommonException, OSFileOpenError);
+ }
+
+ // Basic configuration test
+ {
+ std::string errMsg;
+ std::auto_ptr<Configuration> pconfig(Configuration::LoadAndVerify("testfiles/config1.txt", &verify, errMsg));
+ if(!errMsg.empty())
+ {
+ printf("UNEXPECTED error msg is:\n------\n%s------\n", errMsg.c_str());
+ }
+ TEST_THAT_ABORTONFAIL(pconfig.get() != 0);
+ TEST_THAT(errMsg.empty());
+ TEST_THAT(pconfig->KeyExists("TOPlevel"));
+ TEST_THAT(pconfig->GetKeyValue("TOPlevel") == "value");
+ TEST_THAT(pconfig->KeyExists("MultiValue"));
+ TEST_THAT(pconfig->GetKeyValue("MultiValue") == "single");
+ TEST_THAT(!pconfig->KeyExists("not exist"));
+ TEST_THAT(pconfig->KeyExists("HasDefaultValue"));
+ TEST_THAT(pconfig->GetKeyValue("HasDefaultValue") == "Lovely default value");
+ TEST_CHECK_THROWS(pconfig->GetKeyValue("not exist"), CommonException, ConfigNoKey);
+ // list of keys
+ std::vector<std::string> keylist(pconfig->GetKeyNames());
+ TEST_THAT(keylist.size() == 3);
+ // will be sorted alphanumerically
+ TEST_THAT(keylist[2] == "TOPlevel" && keylist[1] == "MultiValue" && keylist[0] == "HasDefaultValue");
+ // list of sub configurations
+ std::vector<std::string> sublist(pconfig->GetSubConfigurationNames());
+ TEST_THAT(sublist.size() == 2);
+ TEST_THAT(sublist[0] == "test1");
+ TEST_THAT(sublist[1] == "ping");
+ TEST_THAT(pconfig->SubConfigurationExists("test1"));
+ TEST_THAT(pconfig->SubConfigurationExists("ping"));
+ TEST_CHECK_THROWS(pconfig->GetSubConfiguration("nosubconfig"), CommonException, ConfigNoSubConfig);
+ // Get a sub configuration
+ const Configuration &sub1 = pconfig->GetSubConfiguration("test1");
+ TEST_THAT(sub1.GetKeyValueInt("value") == 12);
+ std::vector<std::string> sublist2(sub1.GetSubConfigurationNames());
+ TEST_THAT(sublist2.size() == 4);
+ // And the sub-sub configs
+ const Configuration &sub1_1 = sub1.GetSubConfiguration("subconfig");
+ TEST_THAT(sub1_1.GetKeyValueInt("carrots") == 0x2356);
+ const Configuration &sub1_2 = sub1.GetSubConfiguration("subconfig2");
+ TEST_THAT(sub1_2.GetKeyValueInt("carrots") == -243895);
+ const Configuration &sub1_3 = sub1.GetSubConfiguration("subconfig3");
+ TEST_THAT(sub1_3.GetKeyValueInt("carrots") == 050);
+ TEST_THAT(sub1_3.GetKeyValue("terrible") == "absolutely");
+ }
+
+ static const char *file[] =
+ {
+ "testfiles/config2.txt", // Value missing from root
+ "testfiles/config3.txt", // Unexpected {
+ "testfiles/config4.txt", // Missing }
+ "testfiles/config5.txt", // { expected, but wasn't there
+ "testfiles/config6.txt", // Duplicate key
+ "testfiles/config7.txt", // Invalid key (no name)
+ "testfiles/config8.txt", // Not all sub blocks terminated
+ "testfiles/config9.txt", // Not valid integer
+ "testfiles/config9b.txt", // Not valid integer
+ "testfiles/config9c.txt", // Not valid integer
+ "testfiles/config9d.txt", // Not valid integer
+ "testfiles/config10.txt", // Missing key (in subblock)
+ "testfiles/config11.txt", // Unknown key
+ "testfiles/config12.txt", // Missing block
+ "testfiles/config13.txt", // Subconfig (wildcarded) should exist, but missing (ie nothing present)
+ "testfiles/config16.txt", // bad boolean value
+ 0
+ };
+
+ for(int l = 0; file[l] != 0; ++l)
+ {
+ std::string errMsg;
+ std::auto_ptr<Configuration> pconfig(Configuration::LoadAndVerify(file[l], &verify, errMsg));
+ TEST_THAT(pconfig.get() == 0);
+ TEST_THAT(!errMsg.empty());
+ printf("(%s) Error msg is:\n------\n%s------\n", file[l], errMsg.c_str());
+ }
+
+ // Check that multivalues happen as expected
+ // (single value in a multivalue already checked)
+ {
+ std::string errMsg;
+ std::auto_ptr<Configuration> pconfig(Configuration::LoadAndVerify("testfiles/config14.txt", &verify, errMsg));
+ TEST_THAT(pconfig.get() != 0);
+ TEST_THAT(errMsg.empty());
+ TEST_THAT(pconfig->KeyExists("MultiValue"));
+ // values are separated by a specific character
+ std::string expectedvalue("value1");
+ expectedvalue += Configuration::MultiValueSeparator;
+ expectedvalue += "secondvalue";
+ TEST_THAT(pconfig->GetKeyValue("MultiValue") == expectedvalue);
+ }
+
+ // Check boolean values
+ {
+ std::string errMsg;
+ std::auto_ptr<Configuration> pconfig(Configuration::LoadAndVerify("testfiles/config15.txt", &verify, errMsg));
+ TEST_THAT(pconfig.get() != 0);
+ TEST_THAT(errMsg.empty());
+ TEST_THAT(pconfig->GetKeyValueBool("BoolTrue1") == true);
+ TEST_THAT(pconfig->GetKeyValueBool("BoolTrue2") == true);
+ TEST_THAT(pconfig->GetKeyValueBool("BoolFalse1") == false);
+ TEST_THAT(pconfig->GetKeyValueBool("BoolFalse2") == false);
+ }
+
+ // Test named locks
+ {
+ NamedLock lock1;
+ // Try and get a lock on a name in a directory which doesn't exist
+ TEST_CHECK_THROWS(lock1.TryAndGetLock("testfiles/non-exist/lock"), CommonException, OSFileError);
+ // And a more resonable request
+ TEST_THAT(lock1.TryAndGetLock("testfiles/lock1") == true);
+ // Try to lock something using the same lock
+ TEST_CHECK_THROWS(lock1.TryAndGetLock("testfiles/non-exist/lock2"), CommonException, NamedLockAlreadyLockingSomething);
+ // And again on that name
+ NamedLock lock2;
+ TEST_THAT(lock2.TryAndGetLock("testfiles/lock1") == false);
+ }
+ {
+ // Check that it unlocked when it went out of scope
+ NamedLock lock3;
+ TEST_THAT(lock3.TryAndGetLock("testfiles/lock1") == true);
+ }
+ {
+ // And unlocking works
+ NamedLock lock4;
+ TEST_CHECK_THROWS(lock4.ReleaseLock(), CommonException, NamedLockNotHeld);
+ TEST_THAT(lock4.TryAndGetLock("testfiles/lock4") == true);
+ lock4.ReleaseLock();
+ NamedLock lock5;
+ TEST_THAT(lock5.TryAndGetLock("testfiles/lock4") == true);
+ // And can reuse it
+ TEST_THAT(lock4.TryAndGetLock("testfiles/lock5") == true);
+ }
+
+ // Test the ReadGatherStream
+ {
+ #define GATHER_DATA1 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ #define GATHER_DATA2 "ZYZWVUTSRQPOMNOLKJIHGFEDCBA9876543210zyxwvutsrqpomno"
+
+ // Make two streams
+ MemBlockStream s1(GATHER_DATA1, sizeof(GATHER_DATA1));
+ MemBlockStream s2(GATHER_DATA2, sizeof(GATHER_DATA2));
+
+ // And a gather stream
+ ReadGatherStream gather(false /* no deletion */);
+
+ // Add the streams
+ int s1_c = gather.AddComponent(&s1);
+ int s2_c = gather.AddComponent(&s2);
+ TEST_THAT(s1_c == 0);
+ TEST_THAT(s2_c == 1);
+
+ // Set up some blocks
+ gather.AddBlock(s1_c, 11);
+ gather.AddBlock(s1_c, 2);
+ gather.AddBlock(s1_c, 8, true, 2);
+ gather.AddBlock(s2_c, 20);
+ gather.AddBlock(s1_c, 20);
+ gather.AddBlock(s2_c, 25);
+ gather.AddBlock(s1_c, 10, true, 0);
+ #define GATHER_RESULT "0123456789abc23456789ZYZWVUTSRQPOMNOLKJIHabcdefghijklmnopqrstGFEDCBA9876543210zyxwvuts0123456789"
+
+ // Read them in...
+ char buffer[1024];
+ unsigned int r = 0;
+ while(r < sizeof(GATHER_RESULT) - 1)
+ {
+ int s = gather.Read(buffer + r, 7);
+ r += s;
+
+ TEST_THAT(gather.GetPosition() == r);
+ if(r < sizeof(GATHER_RESULT) - 1)
+ {
+ TEST_THAT(gather.StreamDataLeft());
+ TEST_THAT(static_cast<size_t>(gather.BytesLeftToRead()) == sizeof(GATHER_RESULT) - 1 - r);
+ }
+ else
+ {
+ TEST_THAT(!gather.StreamDataLeft());
+ TEST_THAT(gather.BytesLeftToRead() == 0);
+ }
+ }
+ TEST_THAT(r == sizeof(GATHER_RESULT) - 1);
+ TEST_THAT(::memcmp(buffer, GATHER_RESULT, sizeof(GATHER_RESULT) - 1) == 0);
+ }
+
+ // Test ExcludeList
+ {
+ ExcludeList elist;
+ // Check assumption
+ TEST_THAT(Configuration::MultiValueSeparator == '\x01');
+ // Add definite entries
+ elist.AddDefiniteEntries(std::string("\x01"));
+ elist.AddDefiniteEntries(std::string(""));
+ elist.AddDefiniteEntries(std::string("Definite1\x01/dir/DefNumberTwo\x01\x01ThingDefThree"));
+ elist.AddDefiniteEntries(std::string("AnotherDef"));
+ TEST_THAT(elist.SizeOfDefiniteList() == 4);
+
+ // Add regex entries
+ #ifndef PLATFORM_REGEX_NOT_SUPPORTED
+ elist.AddRegexEntries(std::string("[a-d]+\\.reg$" "\x01" "EXCLUDE" "\x01" "^exclude$"));
+ elist.AddRegexEntries(std::string(""));
+ TEST_CHECK_THROWS(elist.AddRegexEntries(std::string("[:not_valid")), CommonException, BadRegularExpression);
+ TEST_THAT(elist.SizeOfRegexList() == 3);
+ #else
+ TEST_CHECK_THROWS(elist.AddRegexEntries(std::string("[a-d]+\\.reg$" "\x01" "EXCLUDE" "\x01" "^exclude$")), CommonException, RegexNotSupportedOnThisPlatform);
+ TEST_THAT(elist.SizeOfRegexList() == 0);
+ #endif
+ // Try some matches!
+ TEST_THAT(elist.IsExcluded(std::string("Definite1")) == true);
+ TEST_THAT(elist.IsExcluded(std::string("/dir/DefNumberTwo")) == true);
+ TEST_THAT(elist.IsExcluded(std::string("ThingDefThree")) == true);
+ TEST_THAT(elist.IsExcluded(std::string("AnotherDef")) == true);
+ TEST_THAT(elist.IsExcluded(std::string("dir/DefNumberTwo")) == false);
+ #ifndef PLATFORM_REGEX_NOT_SUPPORTED
+ TEST_THAT(elist.IsExcluded(std::string("b.reg")) == true);
+ TEST_THAT(elist.IsExcluded(std::string("e.reg")) == false);
+ TEST_THAT(elist.IsExcluded(std::string("b.Reg")) == false);
+ TEST_THAT(elist.IsExcluded(std::string("DEfinite1")) == false);
+ TEST_THAT(elist.IsExcluded(std::string("DEXCLUDEfinite1")) == true);
+ TEST_THAT(elist.IsExcluded(std::string("DEfinitexclude1")) == false);
+ TEST_THAT(elist.IsExcluded(std::string("exclude")) == true);
+ #endif
+ }
+
+ test_conversions();
+
+ return 0;
+}
diff --git a/test/common/testfiles/config1.txt b/test/common/testfiles/config1.txt
new file mode 100755
index 00000000..d000f759
--- /dev/null
+++ b/test/common/testfiles/config1.txt
@@ -0,0 +1,40 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+MultiValue = single
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config10.txt b/test/common/testfiles/config10.txt
new file mode 100755
index 00000000..02aeec74
--- /dev/null
+++ b/test/common/testfiles/config10.txt
@@ -0,0 +1,37 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config11.txt b/test/common/testfiles/config11.txt
new file mode 100755
index 00000000..cafabe74
--- /dev/null
+++ b/test/common/testfiles/config11.txt
@@ -0,0 +1,39 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ NOTEXPECTED= 34234
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config12.txt b/test/common/testfiles/config12.txt
new file mode 100755
index 00000000..17ed34f1
--- /dev/null
+++ b/test/common/testfiles/config12.txt
@@ -0,0 +1,33 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config13.txt b/test/common/testfiles/config13.txt
new file mode 100755
index 00000000..8de8ea5b
--- /dev/null
+++ b/test/common/testfiles/config13.txt
@@ -0,0 +1,15 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config14.txt b/test/common/testfiles/config14.txt
new file mode 100755
index 00000000..d409beaa
--- /dev/null
+++ b/test/common/testfiles/config14.txt
@@ -0,0 +1,41 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+MultiValue = value1
+MultiValue = secondvalue
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config15.txt b/test/common/testfiles/config15.txt
new file mode 100755
index 00000000..bfa7b022
--- /dev/null
+++ b/test/common/testfiles/config15.txt
@@ -0,0 +1,45 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+MultiValue = single
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
+BoolTrue1 = true
+BoolTrue2 = yes
+BoolFalse1 = fAlse
+BoolFalse2 = nO
+
diff --git a/test/common/testfiles/config16.txt b/test/common/testfiles/config16.txt
new file mode 100755
index 00000000..566070f2
--- /dev/null
+++ b/test/common/testfiles/config16.txt
@@ -0,0 +1,42 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+MultiValue = single
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
+BoolTrue1 = not a valid value
+
diff --git a/test/common/testfiles/config2.txt b/test/common/testfiles/config2.txt
new file mode 100755
index 00000000..724c911a
--- /dev/null
+++ b/test/common/testfiles/config2.txt
@@ -0,0 +1,39 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+# make this value missing
+# TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config3.txt b/test/common/testfiles/config3.txt
new file mode 100755
index 00000000..688675a4
--- /dev/null
+++ b/test/common/testfiles/config3.txt
@@ -0,0 +1,39 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ {
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config4.txt b/test/common/testfiles/config4.txt
new file mode 100755
index 00000000..1563d8aa
--- /dev/null
+++ b/test/common/testfiles/config4.txt
@@ -0,0 +1,40 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+}
+
+
diff --git a/test/common/testfiles/config5.txt b/test/common/testfiles/config5.txt
new file mode 100755
index 00000000..d1821ecc
--- /dev/null
+++ b/test/common/testfiles/config5.txt
@@ -0,0 +1,37 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config6.txt b/test/common/testfiles/config6.txt
new file mode 100755
index 00000000..d7381738
--- /dev/null
+++ b/test/common/testfiles/config6.txt
@@ -0,0 +1,39 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ bing= something else
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config7.txt b/test/common/testfiles/config7.txt
new file mode 100755
index 00000000..6a24d036
--- /dev/null
+++ b/test/common/testfiles/config7.txt
@@ -0,0 +1,39 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ = invalid thing here!
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config8.txt b/test/common/testfiles/config8.txt
new file mode 100755
index 00000000..3a66bbb3
--- /dev/null
+++ b/test/common/testfiles/config8.txt
@@ -0,0 +1,37 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+
diff --git a/test/common/testfiles/config9.txt b/test/common/testfiles/config9.txt
new file mode 100755
index 00000000..936ad6ce
--- /dev/null
+++ b/test/common/testfiles/config9.txt
@@ -0,0 +1,38 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050X
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config9b.txt b/test/common/testfiles/config9b.txt
new file mode 100755
index 00000000..65c44a19
--- /dev/null
+++ b/test/common/testfiles/config9b.txt
@@ -0,0 +1,38 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=C-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config9c.txt b/test/common/testfiles/config9c.txt
new file mode 100755
index 00000000..d9be55ad
--- /dev/null
+++ b/test/common/testfiles/config9c.txt
@@ -0,0 +1,38 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=2430-895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =050
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/config9d.txt b/test/common/testfiles/config9d.txt
new file mode 100755
index 00000000..28ea300e
--- /dev/null
+++ b/test/common/testfiles/config9d.txt
@@ -0,0 +1,38 @@
+test1
+{
+ value=12
+ string1 = carrots in may
+ string2 =on the string
+ subconfig
+ {
+ bing= nothing really
+ carrots =0x2356
+ terrible=lovely
+ }
+ subconfig2
+ {
+ bing= something
+ carrots=-243895
+ terrible=pgin!
+ }
+ subconfig3
+ {
+ bing= 435
+ carrots =090
+ terrible=absolutely
+ }
+ otherthing
+ {
+ string= ping
+ fish =0
+ }
+}
+
+TOPlevel= value
+
+ping
+{
+ carrots=324
+ string = casrts
+}
+
diff --git a/test/common/testfiles/fdgetlinetest.txt b/test/common/testfiles/fdgetlinetest.txt
new file mode 100755
index 00000000..f7b2c829
--- /dev/null
+++ b/test/common/testfiles/fdgetlinetest.txt
@@ -0,0 +1,20 @@
+First line
+ Second line
+ Third
+# comment
+ # comment
+
+ sdf hjjk
+
+ test #coment
+ test#not comment
+ test#not comment #comment
+
+nice line
+fish
+
+ping
+#comment
+
+ Nothing
+ Nothing \ No newline at end of file