Hi all, Still working on the Express and Custom runners for the Terracotta extension to jUnit. Some unexpected work came on top, and, despite what I had expected, this turns out to be much more plumbing than I innocently had expected!
Yet the main bits are in placed and Standalone are functional as of now. Looks like I need to fix some concurrency issue with junit itself still so that the reporting doesn't get confused every now and then... but you can write and run tests. To do so, one would need to annotate his class with the @RunWith(TerracottaRunner.class) annotation. This is currently the most simple way of running a TC backed up test. It will by default involve 2 participants and (once I'm have them properly functioning) run in Custom, Express and Standalone mode. A class can additionally be annotated with : - @TerracottaTest To define the TargetEnvironment the test needs to be run in & the amount of participants: @TerracottaTest(participants = 1, value = TerracottaTest.TargetEnvironment.STANDALONE) - @TerracottaServerConfig To define some l2 properties when run in clustered: @TerracottaServerConfig(hostname = "localhost", dsoPort = 5678, adminPort = 5679) More will probably be added as need arises. At the field level, you can inject the ClusteringToolkit used by annotation the proper typed field with @Inject In standalone, a Dummy implementation is inject that should mimic clustered behavior. Now at the method level, I introduced an (hopefully soon renamed) additional 2 annotations: @BeforeAll @AfterAll These static methods will be executed once for the cluster (like if you need to start a DB instance or something) This can store references in static fields, but these won't be available in other methods (as these will be executed on their l1). @BeforeClass @AfterClass Will be executed once for every participant. In standalone, classloader isolation is mimicking multiple l1 The @Before, @After, @Test annotations work just as with the regular junit runner. (Still wondering about @Ignore, which afaik can't be time bombed) Not all methods from the latest refactorings on ClusteringToolkit are currently implemented for Standalone mode. Mainly ClusterInfo is currently missing... Here is a test from the org.terracotta.test:junit-runner:1.0.0-SNAPSHOT available as forge project in svn, that I hope should explain it all much better: @RunWith(TerracottaRunner.class) public static class SuccessfulRunTest { private static final String OUTER_COUNTER = "outerCounter"; private static final String INNER_COUNTER = "innerCounter"; private static final AtomicInteger classInvokes = new AtomicInteger(0); private static final AtomicInteger aroundInvokes = new AtomicInteger(0); private static final AtomicInteger invokes = new AtomicInteger(0); private static Object someValue; private Object localValue; @Inject private static volatile ClusteringToolkit clusteringToolkit; @Inject private volatile ClusteringToolkit localClusteringToolkit; private volatile Barrier barrier; @BeforeAll public static void once() { assertThat(clusteringToolkit, notNullValue()); ClusteredMap<String, Integer> map = clusteringToolkit.getMap("counters"); if (map.putIfAbsent(OUTER_COUNTER, 1) != null) { for (Integer old = map.get(OUTER_COUNTER); !map.replace(OUTER_COUNTER, old, ++old); old = map.get(OUTER_COUNTER)) ; } someValue = new Object(); assertThat(clusteringToolkit.getMap("counters").get(OUTER_COUNTER), notNullValue()); } @BeforeClass public static void preSetup() { classInvokes.getAndIncrement(); verify(1, 0, 0); assertThat(someValue, nullValue()); } @Before public void setup() { assertThat(localClusteringToolkit, sameInstance(clusteringToolkit)); barrier = localClusteringToolkit.getBarrier("barrier", 2); aroundInvokes.getAndIncrement(); assertThat(someValue, nullValue()); } @Test public void testNothing() throws Exception { assertThat(clusteringToolkit.getMap("counters").get(OUTER_COUNTER), notNullValue()); barrier.await(); assertThat(localClusteringToolkit, sameInstance(clusteringToolkit)); assertThat(invokes.incrementAndGet(), equalTo(1)); localValue = new Object(); assertThat(someValue, nullValue()); } @Test public void testNothingAgain() { assertThat(invokes.incrementAndGet(), equalTo(2)); assertThat(localValue, notNullValue()); assertThat(someValue, nullValue()); clusteringToolkit.getAtomicLong(INNER_COUNTER).getAndIncrement(); } @After public void tearDown() { assertThat(classInvokes.get(), equalTo(1)); aroundInvokes.getAndIncrement(); assertThat(someValue, nullValue()); } @AfterClass public static void afterTearDown() { classInvokes.getAndIncrement(); verify(2, 4, 2); assertThat(someValue, nullValue()); } @AfterAll public static void checkOuterCounter() { assertThat("BeforeAll methods is to be called once only!", (Integer)clusteringToolkit.getMap("counters").get(OUTER_COUNTER), equalTo(1)); assertThat("Value should still be visible here", someValue, notNullValue()); assertThat("This should have been incremented twice in SuccessfulRunTest.testNothingAgain", clusteringToolkit.getAtomicLong(INNER_COUNTER).get(), is(2L)); } private static void verify(final int beforeClass, final int before, final int invokes) { assertThat("Wrong (Before|After)Class invocation count", classInvokes.get(), equalTo(beforeClass)); assertThat("Wrong (Before|After) invocation count", aroundInvokes.get(), equalTo(before)); assertThat("Wrong test method invocation count", SuccessfulRunTest.invokes.get(), equalTo(invokes)); } } Questions, comments, requests, ... complaints ? (sounds familiar somehow...) Cheers, Alex _______________________________________________ tc-dev mailing list tc-dev@lists.terracotta.org http://lists.terracotta.org/mailman/listinfo/tc-dev