From da9dd6be1b0203c496af4aff16df60fedc64463a Mon Sep 17 00:00:00 2001
From: Constantin Michael <constantin@codesynthesis.com>
Date: Tue, 12 Apr 2011 15:48:17 +0200
Subject: Add UNIX time tests for qt/date-time SQLite implementation

---
 qt/sqlite/date-time/driver.cxx | 132 +++++++++++++++++++++++++++++++++--------
 qt/sqlite/date-time/test.hxx   |  15 +++--
 2 files changed, 117 insertions(+), 30 deletions(-)

(limited to 'qt/sqlite/date-time')

diff --git a/qt/sqlite/date-time/driver.cxx b/qt/sqlite/date-time/driver.cxx
index 1f1a1bd..277c29b 100644
--- a/qt/sqlite/date-time/driver.cxx
+++ b/qt/sqlite/date-time/driver.cxx
@@ -23,6 +23,9 @@
 using namespace std;
 using namespace odb::core;
 
+bool
+test_out_of_range_value (object&, database&);
+
 int
 main (int argc, char* argv[])
 {
@@ -30,56 +33,117 @@ main (int argc, char* argv[])
   {
     auto_ptr<database> db (create_database (argc, argv));
 
-    //
-    // Check valid dates and times.
-    //
-
-    object o;
-
     // Check persistence of null values.
     //
+    object o1;
     {
       transaction t (db->begin ());
-      db->persist (o);
+      db->persist (o1);
       t.commit ();
     }
 
     {
       transaction t (db->begin ());
-      auto_ptr<object> ol (db->load<object> (o.id));
+      auto_ptr<object> ol1 (db->load<object> (o1.id));
       t.commit ();
 
-      assert (ol->is_null ());
+      assert (ol1->is_null ());
     }
 
+    QDateTime ct (QDateTime::currentDateTime ());
+    QDateTime ct_no_ms = QDateTime (QDate (ct.date ().year (),
+                                           ct.date ().month (),
+                                           ct.date ().day ()),
+                                    QTime (ct.time ().hour (),
+                                           ct.time ().minute (),
+                                           ct.time ().second ()));
+
     // Check persistence of valid dates and times.
     //
-    QDateTime t (QDateTime::currentDateTime ());
-    o.date = t.date ();
-    o.julian_day = t.date ();
-    o.time = t.time ();
-
-    // We do not take milliseconds into account when storing
-    // time as seconds. Zero the millisecond part to avoid a
-    // false negative.
-    //
-    o.seconds = QTime (t.time ().hour (),
-                       t.time ().minute (),
-                       t.time ().second ());
-    o.date_time = t;
+    object o2;
+    {
+      o2.date = ct.date ();
+      o2.unix_day = ct.date ();
+      o2.time = ct.time ();
+
+      // QTime stored as SQLite INTEGER has second resolution.
+      // The millsecond part is zeroed to avoid false negatives.
+      //
+      o2.seconds = ct_no_ms.time ();
+
+      o2.date_time = ct;
+
+      // UNIX time has second reolution. The millsecond part is
+      // zeroed to avoid false negatives.
+      //
+      o2.unix_time = ct_no_ms;
+
+      transaction t (db->begin ());
+      db->persist (o2);
+      t.commit ();
+    }
 
     {
       transaction t (db->begin ());
-      db->persist (o);
+      auto_ptr<object> ol2 (db->load<object> (o2.id));
       t.commit ();
+
+      assert (*ol2 == o2);
     }
 
+    // Test different time zones are handled correctly by
+    // QDateTime traits UNIX time implementation.
+    //
+    object o3, o4, o5;
     {
+      // o3 is set to ct local time. o4 is set to ct UTC. o5
+      // is set to o3's equivalent UTC time.
+      //
+      o3.unix_time = ct_no_ms;
+
+      o4.unix_time = ct_no_ms;
+      o4.unix_time.setTimeSpec (Qt::UTC);
+
+      o5.unix_time = ct_no_ms.toTimeSpec (Qt::UTC);
+
       transaction t (db->begin ());
-      auto_ptr<object> ol (db->load<object> (o.id));
+      db->persist (o3);
+      db->persist (o4);
+      db->persist (o5);
       t.commit ();
+    }
 
-      assert (*ol == o);
+    {
+      transaction t (db->begin ());
+      auto_ptr<object> ol3 (db->load<object> (o3.id));
+      auto_ptr<object> ol4 (db->load<object> (o4.id));
+      auto_ptr<object> ol5 (db->load<object> (o5.id));
+      t.commit ();
+
+      assert (ol3->unix_time != ol4->unix_time);
+      assert (ol3->unix_time == ol5->unix_time);
+    }
+
+    // Test out of range values for QDateTime traits UNIX time
+    // implementation.
+    //
+    {
+      object o;
+      o.unix_time = QDateTime (QDate (1969, 12, 31),
+                               QTime (23, 59, 59),
+                               Qt::UTC);
+
+      assert (test_out_of_range_value (o, *db));
+    }
+
+    // Test out of range values for QDate traits UNIX time
+    // implementation.
+    //
+    {
+      object o;
+      o.unix_day = QDate (QDate (1969, 12, 31));
+
+      assert (test_out_of_range_value (o, *db));
     }
   }
   catch (const odb::exception& e)
@@ -88,3 +152,21 @@ main (int argc, char* argv[])
     return 1;
   }
 }
+
+bool
+test_out_of_range_value (object& x, database& db)
+{
+  try
+  {
+    transaction t (db.begin ());
+    db.persist (x);
+    t.rollback ();
+
+    return false;
+  }
+  catch (const odb::qt::date_time::value_out_of_range&)
+  {
+  }
+
+  return true;
+}
diff --git a/qt/sqlite/date-time/test.hxx b/qt/sqlite/date-time/test.hxx
index 27ba341..0a140b7 100644
--- a/qt/sqlite/date-time/test.hxx
+++ b/qt/sqlite/date-time/test.hxx
@@ -21,10 +21,11 @@ struct object
     return
       id == x.id &&
       date == x.date &&
-      julian_day == x.julian_day &&
+      unix_day == x.unix_day &&
       time == x.time &&
       seconds == x.seconds &&
-      date_time == x.date_time;
+      date_time == x.date_time &&
+      unix_time == x.unix_time;
   }
 
   bool
@@ -32,10 +33,11 @@ struct object
   {
     return
       date.isNull () &&
-      julian_day.isNull () &&
+      unix_day.isNull () &&
       time.isNull () &&
       seconds.isNull () &&
-      date_time.isNull ();
+      date_time.isNull () &&
+      unix_time.isNull ();
   }
 
   #pragma db id auto
@@ -44,7 +46,7 @@ struct object
   QDate date;
 
   #pragma db type ("INTEGER")
-  QDate julian_day;
+  QDate unix_day;
 
   QTime time;
 
@@ -52,6 +54,9 @@ struct object
   QTime seconds;
 
   QDateTime date_time;
+
+  #pragma db type ("INTEGER")
+  QDateTime unix_time;
 };
 
 #endif // TEST_HXX
-- 
cgit v1.1