Branch 'c++/master' - c++/compiled c++/lib c++/tests

Christian Mollekopf mollekopf at kolabsys.com
Wed Feb 8 20:51:49 CET 2012


 c++/compiled/XMLParserWrapper.cpp |    6 +
 c++/lib/global_definitions.h      |   12 +++
 c++/lib/kolabformat.cpp           |   27 ++++++++
 c++/lib/kolabformat.h             |    8 ++
 c++/lib/kolabformat.i             |    3 
 c++/lib/utils.cpp                 |   53 ++++++++++++++++
 c++/lib/utils.h                   |   14 ++++
 c++/lib/xcalconversions.h         |  121 ++++++++++++++++++++------------------
 c++/tests/bindingstest.cpp        |   52 ++++++++++++----
 c++/tests/bindingstest.h          |    6 +
 10 files changed, 232 insertions(+), 70 deletions(-)

New commits:
commit e75e0dbed221f15d297e860cb1c90cc5f5901f6d
Author: Christian Mollekopf <mollekopf at kolabsys.com>
Date:   Wed Feb 8 20:51:42 2012 +0100

    Basic Error handling/reporting/logging facilites. Not yet thread-safe. Make the parser recover from errors.

diff --git a/c++/compiled/XMLParserWrapper.cpp b/c++/compiled/XMLParserWrapper.cpp
index 25140bd..ce38d2c 100644
--- a/c++/compiled/XMLParserWrapper.cpp
+++ b/c++/compiled/XMLParserWrapper.cpp
@@ -272,6 +272,10 @@ xml_schema::dom::auto_ptr<xercesc::DOMDocument> XMLParserWrapper::parse(std::ist
     {
         cerr << ": unable to open or read failure" << endl;
     }
-
+    catch (...)
+    {
+        cerr << ": unknown exception thrown" << endl;
+    }
+    eh.reset();
     return xml_schema::dom::auto_ptr<xercesc::DOMDocument>();
 }
\ No newline at end of file
diff --git a/c++/lib/global_definitions.h b/c++/lib/global_definitions.h
index 38d31dd..1146e9c 100644
--- a/c++/lib/global_definitions.h
+++ b/c++/lib/global_definitions.h
@@ -17,9 +17,21 @@
 
 #ifndef GLOBAL_DEFINITIONS_H
 #define GLOBAL_DEFINITIONS_H
+#include <string>
+
+namespace Kolab {
 
 const char* const KOLAB_LIBNAME = "libkolabxml";
 const char* const KOLAB_LIB_VERSION = "0.9";
 const char* const KOLAB_FORMAT_VERSION = "2.9.0";
 
+enum ErrorSeverity {
+    NoError,
+    Warning, //Warning, error could be corrected, object can be used without dataloss
+    Error, //Potentially corrupt object, writing the object back could result in dataloss. (Object could still be used to display the data readonly).
+    Critical //Ciritcal error, produced object cannot be used and should be thrown away (writing back will result in dataloss).
+};
+
+}
+
 #endif
diff --git a/c++/lib/kolabformat.cpp b/c++/lib/kolabformat.cpp
index f199be9..1538fad 100644
--- a/c++/lib/kolabformat.cpp
+++ b/c++/lib/kolabformat.cpp
@@ -21,8 +21,35 @@
 #include "xcalconversions.h"
 
 #include "xcardconversions.h"
