changeset 76:8136057988bc

Fixes to automatic report generating system. A lot of new unittests.
author Tom Fredrik Blenning Klaussen <bfg@bfgconsult.no>
date Sat, 16 Feb 2013 15:32:20 +0100
parents aaf0a2878f67
children a827f3687c4a
files BurnBitArray.cpp CMakeLists.txt TestDatabase.cpp TestDatabase.hpp TestFileDBLink.cpp TestFramework.cpp TestFramework.hpp TestMemoryDBLink.cpp TestSQLGenerator.cpp
diffstat 9 files changed, 734 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BurnBitArray.cpp	Sat Feb 16 15:32:20 2013 +0100
@@ -0,0 +1,198 @@
+#include "TestFramework.hpp"
+
+#include "BitDecoder.hpp"
+
+#define BURN_MAX 100000
+#define BURN for(size_t burn_counter = BURN_MAX; burn_counter > 0; --burn_counter)
+
+BOOST_AUTO_TEST_CASE( TestBasic )
+{
+  BURN {
+    BitArray tbits(16, true);
+    BitArray fbits(16, false);
+    for (uint i = 0; i < tbits.size(); ++i) {
+      BOOST_REQUIRE_EQUAL(tbits.testBit(i), true);
+      BOOST_REQUIRE_EQUAL(fbits.testBit(i), false);
+    }
+  }
+
+  BURN {
+    BitArray tbits(9, true);
+    BitArray fbits(9, false);
+    for (uint i = 0; i < tbits.size(); ++i) {
+      BOOST_REQUIRE_EQUAL(tbits.testBit(i), true);
+      BOOST_REQUIRE_EQUAL(fbits.testBit(i), false);
+    }
+  }
+
+  BURN {
+    BitArray tbits(13, true);
+    BitArray fbits(13, false);
+    for (uint i = 0; i < tbits.size(); ++i) {
+      BOOST_REQUIRE_EQUAL(tbits.testBit(i), true);
+      BOOST_REQUIRE_EQUAL(fbits.testBit(i), false);
+    }
+  }
+
+}
+
+
+BOOST_AUTO_TEST_CASE( TestSetBit )
+{
+
+  BURN {
+    for (uint i = 0; i < 13; ++i) {
+      BitArray tbits(13, true);
+      BitArray fbits(13, false);
+      tbits.setBit(i, false);
+      fbits.setBit(i, true);
+      for (uint j = 0; j < tbits.size(); ++j) {
+	BOOST_REQUIRE_EQUAL(tbits.testBit(j), i != j);
+	BOOST_REQUIRE_EQUAL(fbits.testBit(j), i == j);
+      }
+    }
+  }
+
+}
+
+BOOST_AUTO_TEST_CASE( TestSetBit2 )
+{
+  BURN {
+  BitArray tbits(8, true);
+  BitArray fbits(8, false);
+  BOOST_REQUIRE_EQUAL(tbits, BitDecoder::bitsFromString("11111111"));
+  BOOST_REQUIRE_EQUAL(fbits, BitDecoder::bitsFromString("00000000"));
+
+  tbits.setBit(0, false);
+  fbits.setBit(0, false);
+  BOOST_REQUIRE_EQUAL(tbits, BitDecoder::bitsFromString("01111111"));
+  BOOST_REQUIRE_EQUAL(fbits, BitDecoder::bitsFromString("00000000"));
+
+  tbits.setBit(1, true);
+  fbits.setBit(1, true);
+  BOOST_REQUIRE_EQUAL(tbits, BitDecoder::bitsFromString("01111111"));
+  BOOST_REQUIRE_EQUAL(fbits, BitDecoder::bitsFromString("01000000"));
+
+  tbits.setBit(2, false);
+  fbits.setBit(2, false);
+  BOOST_REQUIRE_EQUAL(tbits, BitDecoder::bitsFromString("01011111"));
+  BOOST_REQUIRE_EQUAL(fbits, BitDecoder::bitsFromString("01000000"));
+
+  tbits.setBit(3, false);
+  fbits.setBit(3, false);
+  BOOST_REQUIRE_EQUAL(tbits, BitDecoder::bitsFromString("01001111"));
+  BOOST_REQUIRE_EQUAL(fbits, BitDecoder::bitsFromString("01000000"));
+
+  tbits.setBit(4, false);
+  fbits.setBit(4, false);
+  BOOST_REQUIRE_EQUAL(tbits, BitDecoder::bitsFromString("01000111"));
+  BOOST_REQUIRE_EQUAL(fbits, BitDecoder::bitsFromString("01000000"));
+
+  tbits.setBit(5, true);
+  fbits.setBit(5, true);
+  BOOST_REQUIRE_EQUAL(tbits, BitDecoder::bitsFromString("01000111"));
+  BOOST_REQUIRE_EQUAL(fbits, BitDecoder::bitsFromString("01000100"));
+
+  tbits.setBit(6, true);
+  fbits.setBit(6, true);
+  BOOST_REQUIRE_EQUAL(tbits, BitDecoder::bitsFromString("01000111"));
+  BOOST_REQUIRE_EQUAL(fbits, BitDecoder::bitsFromString("01000110"));
+
+  tbits.setBit(7, false);
+  fbits.setBit(7, false);
+  BOOST_REQUIRE_EQUAL(tbits, BitDecoder::bitsFromString("01000110"));
+  BOOST_REQUIRE_EQUAL(fbits, BitDecoder::bitsFromString("01000110"));
+
+  }
+}
+
+BOOST_AUTO_TEST_CASE( TestPaddedChar )
+{
+  BURN {
+  BitArray bits = BitDecoder::bitsFromString("0100011011");
+
+  BOOST_REQUIRE_EQUAL(bits.size(), 10u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(0), 70);
+
+  bits = BitDecoder::bitsFromString("0000000001");
+  BOOST_REQUIRE_EQUAL(bits.size(), 10u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(2), 1u);
+
+  bits = BitDecoder::bitsFromString("0000000011");
+  BOOST_REQUIRE_EQUAL(bits.size(), 10u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(2), 3u);
+
+  bits = BitDecoder::bitsFromString("000000000011");
+  BOOST_REQUIRE_EQUAL(bits.size(), 12u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(4), 3u);
+
+  bits = BitDecoder::bitsFromString("0000000000011");
+  BOOST_REQUIRE_EQUAL(bits.size(), 13u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(5), 3u);
+
+  bits = BitDecoder::bitsFromString("00000000000011");
+  BOOST_REQUIRE_EQUAL(bits.size(), 14u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(6), 3u);
+
+  bits = BitDecoder::bitsFromString("000000000000011");
+  BOOST_REQUIRE_EQUAL(bits.size(), 15u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(7), 3u);
+
+  bits = BitDecoder::bitsFromString("10000001");
+  BOOST_REQUIRE_EQUAL(bits.size(), 8u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(0), 129u);
+
+  bits = BitDecoder::bitsFromString("010000001");
+  BOOST_REQUIRE_EQUAL(bits.size(), 9u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(1), 129u);
+
+  bits = BitDecoder::bitsFromString("0010000001");
+  BOOST_REQUIRE_EQUAL(bits.size(), 10u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(2), 129u);
+
+  bits = BitDecoder::bitsFromString("00010000001");
+  BOOST_REQUIRE_EQUAL(bits.size(), 11u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(3), 129u);
+
+  bits = BitDecoder::bitsFromString("000010000001");
+  BOOST_REQUIRE_EQUAL(bits.size(), 12u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(4), 129u);
+
+  bits = BitDecoder::bitsFromString("0000010000001");
+  BOOST_REQUIRE_EQUAL(bits.size(), 13u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(5), 129u);
+
+  bits = BitDecoder::bitsFromString("00000010000001");
+  BOOST_REQUIRE_EQUAL(bits.size(), 14u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(6), 129u);
+
+  bits = BitDecoder::bitsFromString("000000010000001");
+  BOOST_REQUIRE_EQUAL(bits.size(), 15u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(7), 129u);
+
+
+  bits = BitDecoder::bitsFromString("0100011011");
+  BOOST_REQUIRE_EQUAL(bits.size(), 10u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(2), 27u);
+  }
+}
+
+BOOST_AUTO_TEST_CASE( TestCorrectChar )
+{
+  BURN {
+  BitArray bits = BitDecoder::bitsFromString("00000001");
+  BOOST_REQUIRE_EQUAL(bits.size(), 8u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(0), 1u);
+
+  bits = BitDecoder::bitsFromString("00000011");
+  BOOST_REQUIRE_EQUAL(bits.size(), 8u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(0), 3u);
+
+  bits = BitDecoder::bitsFromString("10000000");
+  BOOST_REQUIRE_EQUAL(bits.size(), 8u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(0), 128u);
+  bits = BitDecoder::bitsFromString("11000000");
+  BOOST_REQUIRE_EQUAL(bits.size(), 8u);
+  BOOST_REQUIRE_EQUAL(bits.getPaddedChar(0), 192u);
+  }
+}
--- a/CMakeLists.txt	Sat Feb 16 15:30:12 2013 +0100
+++ b/CMakeLists.txt	Sat Feb 16 15:32:20 2013 +0100
@@ -9,11 +9,31 @@
   SET(COVERAGE_FLAGS "--coverage")
 ENDIF()
 
