// Copyright © 2009-2012 Esko Luontola <www.orfjackal.net>
// This software is released under the Apache License 2.0.
// The license text is at http://www.apache.org/licenses/LICENSE-2.0

package net.orfjackal.nestedjunit;

import org.junit.*;
import org.junit.internal.TextListener;
import org.junit.runner.*;

import java.util.*;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

public class NestedJUnitTest {

    private static final List<String> spy = new ArrayList<String>();

    private final JUnitCore junit = new JUnitCore();

    {
        junit.addListener(new TextListener(System.out));
    }

    @Before
    public void resetGlobals() {
        spy.clear();
    }


    @Test
    public void level_1_nesting() throws Exception {
        Result result = junit.run(Level1Nesting.class);

        assertThat("success", result.wasSuccessful(), is(true));
        assertThat(spy, is(Arrays.asList("L1 before", "L1 test", "L1 after")));
    }

    @RunWith(NestedJUnit.class)
    public static class Level1Nesting {

        @Before
        public void before() {
            spy.add("L1 before");
        }

        @After
        public void after() {
            spy.add("L1 after");
        }

        @Test
        public void foo() {
            spy.add("L1 test");
        }
    }


    @Test
    public void level_2_nesting() throws Exception {
        Result result = junit.run(Level2Nesting.class);

        assertThat("success", result.wasSuccessful(), is(true));
        assertThat(spy, is(Arrays.asList("L1 before", "L2 before", "L2 test", "L2 after", "L1 after")));
    }

    @RunWith(NestedJUnit.class)
    public static class Level2Nesting {

        @Before
        public void before() {
            spy.add("L1 before");
        }

        @After
        public void after() {
            spy.add("L1 after");
        }

        public class Foo {

            @Before
            public void before() {
                spy.add("L2 before");
            }

            @After
            public void after() {
                spy.add("L2 after");
            }

            @Test
            public void foo() {
                spy.add("L2 test");
            }
        }
    }

    // TODO: level 3 (arbitrary) nesting
}

@@ -1570,24 +1570,26 @@
 t(%22L1 before
+ 1
 %22, %22L2 befor
@@ -1585,24 +1585,26 @@
 , %22L2 before
+ 2
 %22, %22L2 test%22
@@ -1598,24 +1598,26 @@
 2%22, %22L2 test
+ 3
 %22, %22L2 after
@@ -1616,16 +1616,18 @@
 L2 after
+ 4
 %22, %22L1 a
@@ -1622,32 +1622,34 @@
 er 4%22, %22L1 after
+ 5
 %22)));%0A    %7D%0A%0A   
@@ -1710,32 +1710,65 @@
 evel2Nesting %7B%0A%0A
+        private int shared = 0;%0A%0A
         @Before%0A
@@ -1790,32 +1790,54 @@
 void before() %7B%0A
+            shared++;%0A
             spy.
@@ -1842,33 +1842,43 @@
 y.add(%22L1 before
-%22
+ %22 + shared
 );%0A        %7D%0A%0A  
@@ -1912,32 +1912,54 @@
  void after() %7B%0A
+            shared++;%0A
             spy.
@@ -1963,33 +1963,43 @@
 py.add(%22L1 after
-%22
+ %22 + shared
 );%0A        %7D%0A%0A  
@@ -2071,32 +2071,58 @@
 void before() %7B%0A
+                shared++;%0A
                 
@@ -2135,25 +2135,35 @@
 d(%22L2 before
-%22
+ %22 + shared
 );%0A         
@@ -2213,32 +2213,58 @@
  void after() %7B%0A
+                shared++;%0A
                 
@@ -2276,25 +2276,35 @@
 dd(%22L2 after
-%22
+ %22 + shared
 );%0A         
@@ -2351,32 +2351,58 @@
 ic void foo() %7B%0A
+                shared++;%0A
                 
@@ -2413,25 +2413,35 @@
 add(%22L2 test
-%22
+ %22 + shared
 );%0A         

Check that sharing state works across levels