+#include "utils.h"
 
 namespace Kolab {
+    
+ErrorSeverity error()
+{
+    return getError();
+}
+
+std::string errorMessage()
+{
+    return getErrorMessage();
+}
+
+std::string productId()
+{
+    return XCAL::global_productId;
+}
+
+std::string xCalVersion()
+{
+    return XCAL::global_xCalVersion;
+}
+
+std::string xKolabVersion()
+{
+    return XCAL::global_xKolabVersion;
+}
+
 
 Kolab::Event readEvent(const std::string& s, bool isUrl)
 {
diff --git a/c++/lib/kolabformat.h b/c++/lib/kolabformat.h
index d0a8b62..5af254a 100644
--- a/c++/lib/kolabformat.h
+++ b/c++/lib/kolabformat.h
@@ -22,8 +22,16 @@
 #include "kolabcontainers.h"
 #include "kolabtodo.h"
 #include "kolabevent.h"
+#include "global_definitions.h"
 
 namespace Kolab {
+    
+Kolab::ErrorSeverity error();
+std::string errorMessage();
+
+std::string productId();
+std::string xKolabVersion();
+std::string xCalVersion();
 
 Kolab::Event readEvent(const std::string& s, bool isUrl);
 std::string writeEvent(const Kolab::Event &);
diff --git a/c++/lib/kolabformat.i b/c++/lib/kolabformat.i
index d151556..9fb87c0 100644
--- a/c++/lib/kolabformat.i
+++ b/c++/lib/kolabformat.i
@@ -5,11 +5,11 @@
     /* This macro ensures that return vectors remain a vector also in python and are not converted to tuples */
     #define SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS 
 
+    #include "global_definitions.h"
     #include "kolabformat.h"
     #include "kolabcontainers.h"
     #include "kolabevent.h"
     #include "kolabtodo.h"
-
 %}
 
 %include "std_string.i"
@@ -24,6 +24,7 @@ namespace std {
 
 /*%apply const std::string& {std::string* foo};*/
 
+%include "global_definitions.h"
 %include "kolabcontainers.h"
 %include "kolabevent.h"
 %include "kolabtodo.h"
diff --git a/c++/lib/utils.cpp b/c++/lib/utils.cpp
index e428c5e..2b9d54a 100644
--- a/c++/lib/utils.cpp
+++ b/c++/lib/utils.cpp
@@ -20,6 +20,7 @@
 #include <boost/uuid/uuid.hpp>
 #include <boost/uuid/uuid_io.hpp>
 #include <time.h>
+#include <boost/lexical_cast.hpp>
 
 namespace Kolab {
 
@@ -47,4 +48,56 @@ DateTime getCurrentTime()
     return DateTime(ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, true);
 }
 
+ErrorSeverity global_errorBit;
+std::string global_errorMessage;
+
+void logMessage(const std::string &m, ErrorSeverity s)
+{
+    switch (s) {
+        case NoError:
+            std::cout << "Debug: " << m << std::endl;
+            break;
+        case Warning:
+            std::cerr << "Warning: " << m << std::endl;
+            break;
+        case Error:
+            std::cerr << "Error: " << m << std::endl;
+            if (global_errorBit < Error) {
+                global_errorBit = Error;
+                global_errorMessage = m;
+            }
+            break;
+        case Critical:
+        default:
+            std::cerr << "Critical: " << m << std::endl;
+            if (global_errorBit < Critical) {
+                global_errorBit = Critical;
+                global_errorMessage = m;
+            }
+            
+    }
+}
+
+void logMessage(const std::string &message, const std::string &file, int line, ErrorSeverity s)
+{
+   logMessage(file+" "+boost::lexical_cast<std::string>(line)+": " + "  " + message, s);
+}
+
+void clearErrors()
+{
+    global_errorBit = NoError;
+    global_errorMessage.clear();
+}
+
+ErrorSeverity getError()
+{
+    return global_errorBit;
+}
+
+std::string getErrorMessage()
+{
+    return global_errorMessage;
+}
+
+
 }
\ No newline at end of file
diff --git a/c++/lib/utils.h b/c++/lib/utils.h
index d0cf739..886d181 100644
--- a/c++/lib/utils.h
+++ b/c++/lib/utils.h
@@ -20,6 +20,7 @@
 
 #include <string>
 #include "kolabcontainers.h"
+#include "global_definitions.h"
 
 namespace Kolab {
 
@@ -28,6 +29,19 @@ std::string getUID(const std::string &);
 
 DateTime getCurrentTime();
 
+void logMessage(const std::string &,const std::string &, int, ErrorSeverity s);
+     
+#define LOG(message) logMessage(message,__FILE__, __LINE__, NoError);
+#define WARNING(message) logMessage(message,__FILE__, __LINE__, Warning);
+#define ERROR(message) logMessage(message,__FILE__, __LINE__, Error);
+#define CRITICAL(message) logMessage(message,__FILE__, __LINE__, Critical);
+
+void logMessage(const std::string &, ErrorSeverity s = Warning);
+
+void clearErrors();
+ErrorSeverity getError();
+std::string getErrorMessage();
+
 }
 
 #endif
\ No newline at end of file
diff --git a/c++/lib/xcalconversions.h b/c++/lib/xcalconversions.h
index b0bfd8d..74df6e3 100644
--- a/c++/lib/xcalconversions.h
+++ b/c++/lib/xcalconversions.h
@@ -42,7 +42,10 @@
 
 namespace Kolab {
     namespace XCAL {
-
+        
+std::string global_productId;
+std::string global_xKolabVersion;
+std::string global_xCalVersion;
 
 const char* const XCAL_VERSION = "2.0";
 const char* const XCAL_NAMESPACE = "urn:ietf:params:xml:ns:icalendar-2.0";
@@ -102,14 +105,13 @@ template <typename T>
 int convertToInt(T integer)
 {
     try {
-        int i = boost::numeric_cast<int>(integer);
-        return i;
+        return boost::numeric_cast<int>(integer);
     } catch(boost::numeric::negative_overflow& e) {
-        std::cerr << e.what();
+        logMessage(e.what(), Error);
     } catch(boost::numeric::positive_overflow& e) {
-        std::cerr << e.what();
+        logMessage(e.what(), Error);
     } catch(boost::numeric::bad_numeric_cast& e) {
-        std::cerr << e.what();
+        logMessage(e.what(), Error);
     }
     return 0;
 }
@@ -118,14 +120,13 @@ template <typename T>
 T fromInt(int integer)
 {
     try {
-        T i = boost::numeric_cast<T>(integer);
-        return i;
+        return boost::numeric_cast<T>(integer);
     } catch(boost::numeric::negative_overflow& e) {
-        std::cerr << e.what();
+        logMessage(e.what(), Error);
     } catch(boost::numeric::positive_overflow& e) {
-        std::cerr << e.what();
+        logMessage(e.what(), Error);
     } catch(boost::numeric::bad_numeric_cast& e) {
-        std::cerr << e.what();
+        logMessage(e.what(), Error);
     }
     return 0;
 }
@@ -217,7 +218,7 @@ Kolab::DayPos toDayPos(const std::string &s)
                     try {
                         occurrence = boost::lexical_cast<int>(number);
                     } catch(boost::bad_lexical_cast &) {
-                        std::cerr << "failed to convert: " <<  number <<  std::endl;
+                        logMessage("failed to convert: " + number, Error);
                         return DayPos();
                     }
                     number.clear();
@@ -282,7 +283,7 @@ std::string fromDuration(const Kolab::Duration &d)
         }
         
     } catch(boost::bad_lexical_cast &) { 
-        std::cerr << "failed to convert duration"<<  std::endl;
+        ERROR("failed to convert duration");
         return std::string();
     }
     return s;
@@ -317,7 +318,7 @@ Kolab::Duration toDuration(const icalendar_2_0::DurationValueType &d)
                 try {
                     hours = boost::lexical_cast<int>(number);
                 } catch(boost::bad_lexical_cast &) {
-                    std::cerr << "failed to convert: " <<  number <<  std::endl;
+                    ERROR("failed to convert: " +  number);
                     return Duration();
                 }
                 number.clear();
@@ -326,7 +327,7 @@ Kolab::Duration toDuration(const icalendar_2_0::DurationValueType &d)
                 try {
                     minutes = boost::lexical_cast<int>(number);
                 } catch(boost::bad_lexical_cast &) {
-                    std::cerr << "failed to convert: " << number <<  std::endl;
+                    ERROR("failed to convert: " + number);
                     return Duration();
                 }
                 number.clear();
@@ -335,7 +336,7 @@ Kolab::Duration toDuration(const icalendar_2_0::DurationValueType &d)
                 try {
                     seconds = boost::lexical_cast<int>(number);
                 } catch(boost::bad_lexical_cast &) { 
-                    std::cerr << "failed to convert: " << number <<  std::endl;
+                    ERROR("failed to convert: " + number);
                     return Duration();
                 }
                 number.clear();
@@ -346,7 +347,7 @@ Kolab::Duration toDuration(const icalendar_2_0::DurationValueType &d)
                 try {
                     weeks = boost::lexical_cast<int>(number);
                 } catch(boost::bad_lexical_cast &) { 
-                    std::cerr << "failed to convert: " << number <<  std::endl;
+                    ERROR("failed to convert: " + number);
                     return Duration();
                 }
                 return Duration(weeks, negative);
@@ -354,7 +355,7 @@ Kolab::Duration toDuration(const icalendar_2_0::DurationValueType &d)
                 try {
                     days = boost::lexical_cast<int>(number);
                 } catch(boost::bad_lexical_cast &) { 
-                    std::cerr << "failed to convert: " << number <<  std::endl;
+                    ERROR("failed to convert: " + number);
                     return Duration();
                 }
                 number.clear();
@@ -367,7 +368,8 @@ Kolab::Duration toDuration(const icalendar_2_0::DurationValueType &d)
             case 'P':
                 break;
             default:
-                std::cerr << "error: " << *it << std::endl;
+                ERROR("failed to convert duration: " + *it);
+                return Duration();
         }
     }
     return Duration(days, hours, minutes, seconds, negative);