+SET(ALL_TESTS)
+
 MACRO(NEW_TEST file)
   STRING(REPLACE "/" "_" TARGET ${file})
   ADD_EXECUTABLE(${TARGET} ${file}.cpp ${TEST_SOURCES})
   ADD_TEST(${TARGET} ${TARGET})
-  TARGET_LINK_LIBRARIES(${TARGET} ${QT_LIBRARIES} ${Boost_LIBRARIES} ${COVERAGE_FLAGS})
+  TARGET_LINK_LIBRARIES(${TARGET} ${QT_LIBRARIES} ${Boost_LIBRARIES}
+  ${COVERAGE_FLAGS})
+
+  ADD_CUSTOM_COMMAND(OUTPUT "BUILD_${TARGET}"
+					     COMMAND "${CMAKE_COMMAND}"
+                                       --build ${CMAKE_BINARY_DIR}
+					     --target ${TARGET}
+					     COMMENT "Building test ${TARGET}"
+  )
+  SET(BUILD_ALL_TESTS ${BUILD_ALL_TESTS} BUILD_${TARGET})
+
+  SET(ALL_TESTS ${ALL_TESTS} RUN_${TARGET})
+  ADD_CUSTOM_TARGET(RUN_${TARGET} ${CMAKE_BINARY_DIR}/${TARGET} --log_level=nothing --report_level=no
+ 				  DEPENDS zero_counters_test_with_base
+  BUILD_${TARGET}
+					     COMMENT "Running test ${TARGET}"
+
+)
+
 ENDMACRO()
 
 SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMake_Modules/")
