Author: svn-role Date: Fri Apr 3 04:00:20 2015 New Revision: 1670996 URL: http://svn.apache.org/r1670996 Log: Merge the r1664938 group from trunk:
* r1664938, r1664939, r1664940, r1664978, r1664984 libsvn_javahl: wrap and unwrap java exceptions via svn_error_t Justification: This patch makes Java callbacks that throw errors report their error to the subversion function that called them. This allows this function to properly handle the error condition instead of continuing as if nothing happened. If further callbacks are needed during error handling these callbacks will now just work and Subversion can ignore certain kinds of errors as needed, by just clearing the error. Votes: +1: rhuijben (not after 1.9.0), brane Added: subversion/branches/1.9.x/subversion/bindings/javahl/tests/org/apache/subversion/javahl/ExceptionTests.java - copied, changed from r1664938, subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/ExceptionTests.java Modified: subversion/branches/1.9.x/ (props changed) subversion/branches/1.9.x/STATUS subversion/branches/1.9.x/subversion/bindings/javahl/native/BlameCallback.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/CommitCallback.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/CommitMessage.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/InfoCallback.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/JNIUtil.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/JNIUtil.h subversion/branches/1.9.x/subversion/bindings/javahl/native/ListCallback.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/LogMessageCallback.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/OperationContext.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/PatchCallback.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/ProplistCallback.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/StatusCallback.cpp subversion/branches/1.9.x/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp subversion/branches/1.9.x/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java Propchange: subversion/branches/1.9.x/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Fri Apr 3 04:00:20 2015 @@ -89,4 +89,4 @@ /subversion/branches/verify-at-commit:1462039-1462408 /subversion/branches/verify-keep-going:1439280-1546110 /subversion/branches/wc-collate-path:1402685-1480384 -/subversion/trunk:1660545-1660547,1660549-1662901,1663003,1663183-1663184,1663338,1663347,1663355,1663374,1663450,1663697,1663706,1663738,1663749,1663791,1664078,1664080,1664084-1664085,1664187,1664191,1664193,1664200,1664344,1664476,1664480-1664481,1664483,1664507,1664520-1664521,1664523,1664526-1664527,1664531-1664532,1664588,1664653,1664684,1664927,1664997,1665164,1665195,1665318,1665437-1665438,1665611-1665612,1665845,1665850,1665852,1665886,1665894,1665896,1666096,1666270,1666272,1666379,1666449,1666690,1666851,1667101,1667106-1667107,1667941,1667976,1668598,1668600,1668602-1668603,1670329 +/subversion/trunk:1660545-1660547,1660549-1662901,1663003,1663183-1663184,1663338,1663347,1663355,1663374,1663450,1663697,1663706,1663738,1663749,1663791,1664078,1664080,1664084-1664085,1664187,1664191,1664193,1664200,1664344,1664476,1664480-1664481,1664483,1664507,1664520-1664521,1664523,1664526-1664527,1664531-1664532,1664588,1664653,1664684,1664927,1664938-1664940,1664978,1664984,1664997,1665164,1665195,1665318,1665437-1665438,1665611-1665612,1665845,1665850,1665852,1665886,1665894,1665896,1666096,1666270,1666272,1666379,1666449,1666690,1666851,1667101,1667106-1667107,1667941,1667976,1668598,1668600,1668602-1668603,1670329 Modified: subversion/branches/1.9.x/STATUS URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/STATUS?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/STATUS (original) +++ subversion/branches/1.9.x/STATUS Fri Apr 3 04:00:20 2015 @@ -216,18 +216,6 @@ Veto-blocked changes: Approved changes: ================= - * r1664938, r1664939, r1664940, r1664978, r1664984 - libsvn_javahl: wrap and unwrap java exceptions via svn_error_t - Justification: - This patch makes Java callbacks that throw errors report - their error to the subversion function that called them. This - allows this function to properly handle the error condition instead - of continuing as if nothing happened. If further callbacks are needed - during error handling these callbacks will now just work and Subversion - can ignore certain kinds of errors as needed, by just clearing the error. - Votes: - +1: rhuijben (not after 1.9.0), brane - * r1669749 Make the new svn_fs_dir_optimal_order use two pools. Justification: Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/BlameCallback.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/BlameCallback.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/BlameCallback.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/BlameCallback.cpp Fri Apr 3 04:00:20 2015 @@ -128,8 +128,6 @@ BlameCallback::singleLine(svn_revnum_t s env->CallVoidMethod(m_callback, mid, (jlong)line_no, (jlong)revision, jrevProps, (jlong)mergedRevision, jmergedRevProps, jmergedPath, jline, (jboolean)localChange); - // No need to check for an exception here, because we return anyway. - env->PopLocalFrame(NULL); - return SVN_NO_ERROR; + POP_AND_RETURN_EXCEPTION_AS_SVNERROR(); } Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/CommitCallback.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/CommitCallback.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/CommitCallback.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/CommitCallback.cpp Fri Apr 3 04:00:20 2015 @@ -96,10 +96,8 @@ CommitCallback::commitInfo(const svn_com POP_AND_RETURN(SVN_NO_ERROR); env->CallVoidMethod(m_callback, sm_mid, jcommitInfo); - // No need to check for an exception here, because we return anyway. - env->PopLocalFrame(NULL); - return SVN_NO_ERROR; + POP_AND_RETURN_EXCEPTION_AS_SVNERROR(); } Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/CommitMessage.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/CommitMessage.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/CommitMessage.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/CommitMessage.cpp Fri Apr 3 04:00:20 2015 @@ -106,7 +106,7 @@ CommitMessage::getCommitMessage(const ch midCallback, CreateJ::Set(jitems)); if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN(SVN_NO_ERROR); + POP_AND_RETURN_EXCEPTION_AS_SVNERROR(); if (jmessage != NULL) { Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/DiffSummaryReceiver.cpp Fri Apr 3 04:00:20 2015 @@ -117,8 +117,5 @@ DiffSummaryReceiver::onSummary(const svn // Invoke the Java DiffSummaryReceiver callback. env->CallVoidMethod(m_receiver, callback, jDiffSummary); - // We return whether an exception was thrown or not. - - env->PopLocalFrame(NULL); - return SVN_NO_ERROR; + POP_AND_RETURN_EXCEPTION_AS_SVNERROR(); } Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/InfoCallback.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/InfoCallback.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/InfoCallback.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/InfoCallback.cpp Fri Apr 3 04:00:20 2015 @@ -95,8 +95,6 @@ InfoCallback::singleInfo(const char *pat POP_AND_RETURN(SVN_NO_ERROR); env->CallVoidMethod(m_callback, mid, jinfo2); - // Return SVN_NO_ERROR here regardless of an exception or not. - env->PopLocalFrame(NULL); - return SVN_NO_ERROR; + POP_AND_RETURN_EXCEPTION_AS_SVNERROR(); } Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/JNIUtil.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/JNIUtil.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/JNIUtil.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/JNIUtil.cpp Fri Apr 3 04:00:20 2015 @@ -77,6 +77,11 @@ bool JNIUtil::g_initException; int JNIUtil::g_logLevel = JNIUtil::noLog; std::ofstream JNIUtil::g_logStream; +/* The error code we will use to signal a Java exception */ +static const apr_status_t +SVN_ERR_JAVAHL_WRAPPED = SVN_ERR_MALFUNC_CATEGORY_START + + SVN_ERR_CATEGORY_SIZE - 10; + /** * Return the JNI environment to use * @return the JNI environment @@ -446,7 +451,8 @@ ErrorMessageStack assemble_error_message { /* When we're recursing, don't repeat the top-level message if its * the same as before. */ - if (depth == 0 || err->apr_err != parent_apr_err) + if ((depth == 0 || err->apr_err != parent_apr_err) + && err->apr_err != SVN_ERR_JAVAHL_WRAPPED) { const char *message; /* Is this a Subversion-specific error code? */ @@ -586,6 +592,9 @@ void JNIUtil::wrappedHandleSVNError(svn_ #endif #endif + if (!jcause) + jcause = JNIUtil::unwrapJavaException(err); + // Much of the following is stolen from throwNativeException(). As much as // we'd like to call that function, we need to do some manual stack // unrolling, so it isn't feasible. @@ -1043,3 +1052,91 @@ svn_error_t *JNIUtil::preprocessPath(con return NULL; } + +/* Tag to use on the apr_pool_t to store a WrappedException reference */ +static const char *WrapExceptionTag = "org.apache.subversion.JavaHL.svnerror"; + +class WrappedException +{ + JNIEnv *m_env; + jthrowable m_exception; +#ifdef SVN_DEBUG + bool m_fetched; +#endif +public: + WrappedException(JNIEnv *env) + { + m_env = env; + + // Fetch exception inside local frame + jthrowable exceptionObj = env->ExceptionOccurred(); + + // Now clear exception status + env->ExceptionClear(); + + // As adding a reference in exception state fails + m_exception = static_cast<jthrowable>(env->NewGlobalRef(exceptionObj)); + +#ifdef SVN_DEBUG + m_fetched = false; +#endif + } + + static jthrowable get_exception(apr_pool_t *pool) + { + void *data; + if (! apr_pool_userdata_get(&data, WrapExceptionTag, pool)) + { + WrappedException *we = reinterpret_cast<WrappedException *>(data); + + if (we) + { +#ifdef SVN_DEBUG + we->m_fetched = TRUE; +#endif + // Create reference in local frame, as the pool will be cleared + return static_cast<jthrowable>( + we->m_env->NewLocalRef(we->m_exception)); + } + } + return NULL; + } + +private: + ~WrappedException() + { +#ifdef SVN_DEBUG + if (!m_fetched) + SVN_DBG(("Cleared svn_error_t * before Java exception was fetched")); +#endif + m_env->DeleteGlobalRef(m_exception); + } +public: + static apr_status_t cleanup(void *data) + { + WrappedException *we = reinterpret_cast<WrappedException *>(data); + + delete we; + return APR_SUCCESS; + } +}; + +svn_error_t* JNIUtil::wrapJavaException() +{ + if (!isExceptionThrown()) + return SVN_NO_ERROR; + + svn_error_t *err = svn_error_create(SVN_ERR_JAVAHL_WRAPPED, NULL, + "Wrapped Java Exception"); + apr_pool_userdata_set(new WrappedException(getEnv()), WrapExceptionTag, + WrappedException::cleanup, err->pool); + return err; +} + +jthrowable JNIUtil::unwrapJavaException(const svn_error_t *err) +{ + if (!err) + return NULL; + return + WrappedException::get_exception(err->pool); +} Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/JNIUtil.h URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/JNIUtil.h?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/JNIUtil.h (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/JNIUtil.h Fri Apr 3 04:00:20 2015 @@ -86,6 +86,9 @@ class JNIUtil return getEnv()->ExceptionCheck(); } + static svn_error_t *wrapJavaException(); + static jthrowable unwrapJavaException(const svn_error_t *err); + static void handleAPRError(int error, const char *op); /** @@ -265,6 +268,16 @@ class JNIUtil } \ while (0) +#define POP_AND_RETURN_EXCEPTION_AS_SVNERROR() \ + do \ + { \ + svn_error_t *svn__err_for_exception = JNIUtil::wrapJavaException(); \ + \ + env->PopLocalFrame(NULL); \ + return svn__err_for_exception; \ + } \ + while (0) + /** * A useful macro. Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/ListCallback.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/ListCallback.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/ListCallback.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/ListCallback.cpp Fri Apr 3 04:00:20 2015 @@ -113,10 +113,8 @@ ListCallback::doList(const char *path, // call the Java method env->CallVoidMethod(m_callback, mid, jdirentry, jlock); - // No need to check for exception here, because we'll just return anyway - env->PopLocalFrame(NULL); - return SVN_NO_ERROR; + POP_AND_RETURN_EXCEPTION_AS_SVNERROR(); } /** Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/LogMessageCallback.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/LogMessageCallback.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/LogMessageCallback.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/LogMessageCallback.cpp Fri Apr 3 04:00:20 2015 @@ -125,8 +125,6 @@ LogMessageCallback::singleMessage(svn_lo (jlong)log_entry->revision, jrevprops, (jboolean)log_entry->has_children); - // No need to check for an exception here, because we return anyway. - env->PopLocalFrame(NULL); - return SVN_NO_ERROR; + POP_AND_RETURN_EXCEPTION_AS_SVNERROR(); } Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/OperationContext.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/OperationContext.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/OperationContext.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/OperationContext.cpp Fri Apr 3 04:00:20 2015 @@ -358,6 +358,9 @@ OperationContext::checkCancel(void *canc OperationContext *that = static_cast<OperationContext *>(cancelBaton); if (that->isCancelledOperation()) return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Operation cancelled")); + else if (JNIUtil::isJavaExceptionThrown()) + return svn_error_create(SVN_ERR_CANCELLED, JNIUtil::wrapJavaException(), + _("Operation cancelled")); else return SVN_NO_ERROR; } Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/PatchCallback.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/PatchCallback.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/PatchCallback.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/PatchCallback.cpp Fri Apr 3 04:00:20 2015 @@ -106,7 +106,7 @@ PatchCallback::singlePatch(svn_boolean_t jboolean jfiltered = env->CallBooleanMethod(m_callback, mid, jcanonPath, jpatchAbsPath, jrejectAbsPath); if (JNIUtil::isJavaExceptionThrown()) - POP_AND_RETURN(SVN_NO_ERROR); + POP_AND_RETURN_EXCEPTION_AS_SVNERROR(); *filtered = (jfiltered ? TRUE : FALSE); Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/ProplistCallback.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/ProplistCallback.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/ProplistCallback.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/ProplistCallback.cpp Fri Apr 3 04:00:20 2015 @@ -112,9 +112,7 @@ svn_error_t *ProplistCallback::singlePat env->CallVoidMethod(m_callback, mid, jpath, jmap); // We return whether an exception was thrown or not. - env->PopLocalFrame(NULL); - - return SVN_NO_ERROR; + POP_AND_RETURN_EXCEPTION_AS_SVNERROR(); } Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/StatusCallback.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/StatusCallback.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/StatusCallback.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/StatusCallback.cpp Fri Apr 3 04:00:20 2015 @@ -101,11 +101,8 @@ StatusCallback::doStatus(const char *loc POP_AND_RETURN(SVN_NO_ERROR); env->CallVoidMethod(m_callback, mid, jPath, jStatus); - // We return here regardless of whether an exception is thrown or not, - // so we do not need to explicitly check for one. - env->PopLocalFrame(NULL); - return SVN_NO_ERROR; + POP_AND_RETURN_EXCEPTION_AS_SVNERROR(); } void Modified: subversion/branches/1.9.x/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/native/jniwrapper/jni_base.cpp Fri Apr 3 04:00:20 2015 @@ -375,7 +375,8 @@ const char* unknown_cxx_exception_messag svn_error_t* caught_java_exception_error(apr_status_t status) throw() { - return svn_error_create(status, NULL, _("Java exception")); + return svn_error_create(status, JNIUtil::wrapJavaException(), + _("Java exception")); } } // namespace Java Copied: subversion/branches/1.9.x/subversion/bindings/javahl/tests/org/apache/subversion/javahl/ExceptionTests.java (from r1664938, subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/ExceptionTests.java) URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/tests/org/apache/subversion/javahl/ExceptionTests.java?p2=subversion/branches/1.9.x/subversion/bindings/javahl/tests/org/apache/subversion/javahl/ExceptionTests.java&p1=subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/ExceptionTests.java&r1=1664938&r2=1670996&rev=1670996&view=diff ============================================================================== --- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/ExceptionTests.java (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/tests/org/apache/subversion/javahl/ExceptionTests.java Fri Apr 3 04:00:20 2015 @@ -85,6 +85,10 @@ public class ExceptionTests extends SVNT } } + /** + * Specific exception class to verify if the marshalling of errors + * through Subversion is handled properly. + */ final class TestException extends RuntimeException { private static final long serialVersionUID = 1L; @@ -100,7 +104,7 @@ public class ExceptionTests extends SVNT } } - public void testStatusCallback() throws Throwable + public void testStatusCallback() throws Exception { // build the test setup OneTest thisTest = new OneTest(); @@ -130,7 +134,7 @@ public class ExceptionTests extends SVNT assertTrue(handled); } - public void testInfoCallback() throws Throwable + public void testInfoCallback() throws Exception { // build the test setup OneTest thisTest = new OneTest(); @@ -160,7 +164,7 @@ public class ExceptionTests extends SVNT assertTrue(handled); } - public void testListCallback() throws Throwable + public void testListCallback() throws Exception { // build the test setup OneTest thisTest = new OneTest(); @@ -190,7 +194,7 @@ public class ExceptionTests extends SVNT assertTrue(handled); } - public void testBlameCallback() throws Throwable + public void testBlameCallback() throws Exception { // build the test setup OneTest thisTest = new OneTest(); @@ -225,7 +229,7 @@ public class ExceptionTests extends SVNT assertTrue(handled); } - public void testLogMessageCallback() throws Throwable + public void testLogMessageCallback() throws Exception { // build the test setup OneTest thisTest = new OneTest(); @@ -264,7 +268,7 @@ public class ExceptionTests extends SVNT assertTrue(handled); } - public void testDiffSummaryReceiver() throws Throwable + public void testDiffSummaryReceiver() throws Exception { // build the test setup OneTest thisTest = new OneTest(); @@ -301,7 +305,42 @@ public class ExceptionTests extends SVNT assertTrue(handled); } - private boolean VerifyCause(Throwable caught, Throwable needle) throws TestException + public void testNotify() throws Exception + { + // build the test setup + OneTest thisTest = new OneTest(); + + final TestException theException = new TestException("The Exception"); + boolean handled = false; + // Test status of non-existent file + try + { + client.notification2(new ClientNotifyCallback() + { + public void onNotify(ClientNotifyInformation info) + { + throw new TestException("inner", + theException); + } + }); + + client.remove(thisTest.getWCPathSet("/A"), false, false, + null, null, null); + } + catch (ClientException e) + { + if (VerifyCause(e, theException)) + handled = true; + else + throw e; + } + assertTrue(handled); + } + + /** + * Verifies if a specific throwable instance is recorded in the exception chain + */ + private boolean VerifyCause(Throwable caught, Throwable needle) { if (caught == needle) return true; Modified: subversion/branches/1.9.x/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java URL: http://svn.apache.org/viewvc/subversion/branches/1.9.x/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java?rev=1670996&r1=1670995&r2=1670996&view=diff ============================================================================== --- subversion/branches/1.9.x/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java (original) +++ subversion/branches/1.9.x/subversion/bindings/javahl/tests/org/apache/subversion/javahl/RunTests.java Fri Apr 3 04:00:20 2015 @@ -95,6 +95,7 @@ public class RunTests suite.addTestSuite(UtilTests.class); suite.addTestSuite(SVNRemoteTests.class); suite.addTestSuite(SVNReposTests.class); + suite.addTestSuite(ExceptionTests.class); } else {