@@ -401,7 +403,7 @@ Kolab::Attachment toAttachment(T aProp)
             }
             if (const icalendar_2_0::EncodingParamType *p = dynamic_cast<const icalendar_2_0::EncodingParamType*> (&*it)) {
                 if (p->text() != BASE64) {
-                    std::cerr << "wrong encoding";
+                    ERROR("wrong encoding");
                     return Kolab::Attachment();
                 }
             }
@@ -411,7 +413,7 @@ Kolab::Attachment toAttachment(T aProp)
         }
     }
     if (mimetype.empty()) {
-        std::cerr << "no mimetype" << std::endl;
+        ERROR("no mimetype");
     }
 
     if (aProp.uri()) {
@@ -419,7 +421,7 @@ Kolab::Attachment toAttachment(T aProp)
     } else if (aProp.binary()) {
         a.setData(base64_decode(*aProp.binary()), mimetype);
     } else {
-        std::cerr << "not uri and no data available" << std::endl;
+        ERROR("not uri and no data available");
     }
     return a;
 }
@@ -439,7 +441,7 @@ icalendar_2_0::AttachPropType fromAttachment(const Kolab::Attachment &a)
         attachment.binary(base64_encode(reinterpret_cast<const unsigned char*>(a.data().c_str()), a.data().length()));
         p.baseParameter().push_back(icalendar_2_0::EncodingParamType(BASE64));
     } else {
-        std::cerr << "no uri and no data" << std::endl;
+        ERROR("no uri and no data");
     }
     
     attachment.parameters(p);
