diff options
12 files changed, 519 insertions, 7 deletions
diff --git a/runtime/src/main/java/org/aspectj/runtime/reflect/JoinPointImpl.java b/runtime/src/main/java/org/aspectj/runtime/reflect/JoinPointImpl.java index bb09e6869..851a8b3dc 100644 --- a/runtime/src/main/java/org/aspectj/runtime/reflect/JoinPointImpl.java +++ b/runtime/src/main/java/org/aspectj/runtime/reflect/JoinPointImpl.java @@ -79,6 +79,18 @@ class JoinPointImpl implements ProceedingJoinPoint { } } + static class InheritableThreadLocalAroundClosureStack extends InheritableThreadLocal<Stack<AroundClosure>> { + @Override + protected Stack<AroundClosure> initialValue() { + return new Stack<>(); + } + + @Override + protected Stack<AroundClosure> childValue(Stack<AroundClosure> parentValue) { + return (Stack<AroundClosure>) parentValue.clone(); + } + } + Object _this; Object target; Object[] args; @@ -140,7 +152,7 @@ class JoinPointImpl implements ProceedingJoinPoint { // will either be using arc or arcs but not both. arcs being non-null // indicates it is in use (even if an empty stack) private AroundClosure arc = null; - private Stack<AroundClosure> arcs = null; + private InheritableThreadLocalAroundClosureStack arcs = null; public void set$AroundClosure(AroundClosure arc) { this.arc = arc; @@ -149,12 +161,12 @@ class JoinPointImpl implements ProceedingJoinPoint { public void stack$AroundClosure(AroundClosure arc) { // If input parameter arc is null this is the 'unlink' call from AroundClosure if (arcs == null) { - arcs = new Stack<>(); + arcs = new InheritableThreadLocalAroundClosureStack(); } if (arc==null) { - this.arcs.pop(); + this.arcs.get().pop(); } else { - this.arcs.push(arc); + this.arcs.get().push(arc); } } @@ -167,7 +179,8 @@ class JoinPointImpl implements ProceedingJoinPoint { return arc.run(arc.getState()); } } else { - return arcs.peek().run(arcs.peek().getState()); + final AroundClosure ac = arcs.get().peek(); + return ac.run(ac.getState()); } } @@ -177,7 +190,7 @@ class JoinPointImpl implements ProceedingJoinPoint { if (arcs == null) { ac = arc; } else { - ac = arcs.peek(); + ac = arcs.get().peek(); } if (ac == null) { diff --git a/testing/src/test/java/org/aspectj/testing/RunSpec.java b/testing/src/test/java/org/aspectj/testing/RunSpec.java index 534ed6374..181eb9062 100644 --- a/testing/src/test/java/org/aspectj/testing/RunSpec.java +++ b/testing/src/test/java/org/aspectj/testing/RunSpec.java @@ -36,6 +36,7 @@ public class RunSpec implements ITestStep { private String options; private String cpath; private String mpath; + private String orderedStdout; private String orderedStderr; private AjcTest myTest; private OutputSpec stdErrSpec; @@ -82,7 +83,7 @@ public class RunSpec implements ITestStep { stdErrSpec.matchAgainst(rr.getStdErr(), orderedStderr); } if (stdOutSpec != null) { - stdOutSpec.matchAgainst(rr.getStdOut()); + stdOutSpec.matchAgainst(rr.getStdOut(), orderedStdout); } } finally { restoreProperties(); @@ -175,6 +176,10 @@ public class RunSpec implements ITestStep { this.orderedStderr = orderedStderr; } + public void setOrderedStdout(String orderedStdout) { + this.orderedStdout = orderedStdout; + } + public String getClassToRun() { return classToRun; } diff --git a/testing/src/test/java/org/aspectj/testing/XMLBasedAjcTestCase.java b/testing/src/test/java/org/aspectj/testing/XMLBasedAjcTestCase.java index 3954c7ecc..6af8ced47 100644 --- a/testing/src/test/java/org/aspectj/testing/XMLBasedAjcTestCase.java +++ b/testing/src/test/java/org/aspectj/testing/XMLBasedAjcTestCase.java @@ -251,6 +251,7 @@ public abstract class XMLBasedAjcTestCase extends AjcTestCase { digester.addSetProperties("suite/ajc-test/run", "module", "moduleToRun"); digester.addSetProperties("suite/ajc-test/run", "ltw", "ltwFile"); digester.addSetProperties("suite/ajc-test/run", "xlintfile", "xlintFile"); + digester.addSetProperties("suite/ajc-test/run/stdout", "ordered", "orderedStdout"); digester.addSetProperties("suite/ajc-test/run/stderr", "ordered", "orderedStderr"); digester.addSetNext("suite/ajc-test/run", "addTestStep", "org.aspectj.testing.ITestStep"); digester.addObjectCreate("*/message", ExpectedMessageSpec.class); diff --git a/tests/bugs198/github_128/Application.java b/tests/bugs198/github_128/Application.java new file mode 100644 index 000000000..9a4a7312f --- /dev/null +++ b/tests/bugs198/github_128/Application.java @@ -0,0 +1,42 @@ +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +public class Application { + static int proceedTimesOuter; + static int proceedTimesInner; + static boolean useThreadPool = false; + static ExecutorService executorService = Executors.newFixedThreadPool(2); + + @MarkerA + @MarkerB + public void doSomething() { + System.out.println(" Doing something"); + } + + public static void main(String[] args) throws ExecutionException, InterruptedException { + proceedTimesOuter = Integer.parseInt(args[0]); + proceedTimesInner = Integer.parseInt(args[1]); + useThreadPool = args.length > 2 && args[2].trim().equalsIgnoreCase("true"); + if (useThreadPool) + prepopulateFixedThreadPool(); + + new Application().doSomething(); + Thread.sleep(500); + } + + private static void prepopulateFixedThreadPool() throws InterruptedException, ExecutionException { + Future<?> future1 = executorService.submit(() -> { + try { Thread.sleep(250); } + catch (InterruptedException e) { e.printStackTrace(); } + }); + Future<?> future2 = executorService.submit(() -> { + try { Thread.sleep(250); } + catch (InterruptedException e) { e.printStackTrace(); } + }); + future1.get(); + future2.get(); + } + +} diff --git a/tests/bugs198/github_128/MarkerA.java b/tests/bugs198/github_128/MarkerA.java new file mode 100644 index 000000000..89e60978c --- /dev/null +++ b/tests/bugs198/github_128/MarkerA.java @@ -0,0 +1,9 @@ +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target(METHOD) +public @interface MarkerA {} diff --git a/tests/bugs198/github_128/MarkerB.java b/tests/bugs198/github_128/MarkerB.java new file mode 100644 index 000000000..6f6aa3dd0 --- /dev/null +++ b/tests/bugs198/github_128/MarkerB.java @@ -0,0 +1,9 @@ +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target(METHOD) +public @interface MarkerB {} diff --git a/tests/bugs198/github_128/annotation_syntax/MarkerAAspect.aj b/tests/bugs198/github_128/annotation_syntax/MarkerAAspect.aj new file mode 100644 index 000000000..d090ed9ea --- /dev/null +++ b/tests/bugs198/github_128/annotation_syntax/MarkerAAspect.aj @@ -0,0 +1,21 @@ +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.DeclarePrecedence; + +@Aspect +@DeclarePrecedence("MarkerAAspect, MarkerBAspect") +public class MarkerAAspect { + @Around("@annotation(MarkerA) && execution(* *(..))") + public Object intercept(ProceedingJoinPoint thisJoinPoint) throws Throwable { + System.out.println(">> Outer intercept"); + Object result = null; + for (int i = 0; i < Application.proceedTimesOuter; i++) { + System.out.println(" >> Outer proceed"); + result = thisJoinPoint.proceed(); + System.out.println(" << Outer proceed"); + } + System.out.println("<< Outer intercept"); + return result; + } +} diff --git a/tests/bugs198/github_128/annotation_syntax/MarkerBAspect.aj b/tests/bugs198/github_128/annotation_syntax/MarkerBAspect.aj new file mode 100644 index 000000000..d5548f9da --- /dev/null +++ b/tests/bugs198/github_128/annotation_syntax/MarkerBAspect.aj @@ -0,0 +1,37 @@ +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@Aspect +public class MarkerBAspect { + @Around("@annotation(MarkerB) && execution(* *(..))") + public Object intercept(ProceedingJoinPoint thisJoinPoint) throws Throwable { + Runnable runnable = new Runnable() { + @Override + public void run() { + try { + for (int i = 0; i < Application.proceedTimesInner; i++) { + System.out.println(" >> Inner proceed"); + thisJoinPoint.proceed(); + System.out.println(" << Inner proceed"); + } + } + catch (Throwable throwable) { + throwable.printStackTrace(System.out); + } + } + }; + + System.out.println(" >> Inner intercept"); + if (Application.useThreadPool) + Application.executorService.submit(runnable); + else + new Thread(runnable).start(); + System.out.println(" << Inner intercept"); + return null; + } +} diff --git a/tests/bugs198/github_128/native_syntax/MarkerAAspect.aj b/tests/bugs198/github_128/native_syntax/MarkerAAspect.aj new file mode 100644 index 000000000..5e2ac5424 --- /dev/null +++ b/tests/bugs198/github_128/native_syntax/MarkerAAspect.aj @@ -0,0 +1,15 @@ +public aspect MarkerAAspect { + declare precedence : MarkerAAspect, MarkerBAspect; + + Object around() : @annotation(MarkerA) && execution(* *(..)) { + System.out.println(">> Outer intercept"); + Object result = null; + for (int i = 0; i < Application.proceedTimesOuter; i++) { + System.out.println(" >> Outer proceed"); + result = proceed(); + System.out.println(" << Outer proceed"); + } + System.out.println("<< Outer intercept"); + return result; + } +} diff --git a/tests/bugs198/github_128/native_syntax/MarkerBAspect.aj b/tests/bugs198/github_128/native_syntax/MarkerBAspect.aj new file mode 100644 index 000000000..52e95d1eb --- /dev/null +++ b/tests/bugs198/github_128/native_syntax/MarkerBAspect.aj @@ -0,0 +1,27 @@ +public aspect MarkerBAspect { + Object around() : @annotation(MarkerB) && execution(* *(..)) { + Runnable runnable = new Runnable() { + @Override + public void run() { + try { + for (int i = 0; i < Application.proceedTimesInner; i++) { + System.out.println(" >> Inner proceed"); + proceed(); + System.out.println(" << Inner proceed"); + } + } + catch (Throwable throwable) { + throwable.printStackTrace(System.out); + } + } + }; + + System.out.println(" >> Inner intercept"); + if (Application.useThreadPool) + Application.executorService.submit(runnable); + else + new Thread(runnable).start(); + System.out.println(" << Inner intercept"); + return null; + } +} diff --git a/tests/src/test/java/org/aspectj/systemtest/ajc198/Bugs198Tests.java b/tests/src/test/java/org/aspectj/systemtest/ajc198/Bugs198Tests.java index cb3b781bb..8453bc163 100644 --- a/tests/src/test/java/org/aspectj/systemtest/ajc198/Bugs198Tests.java +++ b/tests/src/test/java/org/aspectj/systemtest/ajc198/Bugs198Tests.java @@ -21,6 +21,23 @@ public class Bugs198Tests extends XMLBasedAjcTestCase { runTest("ITD annotation with mandatory parameter via aspectpath"); } + public void testAsyncProceedNestedAroundAdvice_gh128() { + runTest("asynchronous proceed for nested around-advice (@AspectJ)"); + } + + public void testAsyncProceedNestedAroundAdviceThreadPool_gh128() { + // TODO: future improvement, see https://github.com/eclipse/org.aspectj/issues/141 + // runTest("asynchronous proceed for nested around-advice (@AspectJ, thread pool)"); + } + + public void testAsyncProceedNestedAroundAdviceNative_gh128() { + runTest("asynchronous proceed for nested around-advice (native)"); + } + + public void testAsyncProceedNestedAroundAdviceNativeThreadPool_gh128() { + runTest("asynchronous proceed for nested around-advice (native, thread pool)"); + } + public static Test suite() { return XMLBasedAjcTestCase.loadSuite(Bugs198Tests.class); } diff --git a/tests/src/test/resources/org/aspectj/systemtest/ajc198/ajc198.xml b/tests/src/test/resources/org/aspectj/systemtest/ajc198/ajc198.xml index 85bd872b3..6f2a34274 100644 --- a/tests/src/test/resources/org/aspectj/systemtest/ajc198/ajc198.xml +++ b/tests/src/test/resources/org/aspectj/systemtest/ajc198/ajc198.xml @@ -100,4 +100,320 @@ <compile files="Buffers.java" options="--release 8"/> </ajc-test> + <ajc-test dir="bugs198/github_128" title="asynchronous proceed for nested around-advice (@AspectJ)"> + <compile files="Application.java MarkerA.java MarkerB.java annotation_syntax/MarkerAAspect.aj annotation_syntax/MarkerBAspect.aj" options="-1.8" /> + <run class="Application" options="1,1"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text="<< Outer intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + </stdout> + </run> + <run class="Application" options="2,1"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text="<< Outer intercept"/> + </stdout> + </run> + <run class="Application" options="1,2"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text="<< Outer intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + </stdout> + </run> + <run class="Application" options="2,2"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" >> Inner proceed"/> + <line text=" << Inner intercept"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" << Outer proceed"/> + <line text=" >> Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text="<< Outer intercept"/> + </stdout> + </run> + </ajc-test> + + <ajc-test dir="bugs198/github_128" title="asynchronous proceed for nested around-advice (@AspectJ, thread pool)"> + <compile files="Application.java MarkerA.java MarkerB.java annotation_syntax/MarkerAAspect.aj annotation_syntax/MarkerBAspect.aj" options="-1.8" /> + <run class="Application" options="1,1,true"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text="<< Outer intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + </stdout> + </run> + <run class="Application" options="2,1,true"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text="<< Outer intercept"/> + </stdout> + </run> + <run class="Application" options="1,2,true"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text="<< Outer intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + </stdout> + </run> + <run class="Application" options="2,2,true"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" >> Inner proceed"/> + <line text=" << Inner intercept"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" << Outer proceed"/> + <line text=" >> Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text="<< Outer intercept"/> + </stdout> + </run> + </ajc-test> + + <ajc-test dir="bugs198/github_128" title="asynchronous proceed for nested around-advice (native)"> + <compile files="Application.java MarkerA.java MarkerB.java native_syntax/MarkerAAspect.aj native_syntax/MarkerBAspect.aj" options="-1.8" /> + <run class="Application" options="1,1"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text="<< Outer intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + </stdout> + </run> + <run class="Application" options="2,1"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text="<< Outer intercept"/> + </stdout> + </run> + <run class="Application" options="1,2"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text="<< Outer intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + </stdout> + </run> + <run class="Application" options="2,2"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" >> Inner proceed"/> + <line text=" << Inner intercept"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" << Outer proceed"/> + <line text=" >> Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text="<< Outer intercept"/> + </stdout> + </run> + </ajc-test> + + <ajc-test dir="bugs198/github_128" title="asynchronous proceed for nested around-advice (native, thread pool)"> + <compile files="Application.java MarkerA.java MarkerB.java native_syntax/MarkerAAspect.aj native_syntax/MarkerBAspect.aj" options="-1.8" /> + <run class="Application" options="1,1,true"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text="<< Outer intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + </stdout> + </run> + <run class="Application" options="2,1,true"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text="<< Outer intercept"/> + </stdout> + </run> + <run class="Application" options="1,2,true"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text="<< Outer intercept"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + </stdout> + </run> + <run class="Application" options="2,2,true"> + <stdout ordered="no"> + <line text=">> Outer intercept"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" << Inner intercept"/> + <line text=" << Outer proceed"/> + <line text=" >> Outer proceed"/> + <line text=" >> Inner intercept"/> + <line text=" >> Inner proceed"/> + <line text=" << Inner intercept"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" << Outer proceed"/> + <line text=" >> Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" >> Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text=" Doing something"/> + <line text=" << Inner proceed"/> + <line text="<< Outer intercept"/> + </stdout> + </run> + </ajc-test> + </suite> |