Java tutorial
/** * Copyright 2008 Matthew Hillsdon * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.hillsdon.reviki.vc.impl; import static java.util.Arrays.asList; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.getCurrentArguments; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Collection; import java.util.Date; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import junit.framework.TestCase; import net.hillsdon.reviki.vc.ChangeInfo; import net.hillsdon.reviki.vc.ChangeType; import net.hillsdon.reviki.vc.PageInfo; import net.hillsdon.reviki.vc.VersionedPageInfo; import net.hillsdon.reviki.vc.PageReference; import net.hillsdon.reviki.vc.PageStoreException; import net.hillsdon.reviki.vc.RenameException; import net.hillsdon.reviki.vc.StoreKind; import net.hillsdon.reviki.vc.impl.SVNPageStore.SVNRenameAction; import org.apache.commons.collections.MapUtils; import org.easymock.EasyMock; import org.easymock.IAnswer; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.io.ISVNEditor; /** * Unit tests {@link SVNPageStore} by exploring its interactions with * {@link BasicSVNOperations}. Mostly useful for edge cases etc. as * this is done via mocks, the more substantial testing of this code * is done via the webtests for now. * * @author mth */ public class TestSVNPageStore extends TestCase { private SVNPageStore _store; private DeletedRevisionTracker _tracker; private BasicSVNOperations _operations; private ISVNEditor _commitEditor; protected void setUp() { _commitEditor = createMock(ISVNEditor.class); _tracker = createMock(DeletedRevisionTracker.class); _operations = createMock(BasicSVNOperations.class); _store = new SVNPageStore("wiki", _tracker, _operations, createMock(AutoPropertiesApplier.class), new FixedMimeIdentifier()); } public void testGetLatestRevisionJustDelegates() throws Exception { expect(_operations.getLatestRevision()).andReturn(4L); replay(); assertEquals(4, _store.getLatestRevision()); verify(); } public void testDeleteAttachment() throws Exception { final String pageName = "ThePage"; final PageReference pageRef = new PageReferenceImpl(pageName); final String attachmentName = "attachment.txt"; _operations.execute((SVNEditAction) anyObject()); expectLastCall().andAnswer(new IAnswer<Object>() { public Object answer() throws Throwable { SVNEditAction action = (SVNEditAction) getCurrentArguments()[0]; action.driveCommitEditor(_commitEditor, _operations); return 2L; } }); _operations.delete((ISVNEditor) anyObject(), eq("ThePage-attachments/attachment.txt"), eq(-1L)); replay(); assertEquals(2, _store.deleteAttachment(pageRef, attachmentName, -1, "A delete")); verify(); } public void testHistoryLogsToHeadIfNoDeletedRevision() throws Exception { final String path = "ThePage"; final ChangeInfo previousEdit = new ChangeInfo(path, path, "mth", new Date(), 3, "An edit", StoreKind.PAGE, ChangeType.MODIFIED, null, -1); expect(_tracker.getChangeThatDeleted(path)).andReturn(null); expect(_operations.log(path, -1, LogEntryFilter.PATH_ONLY, false, 0, -1)).andReturn(asList(previousEdit)); replay(); assertEquals(asList(previousEdit), _store.history(new PageReferenceImpl(path))); verify(); } public void testHistoryLogsUptoDeletedRevisionAndIncludesIt() throws Exception { final String path = "ThePage"; final ChangeInfo previousEdit = new ChangeInfo(path, path, "mth", new Date(), 3, "An edit", StoreKind.PAGE, ChangeType.MODIFIED, null, -1); final ChangeInfo deleteChange = new ChangeInfo(path, path, "mth", new Date(), 7, "Deleted", StoreKind.PAGE, ChangeType.DELETED, null, -1); expect(_tracker.getChangeThatDeleted(path)).andReturn(deleteChange); expect(_operations.log(path, -1, LogEntryFilter.PATH_ONLY, false, 0, deleteChange.getRevision() - 1)) .andReturn(asList(previousEdit)); replay(); List<ChangeInfo> history = _store.history(new PageReferenceImpl(path)); assertEquals(asList(deleteChange, previousEdit), history); verify(); } public void testHistoryStepsBackOverCopies() throws Exception { final String originalName = "TheOriginalPage"; final String copyName = "TheCopiedPage"; final ChangeInfo create = new ChangeInfo(originalName, originalName, "mth", new Date(), 1, "Initial create", StoreKind.PAGE, ChangeType.ADDED, null, -1); final ChangeInfo copyRemove = new ChangeInfo(copyName, copyName, "mth", new Date(), 2, "Copy delete", StoreKind.PAGE, ChangeType.DELETED, null, -1); final ChangeInfo copyAdd = new ChangeInfo(copyName, copyName, "mth", new Date(), 2, "Copy add", StoreKind.PAGE, ChangeType.ADDED, originalName, 1); final ChangeInfo edit = new ChangeInfo(copyName, copyName, "mth", new Date(), 3, "Edit", StoreKind.PAGE, ChangeType.MODIFIED, null, -1); expect(_tracker.getChangeThatDeleted(copyName)).andReturn(null); expect(_operations.log(copyName, -1, LogEntryFilter.PATH_ONLY, false, 0, -1)) .andReturn(asList(edit, copyAdd)); expect(_operations.log(originalName, -1, LogEntryFilter.PATH_ONLY, false, 0, 1)) .andReturn(asList(copyRemove, create)); replay(); assertEquals(asList(edit, copyAdd, copyRemove, create), _store.history(new PageReferenceImpl(copyName))); verify(); } public void testRename() throws Exception { String originalName = "TheOriginalPage"; String newName = "TheRenamedPage"; final PageReference originalPage = new PageReferenceImpl(originalName); final PageReference newPage = new PageReferenceImpl(newName); _operations.moveFile(null, originalName, 1, newName); replay(); SVNRenameAction action = new SVNPageStore.SVNRenameAction("", newPage, false, originalPage, 1); action.driveCommitEditor(null, _operations); verify(); } public void testRenameWithAttachments() throws Exception { String originalName = "TheOriginalPage"; String newName = "TheRenamedPage"; final PageReference originalPage = new PageReferenceImpl(originalName); final PageReference newPage = new PageReferenceImpl(newName); _operations.moveFile(null, originalName, 1, newName); _operations.moveDir(null, originalName + "-attachments", 1, newName + "-attachments"); replay(); SVNRenameAction action = new SVNPageStore.SVNRenameAction("", newPage, true, originalPage, 1); action.driveCommitEditor(null, _operations); verify(); } public void testRenameLocked() throws Exception { String originalName = "TheOriginalPage"; String newName = "TheRenamedPage"; final PageReference originalPage = new PageReferenceImpl(originalName); final PageReference newPage = new PageReferenceImpl(newName); _operations.moveFile(null, originalName, 1, newName); expectLastCall().andThrow(new SVNException(SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED))); replay(); SVNRenameAction action = new SVNPageStore.SVNRenameAction("", newPage, false, originalPage, 1); try { action.driveCommitEditor(null, _operations); fail("Expected RenameException"); } catch (RenameException ex) { // OK } verify(); } public void testCreateLocksMapThrowsException() throws Exception { String name = "ThePage"; String lockToken = ""; try { _store.createLocksMap(name, lockToken); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException ex) { // OK } } @SuppressWarnings("unchecked") public void testGetPage() throws PageStoreException { final String content = "Content"; PageReferenceImpl ref = new PageReferenceImpl("Page"); expect(_operations.checkPath(ref.getPath(), -1L)).andReturn(SVNNodeKind.FILE); _operations.getFile(eq(ref.getPath()), eq(-1L), (Map<String, String>) anyObject(), (OutputStream) anyObject()); expectLastCall().andAnswer(new IAnswer<Object>() { public Object answer() throws Throwable { OutputStream out = (OutputStream) getCurrentArguments()[3]; out.write(content.getBytes()); return null; } }); expect(_operations.getLock(ref.getPath())).andReturn(null); replay(); VersionedPageInfo returnValue = _store.get(ref, -1); assertEquals(ref.getName(), returnValue.getName()); assertEquals(content, returnValue.getContent()); assertEquals(MapUtils.EMPTY_MAP, returnValue.getAttributes()); verify(); } public void testGetPages() throws PageStoreException, IOException { final Map<String, ByteArrayOutputStream> pathsOutput = new LinkedHashMap<String, ByteArrayOutputStream>(); List<String> paths = new LinkedList<String>(); List<PageReference> pages = new LinkedList<PageReference>(); int NUM = 10; for (int i = 0; i < NUM; i++) { ByteArrayOutputStream content = new ByteArrayOutputStream(); String pathName = String.format("Path%d", i); content.write(String.format("Content%d", i).getBytes()); pathsOutput.put(pathName, content); paths.add(pathName); pages.add(new PageReferenceImpl(pathName)); } _operations.getFiles(eq(-1L), (Map<String, Map<String, String>>) anyObject(), (Map<String, OutputStream>) anyObject()); expectLastCall().andAnswer(new IAnswer<Object>() { public Object answer() throws Throwable { Map<String, OutputStream> outputStreams = (Map<String, OutputStream>) getCurrentArguments()[2]; for (Map.Entry<String, OutputStream> e : outputStreams.entrySet()) { e.getValue().write(pathsOutput.get(e.getKey()).toByteArray()); } return null; } }); replay(); Collection<PageInfo> returnValue = _store.getPages(pages, -1); int j = 0; for (PageInfo p : returnValue) { assertEquals(p.getPath(), String.format("Path%d", j)); assertEquals(p.getContent(), String.format("Content%d", j)); j++; } assertEquals(j, NUM); } @SuppressWarnings("unchecked") public void testGetPageWithAttributes() throws PageStoreException { final String content = "Content"; PageReferenceImpl ref = new PageReferenceImpl("Page"); expect(_operations.checkPath(ref.getPath(), -1L)).andReturn(SVNNodeKind.FILE); _operations.getFile(eq(ref.getPath()), eq(-1L), (Map<String, String>) anyObject(), (OutputStream) anyObject()); expectLastCall().andAnswer(new IAnswer<Object>() { public Object answer() throws Throwable { Map<String, String> properties = (Map<String, String>) getCurrentArguments()[2]; properties.put("reviki:someKey", "someValue1"); properties.put("svn:someKey", "someValue2"); properties.put("someOtherKey", "someValue3"); OutputStream out = (OutputStream) getCurrentArguments()[3]; out.write(content.getBytes()); return null; } }); expect(_operations.getLock(ref.getPath())).andReturn(null); replay(); VersionedPageInfo pageInfo = _store.get(ref, -1); assertEquals(ref.getName(), pageInfo.getName()); assertEquals(content, pageInfo.getContent()); LinkedHashMap<String, String> expectedProperties = new LinkedHashMap<String, String>(); expectedProperties.put("someKey", "someValue1"); assertEquals(expectedProperties, pageInfo.getAttributes()); verify(); } private void verify() { EasyMock.verify(_tracker, _operations); } private void replay() { EasyMock.replay(_tracker, _operations); } }