@@ -492,7 +494,7 @@ typedef boost::shared_ptr<DateTime> DateTimePtr;
             if (tzid.find(TZ_PREFIX) != std::string::npos) {
                 tzid.erase(0, strlen(TZ_PREFIX));
             } else {
-                std::cerr << "/kolab.org/ timezone prefix is missing";
+                WARNING("/kolab.org/ timezone prefix is missing");
             }
             return tzid;
         }
@@ -526,7 +528,7 @@ DateTimePtr toDate(const icalendar_2_0::UtcDatetimePropertyType &dtProperty)
         date = toDate(*dtProperty.date_time());
     } else { //The utc-date-time element shouldn't even exist
         date = DateTimePtr(new DateTime());
-        std::cerr << "This element shouldn't even be existing";
+        ERROR("This element shouldn't even be existing");
         //TODO Implement anyways?
         return date;
     }
@@ -636,7 +638,7 @@ std::string mapPartStat(PartStatus status)
         case PartTentative:
             return PARTTENTATIVE;
     }
-    std::cout << "PartStat not handled: " << status;
+    ERROR("PartStat not handled: " + status);
     return std::string();
 }
 
@@ -653,7 +655,7 @@ PartStatus mapPartStat(const std::string &status)
     } else if (status == PARTTENTATIVE) {
         return PartTentative;
     }
