3
* ====================================================================
4
* Licensed to the Apache Software Foundation (ASF) under one
5
* or more contributor license agreements. See the NOTICE file
6
* distributed with this work for additional information
7
* regarding copyright ownership. The ASF licenses this file
8
* to you under the Apache License, Version 2.0 (the
9
* "License"); you may not use this file except in compliance
10
* with the License. You may obtain a copy of the License at
12
* http://www.apache.org/licenses/LICENSE-2.0
14
* Unless required by applicable law or agreed to in writing,
15
* software distributed under the License is distributed on an
16
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
* KIND, either express or implied. See the License for the
18
* specific language governing permissions and limitations
20
* ====================================================================
23
package org.apache.subversion.javahl;
25
import org.apache.subversion.javahl.*;
26
import org.apache.subversion.javahl.remote.*;
27
import org.apache.subversion.javahl.callback.*;
28
import org.apache.subversion.javahl.types.*;
30
import java.util.Arrays;
31
import java.util.ArrayList;
32
import java.util.Collections;
33
import java.util.Date;
34
import java.util.List;
37
import java.util.HashMap;
38
import java.util.HashSet;
39
import java.io.ByteArrayInputStream;
40
import java.io.ByteArrayOutputStream;
42
import java.io.FileInputStream;
43
import java.io.FileOutputStream;
44
import java.io.IOException;
45
import java.nio.charset.Charset;
46
import java.security.MessageDigest;
47
import java.security.NoSuchAlgorithmException;
50
* This class is used for testing the SVNReposAccess class
52
* More methodes for testing are still needed
54
public class SVNRemoteTests extends SVNTests
56
protected OneTest thisTest;
58
public SVNRemoteTests()
62
public SVNRemoteTests(String name)
67
protected void setUp() throws Exception
71
thisTest = new OneTest();
74
public static ISVNRemote getSession(String url, String configDirectory)
78
RemoteFactory factory = new RemoteFactory();
79
factory.setConfigDirectory(configDirectory);
80
factory.setUsername(USERNAME);
81
// Do not set default password, exercise prompter instead.
82
if (DefaultAuthn.useDeprecated())
83
factory.setPrompt(DefaultAuthn.getDeprecated());
85
factory.setPrompt(DefaultAuthn.getDefault());
87
ISVNRemote raSession = factory.openRemoteSession(url);
88
assertNotNull("Null session was returned by factory", raSession);
93
throw new RuntimeException(ex);
97
private ISVNRemote getSession()
99
return getSession(getTestRepoUrl(), super.conf.getAbsolutePath());
103
* Test the basic SVNAdmin.create functionality
104
* @throws SubversionException
106
public void testCreate()
107
throws SubversionException, IOException
109
assertTrue("repository exists", thisTest.getRepository().exists());
112
public void testGetSession_ConfigConstructor() throws Exception
117
if (DefaultAuthn.useDeprecated())
118
session = new RemoteFactory(
119
super.conf.getAbsolutePath(),
120
USERNAME, null, // Do not set default password.
121
DefaultAuthn.getDeprecated(),
123
.openRemoteSession(getTestRepoUrl());
125
session = new RemoteFactory(
126
super.conf.getAbsolutePath(),
127
USERNAME, null, // Do not set default password.
128
DefaultAuthn.getDefault(),
130
.openRemoteSession(getTestRepoUrl());
132
catch (ClientException ex)
134
throw new RuntimeException(ex);
136
assertNotNull("Null session was returned by factory", session);
137
assertEquals(getTestRepoUrl(), session.getSessionUrl());
140
public void testDispose() throws Exception
142
ISVNRemote session = getSession();
146
public void testSessionGC() throws Exception
148
int svnErrorCode = 0;
151
String prefix = getTestRepoUrl().substring(
152
0, 1 + getTestRepoUrl().lastIndexOf("/"));
154
if (DefaultAuthn.useDeprecated())
156
super.conf.getAbsolutePath(),
157
USERNAME, null, // Do not set default password.
158
DefaultAuthn.getDeprecated(),
160
.openRemoteSession(prefix + "repositorydoesnotexisthere");
163
super.conf.getAbsolutePath(),
164
USERNAME, null, // Do not set default password.
165
DefaultAuthn.getDefault(),
167
.openRemoteSession(prefix + "repositorydoesnotexisthere");
171
for(int i = 0; i < 100; i++)
173
Runtime.getRuntime().gc(); // GC should run finalize
176
byte[] memEater = new byte[1024 * 1024];
177
Arrays.fill(memEater, (byte) i);
179
// Do some more javahl activity (this url is OK)
180
final ISVNRemote session = getSession();
181
session.getLatestRevision();
186
catch (ClientException ex)
188
List<ClientException.ErrorMessage> msgs = ex.getAllMessages();
189
svnErrorCode = msgs.get(msgs.size() - 1).getCode();
192
assertTrue(svnErrorCode == 180001 // file:
193
|| svnErrorCode == 210005 // svn:
194
|| svnErrorCode == 2); // http:
197
public void testDatedRev() throws Exception
199
ISVNRemote session = getSession();
201
long revision = session.getRevisionByDate(new Date());
202
assertEquals(revision, 1);
205
public void testGetLocks() throws Exception
207
ISVNRemote session = getSession();
209
Set<String> iotaPathSet = new HashSet<String>(1);
210
String iotaPath = thisTest.getWCPath() + "/iota";
211
iotaPathSet.add(iotaPath);
213
client.lock(iotaPathSet, "foo", false);
215
Map<String, Lock> locks = session.getLocks("iota", Depth.infinity);
217
assertEquals(locks.size(), 1);
218
Lock lock = locks.get("/iota");
220
assertEquals(lock.getOwner(), "jrandom");
223
public void testCheckPath() throws Exception
225
ISVNRemote session = getSession();
227
NodeKind kind = session.checkPath("iota", 1);
228
assertEquals(NodeKind.file, kind);
230
kind = session.checkPath("iota", 0);
231
assertEquals(NodeKind.none, kind);
233
kind = session.checkPath("A", 1);
234
assertEquals(NodeKind.dir, kind);
237
public void testStat() throws Exception
239
ISVNRemote session = getSession();
241
DirEntry dirent = session.stat("iota", 1);
242
assertEquals(NodeKind.file, dirent.getNodeKind());
244
dirent = session.stat("iota", 0);
247
dirent = session.stat("A", 1);
248
assertEquals(NodeKind.dir, dirent.getNodeKind());
251
private String getTestRepoUrl()
253
return thisTest.getUrl().toASCIIString();
256
public void testGetLatestRevision() throws Exception
258
ISVNRemote session = getSession();
259
long revision = session.getLatestRevision();
260
assertEquals(revision, 1);
263
public void testGetUUID() throws Exception
265
ISVNRemote session = getSession();
269
* TODO: Test for actual UUID once test dump file has
272
assertNotNull(session.getReposUUID());
275
public void testGetUrl() throws Exception
277
ISVNRemote session = getSession();
279
assertEquals(getTestRepoUrl(), session.getSessionUrl());
282
public void testGetRootUrl() throws Exception
284
ISVNRemote session = getSession();
285
session.reparent(session.getSessionUrl() + "/A/B/E");
286
assertEquals(getTestRepoUrl(), session.getReposRootUrl());
289
public void testGetUrl_viaSVNClient() throws Exception
291
ISVNRemote session = client.openRemoteSession(getTestRepoUrl());
293
assertEquals(getTestRepoUrl(), session.getSessionUrl());
296
public void testGetUrl_viaSVNClientWorkingCopy() throws Exception
298
ISVNRemote session = client.openRemoteSession(thisTest.getWCPath());
300
assertEquals(getTestRepoUrl(), session.getSessionUrl());
303
public void testReparent() throws Exception
305
ISVNRemote session = getSession();
306
String newUrl = session.getSessionUrl() + "/A/B/E";
307
session.reparent(newUrl);
308
assertEquals(newUrl, session.getSessionUrl());
311
public void testGetRelativePath() throws Exception
313
ISVNRemote session = getSession();
314
String baseUrl = session.getSessionUrl() + "/A/B/E";
315
session.reparent(baseUrl);
317
String relPath = session.getSessionRelativePath(baseUrl + "/alpha");
318
assertEquals("alpha", relPath);
320
relPath = session.getReposRelativePath(baseUrl + "/beta");
321
assertEquals("A/B/E/beta", relPath);
324
public void testGetCommitEditor() throws Exception
326
ISVNRemote session = getSession();
327
session.getCommitEditor(null, null, null, false);
330
public void testDisposeCommitEditor() throws Exception
332
ISVNRemote session = getSession();
333
session.getCommitEditor(null, null, null, false);
337
public void testHasCapability() throws Exception
339
ISVNRemote session = getSession();
340
assert(session.hasCapability(ISVNRemote.Capability.depth));
343
public void testChangeRevpropNoAtomic() throws Exception
345
Charset UTF8 = Charset.forName("UTF-8");
346
ISVNRemote session = getSession();
349
session.hasCapability(ISVNRemote.Capability.atomic_revprops);
354
boolean exceptioned = false;
357
byte[] oldValue = "bumble".getBytes(UTF8);
358
byte[] newValue = "bee".getBytes(UTF8);
359
session.changeRevisionProperty(1, "svn:author",
362
catch (IllegalArgumentException ex)
369
public void testChangeRevpropAtomic() throws Exception
371
Charset UTF8 = Charset.forName("UTF-8");
372
ISVNRemote session = getSession();
375
session.hasCapability(ISVNRemote.Capability.atomic_revprops);
380
byte[] oldValue = client.revProperty(getTestRepoUrl(), "svn:author",
381
Revision.getInstance(1));
382
byte[] newValue = "rayjandom".getBytes(UTF8);
385
session.changeRevisionProperty(1, "svn:author",
388
catch (ClientException ex)
390
ClientException.ErrorMessage error = null;
391
for (ClientException.ErrorMessage m : ex.getAllMessages())
392
if (!m.isGeneric()) {
398
fail("Failed with no error message");
400
if (error.getCode() != 175002 && // SVN_ERR_RA_DAV_REQUEST_FAILED
401
error.getCode() != 165006) // SVN_ERR_REPOS_DISABLED_FEATURE
402
fail(error.getMessage());
407
byte[] check = client.revProperty(getTestRepoUrl(), "svn:author",
408
Revision.getInstance(1));
409
assertTrue(Arrays.equals(check, newValue));
412
public void testGetRevpropList() throws Exception
414
Charset UTF8 = Charset.forName("UTF-8");
415
ISVNRemote session = getSession();
417
Map<String, byte[]> proplist = session.getRevisionProperties(1);
418
assertTrue(Arrays.equals(proplist.get("svn:author"),
419
USERNAME.getBytes(UTF8)));
422
public void testGetRevprop() throws Exception
424
Charset UTF8 = Charset.forName("UTF-8");
425
ISVNRemote session = getSession();
427
byte[] propval = session.getRevisionProperty(1, "svn:author");
428
assertTrue(Arrays.equals(propval, USERNAME.getBytes(UTF8)));
431
public void testGetFile() throws Exception
433
Charset UTF8 = Charset.forName("UTF-8");
434
ISVNRemote session = getSession();
436
ByteArrayOutputStream contents = new ByteArrayOutputStream();
437
HashMap<String, byte[]> properties = new HashMap<String, byte[]>();
438
properties.put("fakename", "fakecontents".getBytes(UTF8));
440
session.getFile(Revision.SVN_INVALID_REVNUM, "A/B/lambda",
441
contents, properties);
442
assertEquals(fetched_rev, 1);
443
assertEquals(contents.toString("UTF-8"),
444
"This is the file 'lambda'.");
445
for (Map.Entry<String, byte[]> e : properties.entrySet()) {
446
final String key = e.getKey();
447
assertTrue(key.startsWith("svn:entry:")
448
|| key.startsWith("svn:wc:"));
452
public void testGetDirectory() throws Exception
454
Charset UTF8 = Charset.forName("UTF-8");
455
ISVNRemote session = getSession();
457
HashMap<String, DirEntry> dirents = new HashMap<String, DirEntry>();
458
dirents.put("E", null);
459
dirents.put("F", null);
460
dirents.put("lambda", null);
461
HashMap<String, byte[]> properties = new HashMap<String, byte[]>();
462
properties.put("fakename", "fakecontents".getBytes(UTF8));
464
session.getDirectory(Revision.SVN_INVALID_REVNUM, "A/B",
465
DirEntry.Fields.all, dirents, properties);
466
assertEquals(fetched_rev, 1);
467
assertEquals(dirents.get("E").getPath(), "E");
468
assertEquals(dirents.get("F").getPath(), "F");
469
assertEquals(dirents.get("lambda").getPath(), "lambda");
470
for (Map.Entry<String, byte[]> e : properties.entrySet()) {
471
final String key = e.getKey();
472
assertTrue(key.startsWith("svn:entry:")
473
|| key.startsWith("svn:wc:"));
477
private static final class CommitContext implements CommitCallback
479
public final ISVNEditor editor;
480
public CommitContext(ISVNRemote session, String logstr,
481
ISVNEditor.ProvideBaseCallback getBase,
482
ISVNEditor.ProvidePropsCallback getProps,
483
ISVNEditor.GetNodeKindCallback getKind)
484
throws ClientException
486
Charset UTF8 = Charset.forName("UTF-8");
487
byte[] log = (logstr == null
489
: logstr.getBytes(UTF8));
490
HashMap<String, byte[]> revprops = new HashMap<String, byte[]>();
491
revprops.put("svn:log", log);
493
// Run the getCommitEditor overloads through their paces, too.
494
if (getBase == null && getProps == null && getKind == null)
495
editor = session.getCommitEditor(revprops, this, null, false);
497
editor = session.getCommitEditor(revprops, this, null, false,
498
getBase, getProps, getKind);
501
public CommitContext(ISVNRemote session, String logstr)
502
throws ClientException
504
this(session, logstr, null, null, null);
507
public void commitInfo(CommitInfo info) { this.info = info; }
508
public long getRevision() { return info.getRevision(); }
510
private CommitInfo info;
513
private static final class EditorCallbacks
515
private final String wcpath;
516
private final long revision;
517
private final Map<String, byte[]> props;
518
private final NodeKind kind;
520
public EditorCallbacks(String wcpath, long revision,
521
Map<String, byte[]> props,
524
this.wcpath = wcpath;
525
this.revision = revision;
530
public final ISVNEditor.ProvideBaseCallback getBase =
531
new ISVNEditor.ProvideBaseCallback()
533
public ISVNEditor.ProvideBaseCallback.ReturnValue
534
getContents(String relpath)
537
return new ISVNEditor.ProvideBaseCallback.ReturnValue(
538
new FileInputStream(wcpath + relpath), revision);
539
} catch (java.io.FileNotFoundException e) {
540
throw new RuntimeException(e);
545
public final ISVNEditor.ProvidePropsCallback getProps =
546
new ISVNEditor.ProvidePropsCallback()
548
public ISVNEditor.ProvidePropsCallback.ReturnValue
549
getProperties(String relpath)
551
return new ISVNEditor.ProvidePropsCallback.ReturnValue(
556
public final ISVNEditor.GetNodeKindCallback getKind =
557
new ISVNEditor.GetNodeKindCallback()
559
public NodeKind getKind(String relpath, long revision)
566
private void testEditorCopy(EditorCallbacks cb) throws Exception
568
ISVNRemote session = getSession();
571
? new CommitContext(session, "Copy A/B/lambda -> A/B/omega",
572
cb.getBase, cb.getProps, cb.getKind)
573
: new CommitContext(session, "Copy A/B/lambda -> A/B/omega"));
576
// FIXME: alter dir A/B first
577
cc.editor.copy("A/B/lambda", 1, "A/B/omega",
578
Revision.SVN_INVALID_REVNUM);
579
cc.editor.complete();
584
assertEquals(2, cc.getRevision());
585
assertEquals(2, session.getLatestRevision());
586
assertEquals(NodeKind.file,
587
session.checkPath("A/B/lambda",
588
Revision.SVN_INVALID_REVNUM));
589
assertEquals(NodeKind.file,
590
session.checkPath("A/B/omega",
591
Revision.SVN_INVALID_REVNUM));
594
public void testEditorCopy() throws Exception
596
testEditorCopy(null);
599
public void testEditorCopy_WithCallbacks() throws Exception
601
testEditorCopy(new EditorCallbacks(thisTest.getWCPath(), 1L,
602
new HashMap<String, byte[]>(),
606
public void testEditorMove() throws Exception
608
ISVNRemote session = getSession();
610
new CommitContext(session, "Move A/B/lambda -> A/B/omega");
613
// FIXME: alter dir A/B first
614
cc.editor.move("A/B/lambda", 1, "A/B/omega",
615
Revision.SVN_INVALID_REVNUM);
616
cc.editor.complete();
621
assertEquals(2, cc.getRevision());
622
assertEquals(2, session.getLatestRevision());
623
assertEquals(NodeKind.none,
624
session.checkPath("A/B/lambda",
625
Revision.SVN_INVALID_REVNUM));
626
assertEquals(NodeKind.file,
627
session.checkPath("A/B/omega",
628
Revision.SVN_INVALID_REVNUM));
631
public void testEditorDelete() throws Exception
633
ISVNRemote session = getSession();
635
new CommitContext(session, "Delete all greek files");
637
String[] filePaths = { "iota",
651
// FIXME: alter a bunch of dirs first
652
for (String path : filePaths)
653
cc.editor.delete(path, 1);
654
cc.editor.complete();
659
assertEquals(2, cc.getRevision());
660
assertEquals(2, session.getLatestRevision());
661
for (String path : filePaths)
662
assertEquals(NodeKind.none,
663
session.checkPath(path, Revision.SVN_INVALID_REVNUM));
666
public void testEditorMkdir() throws Exception
668
ISVNRemote session = getSession();
669
CommitContext cc = new CommitContext(session, "Make hebrew dir");
672
// FIXME: alter dir . first
673
cc.editor.addDirectory("ALEPH",
674
new ArrayList<String>(),
675
new HashMap<String, byte[]>(),
676
Revision.SVN_INVALID_REVNUM);
677
cc.editor.complete();
682
assertEquals(2, cc.getRevision());
683
assertEquals(2, session.getLatestRevision());
684
assertEquals(NodeKind.dir,
685
session.checkPath("ALEPH",
686
Revision.SVN_INVALID_REVNUM));
689
private void testEditorSetDirProps(EditorCallbacks cb) throws Exception
691
Charset UTF8 = Charset.forName("UTF-8");
692
ISVNRemote session = getSession();
694
byte[] ignoreval = "*.pyc\n.gitignore\n".getBytes(UTF8);
695
byte[] binaryval = new byte[]{(byte)0, (byte)13, (byte)255, (byte)8,
696
(byte)127, (byte)128, (byte)129};
697
HashMap<String, byte[]> props = new HashMap<String, byte[]>();
698
props.put("svn:ignore", ignoreval);
699
props.put("binaryprop", binaryval);
703
? new CommitContext(session, "Add svn:ignore and binaryprop",
704
cb.getBase, cb.getProps, cb.getKind)
705
: new CommitContext(session, "Add svn:ignore and binaryprop"));
707
cc.editor.alterDirectory("", 1, null, props);
708
cc.editor.complete();
713
assertEquals(2, cc.getRevision());
714
assertEquals(2, session.getLatestRevision());
715
assertTrue(Arrays.equals(ignoreval,
716
client.propertyGet(session.getSessionUrl(),
720
assertTrue(Arrays.equals(binaryval,
721
client.propertyGet(session.getSessionUrl(),
727
public void testEditorSetDirProps() throws Exception
729
testEditorSetDirProps(null);
732
public void testEditorSetDirProps_WithCallbacks() throws Exception
734
testEditorSetDirProps(new EditorCallbacks(thisTest.getWCPath(), 1L,
735
new HashMap<String, byte[]>(),
739
private static byte[] SHA1(byte[] text) throws NoSuchAlgorithmException
741
MessageDigest md = MessageDigest.getInstance("SHA-1");
742
return md.digest(text);
745
public void testEditorAddFile() throws Exception
747
Charset UTF8 = Charset.forName("UTF-8");
748
ISVNRemote session = getSession();
750
byte[] eolstyle = "native".getBytes(UTF8);
751
HashMap<String, byte[]> props = new HashMap<String, byte[]>();
752
props.put("svn:eol-style", eolstyle);
754
byte[] contents = "This is file 'xi'.".getBytes(UTF8);
755
Checksum hash = new Checksum(SHA1(contents), Checksum.Kind.SHA1);
756
ByteArrayInputStream stream = new ByteArrayInputStream(contents);
758
CommitContext cc = new CommitContext(session, "Add A/xi");
760
// FIXME: alter dir A first
761
cc.editor.addFile("A/xi", hash, stream, props,
762
Revision.SVN_INVALID_REVNUM);
763
cc.editor.complete();
768
assertEquals(2, cc.getRevision());
769
assertEquals(2, session.getLatestRevision());
770
assertEquals(NodeKind.file,
771
session.checkPath("A/xi",
772
Revision.SVN_INVALID_REVNUM));
774
byte[] propval = client.propertyGet(session.getSessionUrl() + "/A/xi",
778
assertTrue(Arrays.equals(eolstyle, propval));
781
public void testEditorDeleteFileProps() throws Exception
783
Charset UTF8 = Charset.forName("UTF-8");
784
client.propertySetRemote(
785
thisTest.getUrl() + "/iota", 1L,
786
"name", "value".getBytes(UTF8),
787
new CommitMessageCallback() {
788
public String getLogMessage(Set<CommitItem> elements) {
789
return "Set property 'name' to 'value'";
791
}, false, null, null);
793
ISVNRemote session = getSession();
794
HashMap<String, byte[]> props = new HashMap<String, byte[]>();
795
assertEquals(2L, session.getFile(Revision.SVN_INVALID_REVNUM, "iota",
799
for (Map.Entry<String, byte[]> e : props.entrySet()) {
800
final String key = e.getKey();
801
if (key.startsWith("svn:entry:") || key.startsWith("svn:wc:"))
805
assertEquals(1, propcount);
807
CommitContext cc = new CommitContext(session, "Remove all props");
810
cc.editor.alterFile("iota", 2L, null, null, props);
811
cc.editor.complete();
816
assertEquals(3L, session.getFile(Revision.SVN_INVALID_REVNUM, "iota",
819
for (Map.Entry<String, byte[]> e : props.entrySet()) {
820
final String key = e.getKey();
821
if (key.startsWith("svn:entry:") || key.startsWith("svn:wc:"))
825
assertEquals(0, propcount);
828
private void testEditorSetFileContents(EditorCallbacks cb) throws Exception
830
Charset UTF8 = Charset.forName("UTF-8");
831
ISVNRemote session = getSession();
833
byte[] contents = "This is modified file 'alpha'.".getBytes(UTF8);
834
Checksum hash = new Checksum(SHA1(contents), Checksum.Kind.SHA1);
835
ByteArrayInputStream stream = new ByteArrayInputStream(contents);
839
? new CommitContext(session, "Change contents of A/B/E/alpha",
840
cb.getBase, cb.getProps, cb.getKind)
841
: new CommitContext(session, "Change contents of A/B/E/alpha"));
843
cc.editor.alterFile("A/B/E/alpha", 1, hash, stream, null);
844
cc.editor.complete();
849
assertEquals(2, cc.getRevision());
850
assertEquals(2, session.getLatestRevision());
851
ByteArrayOutputStream checkcontents = new ByteArrayOutputStream();
852
client.streamFileContent(session.getSessionUrl() + "/A/B/E/alpha",
853
Revision.HEAD, Revision.HEAD, checkcontents);
854
assertTrue(Arrays.equals(contents, checkcontents.toByteArray()));
857
public void testEditorSetFileContents() throws Exception
859
testEditorSetFileContents(null);
862
public void testEditorSetFileContents_WithCallbacks() throws Exception
864
testEditorSetFileContents(new EditorCallbacks(thisTest.getWCPath(), 1L,
865
new HashMap<String, byte[]>(),
869
// Sanity check so that we don't forget about unimplemented methods.
870
public void testEditorNotImplemented() throws Exception
872
ISVNRemote session = getSession();
874
HashMap<String, byte[]> props = new HashMap<String, byte[]>();
875
// ArrayList<ISVNEditor.RotatePair> rotation =
876
// new ArrayList<ISVNEditor.RotatePair>();
878
CommitContext cc = new CommitContext(session, "not implemented");
884
cc.editor.addSymlink("", "", props, 1);
885
} catch (RuntimeException ex) {
886
exmsg = ex.getMessage();
888
assertEquals("Not implemented: CommitEditor.addSymlink", exmsg);
892
cc.editor.alterSymlink("", 1, "", null);
893
} catch (RuntimeException ex) {
894
exmsg = ex.getMessage();
896
assertEquals("Not implemented: CommitEditor.alterSymlink", exmsg);
903
private static final class LogMsg
905
public Set<ChangePath> changedPaths;
906
public long revision;
907
public Map<String, byte[]> revprops;
908
public boolean hasChildren;
911
private static final class LogReceiver implements LogMessageCallback
913
public final ArrayList<LogMsg> logs = new ArrayList<LogMsg>();
915
public void singleMessage(Set<ChangePath> changedPaths,
917
Map<String, byte[]> revprops,
920
LogMsg msg = new LogMsg();
921
msg.changedPaths = changedPaths;
922
msg.revision = revision;
923
msg.revprops = revprops;
924
msg.hasChildren = hasChildren;
929
public void testGetLog() throws Exception
931
ISVNRemote session = getSession();
932
LogReceiver receiver = new LogReceiver();
935
Revision.SVN_INVALID_REVNUM,
936
Revision.SVN_INVALID_REVNUM,
937
0, false, false, false, null,
939
assertEquals(1, receiver.logs.size());
940
assertTrue(receiver.logs.get(0).revprops.size() > 0);
942
receiver.logs.clear();
943
session.reparent(getTestRepoUrl() + "/A");
945
Revision.SVN_INVALID_REVNUM,
946
0, 0, false, false, false, null,
948
assertEquals(2, receiver.logs.size());
949
assertTrue(receiver.logs.get(0).revprops.size() > 0);
952
public void testGetLogMissing() throws Exception
954
ISVNRemote session = getSession();
955
LogReceiver receiver = new LogReceiver();
957
ArrayList<String> paths = new ArrayList<String>(1);
960
boolean exception = false;
962
session.getLog(paths,
963
Revision.SVN_INVALID_REVNUM,
964
Revision.SVN_INVALID_REVNUM,
965
0, false, false, false, null,
967
} catch (ClientException ex) {
968
assertEquals("Filesystem has no item",
969
ex.getAllMessages().get(0).getMessage());
973
assertEquals(0, receiver.logs.size());
974
assertTrue(exception);
977
public void testConfigHandler() throws Exception
979
ConfigEvent handler = new ConfigEvent()
981
public void onLoad(ISVNConfig cfg)
983
//System.out.println("config:");
984
onecat(cfg.config());
985
//System.out.println("servers:");
986
onecat(cfg.servers());
989
private void onecat(ISVNConfig.Category cat)
991
for (String sec : cat.sections()) {
992
//System.out.println(" [" + sec + "]");
993
ISVNConfig.Enumerator en = new ISVNConfig.Enumerator()
995
public void option(String name, String value)
997
//System.out.println(" " + name
1001
cat.enumerate(sec, en);
1010
if (DefaultAuthn.useDeprecated())
1011
session = new RemoteFactory(
1012
super.conf.getAbsolutePath(),
1013
USERNAME, null, // Do not set default password.
1014
DefaultAuthn.getDeprecated(),
1015
null, handler, null)
1016
.openRemoteSession(getTestRepoUrl());
1018
session = new RemoteFactory(
1019
super.conf.getAbsolutePath(),
1020
USERNAME, null, // Do not set default password.
1021
DefaultAuthn.getDefault(),
1022
null, handler, null)
1023
.openRemoteSession(getTestRepoUrl());
1025
catch (ClientException ex)
1027
throw new RuntimeException(ex);
1029
session.getLatestRevision();
1032
private static class RemoteStatusReceiver implements RemoteStatus
1034
static class StatInfo implements Comparable<StatInfo>
1036
public String relpath = null;
1037
public char kind = ' '; // F, D, L
1038
public boolean textChanged = false;
1039
public boolean propsChanged = false;
1040
public boolean deleted = false;
1041
public Entry info = null;
1043
StatInfo(String relpath, char kind, boolean added)
1045
this.relpath = relpath;
1047
this.deleted = !added;
1050
StatInfo(String relpath, char kind,
1051
boolean textChanged, boolean propsChanged,
1054
this.relpath = relpath;
1056
this.textChanged = textChanged;
1057
this.propsChanged = propsChanged;
1062
public boolean equals(Object statinfo)
1064
final StatInfo that = (StatInfo)statinfo;
1065
return this.relpath.equals(that.relpath);
1069
public int hashCode()
1071
return this.relpath.hashCode();
1075
public int compareTo(StatInfo that)
1077
return this.relpath.compareTo(that.relpath);
1081
private boolean debug;
1083
public RemoteStatusReceiver()
1088
public RemoteStatusReceiver(boolean debug)
1093
public ArrayList<StatInfo> status = new ArrayList<StatInfo>();
1095
public void addedDirectory(String relativePath)
1098
System.err.println("RemoteStatus: A (dir) " +
1100
status.add(new StatInfo(relativePath, 'D', true));
1103
public void addedFile(String relativePath)
1106
System.err.println("RemoteStatus: A (file) "
1108
status.add(new StatInfo(relativePath, 'F', true));
1111
public void addedSymlink(String relativePath)
1114
System.err.println("RemoteStatus: A (link) "
1116
status.add(new StatInfo(relativePath, 'L', true));
1119
public void modifiedDirectory(String relativePath,
1120
boolean childrenModified,
1121
boolean propsModified,
1125
System.err.println("RemoteStatus: " +
1126
(childrenModified ? 'M' : '_') +
1127
(propsModified ? 'M' : '_') +
1128
" (dir) " + relativePath);
1129
status.add(new StatInfo(relativePath, 'D',
1130
childrenModified, propsModified,
1134
public void modifiedFile(String relativePath,
1135
boolean textModified,
1136
boolean propsModified,
1140
System.err.println("RemoteStatus: " +
1141
(textModified ? 'M' : '_') +
1142
(propsModified ? 'M' : '_') +
1143
" (file) " + relativePath);
1144
status.add(new StatInfo(relativePath, 'F',
1145
textModified, propsModified,
1149
public void modifiedSymlink(String relativePath,
1150
boolean targetModified,
1151
boolean propsModified,
1155
System.err.println("RemoteStatus: " +
1156
(targetModified ? 'M' : '_') +
1157
(propsModified ? 'M' : '_') +
1158
" (link) " + relativePath);
1159
status.add(new StatInfo(relativePath, 'L',
1160
targetModified, propsModified,
1165
public void deleted(String relativePath)
1168
System.err.println("RemoteStatus: D "
1170
status.add(new StatInfo(relativePath, ' ', false));
1174
public void testSimpleStatus() throws Exception
1176
ISVNRemote session = getSession();
1178
RemoteStatusReceiver receiver = new RemoteStatusReceiver();
1179
ISVNReporter rp = session.status(null, Revision.SVN_INVALID_REVNUM,
1180
Depth.infinity, receiver);
1182
rp.setPath("", 0, Depth.infinity, true, null);
1183
assertEquals(1, rp.finishReport());
1187
assertEquals(21, receiver.status.size());
1188
session.checkPath("", Revision.SVN_INVALID_REVNUM);
1191
public void testTextchangeStatus() throws Exception
1193
ISVNRemote session = getSession();
1195
CommitMessageCallback cmcb = new CommitMessageCallback() {
1196
public String getLogMessage(Set<CommitItem> x) {
1197
return "Content change on A/B/E/alpha";
1201
File alpha = new File(thisTest.getWorkingCopy(), "A/B/E/alpha");
1202
FileOutputStream writer = new FileOutputStream(alpha);
1203
writer.write("changed alpha text".getBytes());
1205
client.commit(thisTest.getWCPathSet(), Depth.infinity, false, false,
1206
null, null, cmcb, null);
1208
RemoteStatusReceiver receiver = new RemoteStatusReceiver();
1209
ISVNReporter rp = session.status(null, Revision.SVN_INVALID_REVNUM,
1210
Depth.infinity, receiver);
1212
rp.setPath("", 1, Depth.infinity, false, null);
1213
assertEquals(2, rp.finishReport());
1218
assertEquals(5, receiver.status.size());
1220
// ra_serf returns the entries in inverted order compared to ra_local.
1221
Collections.sort(receiver.status);
1222
RemoteStatusReceiver.StatInfo mod = receiver.status.get(4);
1223
assertEquals("A/B/E/alpha", mod.relpath);
1224
assertEquals('F', mod.kind);
1225
assertEquals("Text Changed", true, mod.textChanged);
1226
assertEquals("Props Changed", false, mod.propsChanged);
1227
assertEquals("Node Deleted", false, mod.deleted);
1228
assertEquals(2, mod.info.getCommittedRevision());
1231
public void testPropchangeStatus() throws Exception
1233
ISVNRemote session = getSession();
1235
CommitMessageCallback cmcb = new CommitMessageCallback() {
1236
public String getLogMessage(Set<CommitItem> x) {
1237
return "Property change on A/D/gamma";
1240
client.propertySetRemote(getTestRepoUrl() + "/A/D/gamma",
1241
1L, "foo", "bar".getBytes(), cmcb,
1244
RemoteStatusReceiver receiver = new RemoteStatusReceiver();
1245
ISVNReporter rp = session.status(null, Revision.SVN_INVALID_REVNUM,
1246
Depth.infinity, receiver);
1248
rp.setPath("", 1, Depth.infinity, false, null);
1249
assertEquals(2, rp.finishReport());
1254
assertEquals(4, receiver.status.size());
1256
// ra_serf returns the entries in inverted order compared to ra_local.
1257
Collections.sort(receiver.status);
1258
RemoteStatusReceiver.StatInfo mod = receiver.status.get(3);
1259
assertEquals("A/D/gamma", mod.relpath);
1260
assertEquals('F', mod.kind);
1261
assertEquals("TextChanged", false, mod.textChanged);
1262
assertEquals("Props Changed", true, mod.propsChanged);
1263
assertEquals("Node Deleted", false, mod.deleted);
1264
assertEquals(2, mod.info.getCommittedRevision());
1267
public void testDeletedStatus() throws Exception
1269
ISVNRemote session = getSession();
1271
CommitMessageCallback cmcb = new CommitMessageCallback() {
1272
public String getLogMessage(Set<CommitItem> x) {
1273
return "Delete A/mu";
1276
HashSet<String> paths = new HashSet<String>(1);
1277
paths.add(getTestRepoUrl() + "/A/mu");
1278
client.remove(paths, false, false, null, cmcb, null);
1280
RemoteStatusReceiver receiver = new RemoteStatusReceiver();
1281
ISVNReporter rp = session.status(null, Revision.SVN_INVALID_REVNUM,
1282
Depth.infinity, receiver);
1284
rp.setPath("", 1, Depth.infinity, false, null);
1285
assertEquals(2, rp.finishReport());
1289
assertEquals(3, receiver.status.size());
1291
// ra_serf returns the entries in inverted order compared to ra_local.
1292
Collections.sort(receiver.status);
1293
RemoteStatusReceiver.StatInfo mod = receiver.status.get(2);
1294
assertEquals("A/mu", mod.relpath);
1295
assertEquals(' ', mod.kind);
1296
assertEquals(false, mod.textChanged);
1297
assertEquals(false, mod.propsChanged);
1298
assertEquals(true, mod.deleted);
1301
public void testTrivialMergeinfo() throws Exception
1303
ISVNRemote session = getSession();
1304
ArrayList<String> paths = new ArrayList<String>(1);
1307
Map<String, Mergeinfo> catalog =
1308
session.getMergeinfo(paths, 1L, Mergeinfo.Inheritance.explicit,
1310
assertEquals(null, catalog);
1313
public void testBranchMergeinfo() throws Exception
1315
CommitMessageCallback cmcb = new CommitMessageCallback() {
1316
public String getLogMessage(Set<CommitItem> x) {
1317
return "testBranchMergeinfo";
1321
ISVNRemote session = getSession();
1324
ArrayList<CopySource> dirA = new ArrayList<CopySource>(1);
1325
dirA.add(new CopySource(getTestRepoUrl() + "/A",
1326
Revision.HEAD, Revision.HEAD));
1327
client.copy(dirA, getTestRepoUrl() + "/Abranch",
1328
false, false, true, null, cmcb, null);
1330
// Check mergeinfo on new branch
1331
ArrayList<String> paths = new ArrayList<String>(1);
1332
paths.add("Abranch");
1333
Map<String, Mergeinfo> catalog =
1334
session.getMergeinfo(paths, 2L, Mergeinfo.Inheritance.explicit,
1336
assertEquals(null, catalog);
1338
// Modify source and merge to branch
1339
client.propertySetRemote(getTestRepoUrl() + "/A/D/gamma",
1340
2L, "foo", "bar".getBytes(), cmcb,
1342
client.update(thisTest.getWCPathSet(), Revision.HEAD, Depth.infinity,
1343
false, false, true, false);
1344
client.merge(getTestRepoUrl() + "/A", Revision.HEAD, null,
1345
thisTest.getWCPath() + "/Abranch", false, Depth.infinity,
1346
false, false, false, false);
1347
client.commit(thisTest.getWCPathSet(), Depth.infinity, false, false,
1348
null, null, cmcb, null);
1350
// Check inherited mergeinfo on updated branch
1351
paths.set(0, "Abranch/mu");
1352
catalog = session.getMergeinfo(paths, 4L,
1353
Mergeinfo.Inheritance.nearest_ancestor,
1355
assertEquals(1, catalog.size());
1356
List<RevisionRange> ranges =
1357
catalog.get("Abranch/mu").getRevisions("/A/mu");
1358
assertEquals(1, ranges.size());
1359
assertEquals("1-3", ranges.get(0).toString());
1362
public void testGetLocations() throws Exception
1364
ISVNRemote session = getSession();
1366
Long expected = new Long(1L);
1367
ArrayList<Long> revs = new ArrayList<Long>(3);
1368
revs.add(new Long(0L));
1371
Map<Long, String> locs = session.getLocations("A", 1, revs);
1373
assertEquals(1, locs.size());
1374
assertTrue(locs.containsKey(expected));
1375
assertEquals("/A", locs.get(expected));
1378
public void testGetLocationSegments() throws Exception
1380
ISVNRemote session = getSession();
1382
List<ISVNRemote.LocationSegment> result =
1383
session.getLocationSegments("A", 1,
1384
Revision.SVN_INVALID_REVNUM,
1385
Revision.SVN_INVALID_REVNUM);
1386
assertEquals(1, result.size());
1387
ISVNRemote.LocationSegment seg = result.get(0);
1388
assertEquals("A", seg.getPath());
1389
assertEquals(1, seg.getStartRevision());
1390
assertEquals(1, seg.getEndRevision());
1393
public void testGetFileRevisions() throws Exception
1395
ISVNRemote session = getSession();
1397
List<ISVNRemote.FileRevision> result =
1398
session.getFileRevisions("iota", 0, 1, true);
1399
assertEquals(1, result.size());
1400
ISVNRemote.FileRevision rev = result.get(0);
1401
assertEquals("/iota", rev.getPath());
1402
assertFalse(rev.isResultOfMerge());
1403
assertTrue(rev.hasTextDelta());
1406
// This test is a result of a threading bug that was identified in
1407
// serf-1.3.2 and earlier. The net result was that opening two RA
1408
// sessions to an https:// URL in two parallel threads would cause
1409
// a crash in serf, due to the OpenSSL library not being
1410
// initialized in a single-threaded context.
1412
// The problem does not appear to exist with other RA methods, but
1413
// the test is here just in case someone is actually pedantic
1414
// enough to test JavaHL with an HTTPS setup.
1415
public void testParallelOpen() throws Exception
1417
final Runnable runnable = new Runnable() {
1420
ISVNRemote session = null;
1422
session = getSession();
1423
assertEquals(1, session.getLatestRevision());
1425
catch (ClientException ex) {
1426
throw new RuntimeException(ex);
1429
if (session != null)
1435
Thread thread1 = new Thread(runnable);
1436
Thread thread2 = new Thread(runnable);