/*
* (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library 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.
*
* Contributors:
* Thierry Delprat
* Florent Guillaume
*/
package org.nuxeo.ecm.core.trash.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.security.Principal;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.nuxeo.common.utils.Path;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.DocumentRef;
import org.nuxeo.ecm.core.api.IdRef;
import org.nuxeo.ecm.core.api.VersioningOption;
import org.nuxeo.ecm.core.event.EventService;
import org.nuxeo.ecm.core.test.CoreFeature;
import org.nuxeo.ecm.core.test.annotations.Granularity;
import org.nuxeo.ecm.core.test.annotations.RepositoryConfig;
import org.nuxeo.ecm.core.trash.TrashInfo;
import org.nuxeo.ecm.core.trash.TrashService;
import org.nuxeo.runtime.test.runner.Features;
import org.nuxeo.runtime.test.runner.FeaturesRunner;
import com.google.inject.Inject;
@RunWith(FeaturesRunner.class)
@Features(CoreFeature.class)
@RepositoryConfig(cleanup = Granularity.METHOD)
public class TestTrashService {
@Inject
protected CoreSession session;
@Inject
protected TrashService trashService;
@Inject
protected EventService eventService;
protected DocumentModel fold;
protected DocumentModel doc1;
protected DocumentModel doc2;
protected DocumentModel doc3;
protected Principal principal;
@Before
public void setUp() throws Exception {
principal = session.getPrincipal();
}
public void createDocuments() throws Exception {
fold = session.createDocumentModel("/", "fold", "Folder");
fold = session.createDocument(fold);
doc1 = session.createDocumentModel("/fold", "doc1", "Note");
doc1 = session.createDocument(doc1);
doc2 = session.createDocumentModel("/fold", "doc2", "Note");
doc2 = session.createDocument(doc2);
doc3 = session.createDocumentModel("/", "doc3", "Note");
doc3 = session.createDocument(doc3);
session.save();
}
@Test
public void testBase() throws Exception {
createDocuments();
assertTrue(trashService.folderAllowsDelete(fold));
assertTrue(trashService.checkDeletePermOnParents(Arrays.asList(doc1,
doc2)));
assertTrue(trashService.canDelete(Collections.singletonList(fold),
principal, false));
assertTrue(trashService.canDelete(Collections.singletonList(doc1),
principal, false));
assertTrue(trashService.canDelete(Collections.singletonList(doc2),
principal, false));
assertFalse(trashService.canPurgeOrUndelete(
Collections.singletonList(fold), principal));
assertFalse(trashService.canPurgeOrUndelete(
Collections.singletonList(doc1), principal));
assertFalse(trashService.canPurgeOrUndelete(
Collections.singletonList(doc2), principal));
TrashInfo info = trashService.getTrashInfo(Arrays.asList(fold, doc1,
doc3), principal, false, false);
assertEquals(3, info.docs.size());
assertEquals(2, info.rootRefs.size());
assertEquals(new HashSet<Path>(Arrays.asList(new Path("/fold"),
new Path("/doc3"))), info.rootPaths);
DocumentModel above = trashService.getAboveDocument(doc1,
new HashSet<Path>(Arrays.asList(new Path("/fold/doc1"))));
assertEquals(above.getPathAsString(), fold.getId(), above.getId());
}
@Test
public void testTrashPurgeUndelete() throws Exception {
createDocuments();
// file with name from collision
DocumentModel doc4 = session.createDocumentModel("/", "doc4.1400676936345", "Note");
doc4 = session.createDocument(doc4);
String doc4origname = doc4.getName();
trashService.trashDocuments(Arrays.asList(fold, doc1, doc3, doc4));
eventService.waitForAsyncCompletion();
session.save(); // fetch invalidations from async sessions
// refetch as lifecycle state is cached
fold = session.getDocument(new IdRef(fold.getId()));
doc1 = session.getDocument(new IdRef(doc1.getId()));
doc2 = session.getDocument(new IdRef(doc2.getId()));
doc3 = session.getDocument(new IdRef(doc3.getId()));
doc4 = session.getDocument(new IdRef(doc4.getId()));
assertEquals("deleted", fold.getCurrentLifeCycleState());
assertEquals("deleted", doc1.getCurrentLifeCycleState());
assertEquals("deleted", doc3.getCurrentLifeCycleState());
assertEquals("deleted", doc4.getCurrentLifeCycleState());
// doc2 done by async BulkLifeCycleChangeListener
assertEquals("deleted", doc2.getCurrentLifeCycleState());
// check names changed
assertFalse("fold".equals(fold.getName()));
assertFalse("doc1".equals(doc1.getName()));
String doc3delname = doc3.getName();
assertFalse("doc3".equals(doc3.getName()));
assertFalse(doc4origname.equals(doc4.getName()));
assertFalse("doc4".equals(doc4.getName()));
// when recursing, don't change name
assertEquals("doc2", doc2.getName());
assertTrue(trashService.canPurgeOrUndelete(
Arrays.asList(fold, doc1, doc2, doc3, doc4), principal));
// purge doc1
trashService.purgeDocuments(session,
Collections.singletonList(doc1.getRef()));
assertFalse(session.exists(doc1.getRef()));
// undelete doc2 and doc4
trashService.undeleteDocuments(Arrays.asList(doc2, doc4));
fold = session.getDocument(new IdRef(fold.getId()));
doc2 = session.getDocument(new IdRef(doc2.getId()));
doc4 = session.getDocument(new IdRef(doc4.getId()));
assertEquals("project", doc2.getCurrentLifeCycleState());
assertEquals("project", doc4.getCurrentLifeCycleState());
// fold also undeleted
assertEquals("project", fold.getCurrentLifeCycleState());
// check name restored
assertEquals("fold", fold.getName());
// name still unchanged
assertEquals("doc2", doc2.getName());
// doc4 was restored with a pristine name
assertEquals("doc4", doc4.getName());
// create a new file with same name as old doc3
DocumentModel doc3bis = session.createDocumentModel("/", "doc3", "Note");
doc3bis = session.createDocument(doc3bis);
assertEquals("doc3", doc3bis.getName());
// undelete doc3
trashService.undeleteDocuments(Collections.singletonList(doc3));
doc3 = session.getDocument(new IdRef(doc3.getId()));
assertEquals("project", doc3.getCurrentLifeCycleState());
// check it was renamed again during undelete
assertFalse("doc3".equals(doc3.getName()));
assertFalse(doc3delname.equals(doc3.getName()));
}
@Test
public void testUndeleteChildren() throws Exception {
createDocuments();
trashService.trashDocuments(Collections.singletonList(fold));
eventService.waitForAsyncCompletion();
session.save(); // fetch invalidations from async sessions
// refetch as lifecycle state is cached
fold = session.getDocument(new IdRef(fold.getId()));
doc1 = session.getDocument(new IdRef(doc1.getId()));
doc2 = session.getDocument(new IdRef(doc2.getId()));
assertEquals("deleted", fold.getCurrentLifeCycleState());
// doc1 & doc2 done by async BulkLifeCycleChangeListener
assertEquals("deleted", doc1.getCurrentLifeCycleState());
assertEquals("deleted", doc2.getCurrentLifeCycleState());
// undelete fold
trashService.undeleteDocuments(Collections.singletonList(fold));
eventService.waitForAsyncCompletion();
session.save(); // fetch invalidations from async sessions
fold = session.getDocument(new IdRef(fold.getId()));
doc1 = session.getDocument(new IdRef(doc1.getId()));
doc2 = session.getDocument(new IdRef(doc2.getId()));
assertEquals("project", fold.getCurrentLifeCycleState());
// children done by async BulkLifeCycleChangeListener
assertEquals("project", doc1.getCurrentLifeCycleState());
assertEquals("project", doc2.getCurrentLifeCycleState());
}
@Test
public void testTrashFolderContainingProxy() throws Exception {
createDocuments();
DocumentRef versionRef = session.checkIn(doc3.getRef(),
VersioningOption.MAJOR, null);
DocumentModel version = session.getDocument(versionRef);
DocumentModel proxy = session.createProxy(versionRef, fold.getRef());
session.save();
assertEquals("project", fold.getCurrentLifeCycleState());
assertEquals("project", proxy.getCurrentLifeCycleState());
assertEquals("project", version.getCurrentLifeCycleState());
// now delete the folder
trashService.trashDocuments(Collections.singletonList(fold));
eventService.waitForAsyncCompletion();
session.save(); // process async invalidations
fold.refresh();
version.refresh();
assertEquals("deleted", fold.getCurrentLifeCycleState());
assertEquals("project", version.getCurrentLifeCycleState());
assertFalse(session.exists(proxy.getRef()));
}
@Test
public void testProxy() throws Exception {
createDocuments();
DocumentRef verRef = doc3.checkIn(null, null);
DocumentModel proxy = session.createProxy(verRef, fold.getRef());
session.save();
assertTrue(trashService.canDelete(Collections.singletonList(proxy),
principal, false));
assertFalse(trashService.canDelete(Collections.singletonList(proxy),
principal, true));
assertFalse(trashService.canPurgeOrUndelete(Collections.singletonList(proxy),
principal));
}
}