package org.tmatesoft.svn.test; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import junit.framework.Assert; import org.junit.Assume; import org.junit.Ignore; import org.junit.Test; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.BasicAuthenticationManager; import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; 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.wc2.SvnCheckout; import org.tmatesoft.svn.core.wc2.SvnOperationFactory; import org.tmatesoft.svn.core.wc2.SvnSetLock; import org.tmatesoft.svn.core.wc2.SvnTarget; import org.tmatesoft.svn.core.wc2.SvnUnlock; public class DavLockTest { @Test public void testUnlockWithAnotherUserDoesntResultIntoException() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllApacheOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testUnlockWithAnotherUserDoesntResultIntoException", options); try { BasicAuthenticationManager authenticationManager1 = new BasicAuthenticationManager("user1", "password1"); BasicAuthenticationManager authenticationManager2 = new BasicAuthenticationManager("user2", "password2"); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user1", "password1"); loginToPassword.put("user2", "password2"); final SVNURL url = sandbox.createSvnRepositoryWithDavAccess(loginToPassword); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.setAuthenticationManager(authenticationManager1); commitBuilder.addFile("file"); commitBuilder.commit(); final File workingCopyDirectory = sandbox.createDirectory("wc"); //checkout with user1 svnOperationFactory.setAuthenticationManager(authenticationManager1); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final File file = new File(workingCopyDirectory, "file"); //lock with user1 final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setLockMessage("Locked"); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); //unlock with user2 svnOperationFactory.setAuthenticationManager(authenticationManager2); //create event handler that would check for failed unlock final LockEventHandler lockEventHandler = createUnlockEventHandler(); svnOperationFactory.setEventHandler(lockEventHandler); final SvnUnlock unlock = svnOperationFactory.createUnlock(); unlock.setSingleTarget(SvnTarget.fromFile(file)); unlock.run(); final List<SVNEvent> events = lockEventHandler.events; Assert.assertEquals(1, events.size()); SVNErrorMessage errorMessage = events.get(0).getErrorMessage(); final String path = (String) errorMessage.getRelatedObjects()[0]; Assert.assertEquals(SVNErrorCode.FS_LOCK_OWNER_MISMATCH, errorMessage.getErrorCode()); Assert.assertEquals("file", path); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testLockingNonExistingInHeadPathIsNotAllowed() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllApacheOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testLockingNonExistingInHeadPathIsNotAllowed", options); try { BasicAuthenticationManager authenticationManager1 = new BasicAuthenticationManager("user1", "password1"); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user1", "password1"); final SVNURL url = sandbox.createSvnRepositoryWithDavAccess(loginToPassword); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.setAuthenticationManager(authenticationManager1); commitBuilder1.addFile("file"); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.setAuthenticationManager(authenticationManager1); commitBuilder2.delete("file"); commitBuilder2.commit(); final File workingCopyDirectory = sandbox.createDirectory("wc"); //checkout with user1 svnOperationFactory.setAuthenticationManager(authenticationManager1); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setRevision(SVNRevision.create(1)); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final File file = new File(workingCopyDirectory, "file"); //create event handler that would check for failed unlock final LockEventHandler lockEventHandler = createUnlockEventHandler(); svnOperationFactory.setEventHandler(lockEventHandler); //lock with user1 final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setLockMessage("Locked"); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); final List<SVNEvent> events = lockEventHandler.events; Assert.assertEquals(1, events.size()); SVNErrorMessage errorMessage = events.get(0).getErrorMessage(); Assert.assertEquals(SVNErrorCode.FS_OUT_OF_DATE, errorMessage.getErrorCode()); final Integer httpCode = (Integer) errorMessage.getRelatedObjects()[0]; final String path = (String) errorMessage.getRelatedObjects()[1]; Assert.assertEquals(405, httpCode.intValue()); Assert.assertEquals("Method Not Allowed", path); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testFailingUnlockHookBlocksUnlocking() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllApacheOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testFailingUnlockHookBlocksUnlocking", options); try { BasicAuthenticationManager authenticationManager1 = new BasicAuthenticationManager("user1", "password1"); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user1", "password1"); final SVNURL url = sandbox.createSvnRepositoryWithDavAccess(loginToPassword); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.setAuthenticationManager(authenticationManager1); commitBuilder.addFile("file"); commitBuilder.commit(); sandbox.createFailingHook(url, "pre-unlock"); final File workingCopyDirectory = sandbox.createDirectory("wc"); //checkout with user1 svnOperationFactory.setAuthenticationManager(authenticationManager1); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final File file = new File(workingCopyDirectory, "file"); //lock with user1 final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setLockMessage("Locked"); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); //create event handler that would check for failed unlock final LockEventHandler lockEventHandler = createUnlockEventHandler(); svnOperationFactory.setEventHandler(lockEventHandler); final SvnUnlock unlock = svnOperationFactory.createUnlock(); unlock.setSingleTarget(SvnTarget.fromFile(file)); try { unlock.run(); Assert.fail("An exception should be thrown"); } catch (SVNException e) { //expected e.printStackTrace(); Assert.assertEquals(SVNErrorCode.RA_DAV_REQUEST_FAILED, e.getErrorMessage().getErrorCode()); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Ignore @Test public void testIncorrectLockHookBlocksLocking() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllApacheOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testIncorrectLockHookBlocksLocking", options); try { BasicAuthenticationManager authenticationManager1 = new BasicAuthenticationManager("user1", "password1"); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user1", "password1"); final SVNURL url = sandbox.createSvnRepositoryWithDavAccess(loginToPassword); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.setAuthenticationManager(authenticationManager1); commitBuilder.addFile("file"); commitBuilder.commit(); sandbox.createHook(url, "pre-lock", getIncorrectLockHookContents()); final File workingCopyDirectory = sandbox.createDirectory("wc"); //checkout with user1 svnOperationFactory.setAuthenticationManager(authenticationManager1); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final File file = new File(workingCopyDirectory, "file"); //create event handler that would check for failed unlock final LockEventHandler lockEventHandler = createUnlockEventHandler(); svnOperationFactory.setEventHandler(lockEventHandler); //lock with user1 final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setLockMessage("Locked"); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); //TODO: finish the test } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } private String getIncorrectLockHookContents() { final String token = "token"; if (SVNFileUtil.isWindows) { return "@echo off" + "\r\n" + "echo|set /p=" + token + "\r\n" + "exit 0" + "\r\n"; } else { return "#!/bin/sh" + "\n" + "echo -n " + token + "\n" + "exit 0" + "\n"; } } public String getTestName() { return "DavLockTest"; } private LockEventHandler createUnlockEventHandler() { return new LockEventHandler(); } private static class LockEventHandler implements ISVNEventHandler { private final List<SVNEvent> events; private LockEventHandler() { events = new ArrayList<SVNEvent>(); } public void handleEvent(SVNEvent event, double progress) throws SVNException { if (event.getAction() == SVNEventAction.LOCK_FAILED || event.getAction() == SVNEventAction.UNLOCK_FAILED) { events.add(event); } } public void checkCancelled() throws SVNCancelException { } } }