/*
* (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Florent Guillaume
*/
package org.nuxeo.common.file;
import java.io.ByteArrayInputStream;
import java.io.File;
import org.junit.Before;
import org.junit.After;
import org.junit.Test;
import static org.junit.Assert.*;
import org.nuxeo.common.file.LRUFileCache;
import org.nuxeo.common.utils.FileUtils;
public class TestLRUFileCache {
public File dir;
@Before
public void setUp() throws Exception {
dir = File.createTempFile("nxtestlrufilecache.", "");
dir.delete();
dir.mkdir();
}
@After
public void tearDown() throws Exception {
FileUtils.deleteTree(dir);
}
public long getDirSize() {
long size = 0;
for (File f : dir.listFiles()) {
size += f.length();
}
return size;
}
@Test
public void testLRUFileCache() throws Exception {
LRUFileCache cache = new LRUFileCache(dir, 100);
assertEquals(0, cache.getSize());
assertEquals(0, getDirSize());
assertEquals(0, cache.getNumberOfItems());
byte[] buf = new byte[30];
cache.putFile("1", new ByteArrayInputStream(buf));
assertEquals(1, cache.getNumberOfItems());
assertEquals(30, cache.getSize());
assertEquals(30, getDirSize());
File[] held = new File[1];
held[0] = cache.putFile("2", new ByteArrayInputStream(buf));
assertEquals(2, cache.getNumberOfItems());
assertEquals(60, cache.getSize());
assertEquals(60, getDirSize());
cache.putFile("3", new ByteArrayInputStream(buf));
assertEquals(3, cache.getNumberOfItems());
assertEquals(90, cache.getSize());
assertEquals(90, getDirSize());
cache.putFile("4", new ByteArrayInputStream(buf));
assertEquals(3, cache.getNumberOfItems());
assertEquals(90, cache.getSize());
System.gc();
Thread.sleep(1000);
assertEquals(90, getDirSize());
assertFalse(new File(dir, "1").exists());
// again while keep the "2" referenced
cache.putFile("5", new ByteArrayInputStream(buf));
assertEquals(3, cache.getNumberOfItems());
assertEquals(90, cache.getSize());
System.gc();
Thread.sleep(1000);
assertEquals(120, getDirSize()); // one file non deleted
assertTrue(new File(dir, "2").exists());
// clear reference
held[0] = null;
System.gc();
Thread.sleep(1000);
assertEquals(90, getDirSize());
assertFalse(new File(dir, "2").exists());
// store something bigger than the whole cache
buf = new byte[150];
cache.putFile("6", new ByteArrayInputStream(buf));
assertEquals(1, cache.getNumberOfItems());
assertEquals(150, cache.getSize());
System.gc();
Thread.sleep(1000);
assertEquals(150, getDirSize());
assertFalse(new File(dir, "5").exists());
assertTrue(new File(dir, "6").exists());
// clear
cache.clear();
assertEquals(0, cache.getNumberOfItems());
assertEquals(0, cache.getSize());
System.gc();
Thread.sleep(1000);
assertEquals(0, getDirSize());
}
@Test
public void testLRUFileCachePrematureRemoval() throws Exception {
LRUFileCache cache = new LRUFileCache(dir, 100);
File[] held = new File[2];
byte[] buf = new byte[80];
held[0] = cache.putFile("1", new ByteArrayInputStream(buf));
assertEquals(1, cache.getNumberOfItems());
assertEquals(80, cache.getSize());
assertEquals(80, getDirSize());
cache.putFile("2", new ByteArrayInputStream(buf));
assertEquals(1, cache.getNumberOfItems());
assertEquals(80, cache.getSize());
assertEquals(160, getDirSize()); // not GCed because referenced
System.gc();
Thread.sleep(1000);
assertEquals(1, cache.getNumberOfItems());
assertEquals(80, cache.getSize());
assertEquals(160, getDirSize()); // still not GCed
assertTrue(new File(dir, "1").exists());
assertTrue(new File(dir, "2").exists());
// make new reference to "1"
held[1] = cache.putFile("1", new ByteArrayInputStream(buf));
assertEquals(1, cache.getNumberOfItems());
assertEquals(80, cache.getSize());
assertEquals(160, getDirSize());
assertTrue(new File(dir, "1").exists());
assertTrue(new File(dir, "2").exists());
// clear first reference and make GC run
// file "1" should not be deleted as a new reference to it was made
held[0] = null;
System.gc();
Thread.sleep(1000);
assertEquals(1, cache.getNumberOfItems());
assertEquals(80, cache.getSize());
assertEquals(80, getDirSize());
assertTrue(new File(dir, "1").exists());
// new file evicting "1"
cache.putFile("2", new ByteArrayInputStream(buf));
assertEquals(1, cache.getNumberOfItems());
assertEquals(80, cache.getSize());
assertEquals(160, getDirSize()); // not GCed because referenced
// clear second reference and make GC run
held[1] = null;
System.gc();
Thread.sleep(1000);
assertEquals(1, cache.getNumberOfItems());
assertEquals(80, cache.getSize());
assertEquals(80, getDirSize());
assertFalse(new File(dir, "1").exists());
assertTrue(new File(dir, "2").exists());
}
}