Matt Ward ac8b3ce1fc ALF-9613: caching content store. Various improvements and bug fixes. Including:
ALF-10097: disk-persistent cache settings in ehcache
ALF-10098: clean up  process should remove empty parent directories from content cache disk directory
ALF-10126: timeToIdle ehcache property was not affecting cache cleaner job
ALF-10127: externally deleted cached content files were not re-cached until after the items expired from ehcache

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@30171 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2011-09-02 09:03:49 +00:00

229 lines
7.8 KiB
Java

/*
* Copyright (C) 2005-2011 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco 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 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.content.caching;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.content.filestore.FileContentReader;
import org.alfresco.repo.content.filestore.FileContentWriter;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.util.TempFileProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
/**
* Tests for the ContentCacheImpl class.
*
* @author Matt Ward
*/
@RunWith(MockitoJUnitRunner.class)
public class ContentCacheImplTest
{
private ContentCacheImpl contentCache;
private @Mock SimpleCache<Key, String> lookupTable;
@Before
public void setUp() throws Exception
{
contentCache = new ContentCacheImpl();
contentCache.setMemoryStore(lookupTable);
contentCache.setCacheRoot(TempFileProvider.getTempDir());
}
@Test
public void canGetReaderForItemInCacheHavingLiveFile()
{
final String url = "store://content/url.bin";
Mockito.when(lookupTable.contains(Key.forUrl(url))).thenReturn(true);
final String path = tempfile().getAbsolutePath();
Mockito.when(lookupTable.get(Key.forUrl(url))).thenReturn(path);
FileContentReader reader = (FileContentReader) contentCache.getReader(url);
assertEquals("Reader should have correct URL", url, reader.getContentUrl());
assertEquals("Reader should be for correct cached content file", path, reader.getFile().getAbsolutePath());
// Important the get(path) was called, so that the timeToIdle is reset
// for the 'reverse lookup' as well as the URL to path mapping.
Mockito.verify(lookupTable).get(Key.forCacheFile(path));
}
@Test(expected=CacheMissException.class)
public void getReaderForItemInCacheButMissingContentFile()
{
final String url = "store://content/url.bin";
Mockito.when(lookupTable.contains(Key.forUrl(url))).thenReturn(true);
final String path = "/no/content/file/at/this/path.bin";
Mockito.when(lookupTable.get(Key.forUrl(url))).thenReturn(path);
try
{
contentCache.getReader(url);
}
finally
{
// Important the get(path) was called, so that the timeToIdle is reset
// for the 'reverse lookup' as well as the URL to path mapping.
Mockito.verify(lookupTable).get(Key.forCacheFile(path));
}
}
private File tempfile()
{
File file = TempFileProvider.createTempFile("cached-content", ".bin");
file.deleteOnExit();
return file;
}
@Test(expected=CacheMissException.class)
public void getReaderWhenItemNotInCache()
{
final String url = "store://content/url.bin";
Mockito.when(lookupTable.contains(Key.forUrl(url))).thenReturn(false);
contentCache.getReader(url);
}
@Test
public void contains()
{
final String url = "store://content/url.bin";
Mockito.when(lookupTable.contains(Key.forUrl(url))).thenReturn(true);
assertTrue(contentCache.contains(Key.forUrl(url)));
assertTrue(contentCache.contains(url));
Mockito.when(lookupTable.contains(Key.forUrl(url))).thenReturn(false);
assertFalse(contentCache.contains(Key.forUrl(url)));
assertFalse(contentCache.contains(url));
}
@Test
public void putIntoLookup()
{
final Key key = Key.forUrl("store://some/url");
final String value = "/some/path";
contentCache.putIntoLookup(key, value);
Mockito.verify(lookupTable).put(key, value);
}
@Test
public void getCacheFilePath()
{
final String url = "store://some/url.bin";
final String expectedPath = "/some/cache/file/path";
Mockito.when(lookupTable.get(Key.forUrl(url))).thenReturn(expectedPath);
String path = contentCache.getCacheFilePath(url);
assertEquals("Paths must match", expectedPath, path);
}
@Test
public void getContentUrl()
{
final File cacheFile = new File("/some/path");
final String expectedUrl = "store://some/url";
Mockito.when(lookupTable.get(Key.forCacheFile(cacheFile))).thenReturn(expectedUrl);
String url = contentCache.getContentUrl(cacheFile);
assertEquals("Content URLs should match", expectedUrl, url);
}
@Test
public void putForZeroLengthFile()
{
ContentReader contentReader = Mockito.mock(ContentReader.class);
Mockito.when(contentReader.getSize()).thenReturn(0L);
boolean putResult = contentCache.put("", contentReader);
assertFalse("Zero length files should not be cached", putResult);
}
@Test
public void putForNonEmptyFile()
{
ContentReader contentReader = Mockito.mock(ContentReader.class);
Mockito.when(contentReader.getSize()).thenReturn(999000L);
final String url = "store://some/url.bin";
boolean putResult = contentCache.put(url, contentReader);
assertTrue("Non-empty files should be cached", putResult);
ArgumentCaptor<File> cacheFileArg = ArgumentCaptor.forClass(File.class);
Mockito.verify(contentReader).getContent(cacheFileArg.capture());
// Check cached item is recorded properly in ehcache
Mockito.verify(lookupTable).put(Key.forUrl(url), cacheFileArg.getValue().getAbsolutePath());
Mockito.verify(lookupTable).put(Key.forCacheFile(cacheFileArg.getValue().getAbsolutePath()), url);
}
@Test
public void remove()
{
final String url = "store://some/url.bin";
final String path = "/some/path";
Mockito.when(lookupTable.get(Key.forUrl(url))).thenReturn(path);
contentCache.remove(url);
Mockito.verify(lookupTable).remove(Key.forUrl(url));
Mockito.verify(lookupTable).remove(Key.forCacheFile(path));
}
@Test
public void getWriter()
{
final String url = "store://some/url.bin";
FileContentWriter writer = (FileContentWriter) contentCache.getWriter(url);
writer.putContent("Some test content for " + getClass().getName());
assertEquals(url, writer.getContentUrl());
// Check cached item is recorded properly in ehcache
Mockito.verify(lookupTable).put(Key.forUrl(url), writer.getFile().getAbsolutePath());
Mockito.verify(lookupTable).put(Key.forCacheFile(writer.getFile().getAbsolutePath()), url);
}
}