You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2012/12/29 12:36:11 UTC

svn commit: r1426747 - in /subversion/trunk/subversion/bindings/cxxhl: include/svncxxhl/exception.hpp src/exception.cpp tests/test_exception.cpp

Author: brane
Date: Sat Dec 29 11:36:10 2012
New Revision: 1426747

URL: http://svn.apache.org/viewvc?rev=1426747&view=rev
Log:
Enhance error chain conversion in C++ bindings.

* subversion/bindings/cxxhl/include/svncxxhl/exception.hpp
  (subversion::cxxhl::version_1_9_dev::error): Change private constructor to
   protected so that the "cancelled" subclass can access it.
  (subversion::cxxhl::version_1_9_dev::cancelled): Enable the parent class'
   public throw_svn_error factory to create instances of this class.

* subversion/bindings/cxxhl/src/exception.cpp
  (subversion::cxxhl::version_1_9_dev::error::thow_svn_error): Refactor
   implementation so that we can properly throw "cancelled" exceptions
   if the error chain indicates cancellation.

* subversion/bindings/cxxhl/tests/test_exception.cpp: Test throw_svn_error with
   both cancellation and regular error chains.

Modified:
    subversion/trunk/subversion/bindings/cxxhl/include/svncxxhl/exception.hpp
    subversion/trunk/subversion/bindings/cxxhl/src/exception.cpp
    subversion/trunk/subversion/bindings/cxxhl/tests/test_exception.cpp

Modified: subversion/trunk/subversion/bindings/cxxhl/include/svncxxhl/exception.hpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxxhl/include/svncxxhl/exception.hpp?rev=1426747&r1=1426746&r2=1426747&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxxhl/include/svncxxhl/exception.hpp (original)
+++ subversion/trunk/subversion/bindings/cxxhl/include/svncxxhl/exception.hpp Sat Dec 29 11:36:10 2012
@@ -115,8 +115,10 @@ public:
   /** Used internally by the implementation. */
   static void throw_svn_error(svn_error_t*);
 
-private:
+protected:
   error(int error_code, detail::error_description* description) throw();
+
+private:
   std::vector<message> compile_messages(bool show_traces) const;
 
   int m_errno;                /**< The (SVN or APR) error code. */
@@ -125,7 +127,15 @@ private:
   detail::error_description* m_description;
 };
 
-class canceled : public error {};
+class cancelled : public error
+{
+  friend void error::throw_svn_error(svn_error_t*);
+
+protected:
+  cancelled(int error_code, detail::error_description* description) throw()
+    : error(error_code, description)
+    {}
+};
 
 } // namespace version_1_9_dev
 } // namespace cxxhl

