package org.jboss.cache.loader;
import org.jboss.cache.CacheSPI;
import org.jboss.cache.DefaultCacheFactory;
import org.jboss.cache.Fqn;
import org.jboss.cache.config.CacheLoaderConfig;
import org.jboss.cache.factories.XmlConfigurationParser;
import org.jboss.cache.marshall.NodeData;
import org.jboss.cache.misc.TestingUtil;
import org.jboss.cache.statetransfer.StateTransferManager;
import org.jboss.cache.xml.XmlHelper;
import org.jboss.util.stream.MarshalledValueInputStream;
import org.jboss.util.stream.MarshalledValueOutputStream;
import static org.testng.AssertJUnit.*;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.w3c.dom.Element;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Properties;
/**
* Tests the compatibility between <tt>JDBCCacheLoader</tt> and <tt>JDBCCacheLoaderOld</tt>. More exactly,
* it tests whether the new <tt>JDBCCacheLoader</tt> works fine on data previously created
* <tt>JDBCCacheLoaderOld</tt>.
*
* @author Mircea.Markus@iquestint.com
* @version 1.0
*/
@Test(groups = {"functional"})
@SuppressWarnings("deprecation")
public class AdjListJDBCCacheLoaderCompatibilityTest
{
@SuppressWarnings("deprecation")
private JDBCCacheLoaderOld oldImpl;
private JDBCCacheLoader newImpl;
private CacheSPI cache, cache2;
/**
* Note : newImpl is not started here but in each individual test. That's because on start it performs
* some backward compatibility logic.
*
* @see JDBCCacheLoader#start()
*/
@BeforeMethod(alwaysRun = true)
public void setUp() throws Exception
{
newImpl = getNewCacheLoader();
oldImpl = getOldLoader();
cache = (CacheSPI) new DefaultCacheFactory().createCache();
cache2 = (CacheSPI) new DefaultCacheFactory().createCache();
newImpl.setCache(cache);//this is needed for marshaller
oldImpl.setCache(cache2);
oldImpl.start();
oldImpl.remove(Fqn.ROOT);
}
@AfterMethod(alwaysRun = true)
public void tearDown() throws Exception
{
oldImpl.remove(Fqn.ROOT);
oldImpl.stop();
newImpl.stop();
TestingUtil.killCaches(cache, cache2);
}
public void testCommonOperations() throws Exception
{
newImpl.start();
oldImpl.put(Fqn.fromString("/a/b/c"), "key1", "value1");
oldImpl.put(Fqn.fromString("/a/b/d"), "key2", "value2");
oldImpl.put(Fqn.fromString("/a/b/e"), "key3", "value3");
assertTrue(newImpl.exists(Fqn.fromString("/a/b/c")));
assertTrue(newImpl.exists(Fqn.fromString("/a/b/d")));
assertTrue(newImpl.exists(Fqn.fromString("/a/b/e")));
assertEquals("value1", newImpl.get(Fqn.fromString("/a/b/c")).get("key1"));
assertEquals("value2", newImpl.get(Fqn.fromString("/a/b/d")).get("key2"));
assertEquals("value3", newImpl.get(Fqn.fromString("/a/b/e")).get("key3"));
}
/**
* Does the new implementation manage to successfully remove nodes created by old one?
*/
public void testRemove() throws Exception
{
oldImpl.put(Fqn.fromString("/a/b/c"), "key1", "value1");
oldImpl.put(Fqn.fromString("/a/b/d"), "key2", "value2");
oldImpl.put(Fqn.fromString("/a/b/e"), "key3", "value3");
oldImpl.put(Fqn.fromString("/a/f/e"), "key4", "value4");
assertTrue(newImpl.exists(Fqn.fromString("/a/b/c")));
assertTrue(newImpl.exists(Fqn.fromString("/a/b/d")));
assertTrue(newImpl.exists(Fqn.fromString("/a/b/e")));
newImpl.start();
newImpl.remove(Fqn.fromString("/a/b"));
assertFalse(newImpl.exists(Fqn.fromString("/a/b/c")));
assertFalse(newImpl.exists(Fqn.fromString("/a/b/d")));
assertFalse(newImpl.exists(Fqn.fromString("/a/b/e")));
assertTrue(newImpl.exists(Fqn.fromString("/a/f")));
assertTrue(newImpl.exists(Fqn.fromString("/a/f/e")));
}
public void testLoadEntireState() throws Exception
{
oldImpl.put(Fqn.fromString("/a/b/c"), "key1", "value1");
oldImpl.put(Fqn.fromString("/a/b/d"), "key2", "value2");
oldImpl.put(Fqn.fromString("/a/b/e"), "key3", "value3");
oldImpl.put(Fqn.fromString("/a/f/e"), "key4", "value4");
oldImpl.put(Fqn.ROOT, "root_key", "root_value");
ByteArrayOutputStream newBaos = new ByteArrayOutputStream(1024);
MarshalledValueOutputStream newOs = new MarshalledValueOutputStream(newBaos);
newImpl.start();
newImpl.loadEntireState(newOs);
newImpl.getMarshaller().objectToObjectStream(StateTransferManager.STREAMING_DELIMITER_NODE, newOs);
newOs.close();
newImpl.remove(Fqn.ROOT);
assertNull(newImpl.get(Fqn.fromString("/a/b/c")));
assertNull(newImpl.get(Fqn.fromString("/a/b/d")));
assertNull(newImpl.get(Fqn.fromString("/a/b/e")));
assertNull(newImpl.get(Fqn.fromString("/a/f/e")));
assertNull(newImpl.get(Fqn.ROOT));
ByteArrayInputStream bais = new ByteArrayInputStream(newBaos.toByteArray());
MarshalledValueInputStream is = new MarshalledValueInputStream(bais);
newImpl.storeEntireState(is);
assertEquals(newImpl.get(Fqn.fromString("/a/b/c")).get("key1"), "value1");
assertEquals(newImpl.get(Fqn.fromString("/a/b/d")).get("key2"), "value2");
assertEquals(newImpl.get(Fqn.fromString("/a/b/e")).get("key3"), "value3");
assertEquals(newImpl.get(Fqn.fromString("/a/f/e")).get("key4"), "value4");
assertEquals(newImpl.get(Fqn.ROOT).get("root_key"), "root_value");
assertEquals(newImpl.getNodeCount(), 8);
}
public void testLoadNodeState() throws Exception
{
oldImpl.put(Fqn.fromString("/a/b/c"), "key1", "value1");
oldImpl.put(Fqn.fromString("/a/b/d"), "key2", "value2");
oldImpl.put(Fqn.fromString("/a/b/e"), "key3", "value3");
oldImpl.put(Fqn.fromString("/a/f/e"), "key4", "value4");
oldImpl.put(Fqn.ROOT, "root_key", "root_value");
ByteArrayOutputStream newBaos = new ByteArrayOutputStream(1024);
MarshalledValueOutputStream newOs = new MarshalledValueOutputStream(newBaos);
newImpl.start();
newImpl.loadState(Fqn.fromString("/a/b"), newOs);
newImpl.getMarshaller().objectToObjectStream(StateTransferManager.STREAMING_DELIMITER_NODE, newOs);
newOs.close();
newImpl.remove(Fqn.fromString("/a/b"));
assertNull(newImpl.get(Fqn.fromString("/a/b/c")));
assertNull(newImpl.get(Fqn.fromString("/a/b/d")));
assertNull(newImpl.get(Fqn.fromString("/a/b/e")));
assertNull(newImpl.get(Fqn.fromString("/a/b")));
ByteArrayInputStream bais = new ByteArrayInputStream(newBaos.toByteArray());
MarshalledValueInputStream is = new MarshalledValueInputStream(bais);
newImpl.storeState(Fqn.fromString("/a/b"), is);
assertEquals(newImpl.get(Fqn.fromString("/a/b/c")).get("key1"), "value1");
assertEquals(newImpl.get(Fqn.fromString("/a/b/d")).get("key2"), "value2");
assertEquals(newImpl.get(Fqn.fromString("/a/b/e")).get("key3"), "value3");
assertEquals(newImpl.get(Fqn.fromString("/a/f/e")).get("key4"), "value4");
assertEquals(newImpl.get(Fqn.ROOT).get("root_key"), "root_value");
assertEquals(newImpl.getNodeCount(), 8);
}
/**
* getNodeDataList is a template method on which the serialisation process relies. We check here that the new
* implementation works exactelly as the old one.
*/
public void testGetNodeData() throws Exception
{
oldImpl.put(Fqn.fromString("/a/b/c"), "key1", "value1");
oldImpl.put(Fqn.fromString("/a/b/d"), "key2", "value2");
oldImpl.put(Fqn.fromString("/a/b/e"), "key3", "value3");
oldImpl.put(Fqn.fromString("/a/f/e"), "key4", "value4");
oldImpl.put(Fqn.ROOT, "root_key", "root_value");
newImpl.start();
ArrayList<NodeData> oldList = new ArrayList<NodeData>();
oldImpl.getNodeDataList(Fqn.ROOT, oldList);
ArrayList<NodeData> newList = new ArrayList<NodeData>();
newImpl.getNodeDataList(Fqn.ROOT, newList);
assertEquals(new HashSet<NodeData>(oldList), new HashSet<NodeData>(newList));
}
/**
* Tests performs some backward copatibility work. See {@link JDBCCacheLoader#start()} for details.
*/
public void testStartWork() throws Exception
{
oldImpl.put(Fqn.fromString("/a/b/c"), "key1", "value1");
oldImpl.put(Fqn.fromString("/a/b/d"), "key2", "value2");
assertNull(oldImpl.get(Fqn.ROOT));
newImpl.start();
assertNotNull(newImpl.get(Fqn.ROOT));
}
protected CacheLoaderConfig getSingleCacheLoaderConfig(String preload, String cacheloaderClass, String properties) throws Exception
{
String xml = "<config>\n" +
"<passivation>false</passivation>\n" +
"<preload>" + preload + "</preload>\n" +
"<cacheloader>\n" +
"<class>" + cacheloaderClass + "</class>\n" +
"<properties>" + properties + "</properties>\n" +
"<async>false</async>\n" +
"<shared>false</shared>\n" +
"<fetchPersistentState>true</fetchPersistentState>\n" +
"<purgeOnStartup>false</purgeOnStartup>\n" +
"</cacheloader>\n" +
"</config>";
Element element = XmlHelper.stringToElement(xml);
return XmlConfigurationParser.parseCacheLoaderConfig(element);
}
protected Properties getProperties() throws Exception
{
Properties prop = new Properties();
try
{
prop.load(this.getClass().getClassLoader().getResourceAsStream("cache-jdbc.properties"));
return prop;
}
catch (Exception e)
{
throw new Exception("Error loading jdbc properties ", e);
}
}
private JDBCCacheLoader getNewCacheLoader() throws Exception
{
Properties prop = getProperties();
String props = "cache.jdbc.driver =" + prop.getProperty("cache.jdbc.driver") + "\n" +
"cache.jdbc.url=" + prop.getProperty("cache.jdbc.url") + "\n" +
"cache.jdbc.user=" + prop.getProperty("cache.jdbc.user") + "\n" +
"cache.jdbc.password=" + prop.getProperty("cache.jdbc.password") + "\n" +
"cache.jdbc.node.type=" + prop.getProperty("cache.jdbc.node.type") + "\n" +
"cache.jdbc.sql-concat=" + prop.getProperty("cache.jdbc.sql-concat") + "\n";
CacheLoaderConfig.IndividualCacheLoaderConfig base = getSingleCacheLoaderConfig("", "org.jboss.cache.loader.JDBCCacheLoader", props).getFirstCacheLoaderConfig();
JDBCCacheLoader jdbcCacheLoader = new JDBCCacheLoader();
jdbcCacheLoader.setConfig(base);
return jdbcCacheLoader;
}
private JDBCCacheLoaderOld getOldLoader() throws Exception
{
Properties prop = getProperties();
String props = "cache.jdbc.driver =" + prop.getProperty("cache.jdbc.driver") + "\n" +
"cache.jdbc.url=" + prop.getProperty("cache.jdbc.url") + "\n" +
"cache.jdbc.user=" + prop.getProperty("cache.jdbc.user") + "\n" +
"cache.jdbc.password=" + prop.getProperty("cache.jdbc.password") + "\n" +
"cache.jdbc.node.type=" + prop.getProperty("cache.jdbc.node.type") + "\n" +
"cache.jdbc.sql-concat=" + prop.getProperty("cache.jdbc.sql-concat");// + "\n" +
// "cache.jdbc.connection.factory=org.jboss.cache.manualtests.cacheloader.OneConnectionFactory";
CacheLoaderConfig.IndividualCacheLoaderConfig base = getSingleCacheLoaderConfig("", "org.jboss.cache.loader.JDBCCacheLoader", props).getFirstCacheLoaderConfig();
JDBCCacheLoaderOld jdbcCacheLoader = new JDBCCacheLoaderOld();
jdbcCacheLoader.setConfig(base);
return jdbcCacheLoader;
}
}