/*
* JCarder -- cards Java programs to keep threads disentangled
*
* Copyright (C) 2006-2007 Enea AB
* Copyright (C) 2007 Ulrik Svensson
* Copyright (C) 2007 Joel Rosdahl
*
* This program is made available under the GNU GPL version 2, with a special
* exception for linking with JUnit. See the accompanying file LICENSE.txt for
* details.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
package com.enea.jcarder.agent;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import org.junit.Before;
import org.junit.Test;
import com.enea.jcarder.agent.instrument.ClassTransformer;
import com.enea.jcarder.agent.instrument.InstrumentConfig;
import com.enea.jcarder.agent.instrument.TransformClassLoader;
import com.enea.jcarder.common.contexts.ContextMemory;
import com.enea.jcarder.common.events.LockEventListenerIfc;
import com.enea.jcarder.testclasses.agent.ComparableAlternativeSynchronizationRoutes;
import com.enea.jcarder.testclasses.agent.RepeatMostRecentlySynchronization;
import com.enea.jcarder.testclasses.agent.RepeatOlderSynchronization;
import com.enea.jcarder.testclasses.agent.SingleSynchronization;
import com.enea.jcarder.testclasses.agent.SynchronizationTestIfc;
import com.enea.jcarder.testclasses.agent.TwoThreadSynchronization;
import com.enea.jcarder.util.logging.Logger;
/**
* The purpose of this junit class is to test the classes:
* - MonitorEventListener
* - ThreadLocalEnteredMonitors
*
* But it serves also as an integration test with the MonitorEventListener and
* the com.enea.jcarder.agent.instrument package. One interesting aspect of the
* integration is that MonitorEventListener/EnteredMonitor depends on that
* the monitor events are sent BEFORE instead of AFTER the monitor is entered.
*/
public final class TestMonitorEventListener implements LockEventListenerIfc {
private ContextMemory mContextMemory;
private final TransformClassLoader mClassLoader;
private final LinkedList<LockEvent> mEvents = new LinkedList<LockEvent>();
public TestMonitorEventListener() {
ClassTransformer transformer =
new ClassTransformer(new Logger(null),
new File("."),
new InstrumentConfig());
mClassLoader = new TransformClassLoader(transformer);
}
@Before
public void setUp() throws Exception {
mContextMemory = new ContextMemory();
StaticEventListener.setListener(new EventListener(new Logger(null),
this,
mContextMemory));
}
private void testClass(Class clazz) throws Exception {
SynchronizationTestIfc test = transformAsSynchronizationTest(clazz);
test.go();
// String actual = Arrays.deepToString(mEvents.toArray());
// System.out.println(" Actual: " + actual);
// String expected = Arrays.deepToString(test.getExpectedLockEvents());
// System.out.println("Expected: " + expected);
assertEquals(test.getExpectedLockEvents(),
mEvents.toArray());
}
private SynchronizationTestIfc transformAsSynchronizationTest(Class clazz)
throws Exception {
Class c = mClassLoader.transform(clazz);
return (SynchronizationTestIfc) c.newInstance();
}
public void onLockEvent(int lockId,
int lockingContextId,
int lastTakenLockId,
int lastTakenLockingContextId,
long threadId)
throws IOException {
ContextMemory cm = mContextMemory;
LockEvent event =
new LockEvent(cm.readLock(lockId),
cm.readContext(lockingContextId),
cm.readLock(lastTakenLockId),
cm.readContext(lastTakenLockingContextId));
mEvents.add(event);
}
@Test
public void testRepeatMostRecentlySynchronization() throws Exception {
testClass(RepeatMostRecentlySynchronization.class);
}
@Test
public void testRepeatOlderSynchronization() throws Exception {
testClass(RepeatOlderSynchronization.class);
}
@Test
public void testComparableAlternativeSynchronizationRoutes()
throws Exception {
testClass(ComparableAlternativeSynchronizationRoutes.class);
}
@Test
public void testSingleSynchronization() throws Exception {
testClass(SingleSynchronization.class);
}
@Test
public void testTwoThreadSynchronization() throws Exception {
testClass(TwoThreadSynchronization.class);
}
}