package fr.inria.atlanmod.neo4emf.drivers.tests;
import java.io.File;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.google.common.cache.Cache;
import fr.inria.atlanmod.neo4emf.INeo4emfObject;
import fr.inria.atlanmod.neo4emf.INeo4emfResource;
import fr.inria.atlanmod.neo4emf.drivers.IProxyManager;
import fr.inria.atlanmod.neo4emf.drivers.NESession;
import fr.inria.atlanmod.neo4emf.testdata.ContainerType;
import fr.inria.atlanmod.neo4emf.testdata.Link;
import fr.inria.atlanmod.neo4emf.testdata.TestFactory;
import fr.inria.atlanmod.neo4emf.testdata.TestPackage;
import fr.inria.atlanmod.neo4emf.testdata.Vertex;
public class ProxyManagerTest {
private static final File DB_FOLDER = new File("/tmp/ProxyManagerTest");
private INeo4emfResource resource;
private TestFactory factory;
private IProxyManager proxy;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
@Before
public void setUp() throws Exception {
FileUtils.forceMkdir(DB_FOLDER);
URI uri = URI.createURI("neo4emf:"+DB_FOLDER.getAbsolutePath());
// NESession initialization (simpler than previous one)
NESession session = new NESession(TestPackage.eINSTANCE);
resource = session.createResource(uri,1000);
factory = TestFactory.eINSTANCE;
proxy = resource.getPersistenceManager().getProxyManager();
}
@After
public void tearDown() throws Exception {
resource.shutdown();
FileUtils.forceDeleteOnExit(DB_FOLDER);
}
@Test
public void testPutToProxy() {
ContainerType c = factory.createContainerType();
proxy.putToProxy(c);
assert proxy.getInternalProxy().containsKey(c.eClass()) : "The EClass is not an entry of the proxy";
Cache<Long,INeo4emfObject> cache = proxy.getInternalProxy().get(c.eClass());
assert cache.getIfPresent(c.getNodeId()) != null : "The cached value for id " + c.getNodeId() + " is null";
assert cache.getIfPresent(c.getNodeId()) == c : "Wrong cached value for id " + c.getNodeId();
}
@Test
public void testPutManyToProxy() {
int count = 10;
ContainerType[] containers = new ContainerType[count];
Vertex[] vertices = new Vertex[count];
Link[] links = new Link[count];
for(int i = 0; i < count; i++) {
containers[i] = factory.createContainerType();
vertices[i] = factory.createVertex();
links[i] = factory.createLink();
containers[i].setNodeId(i);
vertices[i].setNodeId(i);
links[i].setNodeId(i);
proxy.putToProxy(containers[i]);
proxy.putToProxy(vertices[i]);
proxy.putToProxy(links[i]);
}
Map<EClass,Cache<Long,INeo4emfObject>> internalProxy = proxy.getInternalProxy();
Cache<Long,INeo4emfObject> containerCache = internalProxy.get(TestPackage.eINSTANCE.getContainerType());
Cache<Long,INeo4emfObject> vertexCache = internalProxy.get(TestPackage.eINSTANCE.getVertex());
Cache<Long,INeo4emfObject> linkCache = internalProxy.get(TestPackage.eINSTANCE.getLink());
assert containerCache != null : "The Container EClass is not an entry of the proxy";
assert vertexCache != null : "The Vertex EClass is not an entry of the proxy";
assert linkCache != null : "The Link EClass is not an entry of the proxy";
for(int i = 0; i < count; i++) {
assert containerCache.getIfPresent((long)i) != null : "The cached Container value for id " + i + " is null";
assert vertexCache.getIfPresent((long)i) != null : "The cached Vertex value for id " + i + " is null";
assert linkCache.getIfPresent((long)i) != null : "The cached Link value for id " + i + " is null";
assert containerCache.getIfPresent((long)i) == containers[i] : "Wrong object for id " + i + " in container cache";
assert vertexCache.getIfPresent((long)i) == vertices[i] : "Wrong object for id " + i + " in vertex cache";
assert linkCache.getIfPresent((long)i) == links[i] : "Wrong object for id " + i + " in link cache";
}
}
/**
* The idea is to do a clear that should not release the
* object in the cache (there are some strong references
* on this object)
*/
@Test
public void testPutToProxyAndUselessClear() {
ContainerType c = factory.createContainerType();
proxy.putToProxy(c);
clearSoftReferences();
assert proxy.getInternalProxy().containsKey(c.eClass()) : "The EClass is not an entry of the proxy";
Cache<Long,INeo4emfObject> cache = proxy.getInternalProxy().get(c.eClass());
assert cache.getIfPresent(c.getNodeId()) != null : "The cached value for id " + c.getNodeId() + " is null";
assert cache.getIfPresent(c.getNodeId()) == c : "Wrong cached value for id " + c.getNodeId();
}
/**
* The idea is to do a clear that should release the
* object in the cache (there is no strong references
* on this object)
*/
@Test
public void testPutToProxyAndClear() {
long id = 5;
ContainerType c = factory.createContainerType();
c.setNodeId(id);
proxy.putToProxy(c);
c = null;
clearSoftReferences();
// There is no way to remove the EClass from the proxy (because EClasses are not cached)
assert proxy.getInternalProxy().containsKey(TestPackage.eINSTANCE.getContainerType()) : "The EClass is not an entry of the proxy";
Cache<Long,INeo4emfObject> cache = proxy.getInternalProxy().get(TestPackage.eINSTANCE.getContainerType());
assert cache.getIfPresent(id) == null : "The entry hasn't been removed";
}
@Test
public void testGetObjectFromProxyExistingElement() {
long id = 5;
ContainerType c = factory.createContainerType();
c.setNodeId(id);
proxy.putToProxy(c);
assert proxy.getObjectFromProxy(c.eClass(), id) != null : "Cannot retrieve the added object";
assert proxy.getObjectFromProxy(c.eClass(), id) == c : "Wrong object returned by the proxy";
}
@Test
public void testGetObjectFromProxyNotExistingElement() {
long cId = 5;
long vId = 10;
ContainerType c = factory.createContainerType();
c.setNodeId(cId);
proxy.putToProxy(c);
Vertex v = factory.createVertex();
v.setNodeId(vId);
assert proxy.getObjectFromProxy(v.eClass(), vId) == null : "The Vertex is in the proxy";
}
@Test
public void testGetObjectFromProxyManyExistingElements() {
int count = 10;
ContainerType[] containers = new ContainerType[count];
Vertex[] vertices = new Vertex[count];
Link[] links = new Link[count];
// Add some EObjects to the proxy
for(int i = 0; i < count; i++) {
containers[i] = factory.createContainerType();
vertices[i] = factory.createVertex();
links[i] = factory.createLink();
containers[i].setNodeId(i);
vertices[i].setNodeId(i);
links[i].setNodeId(i);
proxy.putToProxy(containers[i]);
proxy.putToProxy(vertices[i]);
proxy.putToProxy(links[i]);
}
// Check if they all are in the proxy
for(int i = 0; i < count; i++) {
assert proxy.getObjectFromProxy(TestPackage.eINSTANCE.getContainerType(), (long)i) != null : "Container object with id " + i + " is null";
assert proxy.getObjectFromProxy(TestPackage.eINSTANCE.getVertex(), (long)i) != null : "Vertex object with id " + i + " is null";
assert proxy.getObjectFromProxy(TestPackage.eINSTANCE.getLink(), (long)i) !=null : "Link object with id " + i + " is null";
assert proxy.getObjectFromProxy(TestPackage.eINSTANCE.getContainerType(), (long)i) == containers[i] : "Wrong Container object with id " + i;
assert proxy.getObjectFromProxy(TestPackage.eINSTANCE.getVertex(), (long)i) == vertices[i] : "Wrong Vertex object with id " + i;
assert proxy.getObjectFromProxy(TestPackage.eINSTANCE.getLink(), (long)i) == links[i] : "Wrong Link object with id " + i;
}
}
/**
* The idea is to check that the result of the method is not
* modified after a useless soft reference cleaning (useless because
* there are some strong references on the object and the should not
* be released)
*/
@Test
public void testGetObjectFromProxyAfterUselessClear() {
long cId = 5;
long vId = 10;
ContainerType c = factory.createContainerType();
Vertex v = factory.createVertex();
c.setNodeId(cId);
v.setNodeId(vId);
proxy.putToProxy(c);
proxy.putToProxy(v);
clearSoftReferences();
assert proxy.getObjectFromProxy(c.eClass(), cId) != null : "Container in proxy has been released";
assert proxy.getObjectFromProxy(v.eClass(),vId) != null : "Vertex in proxy has been released";
assert proxy.getObjectFromProxy(c.eClass(), cId) == c : "Wrong Container object in proxy";
assert proxy.getObjectFromProxy(v.eClass(), vId) == v : "Wrong Vertex object in proxy";
}
@Test
public void testGetObjectFromProxyAfterClear() {
long cId = 5;
long vId = 10;
ContainerType c = factory.createContainerType();
Vertex v = factory.createVertex();
c.setNodeId(cId);
v.setNodeId(vId);
proxy.putToProxy(c);
proxy.putToProxy(v);
c = null;
v = null;
clearSoftReferences();
assert proxy.getObjectFromProxy(TestPackage.eINSTANCE.getContainerType(), cId) == null : "Container in proxy hasn't been released";
assert proxy.getObjectFromProxy(TestPackage.eINSTANCE.getVertex(), vId) == null : "Vertex in proxy hasn't been released";
}
private void clearSoftReferences() {
try {
Object[] ignored = new Object[(int) Runtime.getRuntime().maxMemory()];
} catch (Throwable e) {
// Ignore OME
}
}
}