Modified: subversion/trunk/subversion/bindings/cxxhl/src/exception.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxxhl/src/exception.cpp?rev=1426747&r1=1426746&r2=1426747&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxxhl/src/exception.cpp (original)
+++ subversion/trunk/subversion/bindings/cxxhl/src/exception.cpp Sat Dec 29 11:36:10 2012
@@ -162,6 +162,7 @@ error::error(int error_code, detail::err
 
 void error::throw_svn_error(svn_error_t* err)
 {
+  const bool throw_cancelled = (err->apr_err == SVN_ERR_CANCELLED);
   detail::error_description* description = NULL;
   try
     {
@@ -169,28 +170,41 @@ void error::throw_svn_error(svn_error_t*
       // the exception unwinder can free them if an allocation fails.
       // The private constructor does not increment the refcount
       // precisely for this reason.
+
+      shared_ptr nested;
+      shared_ptr* current = &nested;
+
+      for (svn_error_t* next = err->child; next; next = next->child)
+        {
+          description = detail::error_description::create(
+              next->message, next->file, next->line,
+              svn_error__is_tracing_link(next));
+          description->reference();
+          current->reset(new error(next->apr_err, description));
+          description = NULL;
+          current = &(*current)->m_nested;
+        }
+
+      const int apr_err = err->apr_err;
       description = detail::error_description::create(
           err->message, err->file, err->line,
           svn_error__is_tracing_link(err));
       description->reference();
-      error converted = error(err->apr_err, description);
-      description = NULL;
-
-      svn_error_t *prev = err;
-      error* current = &converted;
-      for (err = err->child; err; prev = err, err = err->child)
+      svn_error_clear(err);
+      if (throw_cancelled)
         {
-          svn_error_clear(prev);
-          description = detail::error_description::create(
-              err->message, err->file, err->line,
-              svn_error__is_tracing_link(err));
-          description->reference();
-          current->m_nested.reset(new error(err->apr_err, description));
+          cancelled converted = cancelled(apr_err, description);
+          description = NULL;
+          converted.m_nested = nested;
+          throw converted;
+        }
+      else
+        {
+          error converted = error(apr_err, description);
           description = NULL;
-          current = current->m_nested.get();
+          converted.m_nested = nested;
+          throw converted;
         }
-      svn_error_clear(prev);
-      throw converted;
     }
   catch (...)
     {

Modified: subversion/trunk/subversion/bindings/cxxhl/tests/test_exception.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/cxxhl/tests/test_exception.cpp?rev=1426747&r1=1426746&r2=1426747&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/cxxhl/tests/test_exception.cpp (original)
+++ subversion/trunk/subversion/bindings/cxxhl/tests/test_exception.cpp Sat Dec 29 11:36:10 2012
@@ -39,12 +39,52 @@ void trace(const svn::error::message& ms
               << msg.first << ':' << ' ';
   std::cout << msg.second << std::endl;
 }
+
+void traceall(const char *message, const svn::error& err)
+{
+  typedef svn::error::message_list message_list;
+  std::cout << message << std::endl;
+  std::cout << "Traced Messages:" << std::endl;
+  message_list ml = err.traced_messages();
+  std::for_each(ml.begin(), ml.end(), trace);
+  std::cout << "Just Messages:" << std::endl;
+  ml = err.messages();
+  std::for_each(ml.begin(), ml.end(), trace);
+}
 } // anonymous namespace
 
-int main()
+
+bool test_cancel()
 {
-  apr_initialize();
+  try
+    {
+      svn_error_t* err;
+      err = svn_error_create(SVN_ERR_TEST_FAILED, NULL, "original message");
+      err = svn_error_create(SVN_ERR_BASE, err, "wrapper message");
+      err = svn_error_create(SVN_ERR_CANCELLED, err, NULL);
+      err = svn_error_create(SVN_ERR_CANCELLED, err, NULL);
+      err = svn_error_trace(err);
+      svn::error::throw_svn_error(err);
+    }
+  catch (const svn::cancelled& err)
+    {
+      traceall("Caught: CANCEL", err);
+      return true;
+    }
+  catch (const svn::error& err)
+    {
+      traceall("Caught: ERROR", err);
+      return false;
+    }
+  catch (...)
+    {
+      return false;
+    }
+  return false;
+}
 
+int test_error()
+{
   try
     {
       svn_error_t* err;
@@ -54,20 +94,36 @@ int main()
       err = svn_error_create(SVN_ERR_CANCELLED, err, NULL);
       err = svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, err, NULL);
       err = svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, err, NULL);
-      err = svn_error_create(SVN_ERR_CANCELLED, err, NULL);
       err = svn_error_trace(err);
       svn::error::throw_svn_error(err);
     }
+  catch (const svn::cancelled& err)
+    {
+      traceall("Caught: CANCEL", err);
+      return false;
+    }
   catch (const svn::error& err)
     {
-      typedef svn::error::message_list message_list;
-      std::cout << "Traced Messages:" << std::endl;
-      message_list ml = err.traced_messages();
-      std::for_each(ml.begin(), ml.end(), trace);
-      std::cout << "Just Messages:" << std::endl;
-      ml = err.messages();
-      std::for_each(ml.begin(), ml.end(), trace);
+      traceall("Caught: ERROR", err);
+      return true;
     }
+  catch (...)
+    {
+      return false;
+    }
+  return false;
+}
+
+int main()
+{
+  apr_initialize();
+
+  const char *stat  = (test_cancel() ? "OK" : "ERROR");
+  std::cerr << "test_cancel .... " << stat << std::endl;
+
+  stat = (test_error() ? "OK" : "ERROR");
+  std::cerr << "test_error ..... " << stat << std::endl;
 
+  apr_terminate();
   return 0;
 }