001/* 002 * Licensed to DuraSpace under one or more contributor license agreements. 003 * See the NOTICE file distributed with this work for additional information 004 * regarding copyright ownership. 005 * 006 * DuraSpace licenses this file to you under the Apache License, 007 * Version 2.0 (the "License"); you may not use this file except in 008 * compliance with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.fcrepo.kernel.impl.services; 019 020import static org.apache.jena.rdf.model.ResourceFactory.createResource; 021import static org.fcrepo.kernel.api.RdfCollectors.toModel; 022import static org.fcrepo.kernel.api.RdfLexicon.CONTAINS; 023import static org.junit.Assert.assertEquals; 024import static org.junit.Assert.assertTrue; 025import static org.mockito.Mockito.when; 026import static org.springframework.test.util.ReflectionTestUtils.setField; 027 028import java.util.UUID; 029 030import javax.inject.Inject; 031 032import org.fcrepo.kernel.api.ContainmentIndex; 033import org.fcrepo.kernel.api.ReadOnlyTransaction; 034import org.fcrepo.kernel.api.Transaction; 035import org.fcrepo.kernel.api.identifiers.FedoraId; 036import org.fcrepo.kernel.api.models.FedoraResource; 037import org.fcrepo.kernel.impl.TestTransactionHelper; 038 039import org.apache.jena.rdf.model.Model; 040import org.apache.jena.rdf.model.ModelFactory; 041import org.apache.jena.rdf.model.Statement; 042import org.apache.jena.rdf.model.StmtIterator; 043import org.junit.After; 044import org.junit.Before; 045import org.junit.Test; 046import org.junit.runner.RunWith; 047import org.mockito.InjectMocks; 048import org.mockito.Mock; 049import org.mockito.MockitoAnnotations; 050import org.springframework.test.context.ContextConfiguration; 051import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 052 053/** 054 * @author whikloj 055 */ 056@RunWith(SpringJUnit4ClassRunner.class) 057@ContextConfiguration("/containmentIndexTest.xml") 058public class ContainmentTriplesServiceImplTest { 059 060 @Mock 061 private FedoraResource parentResource; 062 063 private Transaction transaction; 064 065 private Transaction transaction2; 066 067 @Inject 068 private ContainmentIndex containmentIndex; 069 070 @InjectMocks 071 private ContainmentTriplesServiceImpl containmentTriplesService; 072 073 private Transaction readOnlyTx; 074 075 @Before 076 public void setup() { 077 MockitoAnnotations.openMocks(this); 078 final FedoraId parentId = FedoraId.create(UUID.randomUUID().toString()); 079 final String txId = UUID.randomUUID().toString(); 080 transaction = TestTransactionHelper.mockTransaction(txId, false); 081 when(parentResource.getFedoraId()).thenReturn(parentId); 082 setField(containmentTriplesService, "containmentIndex", containmentIndex); 083 readOnlyTx = ReadOnlyTransaction.INSTANCE; 084 } 085 086 @After 087 public void cleanUp() { 088 containmentIndex.reset(); 089 } 090 091 @Test 092 public void testNoContains() { 093 assertEquals(0, containmentTriplesService.get(transaction, parentResource).count()); 094 } 095 096 @Test 097 public void testOneChild() { 098 final FedoraId child = FedoraId.create(UUID.randomUUID().toString()); 099 containmentIndex.addContainedBy(transaction, parentResource.getFedoraId(), child); 100 assertEquals(1, containmentTriplesService.get(transaction, parentResource).count()); 101 final Model expectedModel = ModelFactory.createDefaultModel(); 102 expectedModel.add(createResource(parentResource.getFedoraId().getFullId()), CONTAINS, 103 createResource(child.getFullId())); 104 final Model received = containmentTriplesService.get(transaction, parentResource).collect(toModel()); 105 matchModels(expectedModel, received); 106 } 107 108 @Test 109 public void testTwoChildren() { 110 final FedoraId child1 = FedoraId.create(UUID.randomUUID().toString()); 111 final FedoraId child2 = FedoraId.create(UUID.randomUUID().toString()); 112 containmentIndex.addContainedBy(transaction, parentResource.getFedoraId(), child1); 113 containmentIndex.addContainedBy(transaction, parentResource.getFedoraId(), child2); 114 assertEquals(2, containmentTriplesService.get(transaction, parentResource).count()); 115 final Model expectedModel = ModelFactory.createDefaultModel(); 116 expectedModel.add(createResource(parentResource.getFedoraId().getFullId()), CONTAINS, 117 createResource(child1.getFullId())); 118 expectedModel.add(createResource(parentResource.getFedoraId().getFullId()), CONTAINS, 119 createResource(child2.getFullId())); 120 final Model received = containmentTriplesService.get(transaction, parentResource).collect(toModel()); 121 matchModels(expectedModel, received); 122 } 123 124 @Test 125 public void testTenChildren() { 126 final Model expectedModel = ModelFactory.createDefaultModel(); 127 for (var foo = 0; foo < 10; foo += 1) { 128 final FedoraId child = FedoraId.create(UUID.randomUUID().toString()); 129 containmentIndex.addContainedBy(transaction, parentResource.getFedoraId(), child); 130 expectedModel.add(createResource(parentResource.getFedoraId().getFullId()), CONTAINS, 131 createResource(child.getFullId())); 132 } 133 assertEquals(10, containmentTriplesService.get(transaction, parentResource).count()); 134 final Model received = containmentTriplesService.get(transaction, parentResource).collect(toModel()); 135 matchModels(expectedModel, received); 136 } 137 138 @Test 139 public void testAddAndRemove() { 140 final FedoraId child = FedoraId.create(UUID.randomUUID().toString()); 141 final String otherTransactionId = UUID.randomUUID().toString(); 142 143 transaction2 = TestTransactionHelper.mockTransaction(otherTransactionId, false); 144 containmentIndex.addContainedBy(transaction, parentResource.getFedoraId(), child); 145 assertEquals(1, containmentTriplesService.get(transaction, parentResource).count()); 146 final Model expectedModel = ModelFactory.createDefaultModel(); 147 expectedModel.add(createResource(parentResource.getFedoraId().getFullId()), CONTAINS, 148 createResource(child.getFullId())); 149 final Model received = containmentTriplesService.get(transaction, parentResource).collect(toModel()); 150 matchModels(expectedModel, received); 151 // Commit and ensure we can see the child. 152 containmentIndex.commitTransaction(transaction); 153 final Model received2 = containmentTriplesService.get(readOnlyTx, parentResource).collect(toModel()); 154 matchModels(expectedModel, received2); 155 // Now remove the child in a transaction, but verify we can still see it outside the transaction. 156 containmentIndex.removeResource(transaction2, child); 157 final Model received3 = containmentTriplesService.get(readOnlyTx, parentResource).collect(toModel()); 158 matchModels(expectedModel, received3); 159 // Now commit the transaction and ensure it disappears. 160 containmentIndex.commitTransaction(transaction2); 161 assertEquals(0, containmentTriplesService.get(readOnlyTx, parentResource).count()); 162 } 163 164 /** 165 * Ensure the test model contains all the expected statements from the expected model. 166 * @param expected The expected model. 167 * @param test The model to be tested. 168 */ 169 private void matchModels(final Model expected, final Model test) { 170 for (final StmtIterator it = expected.listStatements(); it.hasNext(); ) { 171 final Statement t = it.next(); 172 assertTrue(test.contains(t)); 173 } 174 } 175}