001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.kernel.impl.services;
007
008import static org.junit.Assert.assertEquals;
009import static org.mockito.ArgumentMatchers.any;
010import static org.mockito.Mockito.times;
011import static org.mockito.Mockito.verify;
012import static org.mockito.Mockito.when;
013import static org.springframework.test.util.ReflectionTestUtils.setField;
014
015import java.util.List;
016import java.util.Optional;
017
018import javax.inject.Inject;
019
020import org.fcrepo.kernel.api.ContainmentIndex;
021import org.fcrepo.kernel.api.Transaction;
022import org.fcrepo.kernel.api.auth.ACLHandle;
023import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
024import org.fcrepo.kernel.api.identifiers.FedoraId;
025import org.fcrepo.kernel.api.models.Binary;
026import org.fcrepo.kernel.api.models.Container;
027import org.fcrepo.kernel.api.models.NonRdfSourceDescription;
028import org.fcrepo.kernel.api.models.ResourceFactory;
029import org.fcrepo.kernel.api.models.ResourceHeaders;
030import org.fcrepo.kernel.api.models.WebacAcl;
031import org.fcrepo.kernel.api.observer.EventAccumulator;
032import org.fcrepo.kernel.impl.TestTransactionHelper;
033import org.fcrepo.kernel.impl.operations.DeleteResourceOperationFactoryImpl;
034import org.fcrepo.kernel.impl.operations.PurgeResourceOperation;
035import org.fcrepo.persistence.api.PersistentStorageSession;
036import org.fcrepo.persistence.api.PersistentStorageSessionManager;
037
038import org.junit.Before;
039import org.junit.Test;
040import org.junit.runner.RunWith;
041import org.mockito.ArgumentCaptor;
042import org.mockito.Captor;
043import org.mockito.InjectMocks;
044import org.mockito.Mock;
045import org.mockito.MockitoAnnotations;
046import org.springframework.test.context.ContextConfiguration;
047import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
048
049import com.github.benmanes.caffeine.cache.Cache;
050
051/**
052 * PurgeResourceServiceTest
053 *
054 * Copy of DeleteResourceServiceTest
055 *
056 * @author dbernstein
057 * @author whikloj
058 */
059@RunWith(SpringJUnit4ClassRunner.class)
060@ContextConfiguration("/containmentIndexTest.xml")
061public class PurgeResourceServiceImplTest {
062
063    private static final String USER = "fedoraAdmin";
064
065    private Transaction tx;
066
067    @Mock
068    private EventAccumulator eventAccumulator;
069
070    @Mock
071    private PersistentStorageSession pSession;
072
073    @Inject
074    private ContainmentIndex containmentIndex;
075
076    @Mock
077    private PersistentStorageSessionManager psManager;
078
079    @Mock
080    private ResourceFactory resourceFactory;
081
082    @Mock
083    private Container container;
084
085    @Mock
086    private Container childContainer;
087
088    @Mock
089    private Binary binary;
090
091    @Mock
092    private WebacAcl acl;
093
094    @Mock
095    private NonRdfSourceDescription binaryDesc;
096
097    @Mock
098    private ResourceHeaders resourceHeaders;
099    @Mock
100    private ResourceHeaders childHeaders;
101    @Mock
102    private ResourceHeaders descHeaders;
103    @Mock
104    private ResourceHeaders aclHeaders;
105    @Mock
106    private Cache<String, Optional<ACLHandle>> authHandleCache;
107
108    @Captor
109    private ArgumentCaptor<PurgeResourceOperation> operationCaptor;
110
111    @InjectMocks
112    private PurgeResourceServiceImpl service;
113
114    private static final FedoraId RESOURCE_ID =  FedoraId.create("test-resource");
115    private static final FedoraId CHILD_RESOURCE_ID = RESOURCE_ID.resolve("test-resource-child");
116    private static final FedoraId RESOURCE_DESCRIPTION_ID = RESOURCE_ID.resolve("fcr:metadata");
117    private static final FedoraId RESOURCE_ACL_ID = RESOURCE_ID.resolve("fcr:acl");
118    private static final String TX_ID = "tx-1234";
119
120    @Before
121    public void setup() {
122        MockitoAnnotations.openMocks(this);
123        tx = TestTransactionHelper.mockTransaction(TX_ID, false);
124        when(psManager.getSession(any(Transaction.class))).thenReturn(pSession);
125        final DeleteResourceOperationFactoryImpl factoryImpl = new DeleteResourceOperationFactoryImpl();
126        setField(service, "deleteResourceFactory", factoryImpl);
127        setField(service, "containmentIndex", containmentIndex);
128        setField(service, "eventAccumulator", eventAccumulator);
129        when(container.getFedoraId()).thenReturn(RESOURCE_ID);
130
131        when(pSession.getHeaders(RESOURCE_ID, null)).thenReturn(resourceHeaders);
132        when(pSession.getHeaders(CHILD_RESOURCE_ID, null)).thenReturn(childHeaders);
133        when(pSession.getHeaders(RESOURCE_DESCRIPTION_ID, null)).thenReturn(descHeaders);
134        when(pSession.getHeaders(RESOURCE_ACL_ID, null)).thenReturn(aclHeaders);
135    }
136
137    @Test
138    public void testContainerPurge() throws Exception {
139        when(container.isAcl()).thenReturn(false);
140        when(container.getAcl()).thenReturn(null);
141
142        service.perform(tx, container, USER);
143        verifyResourceOperation(RESOURCE_ID, operationCaptor, pSession);
144    }
145
146    @Test
147    public void testRecursivePurge() throws Exception {
148        when(container.isAcl()).thenReturn(false);
149        when(container.getAcl()).thenReturn(null);
150        when(childContainer.getFedoraId()).thenReturn(CHILD_RESOURCE_ID);
151        when(childContainer.isAcl()).thenReturn(false);
152        when(childContainer.getAcl()).thenReturn(null);
153
154        when(resourceFactory.getResource(tx, CHILD_RESOURCE_ID)).thenReturn(childContainer);
155        containmentIndex.addContainedBy(tx, container.getFedoraId(), childContainer.getFedoraId());
156        containmentIndex.commitTransaction(tx);
157        containmentIndex.removeContainedBy(tx, container.getFedoraId(), childContainer.getFedoraId());
158
159        service.perform(tx, container, USER);
160
161        verify(pSession, times(2)).persist(operationCaptor.capture());
162        final List<PurgeResourceOperation> operations = operationCaptor.getAllValues();
163        assertEquals(2, operations.size());
164
165        assertEquals(CHILD_RESOURCE_ID, operations.get(0).getResourceId());
166        assertEquals(RESOURCE_ID, operations.get(1).getResourceId());
167
168        assertEquals(0, containmentIndex.getContains(tx, RESOURCE_ID).count());
169
170        verify(tx).lockResource(RESOURCE_ID);
171        verify(tx).lockResource(CHILD_RESOURCE_ID);
172    }
173
174    private void verifyResourceOperation(final FedoraId fedoraID,
175                                         final ArgumentCaptor<PurgeResourceOperation> captor,
176                                         final PersistentStorageSession pSession) throws Exception {
177        verify(pSession).persist(captor.capture());
178        final PurgeResourceOperation containerOperation = captor.getValue();
179        assertEquals(fedoraID, containerOperation.getResourceId());
180    }
181
182    @Test
183    public void testAclPurge() throws Exception {
184        when(acl.getFedoraId()).thenReturn(RESOURCE_ACL_ID);
185        when(acl.isAcl()).thenReturn(true);
186        service.perform(tx, acl, USER);
187        verifyResourceOperation(RESOURCE_ACL_ID, operationCaptor, pSession);
188    }
189
190    @Test(expected = RepositoryRuntimeException.class)
191    public void testBinaryDescriptionPurge() throws Exception {
192        when(binaryDesc.getFedoraId()).thenReturn(RESOURCE_DESCRIPTION_ID);
193        service.perform(tx, binaryDesc, USER);
194    }
195
196    @Test
197    public void testBinaryPurgeWithAcl() throws Exception {
198        when(binary.getFedoraId()).thenReturn(RESOURCE_ID);
199        when(binary.isAcl()).thenReturn(false);
200        when(binary.getDescription()).thenReturn(binaryDesc);
201        when(binaryDesc.getFedoraId()).thenReturn(RESOURCE_DESCRIPTION_ID);
202        when(binary.getAcl()).thenReturn(acl);
203        when(acl.getFedoraId()).thenReturn(RESOURCE_ACL_ID);
204
205        service.perform(tx, binary, USER);
206
207        verify(pSession, times(3)).persist(operationCaptor.capture());
208        final List<PurgeResourceOperation> operations = operationCaptor.getAllValues();
209        assertEquals(3, operations.size());
210
211        assertEquals(RESOURCE_DESCRIPTION_ID, operations.get(0).getResourceId());
212        assertEquals(RESOURCE_ACL_ID, operations.get(1).getResourceId());
213        assertEquals(RESOURCE_ID, operations.get(2).getResourceId());
214
215        verify(tx).lockResource(RESOURCE_ID);
216        verify(tx).lockResource(RESOURCE_DESCRIPTION_ID);
217        verify(tx).lockResource(RESOURCE_ACL_ID);
218    }
219
220}