summaryrefslogtreecommitdiff
path: root/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java')
-rw-r--r--subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java749
1 files changed, 694 insertions, 55 deletions
diff --git a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
index 5ed2229..8ca2b1f 100644
--- a/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
+++ b/subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java
@@ -33,6 +33,9 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
import java.text.ParseException;
import java.util.Collection;
import java.util.Arrays;
@@ -136,9 +139,10 @@ public class BasicTests extends SVNTests
*/
public void testVersionExtendedQuiet() throws Throwable
{
+ VersionExtended vx = null;
try
{
- VersionExtended vx = client.getVersionExtended(false);
+ vx = client.getVersionExtended(false);
String result = vx.getBuildDate();
if (result == null || result.trim().length() == 0)
throw new Exception("Build date empty");
@@ -157,6 +161,11 @@ public class BasicTests extends SVNTests
fail("VersionExtended should always be available unless the " +
"native libraries failed to initialize: " + e);
}
+ finally
+ {
+ if (vx != null)
+ vx.dispose();
+ }
}
/**
@@ -165,9 +174,10 @@ public class BasicTests extends SVNTests
*/
public void testVersionExtendedVerbose() throws Throwable
{
+ VersionExtended vx = null;
try
{
- VersionExtended vx = client.getVersionExtended(true);
+ vx = client.getVersionExtended(true);
String result = vx.getRuntimeHost();
if (result == null || result.trim().length() == 0)
throw new Exception("Runtime host empty");
@@ -213,6 +223,38 @@ public class BasicTests extends SVNTests
fail("VersionExtended should always be available unless the " +
"native libraries failed to initialize: " + e);
}
+ finally
+ {
+ if (vx != null)
+ vx.dispose();
+ }
+ }
+
+ /**
+ * Test RuntimeVersion
+ */
+ public void testRuntimeVersion() throws Throwable
+ {
+ try
+ {
+ RuntimeVersion runtimeVersion = client.getRuntimeVersion();
+ String versionString = runtimeVersion.toString();
+ if (versionString == null || versionString.trim().length() == 0)
+ {
+ throw new Exception("Version string empty");
+ }
+ }
+ catch (Exception e)
+ {
+ fail("RuntimeVersion should always be available unless the " +
+ "native libraries failed to initialize: " + e);
+ }
+
+ RuntimeVersion runtimeVersion = client.getRuntimeVersion();
+ Version version = client.getVersion();
+ assertTrue(runtimeVersion.getMajor() > version.getMajor()
+ || (runtimeVersion.getMajor() == version.getMajor()
+ && runtimeVersion.getMinor() >= version.getMinor()));
}
/**
@@ -229,7 +271,7 @@ public class BasicTests extends SVNTests
tempclient.dispose();
// create Y and Y/Z directories in the repository
- addExpectedCommitItem(null, thisTest.getUrl().toString(), "Y", NodeKind.none,
+ addExpectedCommitItem(null, thisTest.getUrl().toString(), "Y", NodeKind.dir,
CommitItemStateFlags.Add);
Set<String> urls = new HashSet<String>(1);
urls.add(thisTest.getUrl() + "/Y");
@@ -239,7 +281,7 @@ public class BasicTests extends SVNTests
}
catch(JNIError e)
{
- return; // Test passes!
+ return; // Test passes!
}
fail("A JNIError should have been thrown here.");
}
@@ -251,16 +293,17 @@ public class BasicTests extends SVNTests
public void testMergeinfoParser() throws Throwable
{
String mergeInfoPropertyValue =
- "/trunk:1-300,305,307,400-405\n/branches/branch:308-400";
+ "/trunk:1-300,305*,307,400-405*\n" +
+ "/branches/branch:308-400";
Mergeinfo info = new Mergeinfo(mergeInfoPropertyValue);
Set<String> paths = info.getPaths();
assertEquals(2, paths.size());
List<RevisionRange> trunkRange = info.getRevisionRange("/trunk");
assertEquals(4, trunkRange.size());
assertEquals("1-300", trunkRange.get(0).toString());
- assertEquals("305", trunkRange.get(1).toString());
+ assertEquals("305*", trunkRange.get(1).toString());
assertEquals("307", trunkRange.get(2).toString());
- assertEquals("400-405", trunkRange.get(3).toString());
+ assertEquals("400-405*", trunkRange.get(3).toString());
List<RevisionRange> branchRange =
info.getRevisionRange("/branches/branch");
assertEquals(1, branchRange.size());
@@ -276,17 +319,31 @@ public class BasicTests extends SVNTests
OneTest thisTest = new OneTest();
// check the status of the working copy
+ thisTest.getWc().setItemDepth("", Depth.infinity);
+ thisTest.getWc().setItemDepth("iota", Depth.unknown);
thisTest.checkStatus();
// Test status of non-existent file
File fileC = new File(thisTest.getWorkingCopy() + "/A", "foo.c");
MyStatusCallback statusCallback = new MyStatusCallback();
- client.status(fileToSVNPath(fileC, false), Depth.unknown, false, true,
- false, false, null, statusCallback);
- if (statusCallback.getStatusArray().length > 0)
- fail("File foo.c should not return a status.");
+ client.status(fileToSVNPath(fileC, false), Depth.unknown,
+ false, true, true, false, false, false,
+ null, statusCallback);
+ final int statusCount = statusCallback.getStatusArray().length;
+ if (statusCount == 1)
+ {
+ Status st = statusCallback.getStatusArray()[0];
+ if (st.isConflicted()
+ || st.getNodeStatus() != Status.Kind.none
+ || st.getRepositoryNodeStatus() != Status.Kind.none)
+ fail("File foo.c should return empty status.");
+ }
+ else if (statusCount > 1)
+ fail("File foo.c should not return more than one status.");
+ else
+ fail("File foo.c should return exactly one empty status.");
}
/**
@@ -357,7 +414,8 @@ public class BasicTests extends SVNTests
statusCallback = new MyStatusCallback();
client.status(thisTest.getWCPath() + "/A/D/G/rho", Depth.immediates,
- false, true, false, false, null, statusCallback);
+ false, true, true, false, false, false,
+ null, statusCallback);
status = statusCallback.getStatusArray()[0];
long rhoCommitDate = status.getLastChangedDate().getTime();
long rhoCommitRev = rev;
@@ -394,7 +452,8 @@ public class BasicTests extends SVNTests
+ "modification to tau");
statusCallback = new MyStatusCallback();
client.status(thisTest.getWCPath() + "/A/D/G/tau", Depth.immediates,
- false, true, false, false, null, statusCallback);
+ false, true, true, false, false, false,
+ null, statusCallback);
status = statusCallback.getStatusArray()[0];
long tauCommitDate = status.getLastChangedDate().getTime();
long tauCommitRev = rev;
@@ -423,7 +482,8 @@ public class BasicTests extends SVNTests
thisTest.getWc().addItem("A/B/I", null);
statusCallback = new MyStatusCallback();
client.status(thisTest.getWCPath() + "/A/B/I", Depth.immediates,
- false, true, false, false, null, statusCallback);
+ false, true, true, false, false, false,
+ null, statusCallback);
status = statusCallback.getStatusArray()[0];
long ICommitDate = status.getLastChangedDate().getTime();
long ICommitRev = rev;
@@ -458,7 +518,8 @@ public class BasicTests extends SVNTests
thisTest.getWc().addItem("A/D/H/nu", "This is the file 'nu'.");
statusCallback = new MyStatusCallback();
client.status(thisTest.getWCPath() + "/A/D/H/nu", Depth.immediates,
- false, true, false, false, null, statusCallback);
+ false, true, true, false, false, false,
+ null, statusCallback);
status = statusCallback.getStatusArray()[0];
long nuCommitDate = status.getLastChangedDate().getTime();
long nuCommitRev = rev;
@@ -475,7 +536,8 @@ public class BasicTests extends SVNTests
thisTest.getWc().setItemWorkingCopyRevision("A/B/F", rev);
statusCallback = new MyStatusCallback();
client.status(thisTest.getWCPath() + "/A/B/F", Depth.immediates,
- false, true, false, false, null, statusCallback);
+ false, true, true, false, false, false,
+ null, statusCallback);
status = statusCallback.getStatusArray()[0];
long FCommitDate = status.getLastChangedDate().getTime();
long FCommitRev = rev;
@@ -506,7 +568,8 @@ public class BasicTests extends SVNTests
"This is the replacement file 'chi'.");
statusCallback = new MyStatusCallback();
client.status(thisTest.getWCPath() + "/A/D/H/chi", Depth.immediates,
- false, true, false, false, null, statusCallback);
+ false, true, true, false, false, false,
+ null, statusCallback);
status = statusCallback.getStatusArray()[0];
long chiCommitDate = status.getLastChangedDate().getTime();
long chiCommitRev = rev;
@@ -557,7 +620,8 @@ public class BasicTests extends SVNTests
assertEquals("wrong revision number from commit", rev, expectedRev++);
statusCallback = new MyStatusCallback();
client.status(thisTest.getWCPath() + "/A/D/H/psi", Depth.immediates,
- false, true, false, false, null, statusCallback);
+ false, true, true, false, false, false,
+ null, statusCallback);
status = statusCallback.getStatusArray()[0];
long psiCommitDate = status.getLastChangedDate().getTime();
long psiCommitRev = rev;
@@ -649,6 +713,47 @@ public class BasicTests extends SVNTests
}
/**
+ * Test SVNClient.status on externals.
+ * @throws Throwable
+ */
+ public void testExternalStatus() throws Throwable
+ {
+ // build the test setup
+ OneTest thisTest = new OneTest();
+
+
+ // Add an externals reference to the working copy.
+ client.propertySetLocal(thisTest.getWCPathSet(), "svn:externals",
+ "^/A/D/H ADHext".getBytes(),
+ Depth.empty, null, false);
+
+ // Update the working copy to bring in the external subtree.
+ client.update(thisTest.getWCPathSet(), Revision.HEAD,
+ Depth.unknown, false, false, false, false);
+
+ // Test status of an external file
+ File psi = new File(thisTest.getWorkingCopy() + "/ADHext", "psi");
+
+ MyStatusCallback statusCallback = new MyStatusCallback();
+ client.status(fileToSVNPath(psi, false), Depth.unknown,
+ false, true, true, false, false, false,
+ null, statusCallback);
+
+ final int statusCount = statusCallback.getStatusArray().length;
+ if (statusCount == 1)
+ {
+ Status st = statusCallback.getStatusArray()[0];
+ assertFalse(st.isConflicted());
+ assertEquals(Status.Kind.normal, st.getNodeStatus());
+ assertEquals(NodeKind.file, st.getNodeKind());
+ }
+ else if (statusCount > 1)
+ fail("File psi should not return more than one status.");
+ else
+ fail("File psi should return exactly one status.");
+ }
+
+ /**
* Test the basic SVNClient.checkout functionality.
* @throws Throwable
*/
@@ -911,9 +1016,9 @@ public class BasicTests extends SVNTests
OneTest thisTest = new OneTest();
// create Y and Y/Z directories in the repository
- addExpectedCommitItem(null, thisTest.getUrl().toString(), "Y", NodeKind.none,
+ addExpectedCommitItem(null, thisTest.getUrl().toString(), "Y", NodeKind.dir,
CommitItemStateFlags.Add);
- addExpectedCommitItem(null, thisTest.getUrl().toString(), "Y/Z", NodeKind.none,
+ addExpectedCommitItem(null, thisTest.getUrl().toString(), "Y/Z", NodeKind.dir,
CommitItemStateFlags.Add);
Set<String> urls = new HashSet<String>(2);
urls.add(thisTest.getUrl() + "/Y");
@@ -967,7 +1072,7 @@ public class BasicTests extends SVNTests
}
client.copy(sources,
new File(thisTest.getWorkingCopy(), "A/B/F").getPath(),
- true, false, false, null, null, null);
+ true, false, false, false, false, null, null, null, null);
// Commit the changes, and check the state of the WC.
checkCommitRevision(thisTest,
@@ -984,7 +1089,7 @@ public class BasicTests extends SVNTests
"A/B").getPath(), Revision.WORKING,
Revision.WORKING));
client.copy(wcSource, thisTest.getUrl() + "/parent/A/B",
- true, true, false, null,
+ true, true, false, false, false, null, null,
new ConstMsg("Copy WC to URL"), null);
// update the WC to get new folder and confirm the copy
@@ -992,6 +1097,221 @@ public class BasicTests extends SVNTests
update(thisTest), 3);
}
+
+ // Set up externals references in the working copy for the
+ // pin-externals tests.
+ private void setupPinExternalsTest(OneTest thisTest) throws Throwable
+ {
+ byte[] extref = ("^/A/D/H ADHext\n" +
+ "^/A/D/H ADHext2\n" +
+ "^/A/D/H@1 peggedADHext\n" +
+ "-r1 ^/A/D/H revvedADHext\n").getBytes();
+ Set<String> paths = new HashSet<String>();
+ paths.add(thisTest.getWCPath() + "/A/B");
+
+ // Add an externals reference to the working copy.
+ client.propertySetLocal(paths, "svn:externals", extref,
+ Depth.empty, null, false);
+
+ // Commit the externals definition
+ client.commit(thisTest.getWCPathSet(), Depth.infinity,
+ false, false, null, null,
+ new ConstMsg("Set svn:externals"), null);
+
+ // Update the working copy to bring in the external subtree.
+ client.update(thisTest.getWCPathSet(), Revision.HEAD,
+ Depth.unknown, false, false, false, false);
+ }
+
+ /**
+ * Test WC-to-WC copy with implicit pinned externals
+ * @throws Throwable
+ */
+ public void testCopyPinExternals_wc2wc() throws Throwable
+ {
+ // build the test setup
+ OneTest thisTest = new OneTest();
+ setupPinExternalsTest(thisTest);
+
+ List<CopySource> sources = new ArrayList<CopySource>(1);
+ sources.add(new CopySource(thisTest.getWCPath() + "/A/B", null, null));
+ String target = thisTest.getWCPath() + "/A/Bcopy";
+ client.copy(sources, target, true, false, false, false,
+ true, // pinExternals
+ null, // externalsToPin
+ null, null, null);
+
+ // Verification
+ String expected = ("^/A/D/H@2 ADHext\n" +
+ "^/A/D/H@2 ADHext2\n" +
+ "^/A/D/H@1 peggedADHext\n" +
+ "-r1 ^/A/D/H@2 revvedADHext\n");
+ String actual =
+ new String(client.propertyGet(target, "svn:externals", null, null));
+
+ assertEquals(expected, actual);
+ }
+
+ /**
+ * Test WC-to-REPO copy with implicit pinned externals
+ * @throws Throwable
+ */
+ public void testCopyPinExternals_wc2repo() throws Throwable
+ {
+ // build the test setup
+ OneTest thisTest = new OneTest();
+ setupPinExternalsTest(thisTest);
+
+ List<CopySource> sources = new ArrayList<CopySource>(1);
+ sources.add(new CopySource(thisTest.getWCPath() + "/A/B", null, null));
+ String target = thisTest.getUrl() + "/A/Bcopy";
+ client.copy(sources, target, true, false, false, false,
+ true, // pinExternals
+ null, // externalsToPin
+ null, new ConstMsg("Copy WC to REPO"), null);
+
+ // Verification
+ String expected = ("^/A/D/H@2 ADHext\n" +
+ "^/A/D/H@2 ADHext2\n" +
+ "^/A/D/H@1 peggedADHext\n" +
+ "-r1 ^/A/D/H@2 revvedADHext\n");
+ String actual =
+ new String(client.propertyGet(target, "svn:externals", null, null));
+
+ assertEquals(expected, actual);
+ }
+
+ /**
+ * Test REPO-to-WC copy with implicit pinned externals
+ * @throws Throwable
+ */
+ public void testCopyPinExternals_repo2wc() throws Throwable
+ {
+ // build the test setup
+ OneTest thisTest = new OneTest();
+ setupPinExternalsTest(thisTest);
+
+ List<CopySource> sources = new ArrayList<CopySource>(1);
+ sources.add(new CopySource(thisTest.getUrl() + "/A/B", null, null));
+ String target = thisTest.getWCPath() + "/A/Bcopy";
+ client.copy(sources, target, true, false, false, false,
+ true, // pinExternals
+ null, // externalsToPin
+ null, null, null);
+
+ // Verification
+ String expected = ("^/A/D/H@2 ADHext\n" +
+ "^/A/D/H@2 ADHext2\n" +
+ "^/A/D/H@1 peggedADHext\n" +
+ "-r1 ^/A/D/H@2 revvedADHext\n");
+ String actual =
+ new String(client.propertyGet(target, "svn:externals", null, null));
+
+ assertEquals(expected, actual);
+ }
+
+ /**
+ * Test REPO-to-REPO copy with implicit pinned externals
+ * @throws Throwable
+ */
+ public void testCopyPinExternals_repo2repo() throws Throwable
+ {
+ // build the test setup
+ OneTest thisTest = new OneTest();
+ setupPinExternalsTest(thisTest);
+
+ List<CopySource> sources = new ArrayList<CopySource>(1);
+ sources.add(new CopySource(thisTest.getUrl() + "/A/B", null, null));
+ String target = thisTest.getUrl() + "/A/Bcopy";
+ client.copy(sources, target, true, false, false, false,
+ true, // pinExternals
+ null, // externalsToPin
+ null, new ConstMsg("Copy WC to REPO"), null);
+
+ // Verification
+ String expected = ("^/A/D/H@2 ADHext\n" +
+ "^/A/D/H@2 ADHext2\n" +
+ "^/A/D/H@1 peggedADHext\n" +
+ "-r1 ^/A/D/H@2 revvedADHext\n");
+ String actual =
+ new String(client.propertyGet(target, "svn:externals", null, null));
+
+ assertEquals(expected, actual);
+ }
+
+ /**
+ * Test REPO-to-REPO copy with eplicit pinned externals
+ * @throws Throwable
+ */
+ public void testCopyPinExternals_repo2repo_explicit() throws Throwable
+ {
+ // build the test setup
+ OneTest thisTest = new OneTest();
+ setupPinExternalsTest(thisTest);
+
+ String sourceUrl = thisTest.getUrl() + "/A/B";
+ Map<String, List<ExternalItem>> externalsToPin =
+ new HashMap<String, List<ExternalItem>>();
+ List<ExternalItem> items = new ArrayList<ExternalItem>(1);
+ items.add(new ExternalItem("ADHext", "^/A/D/H", null, null));
+ externalsToPin.put(sourceUrl, items);
+
+ List<CopySource> sources = new ArrayList<CopySource>(1);
+ sources.add(new CopySource(sourceUrl, null, null));
+ String target = thisTest.getUrl() + "/A/Bcopy";
+ client.copy(sources, target, true, false, false, false,
+ true, // pinExternals
+ externalsToPin,
+ null, new ConstMsg("Copy WC to REPO"), null);
+
+ // Verification
+ String expected = ("^/A/D/H@2 ADHext\n" +
+ "^/A/D/H ADHext2\n" +
+ "^/A/D/H@1 peggedADHext\n" +
+ "-r1 ^/A/D/H revvedADHext\n");
+ String actual =
+ new String(client.propertyGet(target, "svn:externals", null, null));
+
+ assertEquals(expected, actual);
+ }
+
+ /**
+ * Test REPO-to-REPO copy with explicit pinned externals that
+ * don't correspond to actual externals
+ * @throws Throwable
+ */
+ public void testCopyPinExternals_repo2repo_corkscrew() throws Throwable
+ {
+ // build the test setup
+ OneTest thisTest = new OneTest();
+ setupPinExternalsTest(thisTest);
+
+ String sourceUrl = thisTest.getUrl() + "/A/B";
+ Map<String, List<ExternalItem>> externalsToPin =
+ new HashMap<String, List<ExternalItem>>();
+ List<ExternalItem> items = new ArrayList<ExternalItem>(1);
+ items.add(new ExternalItem("ADHext", "^/A/D/H", null, null));
+ externalsToPin.put(sourceUrl + "/A", items);
+
+ List<CopySource> sources = new ArrayList<CopySource>(1);
+ sources.add(new CopySource(sourceUrl, null, null));
+ String target = thisTest.getUrl() + "/A/Bcopy";
+ client.copy(sources, target, true, false, false, false,
+ true, // pinExternals
+ externalsToPin,
+ null, new ConstMsg("Copy WC to REPO"), null);
+
+ // Verification
+ String expected = ("^/A/D/H ADHext\n" +
+ "^/A/D/H ADHext2\n" +
+ "^/A/D/H@1 peggedADHext\n" +
+ "-r1 ^/A/D/H revvedADHext\n");
+ String actual =
+ new String(client.propertyGet(target, "svn:externals", null, null));
+
+ assertEquals(expected, actual);
+ }
+
/**
* Test the {@link SVNClientInterface.move()} API.
* @since 1.5
@@ -1031,7 +1351,8 @@ public class BasicTests extends SVNTests
MyStatusCallback statusCallback = new MyStatusCallback();
String statusPath = fileToSVNPath(new File(thisTest.getWCPath() + "/A/B"), true);
- client.status(statusPath, Depth.infinity, false, false, false, true,
+ client.status(statusPath, Depth.infinity,
+ false, true, false, false, true, false,
null, statusCallback);
Status[] statusList = statusCallback.getStatusArray();
assertEquals(statusPath + "/F/alpha",
@@ -1054,6 +1375,37 @@ public class BasicTests extends SVNTests
}
/**
+ * Check that half a move cannot be committed.
+ * @since 1.9
+ */
+ public void testCommitPartialMove() throws Throwable
+ {
+ OneTest thisTest = new OneTest();
+ String root = thisTest.getWorkingCopy().getAbsolutePath();
+ ClientException caught = null;
+
+ Set<String> srcPaths = new HashSet<String>(1);
+ srcPaths.add(root + "/A/B/E/alpha");
+ client.move(srcPaths, root + "/moved-alpha",
+ false, false, false, false, false, null, null, null);
+
+ try {
+ client.commit(srcPaths, Depth.infinity, false, false, null, null,
+ new ConstMsg("Commit half of a move"), null);
+ } catch (ClientException ex) {
+ caught = ex;
+ }
+
+ assertNotNull("Commit of partial move did not fail", caught);
+
+ List<ClientException.ErrorMessage> msgs = caught.getAllMessages();
+ assertTrue(msgs.size() >= 3);
+ assertTrue(msgs.get(0).getMessage().startsWith("Illegal target"));
+ assertTrue(msgs.get(1).getMessage().startsWith("Commit failed"));
+ assertTrue(msgs.get(2).getMessage().startsWith("Cannot commit"));
+ }
+
+ /**
* Assert that the first merge source suggested for
* <code>destPath</code> at {@link Revision#WORKING} and {@link
* Revision#HEAD} is equivalent to <code>expectedSrc</code>.
@@ -1368,7 +1720,7 @@ public class BasicTests extends SVNTests
/**
* Test the basic SVNClient.cleanup functionality.
* Without a way to force a lock, this test just verifies
- * the method can be called succesfully.
+ * the method can be called successfully.
* @throws Throwable
*/
public void testBasicCleanup() throws Throwable
@@ -1770,7 +2122,7 @@ public class BasicTests extends SVNTests
// check the status of the working copy
thisTest.checkStatus();
- // confirm that the file are realy deleted
+ // confirm that the file are really deleted
assertFalse("failed to remove text modified file",
new File(thisTest.getWorkingCopy(), "A/D/G/rho").exists());
assertFalse("failed to remove prop modified file",
@@ -1798,7 +2150,7 @@ public class BasicTests extends SVNTests
try
{
- // delete non-existant file foo
+ // delete non-existent file foo
Set<String> paths = new HashSet<String>(1);
paths.add(file.getAbsolutePath());
client.remove(paths, true, false, null, null, null);
@@ -2194,7 +2546,7 @@ public class BasicTests extends SVNTests
}
/**
- * Test the basic SVNClient.info2 functionality.
+ * Test the basic SVNClient.info functionality.
* @throws Throwable
* @since 1.2
*/
@@ -2270,8 +2622,9 @@ public class BasicTests extends SVNTests
assertTrue(changelists.equals(cl));
// Does status report this changelist?
MyStatusCallback statusCallback = new MyStatusCallback();
- client.status(path, Depth.immediates, false, false, false, false,
- null, statusCallback);
+ client.status(path, Depth.immediates,
+ false, true, false, false, false, false,
+ null, statusCallback);
Status[] status = statusCallback.getStatusArray();
assertEquals(status[0].getChangelist(), changelistName);
@@ -2284,6 +2637,33 @@ public class BasicTests extends SVNTests
assertTrue(clCallback.isEmpty());
}
+ public void testGetAllChangelists() throws Throwable
+ {
+ OneTest thisTest = new OneTest();
+ final String cl1 = "changelist_one";
+ final String cl2 = "changelist_too";
+ MyChangelistCallback clCallback = new MyChangelistCallback();
+
+ String path = fileToSVNPath(new File(thisTest.getWCPath(), "iota"),
+ true);
+ Set<String> paths = new HashSet<String>(1);
+ paths.add(path);
+ client.addToChangelist(paths, cl1, Depth.infinity, null);
+ paths.remove(path);
+
+ path = fileToSVNPath(new File(thisTest.getWCPath(), "A/B/lambda"),
+ true);
+ paths.add(path);
+ client.addToChangelist(paths, cl2, Depth.infinity, null);
+
+ client.getChangelists(thisTest.getWCPath(), null,
+ Depth.infinity, clCallback);
+ Collection<String> changelists = clCallback.getChangelists();
+ assertEquals(2, changelists.size());
+ assertTrue("Contains " + cl1, changelists.contains(cl1));
+ assertTrue("Contains " + cl2, changelists.contains(cl2));
+ }
+
/**
* Helper method for testing mergeinfo retrieval. Assumes
* that <code>targetPath</code> has both merge history and
@@ -2315,7 +2695,7 @@ public class BasicTests extends SVNTests
List<RevisionRange> ranges = mergeInfo.getRevisions(mergeSrc);
assertTrue("Missing merge info for source '" + mergeSrc + "' on '" +
targetPath + '\'', ranges != null && !ranges.isEmpty());
- RevisionRange range = (RevisionRange) ranges.get(0);
+ RevisionRange range = ranges.get(0);
String expectedMergedRevs = expectedMergeStart + "-" + expectedMergeEnd;
assertEquals("Unexpected first merged revision range for '" +
mergeSrc + "' on '" + targetPath + '\'',
@@ -2578,6 +2958,7 @@ public class BasicTests extends SVNTests
* @throws Throwable
* @since 1.5
*/
+ @SuppressWarnings("deprecation")
public void testMergeReintegrate() throws Throwable
{
OneTest thisTest = setupAndPerformMerge();
@@ -2649,6 +3030,74 @@ public class BasicTests extends SVNTests
}
+
+ /**
+ * Test reintegrating a branch with trunk, using automatic reintegrate.
+ */
+ public void testMergeAutoReintegrate() throws Throwable
+ {
+ OneTest thisTest = setupAndPerformMerge();
+
+ // Test that getMergeinfo() returns null.
+ assertNull(client.getMergeinfo(new File(thisTest.getWCPath(), "A")
+ .toString(), Revision.HEAD));
+
+ // Merge and commit some changes to main (r4).
+ appendText(thisTest, "A/mu", "xxx", 4);
+ checkCommitRevision(thisTest,
+ "wrong revision number from main commit", 4,
+ thisTest.getWCPathSet(), "log msg", Depth.infinity,
+ false, false, null, null);
+ // Merge and commit some changes to branch (r5).
+ appendText(thisTest, "branches/A/D/G/rho", "yyy", -1);
+ checkCommitRevision(thisTest,
+ "wrong revision number from branch commit", 5,
+ thisTest.getWCPathSet(), "log msg", Depth.infinity,
+ false, false, null, null);
+
+ // update the branch WC (to r5) before merge
+ update(thisTest, "/branches");
+
+ String branchPath = thisTest.getWCPath() + "/branches/A";
+ String modUrl = thisTest.getUrl() + "/A";
+ Revision unspec = new Revision(Revision.Kind.unspecified);
+ List<RevisionRange> ranges = new ArrayList<RevisionRange>(1);
+ ranges.add(new RevisionRange(unspec, unspec));
+ client.merge(modUrl, Revision.HEAD, ranges,
+ branchPath, true, Depth.infinity, false, false, false);
+
+ // commit the changes so that we can verify merge
+ addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+ "branches/A", NodeKind.dir,
+ CommitItemStateFlags.PropMods);
+ addExpectedCommitItem(thisTest.getWCPath(), thisTest.getUrl().toString(),
+ "branches/A/mu", NodeKind.file,
+ CommitItemStateFlags.TextMods);
+ checkCommitRevision(thisTest, "wrong revision number from commit", 6,
+ thisTest.getWCPathSet(), "log msg", Depth.infinity,
+ false, false, null, null);
+
+ // now we reintegrate the branch with main
+ String branchUrl = thisTest.getUrl() + "/branches/A";
+ client.merge(branchUrl, Revision.HEAD, null,
+ thisTest.getWCPath() + "/A", false,
+ Depth.unknown, false, false, false, false);
+
+ // make the working copy up-to-date, so that mergeinfo can be committed
+ update(thisTest);
+ // commit the changes so that we can verify merge
+ addExpectedCommitItem(thisTest.getWCPath(),
+ thisTest.getUrl().toString(), "A", NodeKind.dir,
+ CommitItemStateFlags.PropMods);
+ addExpectedCommitItem(thisTest.getWCPath(),
+ thisTest.getUrl().toString(), "A/D/G/rho",
+ NodeKind.file, CommitItemStateFlags.TextMods);
+ checkCommitRevision(thisTest, "wrong revision number from commit", 7,
+ thisTest.getWCPathSet(), "log msg", Depth.infinity,
+ false, false, null, null);
+
+ }
+
/**
* Test automatic merge conflict resolution.
* @throws Throwable
@@ -2781,7 +3230,7 @@ public class BasicTests extends SVNTests
srcs.add(new CopySource(thisTest.getUrl() + "/A", Revision.HEAD,
Revision.HEAD));
client.copy(srcs, thisTest.getUrl() + "/branches/A",
- true, false, false, null,
+ true, false, false, false, false, null, null,
new ConstMsg("create A branch"), null);
// update the WC (to r3) so that it has the branches folder
@@ -2824,7 +3273,7 @@ public class BasicTests extends SVNTests
// Do nothing, right now.
return false;
}
- });
+ });
}
/**
@@ -2885,7 +3334,7 @@ public class BasicTests extends SVNTests
thisTest.getUrl().toString(), diffOutput.getPath(),
Depth.infinity, null, true, true, false, false);
- fail("This test should fail becaus the relativeToDir parameter " +
+ fail("This test should fail because the relativeToDir parameter " +
"does not work with URLs");
}
catch (Exception ignored)
@@ -3234,7 +3683,7 @@ public class BasicTests extends SVNTests
// Rigorously inspect one of our DiffSummary notifications.
final String BETA_PATH = "A/B/E/beta";
- DiffSummary betaDiff = (DiffSummary) summaries.get(BETA_PATH);
+ DiffSummary betaDiff = summaries.get(BETA_PATH);
assertNotNull("No diff summary for " + BETA_PATH, betaDiff);
assertEquals("Incorrect path for " + BETA_PATH, BETA_PATH,
betaDiff.getPath());
@@ -3299,6 +3748,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
@@ -3308,25 +3767,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)
- {
- }
}
/**
@@ -3665,11 +4112,46 @@ public class BasicTests extends SVNTests
false, false, callback);
assertEquals(1, callback.numberOfLines());
BlameCallbackImpl.BlameLine line = callback.getBlameLine(0);
- if (line != null)
- {
- assertEquals(1, line.getRevision());
- assertEquals("jrandom", line.getAuthor());
+ assertNotNull(line);
+ assertEquals(1, line.getRevision());
+ assertEquals("jrandom", line.getAuthor());
+ assertEquals("This is the file 'iota'.", line.getLine());
+ }
+
+ /**
+ * Test blame with diff options.
+ * @since 1.9
+ */
+ public void testBlameWithDiffOptions() throws Throwable
+ {
+ OneTest thisTest = new OneTest();
+ // Modify the file iota, making only whitespace changes.
+ File iota = new File(thisTest.getWorkingCopy(), "iota");
+ FileOutputStream stream = new FileOutputStream(iota, false);
+ stream.write("This is the file 'iota'.\t".getBytes());
+ stream.close();
+ Set<String> srcPaths = new HashSet<String>(1);
+ srcPaths.add(thisTest.getWCPath());
+ try {
+ client.username("rayjandom");
+ client.commit(srcPaths, Depth.infinity, false, false, null, null,
+ new ConstMsg("Whitespace-only change in /iota"), null);
+ } finally {
+ client.username("jrandom");
}
+
+ // Run blame on the result
+ BlameCallbackImpl callback = new BlameCallbackImpl();
+ client.blame(thisTest.getWCPath() + "/iota", Revision.HEAD,
+ Revision.getInstance(1), Revision.HEAD,
+ false, false, callback,
+ new DiffOptions(DiffOptions.Flag.IgnoreWhitespace));
+ assertEquals(1, callback.numberOfLines());
+ BlameCallbackImpl.BlameLine line = callback.getBlameLine(0);
+ assertNotNull(line);
+ assertEquals(1, line.getRevision());
+ assertEquals("jrandom", line.getAuthor());
+ assertEquals("This is the file 'iota'.\t", line.getLine());
}
/**
@@ -3745,6 +4227,149 @@ public class BasicTests extends SVNTests
}
/**
+ * Test RevisionRangeList.remove
+ */
+ public void testRevisionRangeListRemove() throws Throwable
+ {
+ RevisionRangeList ranges =
+ new RevisionRangeList(new ArrayList<RevisionRange>());
+ ranges.getRanges()
+ .add(new RevisionRange(Revision.getInstance(1),
+ Revision.getInstance(5),
+ true));
+ ranges.getRanges()
+ .add(new RevisionRange(Revision.getInstance(7),
+ Revision.getInstance(9),
+ false));
+ RevisionRangeList eraser =
+ new RevisionRangeList(new ArrayList<RevisionRange>());
+ eraser.getRanges()
+ .add(new RevisionRange(Revision.getInstance(7),
+ Revision.getInstance(9),
+ true));
+
+ List<RevisionRange> result = ranges.remove(eraser, true).getRanges();
+ assertEquals(2, ranges.getRanges().size());
+ assertEquals(1, eraser.getRanges().size());
+ assertEquals(2, result.size());
+
+ result = ranges.remove(eraser.getRanges(), false);
+ assertEquals(2, ranges.getRanges().size());
+ assertEquals(1, eraser.getRanges().size());
+ assertEquals(1, result.size());
+ }
+
+ private class Tunnel extends Thread
+ implements TunnelAgent, TunnelAgent.CloseTunnelCallback
+ {
+ public boolean checkTunnel(String name)
+ {
+ return name.equals("test");
+ }
+
+ public TunnelAgent.CloseTunnelCallback
+ openTunnel(ReadableByteChannel request,
+ WritableByteChannel response,
+ String name, String user,
+ String hostname, int port)
+ {
+ this.request = request;
+ this.response = response;
+ start();
+ return this;
+ }
+
+ public void closeTunnel()
+ {
+ Throwable t = null;
+ try {
+ request.close();
+ join();
+ response.close();
+ } catch (Throwable ex) {
+ t = ex;
+ }
+ assertEquals("No exception thrown", null, t);
+ }
+
+ private ReadableByteChannel request;
+ private WritableByteChannel response;
+
+ public void run()
+ {
+
+ int index = 0;
+ byte[] raw_data = new byte[1024];
+ ByteBuffer data = ByteBuffer.wrap(raw_data);
+ while(index < commands.length && request.isOpen()) {
+ try {
+ byte[] command = commands[index++];
+ response.write(ByteBuffer.wrap(command));
+ } catch (IOException ex) {
+ break;
+ }
+
+ try {
+ data.clear();
+ request.read(data);
+ } catch (Throwable ex) {}
+ }
+
+ try {
+ response.close();
+ request.close();
+ } catch (Throwable t) {}
+ }
+
+ private final byte[][] commands = new byte[][]{
+ // Initial capabilities negotiation
+ ("( success ( 2 2 ( ) " +
+ "( edit-pipeline svndiff1 absent-entries commit-revprops " +
+ "depth log-revprops atomic-revprops partial-replay " +
+ "inherited-props ephemeral-txnprops file-revs-reverse " +
+ ") ) ) ").getBytes(),
+
+ // Response for successful connection
+ ("( success ( ( ANONYMOUS EXTERNAL ) " +
+ "36:e3c8c113-03ba-4ec5-a8e6-8fc555e57b91 ) ) ").getBytes(),
+
+ // Response to authentication request
+ ("( success ( ) ) ( success ( " +
+ "36:e3c8c113-03ba-4ec5-a8e6-8fc555e57b91 " +
+ "24:svn+test://localhost/foo ( mergeinfo ) ) ) ").getBytes(),
+
+ // Response to revprop request
+ ("( success ( ( ) 0: ) ) ( success ( ( 4:fake ) ) ) ").getBytes()
+ };
+ }
+
+ /**
+ * Test tunnel handling.
+ */
+ public void testTunnelAgent() throws Throwable
+ {
+ byte[] revprop;
+ SVNClient cl = new SVNClient();
+ try {
+ cl.notification2(new MyNotifier());
+ if (DefaultAuthn.useDeprecated())
+ cl.setPrompt(DefaultAuthn.getDeprecated());
+ else
+ cl.setPrompt(DefaultAuthn.getDefault());
+ cl.username(USERNAME);
+ cl.setProgressCallback(new DefaultProgressListener());
+ cl.setConfigDirectory(conf.getAbsolutePath());
+
+ cl.setTunnelAgent(new Tunnel());
+ revprop = cl.revProperty("svn+test://localhost/foo", "svn:log",
+ Revision.getInstance(0L));
+ } finally {
+ cl.dispose();
+ }
+ assertEquals("fake", new String(revprop));
+ }
+
+ /**
* @return <code>file</code> converted into a -- possibly
* <code>canonical</code>-ized -- Subversion-internal path
* representation.
@@ -3797,8 +4422,16 @@ public class BasicTests extends SVNTests
extends HashMap<String, Collection<String>>
implements ChangelistCallback
{
+ private static final long serialVersionUID = 1L;
+
+ private HashSet<String> allChangelists = new HashSet<String>();
+
public void doChangelist(String path, String changelist)
{
+ if (changelist != null)
+ allChangelists.add(changelist);
+
+ path = fileToSVNPath(new File(path), true);
if (super.containsKey(path))
{
// Append the changelist to the existing list
@@ -3818,6 +4451,11 @@ public class BasicTests extends SVNTests
{
return super.get(path);
}
+
+ public Collection<String> getChangelists()
+ {
+ return allChangelists;
+ }
}
private class MyInfoCallback implements InfoCallback {
@@ -3970,8 +4608,9 @@ public class BasicTests extends SVNTests
{
final List<Info> infos = new ArrayList<Info>();
- client.info2(pathOrUrl, revision, pegRevision, depth, changelists,
- new InfoCallback () {
+ client.info(pathOrUrl, revision, pegRevision, depth,
+ true, true, false,
+ changelists, new InfoCallback () {
public void singleInfo(Info info)
{ infos.add(info); }
});