/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.xpn.xwiki.doc;
import java.util.Date;
import org.jmock.Mock;
import org.suigeneris.jrcs.rcs.Version;
import org.xwiki.model.reference.DocumentReference;
import com.xpn.xwiki.XWiki;
import com.xpn.xwiki.XWikiConfig;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.test.AbstractBridgedXWikiComponentTestCase;
import com.xpn.xwiki.user.api.XWikiRightService;
/**
* Unit tests for {@link XWikiDocumentArchive}.
*
* @version $Id: 7cb0ae11dff0005b2bc4bc63fdbb560b713544eb $
*/
public class XWikiDocumentArchiveTest extends AbstractBridgedXWikiComponentTestCase
{
private XWikiContext context;
private Mock mockXWiki;
@Override
protected void setUp() throws Exception
{
super.setUp();
this.mockXWiki = mock(XWiki.class);
this.mockXWiki.stubs().method("getEncoding").will(returnValue("iso-8859-1"));
this.mockXWiki.stubs().method("getConfig").will(returnValue(new XWikiConfig()));
this.context = new XWikiContext();
this.context.setWiki((XWiki) this.mockXWiki.proxy());
}
/**
* JRCS uses the user.name system property to set the author of a change. Verify that it
* works if the user name has a space in its name. This used to fail and this test is here to
* ensure it'll continue to work fine in the future...
*
* @todo simplify this test. Not sure how to do it. I guess we could create a real document.
*/
public void testUpdateArchiveWhenSpaceInUsername() throws Exception
{
String originalArchive = "head\t1.1;\n" +
"access;\n" +
"symbols;\n" +
"locks; strict;\n" +
"comment\t@# @;\n" +
"\n" +
"\n" +
"1.1\n" +
"date\t2007.02.14.14.01.57;\tauthor vmassol;\tstate Exp;\n" +
"branches;\n" +
"next\t;\n" +
"\n" +
"\n" +
"desc\n" +
"@@\n" +
"\n" +
"\n" +
"1.1\n" +
"log\n" +
"@KnowledgeBase.WebHome\n" +
"@\n" +
"text\n" +
"@<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" +
"\n" +
"<xwikidoc>\n" +
"<web>KnowledgeBase</web>\n" +
"<name>WebHome</name>\n" +
"<language></language>\n" +
"<defaultLanguage>en</defaultLanguage>\n" +
"<translation>0</translation>\n" +
"<parent>Main.Notes</parent>\n" +
"<creator>XWiki.Admin</creator>\n" +
"<author>XWiki.Admin</author>\n" +
"<customClass></customClass>\n" +
"<contentAuthor>XWiki.Admin</contentAuthor>\n" +
"<creationDate>1165874272000</creationDate>\n" +
"<date>1166177448000</date>\n" +
"<contentUpdateDate>1171458116000</contentUpdateDate>\n" +
"<version>1.1</version>\n" +
"<title></title>\n" +
"<template></template>\n" +
"<defaultTemplate></defaultTemplate>\n" +
"<validationScript></validationScript>\n" +
"<object>\n" +
"<class>\n" +
"<name>XWiki.TagClass</name>\n" +
"<customClass></customClass>\n" +
"<customMapping></customMapping>\n" +
"<defaultViewSheet></defaultViewSheet>\n" +
"<defaultEditSheet></defaultEditSheet>\n" +
"<defaultWeb></defaultWeb>\n" +
"<nameField></nameField>\n" +
"<validationScript></validationScript>\n" +
"<tags>\n" +
"<name>tags</name>\n" +
"<prettyName>Tags</prettyName>\n" +
"<unmodifiable>0</unmodifiable>\n" +
"<relationalStorage>1</relationalStorage>\n" +
"<displayType>checkbox</displayType>\n" +
"<multiSelect>1</multiSelect>\n" +
"<size>30</size>\n" +
"<separator> </separator>\n" +
"<separators> ,|</separators>\n" +
"<values></values>\n" +
"<number>1</number>\n" +
"<classType>com.xpn.xwiki.objects.classes.StaticListClass</classType>\n" +
"</tags>\n" +
"</class>\n" +
"<name>KnowledgeBase.WebHome</name>\n" +
"<number>0</number>\n" +
"<className>XWiki.TagClass</className>\n" +
"<property>\n" +
"<tags/>\n" +
"</property>\n" +
"</object>\n" +
"<content>1 Wiki Knowledge Base\n" +
"\n" +
"This is the Wiki Knowledge Base, where you can start writing about your favorite subjects.\n" +
"\n" +
"To create new pages, click edit button and write links using brackets around words.\n" +
"\n" +
"* [Example Link 1]\n" +
"* [Example Link 2]</content>\n" +
"</xwikidoc>\n" +
"@";
XWikiDocumentArchive archive = new XWikiDocumentArchive(123456789L);
archive.setArchive(originalArchive);
// Set a username with a space
System.setProperty("user.name", "Vincent Massol");
XWikiDocument doc = new XWikiDocument(new DocumentReference("Wiki", "KnowledgeBase", "WebHome"));
doc.setContent(doc.getContent() + "\nsomething added");
archive.updateArchive(doc, XWikiRightService.GUEST_USER_FULLNAME, new Date(), "some comment", null, context);
// Try to construct again the archive from the last modification. This will happen when
// XWiki loads a document from the database for example. We verify here that a username
// with a space works.
new XWikiDocumentArchive(123456789L).setArchive(archive.getArchive(context));
}
public void testUpdateLoad() throws XWikiException
{
XWikiDocument doc = new XWikiDocument(new DocumentReference("Test", "Test", "Test"));
doc.setContent("content 1.1");
XWikiDocumentArchive archive = new XWikiDocumentArchive(doc.getId());
assertEquals(0, archive.getNodes().size());
String author = "XWiki.some author";
archive.updateArchive(doc, author, new Date(), "initial, 1.1", null, context);
assertEquals(new Version(1,1), archive.getLatestVersion());
String archive11 = archive.getArchive(context);
assertEquals(1, archive.getNodes().size());
assertEquals(1, archive.getUpdatedNodeInfos().size());
assertEquals(1, archive.getUpdatedNodeContents().size());
XWikiDocumentArchive archive2 = new XWikiDocumentArchive(doc.getId());
archive2.setArchive(archive11);
assertEquals(new Version(1,1), archive2.getLatestVersion());
assertEquals(archive11, archive2.getArchive(context));
assertEquals(1, archive2.getNodes().size());
assertEquals(1, archive2.getUpdatedNodeInfos().size());
assertEquals(1, archive2.getUpdatedNodeContents().size());
doc.setContent("content\n1.2");
archive.updateArchive(doc, author, new Date(), "1.2", new Version(1,2), context);
assertEquals(new Version(1,2), archive.getLatestVersion());
String archive12 = archive.getArchive(context);
assertEquals(2, archive.getNodes().size());
assertEquals(2, archive.getUpdatedNodeInfos().size());
assertEquals(2, archive.getUpdatedNodeContents().size());
XWikiDocumentArchive archive3 = new XWikiDocumentArchive(doc.getId());
archive3.setArchive(archive12);
assertEquals(new Version(1,2), archive3.getLatestVersion());
assertEquals(2, archive3.getNodes().size());
assertEquals(2, archive3.getUpdatedNodeInfos().size());
assertEquals(2, archive3.getUpdatedNodeContents().size());
doc.setContent("major change\ncontent\n2.1");
archive.updateArchive(doc, author, new Date(), "2.1", new Version(1,1), context);
assertEquals(new Version(2,1), archive.getLatestVersion());
assertEquals(3, archive.getNodes().size());
assertEquals(3, archive.getUpdatedNodeInfos().size());
assertEquals(3, archive.getUpdatedNodeContents().size());
doc.setContent("major change\ncontent\n 3.3");
archive.updateArchive(doc, author, new Date(), "2.1", new Version(3,3), context);
assertEquals(new Version(3,3), archive.getLatestVersion());
}
public void testRemoveVersions() throws XWikiException
{
XWikiDocument doc = new XWikiDocument(new DocumentReference("Test", "Test", "Test"));
XWikiDocumentArchive archive = new XWikiDocumentArchive(doc.getId());
doc.setDocumentArchive(archive);
String author = "XWiki.some author";
addRevisionToHistory(archive, doc, "content 1.1", author, "initial 1.1");
XWikiDocument doc11 = doc.clone();
doc.setContent("content 2.1\nqwe @ ");
archive.updateArchive(doc, author, new Date(), "2.1", new Version(2,1), context);
doc.setContent("content 2.2\nqweq@ ");
archive.updateArchive(doc, author, new Date(), "2.2", new Version(2,2), context);
doc.setContent("content 2.3\nqweqe @@");
archive.updateArchive(doc, author, new Date(), "2.3", new Version(2,3), context);
assertEquals(new Version(2,3), archive.getLatestVersion());
archive.removeVersions(new Version(2,1), new Version(2,2), context);
assertEquals(2, archive.getNodes().size());
assertEquals(2, archive.getDeletedNodeInfo().size());
assertNull(archive.getNode(new Version(2,1)));
assertNull(archive.getNode(new Version(2,2)));
XWikiDocument actual = archive.loadDocument(new Version(1,1), context);
assertEquals(doc11.getContent(), actual.getContent());
assertEquals(doc11.getDate(), actual.getDate());
assertEquals(doc11.getAuthor(), actual.getAuthor());
assertEquals(doc11.getComment(), actual.getComment());
}
/**
* Verify issue "When loading a revision of a document the creation date is incorrectly set as the last
* modification date".
* @see <a href="https://jira.xwiki.org/browse/XWIKI-2029">XWIKI-2029</a>
*/
public void testVerifyCreationDateWhenLoadingDocumentFromArchive() throws Exception
{
XWikiDocument doc = new XWikiDocument(new DocumentReference("Test", "Test", "Test"));
XWikiDocumentArchive archive = new XWikiDocumentArchive(doc.getId());
doc.setDocumentArchive(archive);
String author = "XWiki.some author";
addRevisionToHistory(archive, doc, "content 1.1", author, "initial 1.1");
Date creationDate = doc.getCreationDate();
// Wait for 2 seconds and make a change. We'll then load the last revision and verify it has a correct
// creation date.
Thread.sleep(1000L);
doc.setContent("content 2.1\nqwe @ ");
archive.updateArchive(doc, author, new Date(), "2.1", new Version(2,1), context);
XWikiDocument latest = archive.loadDocument(new Version(2,1), context);
assertEquals(creationDate, latest.getCreationDate());
}
public void testVerifyDiffAndFullRevisionAlgorithm() throws Exception
{
XWikiDocument doc = new XWikiDocument(new DocumentReference("Test", "Test", "Test"));
XWikiDocumentArchive archive = new XWikiDocumentArchive(doc.getId());
doc.setDocumentArchive(archive);
String author = "XWiki.some author";
// The first revision is always a full revision (not a diff)
addRevisionToHistory(archive, doc, "content 1.1", author, "1.1");
assertFalse(archive.getNode(new Version(1, 1)).isDiff());
// When a new revision is added the new revision is always the full revision but the previous one is
// modified to be a diff.
addRevisionToHistory(archive, doc, "content 2.1", author, "2.1");
assertTrue(archive.getNode(new Version(1, 1)).isDiff());
assertFalse(archive.getNode(new Version(2, 1)).isDiff());
addRevisionToHistory(archive, doc, "content 3.1", author, "3.1");
assertTrue(archive.getNode(new Version(1, 1)).isDiff());
assertTrue(archive.getNode(new Version(2, 1)).isDiff());
assertFalse(archive.getNode(new Version(3, 1)).isDiff());
addRevisionToHistory(archive, doc, "content 4.1", author, "4.1");
assertTrue(archive.getNode(new Version(1, 1)).isDiff());
assertTrue(archive.getNode(new Version(2, 1)).isDiff());
assertTrue(archive.getNode(new Version(3, 1)).isDiff());
assertFalse(archive.getNode(new Version(4, 1)).isDiff());
// Every 5th revision we save the full content and not a diff
addRevisionToHistory(archive, doc, "content 5.1", author, "5.1");
assertTrue(archive.getNode(new Version(1, 1)).isDiff());
assertTrue(archive.getNode(new Version(2, 1)).isDiff());
assertTrue(archive.getNode(new Version(3, 1)).isDiff());
assertTrue(archive.getNode(new Version(4, 1)).isDiff());
assertFalse(archive.getNode(new Version(5, 1)).isDiff());
// Verify that the 5th revision is kept as a full content revision when the 6th is added
addRevisionToHistory(archive, doc, "content 6.1", author, "6.1");
assertTrue(archive.getNode(new Version(1, 1)).isDiff());
assertTrue(archive.getNode(new Version(2, 1)).isDiff());
assertTrue(archive.getNode(new Version(3, 1)).isDiff());
assertTrue(archive.getNode(new Version(4, 1)).isDiff());
assertFalse(archive.getNode(new Version(5, 1)).isDiff());
assertFalse(archive.getNode(new Version(6, 1)).isDiff());
}
private void addRevisionToHistory(XWikiDocumentArchive archive, XWikiDocument document, String content,
String author, String comment) throws XWikiException
{
document.setContent(content);
document.setAuthor(author);
document.setComment(comment);
document.setDate(new Date());
archive.updateArchive(document, document.getAuthor(), document.getDate(), document.getComment(), null, context);
}
}