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 2013/07/06 15:17:59 UTC
svn commit: r1500255 - in /subversion/trunk/subversion/bindings/javahl:
native/ tests/org/apache/subversion/javahl/
Author: brane
Date: Sat Jul 6 13:17:59 2013
New Revision: 1500255
URL: http://svn.apache.org/r1500255
Log:
Fixed the JavaHL RA implementation, infrastructure and tests so that they
all pass via ra_serf and ra_svn (on a local connection with trunk servers).
[in subversion/bindings/javahl/native]
* JNIUtil.cpp (JNIUtil::makeJByteArray): Check for null svn_string_t.
* CommitEditor.h
(CommitEditor::provide_base_cb, CommitEditor::provide_props_cb): New methods.
* CommitEditor.cpp (open_callback_session): Extracted code for opening the
secondary session that suuports the Ev2 commit editor callbakcs from
CommitEditor::get_copysrc_kind_cb.
(CommitEditor::provide_base_cb, CommitEditor::provide_props_cb): Implement.
(CommitEditor::CommitEditor): Use the new callbacks.
[in subversion/bindings/javahl/tests/org/apache/subversion/javahl]
* BasicTests.java (BasicTests.CountingProgressListener): New private class;
hoisted from BasicTests.testDataTransferProgressReport to avoid
throwing exceptions through native callbacks, which clutter up the
output during the test run.
(BasicTests.testDataTransferProgressReport): Use the new callback class.
* SVNRemoteTests.java
(SVNRemoteTests.testChangeRevpropAtomic): Check list of allowed error codes.
(SVNRemoteTests.testGetFile, SVNRemoteTests.testGetDirectory): Expect wcprops.
(SVNRemoteTests.testEditorSetFileContents): New test case; covers a code path
that had not been tested before.
(SVNRemoteTests.testEditorSetFileProps): Replaced by testEditorSetFileContents.
(SVNRemoteTests.RemoteStatusReceiver): Make StatInfo array sortable.
(SVNRemoteTests.testPropchangeStatus,
SVNRemoteTests.testDeletedStatus): Sort status entries before checking
results because ra_serf sends them in the opposite order than ra_local.
* SVNTests.java (SVNTests.prompt): Return true; we do have credentials info.
Modified:
subversion/trunk/subversion/bindings/javahl/native/CommitEditor.cpp
subversion/trunk/subversion/bindings/javahl/native/CommitEditor.h
subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp
subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
Modified: subversion/trunk/subversion/bindings/javahl/native/CommitEditor.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/CommitEditor.cpp?rev=1500255&r1=1500254&r2=1500255&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/CommitEditor.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/CommitEditor.cpp Sat Jul 6 13:17:59 2013
@@ -69,7 +69,6 @@ CommitEditor::createInstance(jobject jse
return editor->getCppAddr();
}
-
CommitEditor::CommitEditor(RemoteSession* session,
jobject jrevprops, jobject jcommit_callback,
jobject jlock_tokens, jboolean jkeep_locks)
@@ -105,8 +104,8 @@ CommitEditor::CommitEditor(RemoteSession
m_callback.callback, &m_callback,
lock_tokens.hash(subPool, true),
bool(jkeep_locks),
- NULL, // svn_ra__provide_base_cb_t
- NULL, // svn_ra__provide_props_cb_t
+ this->provide_base_cb,
+ this->provide_props_cb,
this->get_copysrc_kind_cb, this,
pool.getPool(), // result pool
subPool.getPool()), // scratch pool
@@ -487,23 +486,20 @@ void CommitEditor::abort()
}
-svn_error_t*
-CommitEditor::get_copysrc_kind_cb(svn_node_kind_t* kind, void* baton,
- const char* repos_relpath,
- svn_revnum_t src_revision,
- apr_pool_t *scratch_pool)
+namespace {
+svn_error_t* open_callback_session(svn_ra_session_t*& session,
+ const char* url, const char* uuid,
+ RemoteSessionContext* context,
+ SVN::Pool& sessionPool)
{
- CommitEditor* editor = static_cast<CommitEditor*>(baton);
- if (!editor->m_callback_session)
+ if (!session)
{
- const char* corrected_url;
- SVN_ERR(svn_ra_open4(&editor->m_callback_session, &corrected_url,
- editor->m_callback_session_url,
- editor->m_callback_session_uuid,
- editor->m_session->m_context->getCallbacks(),
- editor->m_session->m_context->getCallbackBaton(),
- editor->m_session->m_context->getConfigData(),
- editor->pool.getPool()));
+ const char* corrected_url = NULL;
+ SVN_ERR(svn_ra_open4(&session, &corrected_url, url, uuid,
+ context->getCallbacks(),
+ context->getCallbackBaton(),
+ context->getConfigData(),
+ sessionPool.getPool()));
if (corrected_url)
{
@@ -515,12 +511,79 @@ CommitEditor::get_copysrc_kind_cb(svn_no
SVN_ERR_RA_ILLEGAL_URL, NULL,
_("Repository URL changed while session was open.\n"
"Expected URL: %s\nApparent URL: %s"),
- editor->m_callback_session_url, corrected_url);
+ url, corrected_url);
}
}
+ return SVN_NO_ERROR;
+}
+} // anonymous namespace
+
+
+svn_error_t*
+CommitEditor::provide_base_cb(svn_stream_t **contents,
+ svn_revnum_t *revision,
+ void *baton,
+ const char *repos_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *contents = NULL;
+ *revision = NULL;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t*
+CommitEditor::provide_props_cb(apr_hash_t **props,
+ svn_revnum_t *revision,
+ void *baton,
+ const char *repos_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ CommitEditor* editor = static_cast<CommitEditor*>(baton);
+ SVN_ERR(open_callback_session(editor->m_callback_session,
+ editor->m_callback_session_url,
+ editor->m_callback_session_uuid,
+ editor->m_session->m_context,
+ editor->pool));
+
+ svn_node_kind_t kind = svn_node_unknown;
+ SVN_ERR(svn_ra_check_path(editor->m_callback_session,
+ repos_relpath, SVN_INVALID_REVNUM, &kind,
+ scratch_pool));
+
+ // FIXME: Getting properties from the youngest revision is in fact
+ // not such a bright idea, as the path may have been moved or
+ // deleted in the path.
+ if (kind == svn_node_file)
+ return svn_ra_get_file(editor->m_callback_session,
+ repos_relpath, SVN_INVALID_REVNUM,
+ NULL, revision, props, scratch_pool);
+ else if (kind == svn_node_dir)
+ return svn_ra_get_dir2(editor->m_callback_session, NULL, revision, props,
+ repos_relpath, SVN_INVALID_REVNUM, 0, scratch_pool);
+ else
+ return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
+ _("Expected node kind '%s' or '%s' but got '%s'"),
+ svn_node_kind_to_word(svn_node_file),
+ svn_node_kind_to_word(svn_node_dir),
+ svn_node_kind_to_word(kind));
+}
+
+svn_error_t*
+CommitEditor::get_copysrc_kind_cb(svn_node_kind_t* kind, void* baton,
+ const char* repos_relpath,
+ svn_revnum_t src_revision,
+ apr_pool_t *scratch_pool)
+{
+ CommitEditor* editor = static_cast<CommitEditor*>(baton);
+ SVN_ERR(open_callback_session(editor->m_callback_session,
+ editor->m_callback_session_url,
+ editor->m_callback_session_uuid,
+ editor->m_session->m_context,
+ editor->pool));
- SVN::Pool subPool(editor->pool);
return svn_ra_check_path(editor->m_callback_session,
repos_relpath, src_revision, kind,
- subPool.getPool());
+ scratch_pool);
}
Modified: subversion/trunk/subversion/bindings/javahl/native/CommitEditor.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/CommitEditor.h?rev=1500255&r1=1500254&r2=1500255&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/CommitEditor.h (original)
+++ subversion/trunk/subversion/bindings/javahl/native/CommitEditor.h Sat Jul 6 13:17:59 2013
@@ -90,7 +90,19 @@ private:
jobject jrevprops, jobject jcommit_callback,
jobject jlock_tokens, jboolean jkeep_locks);
- // This is our svn_ra__get_copysrc_kind_cb_t for the commit editor.
+ // This is our private callbacks for the commit editor.
+ static svn_error_t* provide_base_cb(svn_stream_t **contents,
+ svn_revnum_t *revision,
+ void *baton,
+ const char *repos_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+ static svn_error_t* provide_props_cb(apr_hash_t **props,
+ svn_revnum_t *revision,
+ void *baton,
+ const char *repos_relpath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
static svn_error_t* get_copysrc_kind_cb(svn_node_kind_t* kind, void* baton,
const char* repos_relpath,
svn_revnum_t src_revision,
Modified: subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp?rev=1500255&r1=1500254&r2=1500255&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp (original)
+++ subversion/trunk/subversion/bindings/javahl/native/JNIUtil.cpp Sat Jul 6 13:17:59 2013
@@ -908,11 +908,9 @@ JNIUtil::getDate(jobject jdate)
*/
jbyteArray JNIUtil::makeJByteArray(const void *data, int length)
{
- if (data == NULL)
- {
- // a NULL will create no Java array
- return NULL;
- }
+ // a NULL will create no Java array
+ if (!data)
+ return NULL;
JNIEnv *env = getEnv();
@@ -943,6 +941,10 @@ jbyteArray JNIUtil::makeJByteArray(const
*/
jbyteArray JNIUtil::makeJByteArray(const svn_string_t *str)
{
+ // a NULL will create no Java array
+ if (!str)
+ return NULL;
+
return JNIUtil::makeJByteArray(str->data, static_cast<int>(str->len));
}
Modified: subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java?rev=1500255&r1=1500254&r2=1500255&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java (original)
+++ subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java Sat Jul 6 13:17:59 2013
@@ -3300,6 +3300,16 @@ public class BasicTests extends SVNTests
}
}
+ private static class CountingProgressListener implements ProgressCallback
+ {
+ public void onProgress(ProgressEvent event)
+ {
+ // TODO: Examine the byte counts from "event".
+ gotProgress = true;
+ }
+ public boolean gotProgress = false;
+ }
+
public void testDataTransferProgressReport() throws Throwable
{
// ### FIXME: This isn't working over ra_local, because
@@ -3309,25 +3319,13 @@ public class BasicTests extends SVNTests
// build the test setup
OneTest thisTest = new OneTest();
- ProgressCallback listener = new ProgressCallback()
- {
- public void onProgress(ProgressEvent event)
- {
- // TODO: Examine the byte counts from "event".
- throw new RuntimeException("Progress reported as expected");
- }
- };
+ CountingProgressListener listener = new CountingProgressListener();
client.setProgressCallback(listener);
// Perform an update to exercise the progress notification.
- try
- {
- update(thisTest);
+ update(thisTest);
+ if (!listener.gotProgress)
fail("No progress reported");
- }
- catch (RuntimeException progressReported)
- {
- }
}
/**
Modified: subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java?rev=1500255&r1=1500254&r2=1500255&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java (original)
+++ subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNRemoteTests.java Sat Jul 6 13:17:59 2013
@@ -29,6 +29,7 @@ import org.apache.subversion.javahl.type
import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
@@ -308,8 +309,20 @@ public class SVNRemoteTests extends SVNT
}
catch (ClientException ex)
{
- assertEquals("Disabled repository feature",
- ex.getAllMessages().get(0).getMessage());
+ ClientException.ErrorMessage error = null;
+ for (ClientException.ErrorMessage m : ex.getAllMessages())
+ if (!m.isGeneric()) {
+ error = m;
+ break;
+ }
+
+ if (error == null)
+ fail("Failed with no error message");
+
+ if (error.getCode() != 175002 && // SVN_ERR_RA_DAV_REQUEST_FAILED
+ error.getCode() != 165006) // SVN_ERR_REPOS_DISABLED_FEATURE
+ fail(error.getMessage());
+
return;
}
@@ -351,8 +364,11 @@ public class SVNRemoteTests extends SVNT
assertEquals(fetched_rev, 1);
assertEquals(contents.toString("UTF-8"),
"This is the file 'lambda'.");
- for (Map.Entry<String, byte[]> e : properties.entrySet())
- assertTrue(e.getKey().startsWith("svn:entry:"));
+ for (Map.Entry<String, byte[]> e : properties.entrySet()) {
+ final String key = e.getKey();
+ assertTrue(key.startsWith("svn:entry:")
+ || key.startsWith("svn:wc:"));
+ }
}
public void testGetDirectory() throws Exception
@@ -373,8 +389,11 @@ public class SVNRemoteTests extends SVNT
assertEquals(dirents.get("E").getPath(), "E");
assertEquals(dirents.get("F").getPath(), "F");
assertEquals(dirents.get("lambda").getPath(), "lambda");
- for (Map.Entry<String, byte[]> e : properties.entrySet())
- assertTrue(e.getKey().startsWith("svn:entry:"));
+ for (Map.Entry<String, byte[]> e : properties.entrySet()) {
+ final String key = e.getKey();
+ assertTrue(key.startsWith("svn:entry:")
+ || key.startsWith("svn:wc:"));
+ }
}
private final class CommitContext implements CommitCallback
@@ -574,19 +593,19 @@ public class SVNRemoteTests extends SVNT
assertTrue(Arrays.equals(eolstyle, propval));
}
- public void testEditorSetFileProps() throws Exception
+ public void testEditorSetFileContents() throws Exception
{
Charset UTF8 = Charset.forName("UTF-8");
ISVNRemote session = getSession();
- byte[] eolstyle = "CRLF".getBytes(UTF8);
- HashMap<String, byte[]> props = new HashMap<String, byte[]>();
- props.put("svn:eol-style", eolstyle);
+ byte[] contents = "This is modified file 'alpha'.".getBytes(UTF8);
+ Checksum hash = new Checksum(SHA1(contents), Checksum.Kind.SHA1);
+ ByteArrayInputStream stream = new ByteArrayInputStream(contents);
CommitContext cc =
- new CommitContext(session, "Change eol-style on A/B/E/alpha");
+ new CommitContext(session, "Change contents of A/B/E/alpha");
try {
- cc.editor.alterFile("A/B/E/alpha", 1, null, null, props);
+ cc.editor.alterFile("A/B/E/alpha", 1, hash, stream, null);
cc.editor.complete();
} finally {
cc.editor.dispose();
@@ -594,12 +613,10 @@ public class SVNRemoteTests extends SVNT
assertEquals(2, cc.getRevision());
assertEquals(2, session.getLatestRevision());
- byte[] propval = client.propertyGet(session.getSessionUrl()
- + "/A/B/E/alpha",
- "svn:eol-style",
- Revision.HEAD,
- Revision.HEAD);
- assertTrue(Arrays.equals(eolstyle, propval));
+ ByteArrayOutputStream checkcontents = new ByteArrayOutputStream();
+ client.streamFileContent(session.getSessionUrl() + "/A/B/E/alpha",
+ Revision.HEAD, Revision.HEAD, checkcontents);
+ assertTrue(Arrays.equals(contents, checkcontents.toByteArray()));
}
// public void testEditorRotate() throws Exception
@@ -787,7 +804,7 @@ public class SVNRemoteTests extends SVNT
private static class RemoteStatusReceiver implements RemoteStatus
{
- static class StatInfo
+ static class StatInfo implements Comparable<StatInfo>
{
public String relpath = null;
public char kind = ' '; // F, D, L
@@ -813,6 +830,18 @@ public class SVNRemoteTests extends SVNT
this.propsChanged = propsChanged;
this.info = info;
}
+
+ @Override
+ public boolean equals(Object statinfo)
+ {
+ final StatInfo that = (StatInfo)statinfo;
+ return this.relpath.equals(that.relpath);
+ }
+
+ public int compareTo(StatInfo that)
+ {
+ return this.relpath.compareTo(that.relpath);
+ }
}
private boolean debug;
@@ -946,7 +975,11 @@ public class SVNRemoteTests extends SVNT
} finally {
rp.dispose();
}
+
assertEquals(4, receiver.status.size());
+
+ // ra_serf returns the entries in inverted order compared to ra_local.
+ Collections.sort(receiver.status);
RemoteStatusReceiver.StatInfo mod = receiver.status.get(3);
assertEquals("A/D/gamma", mod.relpath);
assertEquals('F', mod.kind);
@@ -979,6 +1012,9 @@ public class SVNRemoteTests extends SVNT
rp.dispose();
}
assertEquals(3, receiver.status.size());
+
+ // ra_serf returns the entries in inverted order compared to ra_local.
+ Collections.sort(receiver.status);
RemoteStatusReceiver.StatInfo mod = receiver.status.get(2);
assertEquals("A/mu", mod.relpath);
assertEquals(' ', mod.kind);
Modified: subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java?rev=1500255&r1=1500254&r2=1500255&view=diff
==============================================================================
--- subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java (original)
+++ subversion/trunk/subversion/bindings/javahl/tests/org/apache/subversion/javahl/SVNTests.java Sat Jul 6 13:17:59 2013
@@ -324,12 +324,12 @@ class SVNTests extends TestCase
public boolean prompt(String realm, String username)
{
- return false;
+ return true;
}
public boolean prompt(String realm, String username, boolean maySave)
{
- return false;
+ return true;
}
public String askQuestion(String realm, String question,