-    std::cout << "Unhandled partstatus" << status;
+    ERROR("PartStat not handled: " + status);
     return PartNeedsAction;
 }
 
@@ -669,7 +671,7 @@ std::string mapRole(Role status)
         case Required:
             return REQUIRED;
     }
-    std::cout << "PartStat not handled: " << status;
+    ERROR("PartStat not handled: " + status);
     return std::string();
 }
 
@@ -684,7 +686,7 @@ Role mapRole(const std::string &status)
     } else if (status == REQUIRED) {
         return Required;
     }
-    std::cout << "Unhandled Role" << status;
+    ERROR("Unhandled Role " + status);
     return Required;
 }
 
@@ -719,7 +721,7 @@ Role mapRole(const std::string &status)
             case FreqRecurType::SECONDLY:
                 return RecurrenceRule::Secondly;
             default:
-                std::cout << "invalid unhandled recurrenc type" << freq;
+                ERROR("invalid unhandled recurrenc type" + freq);
         }
         return RecurrenceRule::None;
     }
@@ -744,7 +746,7 @@ Role mapRole(const std::string &status)
             case RecurrenceRule::Secondly:
                 return FreqRecurType::SECONDLY;
             default:
-                std::cout << "invalid unhandled recurrenc type";
+                ERROR("invalid unhandled recurrenc type");
         }
         return 0;
     }
@@ -776,7 +778,7 @@ Role mapRole(const std::string &status)
                 r->setWeekStart(Kolab::Sunday);
                 break;
             default:
-                std::cout << "invalid unhandled weekday" << wkst;
+                ERROR("invalid unhandled weekday" + wkst);
         }
     }
 
@@ -879,7 +881,7 @@ void setIncidenceProperties(I &inc, const T &prop)
     if (prop.rdate()) {
         inc.setRecurrenceDates(toDateTimeList<icalendar_2_0::KolabEvent::properties_type::rdate_type>(*prop.rdate()));
         if (!prop.rdate()->period().empty()) {
-            std::cout << "the period element must not be used, ignored." << std::endl;
+            ERROR("the period element must not be used, ignored.");
         }
     }
 
@@ -931,7 +933,7 @@ void setIncidenceProperties(I &inc, const T &prop)
         } else if (status == FINAL) {
             inc.setStatus(Final);
         } else {
-            std::cout << "Unhandled status";
+            ERROR("Unhandled status");
         }
     }
 
@@ -986,7 +988,7 @@ void setIncidenceProperties(I &inc, const T &prop)
         BOOST_FOREACH(typename T::attach_type aProp, prop.attach()) {
             const Kolab::Attachment &a = toAttachment<typename T::attach_type>(aProp);
             if (!a.isValid()) {
-                std::cerr << "invalid attachment" << std::endl;
+                ERROR("invalid attachment");
                 continue;
             }
             attachments.push_back(a);
@@ -1176,7 +1178,7 @@ void getIncidenceProperties(T &prop, const I &inc)
                 prop.status(typename properties::status_type(FINAL));
                 break;
             default:
-                std::cout << "unhandled status " << inc.status() << std::endl;
+                ERROR("unhandled status " + inc.status());
         }
 
     }
