Clover coverage report -
Coverage timestamp: Thu Jul 5 2007 20:02:32 EDT
file stats: LOC: 466   Methods: 25
NCLOC: 345   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
StateTransferTestBase.java 75% 85.7% 88% 83.8%
coverage coverage
 1    /*
 2    * JBoss, Home of Professional Open Source
 3    * Copyright 2006, JBoss Inc., and individual contributors as indicated
 4    * by the @authors tag. See the copyright.txt in the distribution for a
 5    * full listing of individual contributors.
 6    *
 7    * This is free software; you can redistribute it and/or modify it
 8    * under the terms of the GNU Lesser General Public License as
 9    * published by the Free Software Foundation; either version 2.1 of
 10    * the License, or (at your option) any later version.
 11    *
 12    * This software is distributed in the hope that it will be useful,
 13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 15    * Lesser General Public License for more details.
 16    *
 17    * You should have received a copy of the GNU Lesser General Public
 18    * License along with this software; if not, write to the Free
 19    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 20    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 21    */
 22   
 23    package org.jboss.cache.statetransfer;
 24   
 25    import org.jboss.cache.Cache;
 26    import org.jboss.cache.CacheSPI;
 27    import org.jboss.cache.DefaultCacheFactory;
 28    import org.jboss.cache.Fqn;
 29    import org.jboss.cache.config.Configuration;
 30    import org.jboss.cache.config.Configuration.CacheMode;
 31    import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
 32    import org.jboss.cache.loader.AbstractCacheLoaderTestBase;
 33    import org.jboss.cache.loader.CacheLoader;
 34    import org.jboss.cache.marshall.SelectedClassnameClassLoader;
 35    import org.jboss.cache.misc.TestingUtil;
 36   
 37    import java.io.File;
 38    import java.util.HashMap;
 39    import java.util.Map;
 40    import java.util.Properties;
 41    import java.util.concurrent.Semaphore;
 42    import java.util.concurrent.TimeUnit;
 43   
 44    /**
 45    * Abstract superclass of the StateTransfer tests.
 46    *
 47    * @author <a href="mailto://brian.stansberry@jboss.com">Brian Stansberry</a>
 48    * @version $Revision$
 49    */
 50    public abstract class StateTransferTestBase extends AbstractCacheLoaderTestBase
 51    {
 52    public static final Fqn A_B = Fqn.fromString("/a/b");
 53    public static final Fqn A_C = Fqn.fromString("/a/c");
 54    public static final Fqn A_D = Fqn.fromString("/a/d");
 55    public static final String JOE = "JOE";
 56    public static final String BOB = "BOB";
 57    public static final String JANE = "JANE";
 58    public static final Integer TWENTY = 20;
 59    public static final Integer FORTY = 40;
 60   
 61    protected Map<String, Cache> caches;
 62    private ClassLoader orig_TCL;
 63   
 64   
 65    protected abstract String getReplicationVersion();
 66   
 67  46 protected CacheSPI createCache(String cacheID,
 68    boolean sync,
 69    boolean useMarshalling,
 70    boolean useCacheLoader)
 71    throws Exception
 72    {
 73  46 return createCache(cacheID, sync, useMarshalling, useCacheLoader, false, true);
 74    }
 75   
 76  71 protected CacheSPI createCache(String cacheID,
 77    boolean sync,
 78    boolean useMarshalling,
 79    boolean useCacheLoader,
 80    boolean cacheLoaderAsync,
 81    boolean startCache)
 82    throws Exception
 83    {
 84  71 if (useCacheLoader)
 85    {
 86  14 return createCache(cacheID, sync, useMarshalling, "org.jboss.cache.loader.FileCacheLoader", cacheLoaderAsync, startCache);
 87    }
 88    else
 89    {
 90  57 return createCache(cacheID, sync, useMarshalling, null, cacheLoaderAsync, startCache);
 91    }
 92    }
 93   
 94  105 protected CacheSPI createCache(String cacheID, boolean sync, boolean useMarshalling, String cacheLoaderClass,
 95    boolean cacheLoaderAsync, boolean startCache) throws Exception
 96    {
 97  105 if (caches.get(cacheID) != null)
 98    {
 99  0 throw new IllegalStateException(cacheID + " already created");
 100    }
 101   
 102  105 CacheMode mode = sync ? CacheMode.REPL_SYNC : CacheMode.REPL_ASYNC;
 103  105 Configuration c = UnitTestCacheConfigurationFactory.createConfiguration(mode);
 104  105 if (sync)
 105    {
 106  15 c.setSyncRollbackPhase(true);
 107  15 c.setSyncCommitPhase(true);
 108    }
 109  105 c.setClusterName("VersionedTestBase");
 110  105 c.setReplVersionString(getReplicationVersion());
 111    // Use a long timeout to facilitate setting debugger breakpoints
 112  105 c.setStateRetrievalTimeout(60000);
 113  105 if (useMarshalling)
 114    {
 115  45 c.setUseRegionBasedMarshalling(true);
 116  45 c.setInactiveOnStartup(true);
 117    }
 118  105 if (cacheLoaderClass != null && cacheLoaderClass.length() > 0)
 119    {
 120  48 configureCacheLoader(c, cacheLoaderClass, cacheID, useMarshalling, cacheLoaderAsync);
 121    }
 122    // tree.setConfiguration(c);
 123    //c.setLockAcquisitionTimeout(60000);
 124    //c.setSyncReplTimeout(60000);
 125  105 CacheSPI tree = (CacheSPI) DefaultCacheFactory.getInstance().createCache(c, false);
 126    //c.setLockAcquisitionTimeout(60000); // a whole minute?!?? Lots of state to tfr?
 127    //c.setSyncReplTimeout(60000);
 128  105 configureMultiplexer(tree);
 129   
 130    // Put the cache in the map before starting, so if it fails in
 131    // start it can still be destroyed later
 132  105 caches.put(cacheID, tree);
 133   
 134  105 if (startCache)
 135    {
 136  66 tree.create();
 137  66 tree.start();
 138    }
 139   
 140  104 return tree;
 141    }
 142   
 143    /**
 144    * Provides a hook for multiplexer integration. This default implementation
 145    * is a no-op; subclasses that test mux integration would override
 146    * to integrate the given cache with a multiplexer.
 147    * <p/>
 148    * param cache a cache that has been configured but not yet created.
 149    */
 150  71 protected void configureMultiplexer(Cache cache) throws Exception
 151    {
 152    // default does nothing
 153    }
 154   
 155    /**
 156    * Provides a hook to check that the cache's channel came from the
 157    * multiplexer, or not, as expected. This default impl asserts that
 158    * the channel did not come from the multiplexer.
 159    *
 160    * @param cache a cache that has already been started
 161    */
 162  1 protected void validateMultiplexer(Cache cache)
 163    {
 164  1 assertFalse("Cache is not using multiplexer", cache.getConfiguration().isUsingMultiplexer());
 165    }
 166   
 167  2 protected void startCache(Cache cache) throws Exception
 168    {
 169  2 cache.create();
 170  2 cache.start();
 171   
 172  2 validateMultiplexer(cache);
 173    }
 174   
 175  0 protected void configureCacheLoader(Configuration c,
 176    String cacheID,
 177    boolean useExtended,
 178    boolean async)
 179    throws Exception
 180    {
 181  0 configureCacheLoader(c, "org.jboss.cache.loader.FileCacheLoader", cacheID, useExtended, async);
 182    }
 183   
 184  48 protected void configureCacheLoader(Configuration c, String cacheloaderClass, String cacheID, boolean useExtended,
 185    boolean async) throws Exception
 186    {
 187  48 if (cacheloaderClass != null)
 188    {
 189  48 if (cacheloaderClass.equals("org.jboss.cache.loader.JDBCCacheLoader"))
 190    {
 191  6 Properties prop = new Properties();
 192  6 try
 193    {
 194  6 prop.load(this.getClass().getClassLoader().getResourceAsStream("cache-jdbc.properties"));
 195    }
 196    catch (Exception e)
 197    {
 198  0 System.out.println("Error loading jdbc properties ");
 199    }
 200  6 String props = "cache.jdbc.driver =" + prop.getProperty("cache.jdbc.driver") + "\n" + "cache.jdbc.url="
 201    + prop.getProperty("cache.jdbc.url") + "\n" + "cache.jdbc.user="
 202    + prop.getProperty("cache.jdbc.user") + "\n" + "cache.jdbc.password="
 203    + prop.getProperty("cache.jdbc.password") + "\n" + "cache.jdbc.node.type="
 204    + prop.getProperty("cache.jdbc.node.type") + "\n" + "cache.jdbc.sql-concat="
 205    + prop.getProperty("cache.jdbc.sql-concat");
 206   
 207  6 c.setCacheLoaderConfig(getSingleCacheLoaderConfig("", "org.jboss.cache.loader.JDBCCacheLoader",
 208    props, false, true, false));
 209    }
 210    else
 211    {
 212   
 213  42 String tmp_location = getTempLocation(cacheID);
 214   
 215    // Do cleanup in case it failed before
 216  42 File file = new File(tmp_location);
 217  42 cleanFile(file);
 218   
 219  42 file.mkdir();
 220   
 221  42 tmp_location = escapeWindowsPath(tmp_location);
 222  42 String props = "location = " + tmp_location + "\n";
 223  42 c.setCacheLoaderConfig(getSingleCacheLoaderConfig("", cacheloaderClass, props, async, true, false));
 224    }
 225    }
 226    }
 227   
 228  16 protected void initialStateTferWithLoaderTest(String cacheLoaderClass1, String cacheLoaderClass2, boolean asyncLoader) throws Exception
 229    {
 230  16 CacheSPI cache1 = createCache("cache1", false, false, cacheLoaderClass1, false, true);
 231   
 232  16 cache1.put(A_B, "name", JOE);
 233  16 cache1.put(A_B, "age", TWENTY);
 234  16 cache1.put(A_C, "name", BOB);
 235  16 cache1.put(A_C, "age", FORTY);
 236   
 237  16 CacheSPI cache2 = createCache("cache2", false, false, cacheLoaderClass2, asyncLoader, false);
 238   
 239  16 cache2.start();
 240   
 241    // Pause to give caches time to see each other
 242  16 TestingUtil.blockUntilViewsReceived(new CacheSPI[]{cache1, cache2}, 60000);
 243   
 244  16 if (asyncLoader)
 245    {
 246  2 TestingUtil.sleepThread((long) 100);
 247    }
 248   
 249  16 CacheLoader loader = cache2.getCacheLoaderManager().getCacheLoader();
 250   
 251  16 assertEquals("Incorrect loader name for /a/b", JOE, loader.get(A_B).get("name"));
 252  16 assertEquals("Incorrect loader age for /a/b", TWENTY, loader.get(A_B).get("age"));
 253  16 assertEquals("Incorrect loader name for /a/c", BOB, loader.get(A_C).get("name"));
 254  16 assertEquals("Incorrect loader age for /a/c", FORTY, loader.get(A_C).get("age"));
 255   
 256  16 assertEquals("Incorrect name for /a/b", JOE, cache2.get(A_B, "name"));
 257  16 assertEquals("Incorrect age for /a/b", TWENTY, cache2.get(A_B, "age"));
 258  16 assertEquals("Incorrect name for /a/c", BOB, cache2.get(A_C, "name"));
 259  16 assertEquals("Incorrect age for /a/c", FORTY, cache2.get(A_C, "age"));
 260    }
 261   
 262  157 protected String getTempLocation(String cacheID)
 263    {
 264  157 String tmp_location = System.getProperty("java.io.tmpdir", "c:\\tmp");
 265  157 File file = new File(tmp_location);
 266  157 file = new File(file, cacheID);
 267  157 return file.getAbsolutePath();
 268    }
 269   
 270  42 protected String escapeWindowsPath(String path)
 271    {
 272  42 if ('/' == File.separatorChar)
 273    {
 274  42 return path;
 275    }
 276   
 277  0 char[] chars = path.toCharArray();
 278  0 StringBuffer sb = new StringBuffer();
 279  0 for (char aChar : chars)
 280    {
 281  0 if (aChar == '\\')
 282    {
 283  0 sb.append('\\');
 284    }
 285  0 sb.append(aChar);
 286    }
 287  0 return sb.toString();
 288    }
 289   
 290  58 protected void setUp() throws Exception
 291    {
 292  58 super.setUp();
 293   
 294  58 caches = new HashMap<String, Cache>();
 295   
 296    // Save the TCL in case a test changes it
 297  58 orig_TCL = Thread.currentThread().getContextClassLoader();
 298    }
 299   
 300  58 protected void tearDown() throws Exception
 301    {
 302   
 303  58 System.out.println("*** in tearDown()");
 304   
 305  58 super.tearDown();
 306   
 307    // Restore the TCL in case a test changed it
 308  58 Thread.currentThread().setContextClassLoader(orig_TCL);
 309   
 310  58 for (String cacheID : caches.keySet())
 311    {
 312  115 stopCache(caches.get(cacheID));
 313  115 TestingUtil.sleepThread(1500);
 314  115 File file = new File(getTempLocation(cacheID));
 315  115 cleanFile(file);
 316    }
 317    }
 318   
 319  115 protected void stopCache(Cache cache)
 320    {
 321  115 if (cache != null)
 322    {
 323  115 try
 324    {
 325  115 cache.stop();
 326  115 cache.destroy();
 327    }
 328    catch (Exception e)
 329    {
 330  0 System.out.println("Exception stopping cache " + e.getMessage());
 331  0 e.printStackTrace(System.out);
 332    }
 333    }
 334    }
 335   
 336  341 protected void cleanFile(File file)
 337    {
 338  341 File[] children = file.listFiles();
 339  341 if (children != null)
 340    {
 341  126 for (File child : children)
 342    {
 343  184 cleanFile(child);
 344    }
 345    }
 346   
 347  341 if (file.exists())
 348    {
 349  226 file.delete();
 350    }
 351  341 if (file.exists())
 352    {
 353  0 file.deleteOnExit();
 354    }
 355    }
 356   
 357  4 protected ClassLoader getClassLoader() throws Exception
 358    {
 359  4 String[] includesClasses = {"org.jboss.cache.marshall.Person",
 360    "org.jboss.cache.marshall.Address"};
 361  4 String[] excludesClasses = {};
 362  4 ClassLoader cl = Thread.currentThread().getContextClassLoader();
 363  4 return new SelectedClassnameClassLoader(includesClasses, excludesClasses, cl);
 364    }
 365   
 366  2 protected ClassLoader getNotFoundClassLoader() throws Exception
 367    {
 368  2 String[] notFoundClasses = {"org.jboss.cache.marshall.Person",
 369    "org.jboss.cache.marshall.Address"};
 370  2 ClassLoader cl = Thread.currentThread().getContextClassLoader();
 371  2 return new SelectedClassnameClassLoader(null, null, notFoundClasses, cl);
 372    }
 373   
 374    protected abstract class CacheUser implements Runnable
 375    {
 376    protected Semaphore semaphore;
 377    protected CacheSPI cache;
 378    protected String name;
 379    protected Exception exception;
 380    protected Thread thread;
 381   
 382  0 CacheUser()
 383    {
 384    }
 385   
 386  28 CacheUser(Semaphore semaphore,
 387    String name,
 388    boolean sync,
 389    boolean activateRoot)
 390    throws Exception
 391    {
 392  28 this.cache = createCache(name, sync, true, false);
 393  28 this.semaphore = semaphore;
 394  28 this.name = name;
 395   
 396  28 if (activateRoot)
 397    {
 398  0 cache.getRegion(Fqn.ROOT, true).activate();
 399    }
 400    }
 401   
 402  28 public void run()
 403    {
 404  28 boolean acquired = false;
 405  28 try
 406    {
 407  28 acquired = semaphore.tryAcquire(60, TimeUnit.SECONDS);
 408  28 if (!acquired)
 409    {
 410  0 throw new Exception(name + " cannot acquire semaphore");
 411    }
 412    //System.out.println(name + " acquired semaphore");
 413   
 414  28 useCache();
 415   
 416    }
 417    catch (Exception e)
 418    {
 419  0 System.out.println(name + ": " + e.getLocalizedMessage());
 420  0 e.printStackTrace(System.out);
 421   
 422    // Save it for the test to check
 423  0 exception = e;
 424    }
 425    finally
 426    {
 427  28 if (acquired)
 428    {
 429  28 semaphore.release();
 430    }
 431    }
 432   
 433    }
 434   
 435    abstract void useCache() throws Exception;
 436   
 437  28 public Exception getException()
 438    {
 439  28 return exception;
 440    }
 441   
 442  28 public CacheSPI getCacheSPI()
 443    {
 444  28 return cache;
 445    }
 446   
 447  0 public String getName()
 448    {
 449  0 return name;
 450    }
 451   
 452  28 public void start()
 453    {
 454  28 thread = new Thread(this);
 455  28 thread.start();
 456    }
 457   
 458  28 public void cleanup()
 459    {
 460  28 if (thread != null && thread.isAlive())
 461    {
 462  1 thread.interrupt();
 463    }
 464    }
 465    }
 466    }