@@ -64,7 +84,6 @@
 	HuffmanString.cpp
 	MemoryDBLink.cpp
 	SqliteDBLink.cpp
-	UniqueString.cpp
 )
 
 SET(CLASS_HEADERS
@@ -98,6 +117,7 @@
 SET(TEST_SOURCES
 	${CLASS_SOURCES}
 	${MOC_SOURCES}
+	TestDatabase.cpp
 	TestFramework.cpp
 )
 
@@ -150,6 +170,8 @@
 NEW_TEST(Exception/TestValueExistsException)
 NEW_TEST(Exception/TestPermissionException)
 NEW_TEST(TestBitArray)
+NEW_TEST(TestSQLGenerator)
+NEW_TEST(TestFileDBLink)
 NEW_TEST(TestBitDecoder)
 NEW_TEST(TestDBCache)
 NEW_TEST(TestEditDistance)
@@ -159,35 +181,68 @@
 NEW_TEST(TestMemoryDBLink)
 NEW_TEST(TestSqliteDBLink)
 
+
 #ADD_PRECOMPILED_HEADER(TestEditDistance TestFramework.hpp)
 
+ADD_CUSTOM_COMMAND(OUTPUT build_tests COMMAND "${CMAKE_COMMAND}"
+--build ${CMAKE_BINARY_DIR} --target all)
 
-ADD_CUSTOM_COMMAND(OUTPUT coverage.info
-					  COMMAND lcov --no-external --capture
+ADD_CUSTOM_TARGET(zero_counters_test_with_base
+	lcov -q -z -d ${CMAKE_CURRENT_BINARY_DIR}
+	DEPENDS ${BUILD_ALL_TESTS}
+)
+
+ADD_CUSTOM_COMMAND(OUTPUT test_with_base COMMAND
+true
+DEPENDS zero_counters_test_with_base ${ALL_TESTS}
+					  COMMENT "All test have run"
+)
+
+ADD_CUSTOM_COMMAND(OUTPUT coverage_base_raw.info
+					  COMMAND lcov --no-external
+					  --capture --initial
 					  --directory ${CMAKE_CURRENT_BINARY_DIR}
 					  --base-directory ${CMAKE_CURRENT_SOURCE_DIR}
-					  --output-file coverage.info
+					  --output-file coverage_base_raw.info
+)
+
+ADD_CUSTOM_COMMAND(OUTPUT coverage_test.info
+					  COMMAND lcov -q --no-external --capture
+					  --directory ${CMAKE_CURRENT_BINARY_DIR}
+					  --base-directory ${CMAKE_CURRENT_SOURCE_DIR}
+					  --output-file
+					  coverage_test.info
+					  DEPENDS test_with_base
 )
 
 ADD_CUSTOM_COMMAND(OUTPUT coverage.preprocessed2
-					  COMMAND lcov -r
-					  coverage.info 'moc_*'
+					  COMMAND lcov -q -r
+					  coverage_test.info 'moc_*'
 					  --output-file coverage.preprocessed2
-					  DEPENDS coverage.info
+					  DEPENDS coverage_test.info
+					  COMMENT "Removing \"moc_\"-files" 
 )
 
 
 ADD_CUSTOM_COMMAND(OUTPUT coverage.preprocessed
-					  COMMAND lcov -r
+					  COMMAND lcov -q -r
 					  coverage.preprocessed2 'Test*'
 					  --output-file coverage.preprocessed
-					  DEPENDS coverage.preprocessed2
+					  DEPENDS
+					  coverage.preprocessed2
+					  COMMENT "Removing \"Test\"-files"
 )
 
 
-ADD_CUSTOM_TARGET(coverage_presentation genhtml
+ADD_CUSTOM_TARGET(coverage_presentation genhtml -q
 				    ${CMAKE_CURRENT_BINARY_DIR}/coverage.preprocessed
 				    --output-directory
 				    ${CMAKE_CURRENT_BINARY_DIR}/coverage_presentation 
-				    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/coverage.preprocessed
+				    DEPENDS
+				    ${CMAKE_CURRENT_BINARY_DIR}/coverage.preprocessed
 )
+
+ADD_CUSTOM_TARGET(coverage_base
+				    DEPENDS
+				     ${CMAKE_CURRENT_BINARY_DIR}/coverage_base.info
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TestDatabase.cpp	Sat Feb 16 15:32:20 2013 +0100
@@ -0,0 +1,28 @@
+#include "TestDataBase.hpp"
+
+#include "Exception/IOException.hpp"
+
+TestDatabase::TestDatabase() : connectionName("TestDatabase"),
+			       db(new QSqlDatabase)
+{
+  *db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
+  const QString dbPath(":memory:");
+  db->setDatabaseName(dbPath);
+  if (!db->open())
+    throw
+      IOException(QString("Unable to open SQLite database with path '%1'")
+                  .arg(dbPath));
+
+}
+
+TestDatabase::~TestDatabase()
+{
+  db->close();
+  delete db;
+  QSqlDatabase::removeDatabase(connectionName);
+}
+
+QSqlDatabase TestDatabase::getDatabase()
+{
+  return *db;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TestDatabase.hpp	Sat Feb 16 15:32:20 2013 +0100
@@ -0,0 +1,18 @@
+#ifndef TESTDATABASE_HPP
+#define TESTDATABASE_HPP
+
+#include <QtSql/QSqlDatabase>
+
+class TestDatabase
+{
+public:
+  QSqlDatabase getDatabase();
+  TestDatabase();
+  ~TestDatabase();
+  
+private:
+  const QString connectionName;
+  QSqlDatabase *db;
+};
+
+#endif //TESTDATABASE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TestFileDBLink.cpp	Sat Feb 16 15:32:20 2013 +0100
@@ -0,0 +1,60 @@
+#include "FileDBLink.hpp"
+#include "TestFramework.hpp"
+
+BOOST_AUTO_TEST_CASE( DBInfoSerialize )
+{
+  QString dir("de");
+  QString name("cd");
+  QString path(QString("%1/%2").arg(dir).arg(name));
+  int size = 64;
+  QDateTime time1 = QDateTime::currentDateTime();
+  QByteArray hash = QByteArray::fromHex("ab");
+  FileDBLink::DBInfo info(path, size, time1, hash);
+
+  BOOST_REQUIRE_EQUAL(info.path(), path);
+  BOOST_REQUIRE_EQUAL(info.name(), name);
+  BOOST_REQUIRE_EQUAL(info.size(), size);
+  BOOST_REQUIRE_EQUAL(info.mtime(), time1);
+  BOOST_REQUIRE_EQUAL(info.checksum(), hash);
+
+  BOOST_REQUIRE_EQUAL(info.serialize(),
+		      QString("%1, %2, %3, %4")
+		      .arg(info.path())
+		      .arg(size)
+		      .arg(time1.toString())
+		      .arg(QString(hash.toHex()))
+		      );
+}
+
+BOOST_AUTO_TEST_CASE( ExtendedDBInfoSerialize )
+{
+  QString dir("de");
+  QString name("cd");
+  QString path(QString("%1/%2").arg(dir).arg(name));
+  int size = 64;
+  QDateTime time1 = QDateTime::currentDateTime();
+  QByteArray hash = QByteArray::fromHex("ab");
+  QString closestEditPath = "aa";
+  int editDistance = 1;
+  FileDBLink::ExtendedDBInfo info(FileDBLink::DBInfo(path, size, time1, hash),
+				  closestEditPath,
+				  editDistance
+				  );
+
+  BOOST_REQUIRE_EQUAL(info.path(), path);
+  BOOST_REQUIRE_EQUAL(info.name(), name);
+  BOOST_REQUIRE_EQUAL(info.size(), size);
+  BOOST_REQUIRE_EQUAL(info.mtime(), time1);
+  BOOST_REQUIRE_EQUAL(info.checksum(), hash);
+  BOOST_REQUIRE_EQUAL(info.editDistance(), editDistance);
+
+  BOOST_REQUIRE_EQUAL(info.serialize(),
+		      QString("%1, %2, %3, %4, %5, %6")
+		      .arg(info.path())
+		      .arg(size)
+		      .arg(time1.toString())
+		      .arg(QString(hash.toHex()))
+		      .arg(closestEditPath)
+		      .arg(editDistance)
+		      );
+}
--- a/TestFramework.cpp	Sat Feb 16 15:30:12 2013 +0100
+++ b/TestFramework.cpp	Sat Feb 16 15:32:20 2013 +0100
@@ -9,3 +9,9 @@
 {
   return out << rhs.toString();
 }
+
+std::ostream& operator<<(std::ostream& out, const QByteArray& rhs)
+{
+  QByteArray b64 = rhs.toBase64();
+  return out << b64.constData();
+}
--- a/TestFramework.hpp	Sat Feb 16 15:30:12 2013 +0100
+++ b/TestFramework.hpp	Sat Feb 16 15:32:20 2013 +0100
@@ -19,5 +19,7 @@
 std::ostream& operator<<(std::ostream& out, const QString& rhs);
 class QDateTime;
 std::ostream& operator<<(std::ostream& out, const QDateTime& rhs);
+class QByteArray;
+std::ostream& operator<<(std::ostream& out, const QByteArray& rhs);
 
 #endif //TESTFRAMEWORK_HPP
--- a/TestMemoryDBLink.cpp	Sat Feb 16 15:30:12 2013 +0100
+++ b/TestMemoryDBLink.cpp	Sat Feb 16 15:32:20 2013 +0100
@@ -6,33 +6,60 @@
 {
   MemoryDBLink link;
 
-  QDateTime time1;
+  QDateTime time1 = QDateTime::currentDateTime();
   QDateTime time2 = time1.addSecs(1);
 
+  BOOST_REQUIRE(!link.exists("test"));
   BOOST_REQUIRE_EQUAL(link.existsWithMtime("test", time1), FileDBLink::NONE);
   link.addFile("test", 1, time1, "a");
   BOOST_REQUIRE_EQUAL(link.existsWithMtime("test", time1), FileDBLink::SAME);
+  BOOST_REQUIRE(link.exists("test"));
   BOOST_REQUIRE_THROW(link.addFile("test", 1, time1, "a"),
 		      ValueExistsException);
 
   link.updateFile("test", 1, time2, "a");
   BOOST_REQUIRE_EQUAL(link.existsWithMtime("test", time1), FileDBLink::MTIME_DIFFERENT);
+  BOOST_REQUIRE(link.exists("test"));
   BOOST_REQUIRE_THROW(link.addFile("test", 1, time1, "a"),
 		      ValueExistsException);
 
-  /*
-  BOOST_REQUIRE(!map.find(k4));
-  map.insert(k4);
-  BOOST_WARN_EQUAL(map.depth(), 2u);
-  BOOST_WARN_EQUAL(map.total_depth(), 8u);
-  BOOST_REQUIRE_EQUAL(map.size(), 4u);
-  BOOST_REQUIRE_EQUAL(map.optimal_depth(), 3u);
-  BOOST_REQUIRE_THROW(map.insert(k4), ValueExistsException);
-  BOOST_REQUIRE(map.find(k1));
-  BOOST_REQUIRE_EQUAL(*map.find(k1), k1);
-  BOOST_REQUIRE(map.find(k2));
-  BOOST_REQUIRE_EQUAL(*map.find(k2), k2);
-  BOOST_REQUIRE(map.find(k4));
-  BOOST_REQUIRE_EQUAL(*map.find(k4), k4);
-  */
+
 }
+
+BOOST_AUTO_TEST_CASE( SortUnsortable )
+{
+  MemoryDBLink link;
+
+  QString path1 = "a";
+  int size1 = 1;
+  QDateTime time1 = QDateTime::currentDateTime();
+  QByteArray checksum1 = QByteArray::fromHex("a");
+
+  QString path2 = "b";
+  int size2 = 2;
+  QDateTime time2 = time1.addSecs(1);
+  QByteArray checksum2 = QByteArray::fromHex("b");
+
+
+  link.addFile(path2, size2, time2, checksum2);
+  link.addFile(path1, size1, time1, checksum1);
+
+
+  {
+    QList<FileDBLink::dbinf_ptr_t > out;
+    out = link.sortOn("", FileDBLink::PATH, false);
+
+    bool first = true;
+    QString prev;
+    foreach(FileDBLink::dbinf_ptr_t info, out) {
+      if (first) {
+	first = false;
+      }
+      else {
+	BOOST_REQUIRE(prev <= info->path());
+      }
+      prev = info->path();
+    }
+  }
+  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TestSQLGenerator.cpp	Sat Feb 16 15:32:20 2013 +0100
@@ -0,0 +1,312 @@
+#include "SQLGenerator.hpp"
+#include "TestFramework.hpp"
+#include "TestDataBase.hpp"
+
+#include "Exception/SQLException.hpp"
+
+BOOST_AUTO_TEST_CASE( CreateInsertAndRetrieveQString )
+{
+  TestDatabase tdb;
+  QSqlDatabase db = tdb.getDatabase();
+  QSqlQuery query(db);
+
+  QString tableName = "test";
+
+  QString fieldCreateString1 = SQLGenerator<QString>::createFields("value1");
+  QString fieldCreateString2 = SQLGenerator<QString>::createFields("value2");
+
+
+  QString createQuery = QString("CREATE TABLE %1(%2, %3);")
+    .arg(tableName)
+    .arg(fieldCreateString1)
+    .arg(fieldCreateString2);
+
+  BOOST_REQUIRE(query.exec(createQuery));
+
+
+  QString queryString = QString("INSERT into %1 (%2, %3) VALUES(%4, %5);")
+    .arg(tableName)
+    .arg(SQLGenerator<QString>::fieldName("value1"))
+    .arg(SQLGenerator<QString>::fieldName("value2"))
+    .arg(SQLGenerator<QString>::valueString("value1"))
+    .arg(SQLGenerator<QString>::valueString("value2"));
+  QSqlQuery insertQuery = QSqlQuery(db);
+  BOOST_REQUIRE(insertQuery.prepare(queryString));
+
+  QList<QString> valueList1, valueList2;
+  for (int i = 1; i <= 3; ++i) {
+    valueList1 << QString("a%1").arg(i);
+    valueList2 << QString("b%1").arg(i);
+  }
+
+  SQLGenerator<QString>::bindValues(insertQuery, valueList1, "value1");
+  SQLGenerator<QString>::bindValues(insertQuery, valueList2, "value2");
+  BOOST_REQUIRE(insertQuery.execBatch());
+  insertQuery.finish();
+
+  QString fieldValueString1 = SQLGenerator<QString>::fieldName("value1");
+  QString fieldValueString2 = SQLGenerator<QString>::fieldName("value2");
+
+  QString selectQuery =  QString("SELECT %1, %2 FROM %3;")
+    .arg(fieldValueString1).arg(fieldValueString2).arg(tableName);
+
+  BOOST_REQUIRE(query.exec(selectQuery));
+
+  while (query.next()) {
+    QString value1 = *SQLGenerator<QString>::extract(query, "value1");
+    QString value2 = *SQLGenerator<QString>::extract(query, "value2");
+
+    BOOST_REQUIRE(valueList1.contains(value1));
+    BOOST_REQUIRE(valueList2.contains(value2));
+
+    valueList1.removeAt(valueList1.indexOf(value1));
+    valueList2.removeAt(valueList2.indexOf(value2));
+  }
+
+  boost::optional<QString> empty1 =
+    SQLGenerator<QString>::extract(query, "value1");
+  boost::optional<QString> empty2 =
+    SQLGenerator<QString>::extract(query, "value2");
+
+  BOOST_REQUIRE(!empty1);
+  BOOST_REQUIRE(!empty2);
+
+  BOOST_REQUIRE(valueList1.empty());
+  BOOST_REQUIRE(valueList2.empty());
+
+  query.finish();
+}
+
+BOOST_AUTO_TEST_CASE( CreateInsertAndRetrieveUniqueString )
+{
+  TestDatabase tdb;
+  QSqlDatabase db = tdb.getDatabase();
+  QSqlQuery query(db);
+
+  QString tableName = "test";
+
+  QString fieldCreateString1 =
+    SQLGenerator<UniqueString>::createFields("value1");
+  QString fieldCreateString2 =
+    SQLGenerator<UniqueString>::createFields("value2");
+
+
+  QString createQuery = QString("CREATE TABLE %1(%2, %3);")
+    .arg(tableName)
+    .arg(fieldCreateString1)
+    .arg(fieldCreateString2);
+
+  BOOST_REQUIRE(query.exec(createQuery));
+
+
+  QString queryString = QString("INSERT into %1 (%2, %3) VALUES(%4, %5);")
+    .arg(tableName)
+    .arg(SQLGenerator<UniqueString>::fieldName("value1"))
+    .arg(SQLGenerator<UniqueString>::fieldName("value2"))
+    .arg(SQLGenerator<UniqueString>::valueString("value1"))
+    .arg(SQLGenerator<UniqueString>::valueString("value2"));
+  QSqlQuery insertQuery = QSqlQuery(db);
+  BOOST_REQUIRE(insertQuery.prepare(queryString));
+
+  QList<UniqueString> valueList1, valueList2;
+  for (int i = 1; i <= 3; ++i) {
+    valueList1 << QString("a%1").arg(i);
+    valueList2 << QString("b%1").arg(i);
+  }
+
+  SQLGenerator<UniqueString>::bindValues(insertQuery, valueList1, "value1");
+  SQLGenerator<UniqueString>::bindValues(insertQuery, valueList2, "value2");
+  BOOST_REQUIRE(insertQuery.execBatch());
+  insertQuery.finish();
+
+  QString fieldValueString1 = SQLGenerator<UniqueString>::fieldName("value1");
+  QString fieldValueString2 = SQLGenerator<UniqueString>::fieldName("value2");
+
+  QString selectQuery =  QString("SELECT %1, %2 FROM %3;")
+    .arg(fieldValueString1).arg(fieldValueString2).arg(tableName);
+
+  BOOST_REQUIRE(query.exec(selectQuery));
+
+  while (query.next()) {
+    UniqueString value1 = *SQLGenerator<UniqueString>::extract(query, "value1");
+    UniqueString value2 = *SQLGenerator<UniqueString>::extract(query, "value2");
+
+    BOOST_REQUIRE(valueList1.contains(value1));
+    BOOST_REQUIRE(valueList2.contains(value2));
+
+    valueList1.removeAt(valueList1.indexOf(value1));
+    valueList2.removeAt(valueList2.indexOf(value2));
+  }
+
+  boost::optional<UniqueString> empty1 =
+    SQLGenerator<UniqueString>::extract(query, "value1");
+  boost::optional<UniqueString> empty2 =
+    SQLGenerator<UniqueString>::extract(query, "value2");
+
+  BOOST_REQUIRE(!empty1);
+  BOOST_REQUIRE(!empty2);
+
+  BOOST_REQUIRE(valueList1.empty());
+  BOOST_REQUIRE(valueList2.empty());
+
+  query.finish();
+}
+
+BOOST_AUTO_TEST_CASE( CreateInsertAndRetrieveInt )
+{
+  TestDatabase tdb;
+  QSqlDatabase db = tdb.getDatabase();
+
+  QSqlQuery query(db);
+
+  QString tableName = "test";
+
+  QString fieldCreateString1 = SQLGenerator<int>::createFields("value1");
+  QString fieldCreateString2 = SQLGenerator<int>::createFields("value2");
+
+
+  QString createQuery = QString("CREATE TABLE %1(%2, %3);")
+    .arg(tableName)
+    .arg(fieldCreateString1)
+    .arg(fieldCreateString2);
+
+  BOOST_REQUIRE(query.exec(createQuery));
+  
+  QString queryString = QString("INSERT into %1 (%2, %3) VALUES(%4, %5);")
+    .arg(tableName)
+    .arg(SQLGenerator<int>::fieldName("value1"))
+    .arg(SQLGenerator<int>::fieldName("value2"))
+    .arg(SQLGenerator<int>::valueString("value1"))
+    .arg(SQLGenerator<int>::valueString("value2"));
+  QSqlQuery insertQuery = QSqlQuery(db);
+  BOOST_REQUIRE(insertQuery.prepare(queryString));
+
+  QList<int> valueList1, valueList2;
+  int p1 = 2;
+  int p2 = 3;
+  int v1 = p1;
+  int v2 = p2;
+  for (int i = 1; i <= 3; ++i) {
+    valueList1 << v1;
+    valueList2 << v2;
+    v1 *= p1;
+    v2 *= p2;
+  }
+
+  SQLGenerator<int>::bindValues(insertQuery, valueList1, "value1");
+  SQLGenerator<int>::bindValues(insertQuery, valueList2, "value2");
+  BOOST_REQUIRE(insertQuery.execBatch());
+  insertQuery.finish();
+
+  QString fieldValueString1 = SQLGenerator<int>::fieldName("value1");
+  QString fieldValueString2 = SQLGenerator<int>::fieldName("value2");
+
+  QString selectQuery =  QString("SELECT %1, %2 FROM %3;")
+    .arg(fieldValueString1).arg(fieldValueString2).arg(tableName);
+
+  BOOST_REQUIRE(query.exec(selectQuery));
+
+  while (query.next()) {
+    int value1 = *SQLGenerator<int>::extract(query, "value1");
+    int value2 = *SQLGenerator<int>::extract(query, "value2");
+
+    BOOST_REQUIRE(valueList1.contains(value1));
+    BOOST_REQUIRE(valueList2.contains(value2));
+
+    valueList1.removeAt(valueList1.indexOf(value1));
+    valueList2.removeAt(valueList2.indexOf(value2));
+  }
+  boost::optional<int> empty1 = SQLGenerator<int>::extract(query, "value1");
+  boost::optional<int> empty2 = SQLGenerator<int>::extract(query, "value2");
+
+  BOOST_REQUIRE(!empty1);
+  BOOST_REQUIRE(!empty2);
+
+  BOOST_REQUIRE(valueList1.empty());
+  BOOST_REQUIRE(valueList2.empty());
+
+}
+
+BOOST_AUTO_TEST_CASE( CreateInsertAndRetrieveOrderedPair )
+{
+  TestDatabase tdb;
+  QSqlDatabase db = tdb.getDatabase();
+  QSqlQuery query(db);
+
+  QString tableName = "test";
+
+  QString fieldCreateString1 =
+    SQLGenerator<OrderedPair<int> >::createFields("value1");
+  QString fieldCreateString2 =
+    SQLGenerator<OrderedPair<int> >::createFields("value2");
+
+
+  QString createQuery = QString("CREATE TABLE %1(%2, %3);")
+    .arg(tableName)
+    .arg(fieldCreateString1)
+    .arg(fieldCreateString2);
+
+  BOOST_REQUIRE(query.exec(createQuery));
+
+
+  QString queryString = QString("INSERT into %1 (%2, %3) VALUES(%4, %5);")
+    .arg(tableName)
+    .arg(SQLGenerator<OrderedPair<int> >::fieldName("value1"))
+    .arg(SQLGenerator<OrderedPair<int> >::fieldName("value2"))
+    .arg(SQLGenerator<OrderedPair<int> >::valueString("value1"))
+    .arg(SQLGenerator<OrderedPair<int> >::valueString("value2"));
+  QSqlQuery insertQuery = QSqlQuery(db);
+  BOOST_REQUIRE(insertQuery.prepare(queryString));
+
+  QList<OrderedPair<int> > valueList1, valueList2;
+  int p [] = { 2, 3, 5, 7};
+  int v [] = { 2, 3, 5, 7};
+
+  for (int i = 1; i <= 3; ++i) {
+    valueList1 << OrderedPair<int>(v[0], v[1]);
+    valueList2 << OrderedPair<int>(v[2], v[3]);
+    for (int i = 0; i < 4; ++i)
+      v[i] *= p[i];
+  }
+
+  SQLGenerator<OrderedPair<int> >::bindValues(insertQuery, valueList1, "value1");
+  SQLGenerator<OrderedPair<int> >::bindValues(insertQuery, valueList2, "value2");
+  BOOST_REQUIRE(insertQuery.execBatch());
+  insertQuery.finish();
+
+  QString fieldValueString1 =
+    SQLGenerator<OrderedPair<int> >::fieldName("value1");
+  QString fieldValueString2 =
+    SQLGenerator<OrderedPair<int> >::fieldName("value2");
+
+  QString selectQuery =  QString("SELECT %1, %2 FROM %3;")
+    .arg(fieldValueString1).arg(fieldValueString2).arg(tableName);
+
+  BOOST_REQUIRE(query.exec(selectQuery));
+
+  while (query.next()) {
+    OrderedPair<int> value1 =
+      *SQLGenerator<OrderedPair<int> >::extract(query, "value1");
+    OrderedPair<int> value2 =
+      *SQLGenerator<OrderedPair<int> >::extract(query, "value2");
+
+    BOOST_REQUIRE(valueList1.contains(value1));
+    BOOST_REQUIRE(valueList2.contains(value2));
+
+    valueList1.removeAt(valueList1.indexOf(value1));
+    valueList2.removeAt(valueList2.indexOf(value2));
+  }
+
+  boost::optional<OrderedPair<int> > empty1 =
+    SQLGenerator<OrderedPair<int> >::extract(query, "value1");
+  boost::optional<OrderedPair<int> > empty2 =
+    SQLGenerator<OrderedPair<int> >::extract(query, "value2");
+
+  BOOST_REQUIRE(!empty1);
+  BOOST_REQUIRE(!empty2);
+
+  BOOST_REQUIRE(valueList1.empty());
+  BOOST_REQUIRE(valueList2.empty());
+
+  query.finish();
+}