package org.tmatesoft.svn.test; import java.util.HashSet; import java.util.Set; import junit.framework.Assert; import org.junit.Test; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNEvent; import org.tmatesoft.svn.core.wc.SVNEventAction; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNStatusType; import org.tmatesoft.svn.core.wc2.SvnCleanup; import org.tmatesoft.svn.core.wc2.SvnOperationFactory; import org.tmatesoft.svn.core.wc2.SvnStatus; import org.tmatesoft.svn.core.wc2.SvnTarget; import org.tmatesoft.svn.core.wc2.SvnUpdate; public class SvnInterruptionTest { @Test public void testUpdateInterruptedOnReceive() throws SVNException { Sandbox sandbox = Sandbox.createWithCleanup(getClass().getSimpleName(), TestOptions.getInstance()); final SVNURL url = sandbox.createSvnRepository(); CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.addFile("dir/file", "contents1".getBytes()); commitBuilder.addFile("dir/subdir/file", "contents2".getBytes()); commitBuilder.addDirectory("dir/subdir/inner"); SVNCommitInfo info = commitBuilder.commit(); final long firstRev = info.getNewRevision(); // two files changed, tree added commitBuilder = new CommitBuilder(url); commitBuilder.changeFile("dir/file", "changed".getBytes()); commitBuilder.addFile("dir/file2", "contents1".getBytes()); commitBuilder.addFile("dir/subdir/file2", "contents2".getBytes()); commitBuilder.changeFile("dir/subdir/file", "changed".getBytes()); commitBuilder.addFile("dir/subdir/inner/file3", "file3".getBytes()); info = commitBuilder.commit(); final long secondRev = info.getNewRevision(); final WorkingCopy wc = sandbox.checkoutNewWorkingCopy(url, firstRev); SvnOperationFactory of = new SvnOperationFactory(); // this interrupts update with non-empty wq leaving wc locked. of.setEventHandler(new ISVNEventHandler() { public void checkCancelled() throws SVNCancelException { } public void handleEvent(SVNEvent event, double progress) throws SVNException { if (event.getAction() == SVNEventAction.UPDATE_ADD) { if (wc.getFile("dir/subdir/inner/file3").equals(event.getFile())) { throw new NullPointerException("TEST EXCEPTION"); } } } }); SvnUpdate up = of.createUpdate(); up.setSingleTarget(SvnTarget.fromFile(wc.getWorkingCopyDirectory())); up.setRevision(SVNRevision.create(secondRev)); try { up.run(); Assert.fail(); } catch (Throwable npe) { assertStacktraceContainsMessage("TEST EXCEPTION", npe); } SvnStatus st = wc.getStatus(""); if (TestUtil.isNewWorkingCopyTest()) { Assert.assertTrue(st.isWcLocked()); } Assert.assertEquals(SVNStatusType.STATUS_INCOMPLETE, st.getNodeStatus()); SvnCleanup cup = of.createCleanup(); cup.setSingleTarget(SvnTarget.fromFile(wc.getFile(""))); cup.run(); st = wc.getStatus(""); Assert.assertFalse(st.isWcLocked()); Assert.assertEquals(SVNStatusType.STATUS_INCOMPLETE, st.getNodeStatus()); of.setEventHandler(null); up.run(); st = wc.getStatus(""); Assert.assertFalse(st.isWcLocked()); Assert.assertEquals(SVNStatusType.STATUS_NORMAL, st.getNodeStatus()); } private void assertStacktraceContainsMessage(String message, Throwable th) { final Set<Throwable> seen = new HashSet<Throwable>(); boolean found = false; while (th != null && !seen.contains(th)) { if (message.equals(th.getMessage())) { found = true; break; } seen.add(th); th = th.getCause(); } if (!found) { Assert.fail("Message \"" + message + "\" is not found in the stacktrace"); } } }