Enhancer { public T newInstance() { try { return getEnhancedClass().newInstance(); } catch (Exception e) { logger.error("Could not instantiate enhanced object.", e); throw ExceptionUtil.propagate(e); } } protected  Enhancer(Class<T> baseClass); abstract boolean needsEnhancement(Object object); void validateClassIsEnhanceable(Class<T> baseClass); final Class<T> getBaseClass(); Class<? extends T> getEnhancedClass(); T newInstance(); T enhance(T t);  }
@Test public void enhancerAppearsThreadsafe() throws InterruptedException { int iter = 5000; int threads = 10; ExecutorService exec = Executors.newFixedThreadPool(threads); final CountDownLatch start = new CountDownLatch(1); final CountDownLatch done = new CountDownLatch(threads * iter); final List<SampleClass2> newObjects = Collections.synchronizedList(new ArrayList<SampleClass2>()); final List<Enhancer<SampleClass2>> enhancers = new ArrayList<Enhancer<SampleClass2>>(); enhancers.add(EnhancerHelper.makePersistentEnhancer(SampleClass2.class)); enhancers.add(EnhancerHelper.makePersistentEnhancer(SampleClass2.class)); enhancers.add(EnhancerHelper.makePersistentEnhancer(SampleClass2.class)); enhancers.add(EnhancerHelper.makePersistentEnhancer(SampleClass2.class)); enhancers.add(EnhancerHelper.makePersistentEnhancer(SampleClass2.class)); enhancers.add(EnhancerHelper.makePersistentEnhancer(SampleClass2.class)); enhancers.add(EnhancerHelper.makePersistentEnhancer(SampleClass2.class)); enhancers.add(EnhancerHelper.makePersistentEnhancer(SampleClass2.class)); for (int i = 0; i < threads * iter; i++) { exec.submit(new Runnable() { public void run() { try { Enhancer<SampleClass2> enhancer = enhancers.get(newObjects.size() % enhancers.size()); SampleClass2 test = enhancer.newInstance(); ((Snapshot) test).snapshot(); start.await(); long bar = System.nanoTime(); assertDirty(test, false); test.setBar(bar); assertEquals(bar, test.getBar()); assertDirty(test, true); newObjects.add(test); } catch (Exception e) { e.printStackTrace(); } finally { done.countDown(); } } }); } start.countDown(); done.await(); assertEquals("Bug in test", 0, exec.shutdownNow().size()); assertEquals(threads * iter, newObjects.size()); }
@Test public void newInstanceIsDirtyWorks() { SampleClass enhanced = enhancer.newInstance(); assertDirty(enhanced, true); ((Snapshot) enhanced).snapshot(); assertDirty(enhanced, false); enhanced.setFoo("foo"); assertDirty(enhanced, true); ((Snapshot) enhanced).snapshot(); assertDirty(enhanced, false); enhanced.setFoo(null); assertDirty(enhanced, true); enhanced.setFoo("bar"); assertDirty(enhanced, true); enhanced.setFoo("foo"); assertDirty(enhanced, false); }
@Test public void dirtyDetectionWorksInsideArrays() { SampleClass enhanced = enhancer.newInstance(); ((Snapshot) enhanced).snapshot(); enhanced.setBits(new boolean[] { false, true }); assertDirty(enhanced, true); enhanced.setBits(new SampleClass().getBits()); assertDirty(enhanced, false); }