@@ -1259,7 +1261,7 @@ void setAlarms(typename KolabType::components_type& components, const IncidenceT
             trigger.date_time(fromDateTime(alarm.start()));
         } else {
             if (!alarm.relativeStart().isValid()) {
-                std::cerr << "no start and no relativeStart" << std::endl;
+                ERROR("no start and no relativeStart");
                 continue;
             }
             trigger.duration(PropType::trigger_type::duration_type(fromDuration(alarm.relativeStart())));
@@ -1292,7 +1294,7 @@ void setAlarms(typename KolabType::components_type& components, const IncidenceT
                 p->attach(fromAttachment(alarm.audioFile()));
                 break;
             default:
-                std::cerr << "invalid alarm" << std::endl;
+                ERROR("invalid alarm");
                 continue;
         }
         if (alarm.duration().isValid()) {
@@ -1317,7 +1319,7 @@ void getAlarms(IncidenceType &incidence, const typename KolabType::components_ty
         Kolab::Alarm alarm;
         if (prop.action().text() == DISPLAYALARM) {
             if (!prop.description()) {
-                std::cerr << "description is missing" << std::endl;
+                ERROR("description is missing");
                 continue;
             }
             alarm = Kolab::Alarm((*prop.description()).text());
@@ -1327,30 +1329,30 @@ void getAlarms(IncidenceType &incidence, const typename KolabType::components_ty
                 attendees.push_back((*at).cal_address());
             }
             if (!prop.description() || !prop.summary()) {
-                std::cerr << "description or summary is missing" << std::endl;
+                ERROR("description or summary is missing");
                 continue;
             }
             alarm = Kolab::Alarm((*prop.summary()).text(), (*prop.description()).text(), attendees);
         } else if (prop.action().text() == AUDIOALARM) {
             if (!prop.attach()) {
-                std::cerr << "audio file is missing" << std::endl;
+                ERROR("audio file is missing");
                 continue;
             }
             const Kolab::Attachment &attach = toAttachment<icalendar_2_0::properties::attach_type>(*prop.attach());
             if (!attach.isValid()) {
-                std::cerr << "audio file is invalid" << std::endl;
+                ERROR("audio file is invalid");
                 continue;
             }
             alarm = Kolab::Alarm(attach);
         } else {
-            std::cerr << "unknown alarm type " << prop.action().text() << std::endl;
+            ERROR("unknown alarm type " + prop.action().text());
             continue;
         }
         
         if (prop.trigger().date_time()) {
             alarm.setStart(*toDate(*prop.trigger().date_time()));
             if (!alarm.start().isUTC()) {
-                std::cerr << "The start date time must be in UTC "<< std::endl;
+                ERROR("The start date time must be in UTC ");
                 continue;
             }
         } else if (prop.trigger().duration()) {
@@ -1363,7 +1365,7 @@ void getAlarms(IncidenceType &incidence, const typename KolabType::components_ty
                         } else if (rel->text() == END) {
                             relativeTo = Kolab::End;
                         } else {
-                            std::cerr << "relativeTo not specified, default to start " << std::endl;
+                            LOG("relativeTo not specified, default to start ");
                         }
                     }
                 }
@@ -1371,7 +1373,7 @@ void getAlarms(IncidenceType &incidence, const typename KolabType::components_ty
             
             alarm.setRelativeStart(toDuration(*prop.trigger().duration()), relativeTo);
         } else {
-            std::cerr << "no duration and not starttime " << std::endl;
+            ERROR("no duration and not starttime ");
             continue;
         }
         if (prop.duration()) {
@@ -1459,7 +1461,7 @@ template < > struct IncidenceTrait <Kolab::Event>
             if (event.end().isUTC() != event.end().isUTC() && 
                 event.end().timezone() != event.end().timezone() &&
                 event.end().isDateOnly() != event.end().isDateOnly()) {
-                std::cerr << "dtEnd has wrong timespec" << std::endl;;
+                ERROR("dtEnd has wrong timespec");
             }
         } else if (prop.duration()) {
             event.setDuration(toDuration((*prop.duration()).duration()));
@@ -1471,7 +1473,7 @@ template < > struct IncidenceTrait <Kolab::Event>
             } else {
                 event.setTransparency(false);
                 if (toString(*prop.transp()) != OPAQUE) {
-                    std::cerr << "wrong transparency value " << toString(*prop.transp()) << std::endl;
+                    ERROR("wrong transparency value " + toString(*prop.transp()));
                 }
             }
         }
@@ -1578,6 +1580,8 @@ std::string serializeIncidence(const typename T::IncidenceType &incidence, const
     using namespace icalendar_2_0;
     typedef IncidenceConverter< Incidence, typename T::IncidenceType > IC;
     typedef typename T::KolabType KolabType;
+    
+    clearErrors();
 
     try {
 
@@ -1618,9 +1622,9 @@ std::string serializeIncidence(const typename T::IncidenceType &incidence, const
         icalendar_2_0::icalendar(ostringstream, icalendar, map);
         return ostringstream.str();
     } catch  (const xml_schema::exception& e) {
-        std::cout << "failed to write Incidence" << std::endl;
+        CRITICAL("failed to write Incidence");
     } catch (...) {
-        std::cerr <<  "Unhandled exception" << std::endl;
+        CRITICAL("Unhandled exception");
     }
     return std::string();
 }
@@ -1629,10 +1633,12 @@ std::string serializeIncidence(const typename T::IncidenceType &incidence, const
 template <typename T>
 typename T::IncidencePtr deserializeIncidence(const std::string& s, bool isUrl)
 {
+    using namespace icalendar_2_0;
     typedef typename T::IncidencePtr IncidencePtr;
     typedef typename T::IncidenceType IncidenceType;
     typedef typename T::KolabType KolabType;
     
+    clearErrors();
     try {
         std::auto_ptr<icalendar_2_0::IcalendarType> icalendar;
         if (isUrl) {
@@ -1648,7 +1654,7 @@ typename T::IncidencePtr deserializeIncidence(const std::string& s, bool isUrl)
         }
         
         if (!icalendar.get()) {
-            std::cerr << "failed to parse calendar!" << std::endl;
+            CRITICAL("Failed to parse calendar!");
             return IncidencePtr();
         }
 
@@ -1662,7 +1668,10 @@ typename T::IncidencePtr deserializeIncidence(const std::string& s, bool isUrl)
             incidences.push_back(e);
         }
         
-        //TODO x_kolab_version
+        global_productId = vcalendar.properties().prodid().text();
+        global_xCalVersion = vcalendar.properties().version().text();
+        global_xKolabVersion = vcalendar.properties().x_kolab_version().text();
+
 
         //TODO resolve events, exceptions can be identified based on the recurrence-id attribute
 //         foreach (KCalCore::Event * event, events) {
@@ -1671,14 +1680,14 @@ typename T::IncidencePtr deserializeIncidence(const std::string& s, bool isUrl)
 //             }
 //         }
         if (incidences.size() != 1) {
-            std::cerr << "wrong number of incidences: " << incidences.size() << std::endl;
+            WARNING("wrong number of incidences: "+ incidences.size());
         }
         return *incidences.begin();
     } catch  (const xml_schema::exception& e) {
-        std::cerr <<  e << std::endl;
-        std::cerr <<  "Failed to read incidence!" << std::endl;
+        std::cout <<  e << std::endl;
+        CRITICAL("Failed to read incidence!");
     } catch (...) {
-        std::cerr <<  "Unhandled exception" << std::endl;
+        CRITICAL("Unhandled exception");
     }
     return IncidencePtr();
 }
diff --git a/c++/tests/bindingstest.cpp b/c++/tests/bindingstest.cpp
index b696f9b..0b35721 100644
--- a/c++/tests/bindingstest.cpp
+++ b/c++/tests/bindingstest.cpp
@@ -17,6 +17,7 @@
 #include <iostream>
 #include <fstream>
 #include "serializers.h"
+#include <lib/utils.h>
 
 //TODO remove
 void BindingsTest::writeContact()
@@ -251,15 +252,14 @@ void BindingsTest::eventCompletness()
     ev.setTransparency(true);
     
     std::string result = Kolab::writeEvent(ev);
-    std::cout << result << endl;
+//     std::cout << result << endl;
     Kolab::Event e = Kolab::readEvent(result, false);
-    const Kolab::Event &re = e;
-    checkIncidence(ev, re);
-    QCOMPARE(ev.end(), re.end());
+    checkIncidence(ev, e);
+    QCOMPARE(ev.end(), e.end());
 //     QEXPECT_FAIL("", "Will fix in the next release", Continue);
 //     QVERIFY(ev.duration().isValid());
 //     QCOMPARE(ev.duration(), re.duration());
-    QCOMPARE(ev.transparency(), re.transparency());
+    QCOMPARE(ev.transparency(), e.transparency());
     
 }
 
@@ -285,15 +285,45 @@ void BindingsTest::todoCompletness()
     ev.setPercentComplete(50);
     
     std::string result = Kolab::writeTodo(ev);
-    std::cout << result << endl;
+//     std::cout << result << endl;
+    Kolab::Todo e = Kolab::readTodo(result, false);
+    checkIncidence(ev, e);
+    QCOMPARE(ev.due(), e.due());
+    QCOMPARE(ev.relatedTo(), e.relatedTo());
+    QCOMPARE(ev.percentComplete(), e.percentComplete());
+}
+
+void BindingsTest::versionTest()
+{
+    Kolab::Todo ev;
+    setIncidence(ev);
+    
+    std::string result = Kolab::writeTodo(ev);
     Kolab::Todo e = Kolab::readTodo(result, false);
-    const Kolab::Todo &re = e;
-    checkIncidence(ev, re);
-    QCOMPARE(ev.due(), re.due());
-    QCOMPARE(ev.relatedTo(), re.relatedTo());
-    QCOMPARE(ev.percentComplete(), re.percentComplete());
+    QCOMPARE(Kolab::productId(), std::string(Kolab::KOLAB_LIBNAME) + std::string(Kolab::KOLAB_LIB_VERSION));
+    QCOMPARE(Kolab::xKolabVersion(), std::string(Kolab::KOLAB_FORMAT_VERSION));
+    QCOMPARE(Kolab::xCalVersion(), std::string("2.0"));
+}
+
+void BindingsTest::errorTest()
+{
+    Kolab::Todo e = Kolab::readTodo("klbsdfbklsdbkl", false);
+    QCOMPARE(Kolab::error(), Kolab::Critical);
+    QCOMPARE(Kolab::errorMessage(), std::string("/home/chrigi/work/kolab/xmlformat/libkolabxml/c++/lib/xcalconversions.h 1657:   Failed to parse calendar!"));
+}
 
+//Don't break due to an error
+void BindingsTest::errorRecoveryTest()
+{
+    Kolab::Todo e = Kolab::readTodo("klbsdfbklsdbkl", false);
+    QCOMPARE(Kolab::error(), Kolab::Critical);
+
+    Kolab::Todo ev;
+    setIncidence(ev);
     
+    const std::string result = Kolab::writeTodo(ev);
+    Kolab::readTodo(result, false);
+    QCOMPARE(Kolab::error(), Kolab::NoError);
 }
 
 void BindingsTest::BenchmarkRoundtripKolab()
diff --git a/c++/tests/bindingstest.h b/c++/tests/bindingstest.h
index aa140b1..ab34319 100644
--- a/c++/tests/bindingstest.h
+++ b/c++/tests/bindingstest.h
@@ -32,7 +32,11 @@ class BindingsTest : public QObject
     void eventCompletness();
     void eventDuration();
     void todoCompletness();
-    
+
+    void versionTest();
+    void errorTest();
+    void errorRecoveryTest();
+
     void BenchmarkRoundtripKolab();
     void BenchmarkRoundtripKCAL();
 };





More information about the commits mailing list