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

Reply via email to