ACS-1604 : Update & tests for AggregatingContentStore (#486)

This commit is contained in:
Denis Ungureanu
2021-05-25 10:01:50 +03:00
committed by Andrea Ligios
parent 0b840643f9
commit 57dbd4d12f
2 changed files with 254 additions and 105 deletions

View File

@@ -27,6 +27,7 @@ package org.alfresco.repo.content.replication;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
@@ -65,9 +66,10 @@ import org.apache.commons.logging.LogFactory;
* @see CachingContentStore * @see CachingContentStore
*/ */
public class AggregatingContentStore extends AbstractContentStore public class AggregatingContentStore extends AbstractContentStore
{ {
private static Log logger = LogFactory.getLog(AggregatingContentStore.class); private static final Log logger = LogFactory.getLog(AggregatingContentStore.class);
private static final String REPLICATING_CONTENT_STORE_NOT_INITIALISED = "ReplicatingContentStore not initialised";
private ContentStore primaryStore; private ContentStore primaryStore;
private List<ContentStore> secondaryStores; private List<ContentStore> secondaryStores;
@@ -135,7 +137,7 @@ public class AggregatingContentStore extends AbstractContentStore
{ {
if (primaryStore == null) if (primaryStore == null)
{ {
throw new AlfrescoRuntimeException("ReplicatingContentStore not initialised"); throw new AlfrescoRuntimeException(REPLICATING_CONTENT_STORE_NOT_INITIALISED);
} }
// get a read lock so that we are sure that no replication is underway // get a read lock so that we are sure that no replication is underway
@@ -170,11 +172,12 @@ public class AggregatingContentStore extends AbstractContentStore
} }
} }
@Override
public boolean exists(String contentUrl) public boolean exists(String contentUrl)
{ {
if (primaryStore == null) if (primaryStore == null)
{ {
throw new AlfrescoRuntimeException("ReplicatingContentStore not initialised"); throw new AlfrescoRuntimeException(REPLICATING_CONTENT_STORE_NOT_INITIALISED);
} }
// get a read lock so that we are sure that no replication is underway // get a read lock so that we are sure that no replication is underway
@@ -240,6 +243,7 @@ public class AggregatingContentStore extends AbstractContentStore
} }
} }
@Override
public ContentWriter getWriter(ContentContext ctx) public ContentWriter getWriter(ContentContext ctx)
{ {
// get the writer // get the writer
@@ -254,6 +258,7 @@ public class AggregatingContentStore extends AbstractContentStore
* *
* @return Returns the value returned by the delete on the primary store. * @return Returns the value returned by the delete on the primary store.
*/ */
@Override
public boolean delete(String contentUrl) throws ContentIOException public boolean delete(String contentUrl) throws ContentIOException
{ {
// delete on the primary store // delete on the primary store
@@ -269,6 +274,7 @@ public class AggregatingContentStore extends AbstractContentStore
/** /**
* @return Returns <tt>true</tt> if at least one store supports direct access * @return Returns <tt>true</tt> if at least one store supports direct access
*/ */
@Override
public boolean isDirectAccessSupported() public boolean isDirectAccessSupported()
{ {
// Check the primary store // Check the primary store
@@ -293,11 +299,12 @@ public class AggregatingContentStore extends AbstractContentStore
return isDirectAccessSupported; return isDirectAccessSupported;
} }
@Override
public DirectAccessUrl getDirectAccessUrl(String contentUrl, Date expiresAt) public DirectAccessUrl getDirectAccessUrl(String contentUrl, Date expiresAt)
{ {
if (primaryStore == null) if (primaryStore == null)
{ {
throw new AlfrescoRuntimeException("ReplicatingContentStore not initialised"); throw new AlfrescoRuntimeException(REPLICATING_CONTENT_STORE_NOT_INITIALISED);
} }
// get a read lock so that we are sure that no replication is underway // get a read lock so that we are sure that no replication is underway
@@ -380,25 +387,9 @@ public class AggregatingContentStore extends AbstractContentStore
@Override @Override
public boolean isStorageClassesSupported(Set<String> storageClasses) public boolean isStorageClassesSupported(Set<String> storageClasses)
{ {
// Check the primary store // We only need to provide info about the primary store,
boolean isStorageClassesSupported = primaryStore.isStorageClassesSupported(storageClasses); // because the aggregating CS only allows to be written in the primary
return primaryStore.isStorageClassesSupported(storageClasses);
if (!isStorageClassesSupported)
{
// Storage class is not supported by the primary store so we have to check the
// other stores
for (ContentStore store : secondaryStores)
{
isStorageClassesSupported = store.isDirectAccessSupported();
if (isStorageClassesSupported)
{
break;
}
}
}
return isStorageClassesSupported;
} }
@Override @Override
@@ -408,4 +399,91 @@ public class AggregatingContentStore extends AbstractContentStore
// because the aggregating CS only allows to be written in the primary // because the aggregating CS only allows to be written in the primary
return primaryStore.getSupportedStorageClasses(); return primaryStore.getSupportedStorageClasses();
} }
@Override
public void updateStorageClasses(String contentUrl, Set<String> storageClasses, Map<String, Object> parameters)
{
primaryStore.updateStorageClasses(contentUrl, storageClasses, parameters);
}
@Override
public Set<String> findStorageClasses(String contentUrl)
{
if (primaryStore == null)
{
throw new AlfrescoRuntimeException(REPLICATING_CONTENT_STORE_NOT_INITIALISED);
}
// get a read lock so that we are sure that no replication is underway
readLock.lock();
try
{
// Keep track of the unsupported state of the content URL - it might be a rubbish URL
boolean contentUrlSupported = true;
Set<String> storageClasses = null;
// Check the primary store
try
{
storageClasses = primaryStore.findStorageClasses(contentUrl);
}
catch (UnsupportedContentUrlException e)
{
// The store can't handle the content URL
contentUrlSupported = false;
}
if (storageClasses != null)
{
return storageClasses;
}
// the content is not in the primary store so we have to go looking for it
for (ContentStore store : secondaryStores)
{
try
{
storageClasses = store.findStorageClasses(contentUrl);
}
catch (UnsupportedContentUrlException e)
{
// The store can't handle the content URL
contentUrlSupported = false;
}
if (storageClasses != null)
{
break;
}
}
if (storageClasses == null && !contentUrlSupported)
{
// The content URL was not supported
throw new UnsupportedContentUrlException(this, contentUrl);
}
return storageClasses;
}
finally
{
readLock.unlock();
}
}
@Override
public Map<Set<String>, Set<Set<String>>> getStorageClassesTransitions()
{
// We only need to provide info about the primary store,
// because the aggregating CS only allows to be written in the primary
return primaryStore.getStorageClassesTransitions();
}
@Override
public Map<Set<String>, Set<Set<String>>> findStorageClassesTransitions(String contentUrl)
{
// We only need to provide info about the primary store,
// because the aggregating CS only allows to be written in the primary
return primaryStore.findStorageClassesTransitions(contentUrl);
}
} }

View File

@@ -25,6 +25,8 @@
*/ */
package org.alfresco.repo.content.replication; package org.alfresco.repo.content.replication;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
@@ -32,15 +34,15 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -57,12 +59,11 @@ import org.alfresco.util.GUID;
import org.alfresco.util.TempFileProvider; import org.alfresco.util.TempFileProvider;
import org.alfresco.util.testing.category.NeverRunsTests; import org.alfresco.util.testing.category.NeverRunsTests;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.experimental.categories.Category; import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.junit.MockitoRule;
/** /**
* Tests read and write functionality for the aggregating store. * Tests read and write functionality for the aggregating store.
@@ -74,6 +75,7 @@ import org.mockito.junit.MockitoRule;
* @author Mark Rogers * @author Mark Rogers
*/ */
@Category({OwnJVMTestsCategory.class, NeverRunsTests.class}) @Category({OwnJVMTestsCategory.class, NeverRunsTests.class})
@RunWith(MockitoJUnitRunner.class)
public class AggregatingContentStoreTest extends AbstractWritableContentStoreTest public class AggregatingContentStoreTest extends AbstractWritableContentStoreTest
{ {
private static final String SOME_CONTENT = "The No. 1 Ladies' Detective Agency"; private static final String SOME_CONTENT = "The No. 1 Ladies' Detective Agency";
@@ -86,12 +88,9 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
ContentStore primaryStoreMock; ContentStore primaryStoreMock;
@Mock @Mock
ContentStore secondaryStoreMock; ContentStore secondaryStoreMock;
@Mock
AggregatingContentStore aggregatingContentStoreMock; AggregatingContentStore aggregatingContentStoreMock;
@Rule
public MockitoRule rule = MockitoJUnit.rule();
@Before @Before
public void before() throws Exception public void before() throws Exception
{ {
@@ -107,10 +106,15 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
FileContentStore store = new FileContentStore(ctx, storeDir); FileContentStore store = new FileContentStore(ctx, storeDir);
secondaryStores.add(store); secondaryStores.add(store);
} }
// Create the aggregating store // Create the aggregating store for Spring tests
aggregatingStore = new AggregatingContentStore(); aggregatingStore = new AggregatingContentStore();
aggregatingStore.setPrimaryStore(primaryStore); aggregatingStore.setPrimaryStore(primaryStore);
aggregatingStore.setSecondaryStores(secondaryStores); aggregatingStore.setSecondaryStores(secondaryStores);
// Create a mocked aggregating store
aggregatingContentStoreMock = new AggregatingContentStore();
aggregatingContentStoreMock.setPrimaryStore(primaryStoreMock);
aggregatingContentStoreMock.setSecondaryStores(List.of(secondaryStoreMock));
} }
@Override @Override
@@ -145,6 +149,7 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
return writer.getContentUrl(); return writer.getContentUrl();
} }
@Test
public void testAddContent() throws Exception public void testAddContent() throws Exception
{ {
ContentWriter writer = getWriter(); ContentWriter writer = getWriter();
@@ -166,6 +171,7 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
assertEquals("Reader state differs from expected: " + reader, mustExist, reader.exists()); assertEquals("Reader state differs from expected: " + reader, mustExist, reader.exists());
} }
@Test
public void testDelete() throws Exception public void testDelete() throws Exception
{ {
@@ -182,6 +188,7 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
checkForUrl(contentUrl, false); checkForUrl(contentUrl, false);
} }
@Test
public void testReadFromSecondaryStore() public void testReadFromSecondaryStore()
{ {
// pick a secondary store and write some content to it // pick a secondary store and write some content to it
@@ -194,45 +201,43 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
} }
@Test @Test
public void testIsDirectAccessSupported() public void testDirectAccessUnsupportedByDefault()
{ {
// Create the aggregating store
AggregatingContentStore aggStore = new AggregatingContentStore();
aggStore.setPrimaryStore(primaryStoreMock);
aggStore.setSecondaryStores(List.of(secondaryStoreMock));
// By default it is unsupported // By default it is unsupported
assertFalse(aggStore.isDirectAccessSupported()); assertFalse(aggregatingContentStoreMock.isDirectAccessSupported());
verify(primaryStoreMock, times(1)).isDirectAccessSupported();
// Supported if at least one store supports direct access verify(secondaryStoreMock, times(1)).isDirectAccessSupported();
{
when(primaryStoreMock.isDirectAccessSupported()).thenReturn(false);
when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(true);
assertTrue(aggStore.isDirectAccessSupported());
when(primaryStoreMock.isDirectAccessSupported()).thenReturn(true);
when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(true);
assertTrue(aggStore.isDirectAccessSupported());
when(primaryStoreMock.isDirectAccessSupported()).thenReturn(true);
when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(false);
assertTrue(aggStore.isDirectAccessSupported());
}
} }
@Test
public void testIsDirectAccessSupportedByPrimaryStore()
{
when(primaryStoreMock.isDirectAccessSupported()).thenReturn(false);
when(secondaryStoreMock.isDirectAccessSupported()).thenReturn(true);
assertTrue(aggregatingContentStoreMock.isDirectAccessSupported());
verify(primaryStoreMock, times(1)).isDirectAccessSupported();
verify(secondaryStoreMock, times(1)).isDirectAccessSupported();
}
@Test
public void testIsDirectAccessSupportedBySecondaryStore()
{
when(primaryStoreMock.isDirectAccessSupported()).thenReturn(true);
assertTrue(aggregatingContentStoreMock.isDirectAccessSupported());
verify(primaryStoreMock, times(1)).isDirectAccessSupported();
verifyNoInteractions(secondaryStoreMock);
}
@Test @Test
public void testGetDirectAccessUrl() public void testGetDirectAccessUrl()
{ {
// Create the aggregating store
AggregatingContentStore aggStore = new AggregatingContentStore();
aggStore.setPrimaryStore(primaryStoreMock);
aggStore.setSecondaryStores(List.of(secondaryStoreMock));
UnsupportedOperationException unsupportedExc = new UnsupportedOperationException(); UnsupportedOperationException unsupportedExc = new UnsupportedOperationException();
UnsupportedContentUrlException unsupportedContentUrlExc = new UnsupportedContentUrlException(aggStore, ""); UnsupportedContentUrlException unsupportedContentUrlExc = new UnsupportedContentUrlException(aggregatingContentStoreMock, "");
// By default it is unsupported // By default it is unsupported
DirectAccessUrl directAccessUrl = aggStore.getDirectAccessUrl("url", null); DirectAccessUrl directAccessUrl = aggregatingContentStoreMock.getDirectAccessUrl("url", null);
assertNull(directAccessUrl); assertNull(directAccessUrl);
// Direct access not supported // Direct access not supported
@@ -240,7 +245,7 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
{ {
when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc); when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc); when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
aggStore.getDirectAccessUrl("urlDANotSupported", null); aggregatingContentStoreMock.getDirectAccessUrl("urlDANotSupported", null);
fail(); fail();
} }
catch (UnsupportedOperationException e) catch (UnsupportedOperationException e)
@@ -252,7 +257,7 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
{ {
when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedContentUrlExc); when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedContentUrlExc);
when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc); when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
aggStore.getDirectAccessUrl("urlDANotSupported", null); aggregatingContentStoreMock.getDirectAccessUrl("urlDANotSupported", null);
fail(); fail();
} }
catch (UnsupportedOperationException e) catch (UnsupportedOperationException e)
@@ -264,7 +269,7 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
{ {
when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc); when(primaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedExc);
when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedContentUrlExc); when(secondaryStoreMock.getDirectAccessUrl(eq("urlDANotSupported"), any())).thenThrow(unsupportedContentUrlExc);
aggStore.getDirectAccessUrl("urlDANotSupported", null); aggregatingContentStoreMock.getDirectAccessUrl("urlDANotSupported", null);
fail(); fail();
} }
catch (UnsupportedOperationException e) catch (UnsupportedOperationException e)
@@ -277,7 +282,7 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
{ {
when(primaryStoreMock.getDirectAccessUrl(eq("urlNotSupported"), any())).thenThrow(unsupportedContentUrlExc); when(primaryStoreMock.getDirectAccessUrl(eq("urlNotSupported"), any())).thenThrow(unsupportedContentUrlExc);
when(secondaryStoreMock.getDirectAccessUrl(eq("urlNotSupported"), any())).thenThrow(unsupportedContentUrlExc); when(secondaryStoreMock.getDirectAccessUrl(eq("urlNotSupported"), any())).thenThrow(unsupportedContentUrlExc);
aggStore.getDirectAccessUrl("urlNotSupported", null); aggregatingContentStoreMock.getDirectAccessUrl("urlNotSupported", null);
fail(); fail();
} }
catch (UnsupportedContentUrlException e) catch (UnsupportedContentUrlException e)
@@ -286,30 +291,28 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
} }
when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl()); when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
when(secondaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenThrow(unsupportedExc); directAccessUrl = aggregatingContentStoreMock.getDirectAccessUrl("urlPriSupported", null);
directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null);
assertNotNull(directAccessUrl); assertNotNull(directAccessUrl);
when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl()); when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
when(secondaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenThrow(unsupportedContentUrlExc); directAccessUrl = aggregatingContentStoreMock.getDirectAccessUrl("urlPriSupported", null);
directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null);
assertNotNull(directAccessUrl); assertNotNull(directAccessUrl);
when(primaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenThrow(unsupportedExc); when(primaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenThrow(unsupportedExc);
when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl()); when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null); directAccessUrl = aggregatingContentStoreMock.getDirectAccessUrl("urlSecSupported", null);
assertNotNull(directAccessUrl); assertNotNull(directAccessUrl);
when(primaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenThrow(unsupportedContentUrlExc); when(primaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenThrow(unsupportedContentUrlExc);
when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl()); when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null); directAccessUrl = aggregatingContentStoreMock.getDirectAccessUrl("urlSecSupported", null);
assertNotNull(directAccessUrl); assertNotNull(directAccessUrl);
when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl()); when(primaryStoreMock.getDirectAccessUrl(eq("urlPriSupported"), any())).thenReturn(new DirectAccessUrl());
when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl()); when(secondaryStoreMock.getDirectAccessUrl(eq("urlSecSupported"), any())).thenReturn(new DirectAccessUrl());
directAccessUrl = aggStore.getDirectAccessUrl("urlPriSupported", null); directAccessUrl = aggregatingContentStoreMock.getDirectAccessUrl("urlPriSupported", null);
assertNotNull(directAccessUrl); assertNotNull(directAccessUrl);
directAccessUrl = aggStore.getDirectAccessUrl("urlSecSupported", null); directAccessUrl = aggregatingContentStoreMock.getDirectAccessUrl("urlSecSupported", null);
assertNotNull(directAccessUrl); assertNotNull(directAccessUrl);
} }
@@ -317,46 +320,114 @@ public class AggregatingContentStoreTest extends AbstractWritableContentStoreTes
public void testIsStorageClassesSupported() public void testIsStorageClassesSupported()
{ {
Set<String> sc = Set.of("a-certain-storage-class"); Set<String> sc = Set.of("a-certain-storage-class");
// Create the aggregating store
AggregatingContentStore aggStore = new AggregatingContentStore();
aggStore.setPrimaryStore(primaryStoreMock);
aggStore.setSecondaryStores(List.of(secondaryStoreMock));
// SC supported by the primary store
when(primaryStoreMock.isStorageClassesSupported(sc)).thenReturn(true); when(primaryStoreMock.isStorageClassesSupported(sc)).thenReturn(true);
assertTrue(aggStore.isStorageClassesSupported(sc));
assertTrue(aggregatingContentStoreMock.isStorageClassesSupported(sc));
verify(primaryStoreMock, times(1)).isStorageClassesSupported(sc); verify(primaryStoreMock, times(1)).isStorageClassesSupported(sc);
verify(secondaryStoreMock, never()).isStorageClassesSupported(sc); verifyNoInteractions(secondaryStoreMock);
}
// SC supported by the secondary store @Test
public void testStorageClassesIsNotSupported()
{
Set<String> sc = Set.of("a-certain-storage-class");
when(primaryStoreMock.isStorageClassesSupported(sc)).thenReturn(false); when(primaryStoreMock.isStorageClassesSupported(sc)).thenReturn(false);
when(secondaryStoreMock.isStorageClassesSupported(sc)).thenReturn(true);
assertTrue(aggStore.isStorageClassesSupported(sc)); assertFalse(aggregatingContentStoreMock.isStorageClassesSupported(sc));
verify(primaryStoreMock, times(1)).isStorageClassesSupported(sc); verify(primaryStoreMock, times(1)).isStorageClassesSupported(sc);
verify(secondaryStoreMock, times(1)).isStorageClassesSupported(sc); verifyNoInteractions(secondaryStoreMock);
// SC not supported by the stores
when(primaryStoreMock.isStorageClassesSupported(sc)).thenReturn(false);
when(secondaryStoreMock.isStorageClassesSupported(sc)).thenReturn(false);
assertFalse(aggStore.isStorageClassesSupported(sc));
verify(primaryStoreMock, times(1)).isStorageClassesSupported(sc);
verify(secondaryStoreMock, times(1)).isStorageClassesSupported(sc);
} }
@Test @Test
public void testGetSupportedStorageClasses() public void testGetSupportedStorageClasses()
{ {
Set<String> sc = Collections.emptySet(); when(primaryStoreMock.getSupportedStorageClasses()).thenReturn(emptySet());
// Create the aggregating store
AggregatingContentStore aggStore = new AggregatingContentStore();
aggStore.setPrimaryStore(primaryStoreMock);
aggStore.setSecondaryStores(List.of(secondaryStoreMock));
when(primaryStoreMock.getSupportedStorageClasses()).thenReturn(sc); assertTrue(aggregatingContentStoreMock.getSupportedStorageClasses().isEmpty());
final Set<String> supportedStorageClasses = aggStore.getSupportedStorageClasses();
assertTrue(supportedStorageClasses.isEmpty());
verify(primaryStoreMock, times(1)).getSupportedStorageClasses(); verify(primaryStoreMock, times(1)).getSupportedStorageClasses();
verify(secondaryStoreMock, times(0)).getSupportedStorageClasses(); verifyNoInteractions(secondaryStoreMock);
}
@Test
public void testUpdateStorageClassesForGivenContentUrl()
{
String contentUrl = "contentUrl";
final Set<String> storageClasses = Set.of("a-certain-storage-class");
aggregatingContentStoreMock.updateStorageClasses(contentUrl, storageClasses, null);
verify(primaryStoreMock, times(1)).updateStorageClasses(contentUrl, storageClasses, null);
verifyNoInteractions(secondaryStoreMock);
}
@Test
public void testFindStorageClassesForGivenContentUrlInPrimaryStore()
{
when(primaryStoreMock.findStorageClasses(anyString())).thenReturn(emptySet());
assertTrue(aggregatingContentStoreMock.findStorageClasses("a-contentUrl").isEmpty());
verify(primaryStoreMock, times(1)).findStorageClasses("a-contentUrl");
verifyNoInteractions(secondaryStoreMock);
}
@Test
public void testFindStorageClassesForGivenContentUrlInSecondaryStore()
{
UnsupportedContentUrlException unsupportedContentUrlExc = new UnsupportedContentUrlException(
aggregatingContentStoreMock, "");
when(primaryStoreMock.findStorageClasses(anyString())).thenThrow(unsupportedContentUrlExc);
when(secondaryStoreMock.findStorageClasses(anyString())).thenReturn(emptySet());
assertTrue(aggregatingContentStoreMock.findStorageClasses("a-contentUrl").isEmpty());
verify(primaryStoreMock, times(1)).findStorageClasses("a-contentUrl");
verify(secondaryStoreMock, times(1)).findStorageClasses("a-contentUrl");
}
@Test(expected = UnsupportedContentUrlException.class)
public void testFindStorageClassesForInvalidContentUrl()
{
when(primaryStoreMock.findStorageClasses(anyString()))
.thenThrow(new UnsupportedContentUrlException(aggregatingContentStoreMock, ""));
when(secondaryStoreMock.findStorageClasses(anyString()))
.thenThrow(new UnsupportedContentUrlException(aggregatingContentStoreMock, ""));
aggregatingContentStoreMock.findStorageClasses("a-contentUrl");
verify(primaryStoreMock, times(1)).findStorageClasses("a-contentUrl");
verify(secondaryStoreMock, times(1)).findStorageClasses("a-contentUrl");
}
@Test
public void testGetStorageClassesTransitions()
{
when(primaryStoreMock.getStorageClassesTransitions()).thenReturn(emptyMap());
assertTrue(aggregatingContentStoreMock.getStorageClassesTransitions().isEmpty());
verify(primaryStoreMock, times(1)).getStorageClassesTransitions();
verifyNoInteractions(secondaryStoreMock);
}
@Test
public void testFindStorageClassesTransitionsForGivenContentUrl()
{
when(primaryStoreMock.findStorageClassesTransitions(anyString())).thenReturn(emptyMap());
assertTrue(
aggregatingContentStoreMock.findStorageClassesTransitions("contentUrl").isEmpty());
verify(primaryStoreMock, times(1)).findStorageClassesTransitions("contentUrl");
verifyNoInteractions(secondaryStoreMock);
}
@Test(expected = UnsupportedContentUrlException.class)
public void testFindStorageClassesTransitionsForUnsupportedContentUrl()
{
when(primaryStoreMock.findStorageClassesTransitions(anyString()))
.thenThrow(new UnsupportedContentUrlException(aggregatingContentStoreMock, ""));
aggregatingContentStoreMock.findStorageClassesTransitions("contentUrl");
verify(primaryStoreMock, times(1)).findStorageClassesTransitions("contentUrl");
verifyNoInteractions(secondaryStoreMock);
} }
} }