From 78f5a17c4fd3d0998233c48bcc226752b80cef09 Mon Sep 17 00:00:00 2001 From: sebi Date: Tue, 4 Aug 2015 16:33:58 +0300 Subject: [PATCH 1/2] added block listener support --- .../spockframework/compiler/SpecParser.java | 15 ++++-- .../spockframework/compiler/SpecRewriter.java | 53 ++++++++++++++++++- .../report/log/ReportLogEmitter.java | 10 ++-- .../runtime/AbstractRunListener.java | 1 + .../runtime/AsyncRunListener.java | 6 ++- .../spockframework/runtime/IRunListener.java | 7 ++- .../runtime/MasterRunListener.java | 6 +++ .../extension/ReportLogExtensionSpec.groovy | 2 +- 8 files changed, 87 insertions(+), 13 deletions(-) diff --git a/spock-core/src/main/java/org/spockframework/compiler/SpecParser.java b/spock-core/src/main/java/org/spockframework/compiler/SpecParser.java index 017083a8b7..2abf186388 100755 --- a/spock-core/src/main/java/org/spockframework/compiler/SpecParser.java +++ b/spock-core/src/main/java/org/spockframework/compiler/SpecParser.java @@ -91,7 +91,7 @@ private boolean constructorMayHaveBeenAddedByCompiler(ConstructorNode constructo public void visitMethod(MethodNode method) { if (isIgnoredMethod(method)) return; - + if (isFixtureMethod(method)) buildFixtureMethod(method); else if (isFeatureMethod(method)) @@ -111,7 +111,7 @@ private boolean isFixtureMethod(MethodNode method) { if (!fmName.equalsIgnoreCase(name)) continue; // assertion: is (meant to be) a fixture method, so we'll return true in the end - + if (method.isStatic()) errorReporter.error(method, "Fixture methods must not be static"); if (!fmName.equals(name)) @@ -172,7 +172,7 @@ private void buildFeatureMethod(MethodNode method) { spec.getMethods().add(feature); } - private void buildHelperMethod(MethodNode method) { + private void buildHelperMethod(MethodNode method) { Method helper = new HelperMethod(spec, method); spec.getMethods().add(helper); @@ -192,7 +192,7 @@ private void buildBlocks(Method method) throws InvalidSpecCompileException { else currBlock = addBlock(method, stat); } - + checkIsValidSuccessor(method, BlockParseInfo.METHOD_END, method.getAst().getLastLineNumber(), method.getAst().getLastColumnNumber()); @@ -212,8 +212,13 @@ private Block addBlock(Method method, Statement stat) throws InvalidSpecCompileE String description = getDescription(stat); if (description == null) block.getAst().add(stat); - else + else { + if(block.getName().equalsIgnoreCase("when") || block.getName().equalsIgnoreCase("then") + || block.getName().equalsIgnoreCase("setup")) { + block.getAst().add(stat); + } block.getDescriptions().add(description); + } return block; } diff --git a/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java b/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java index 39de377464..04541c6287 100755 --- a/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java +++ b/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java @@ -19,6 +19,7 @@ import java.util.*; import org.codehaus.groovy.ast.*; +import org.codehaus.groovy.ast.builder.AstBuilder; import org.codehaus.groovy.ast.expr.*; import org.codehaus.groovy.ast.stmt.*; import org.codehaus.groovy.runtime.MetaClassHelper; @@ -33,7 +34,7 @@ /** * A Spec visitor responsible for most of the rewriting of a Spec's AST. - * + * * @author Peter Niederwieser */ // IDEA: mock controller / leaveScope calls should only be inserted when necessary (increases robustness) @@ -176,7 +177,7 @@ def sharedFieldGetter() { sharedInstance.sharedField } class DerivedSpec extends BaseSpec {} // when DerivedSpec is run: - + def sharedInstance = new DerivedSpec() def spec = new DerivedSpec() @@ -312,7 +313,55 @@ public void visitAnyBlock(Block block) { methodHasCondition |= deep.isConditionFound(); } + private void updateNotify(String method, Block block) { + List statements = block.getAst(); + if (!statements.isEmpty()) { + int count = 0; + for (Statement stmt : statements) { + if (stmt instanceof ExpressionStatement) { + ExpressionStatement exptrStmt = (ExpressionStatement) stmt; + if (exptrStmt.getExpression() instanceof GStringExpression || (exptrStmt.getExpression() instanceof ConstantExpression && ((ConstantExpression)exptrStmt.getExpression()).getValue() instanceof String)) { + ForStatement forStmt = getNotifyWhenThen(method, exptrStmt.getExpression()); + statements.set(count, forStmt); + } + } + count++; + } + } + } + + private ForStatement getNotifyWhenThen(String blockType, Expression expr) { + List nodes = new AstBuilder().buildFromString("for( def listener : getSpecificationContext().getCurrentSpec().getListeners()){ \n" + + "true;\n" + + + "}\n"); + ForStatement forStatement = (ForStatement) ((BlockStatement) ((BlockStatement) nodes.get(0)).getStatements().get(0)).getStatements().get(0); + BlockStatement forLoopBlock = new BlockStatement(); + forLoopBlock.addStatement( + new ExpressionStatement( + new BinaryExpression( + new MethodCallExpression( + new VariableExpression("listener"), + new ConstantExpression("block"), + new ArgumentListExpression(new Expression[]{new ConstantExpression(blockType), expr}) + ), + new Token( Types.LOGICAL_OR, "||", -1, -1 ), + new ConstantExpression(true) + ) + ) + ); + forStatement.setLoopBlock(forLoopBlock); + return forStatement; + } + + public void visitWhenBlock(WhenBlock block) throws Exception { + updateNotify("when", block); + + } + public void visitThenBlock(ThenBlock block) { + updateNotify("then", block); + if (block.isFirstInChain()) thenBlockChainHasExceptionCondition = false; DeepBlockRewriter deep = new DeepBlockRewriter(this); diff --git a/spock-core/src/main/java/org/spockframework/report/log/ReportLogEmitter.java b/spock-core/src/main/java/org/spockframework/report/log/ReportLogEmitter.java index 823bb5d4bc..62d00a9515 100644 --- a/spock-core/src/main/java/org/spockframework/report/log/ReportLogEmitter.java +++ b/spock-core/src/main/java/org/spockframework/report/log/ReportLogEmitter.java @@ -77,12 +77,16 @@ public void beforeSpec(SpecInfo spec) { specFailed = false; emit(putAll(mapOf( - "package", spec.getPackage(), - "name", spec.getName(), - "start", getCurrentTime() + "package", spec.getPackage(), + "name", spec.getName(), + "start", getCurrentTime() ), renderNarrative(spec.getNarrative()), renderTags(spec.getTags()))); } + public void block(String type, String description) { +// System.out.println(type+description); + } + public void beforeFeature(FeatureInfo feature) { currentFeature = feature; featureFailed = false; diff --git a/spock-core/src/main/java/org/spockframework/runtime/AbstractRunListener.java b/spock-core/src/main/java/org/spockframework/runtime/AbstractRunListener.java index c229f4e994..11a9ad46e4 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/AbstractRunListener.java +++ b/spock-core/src/main/java/org/spockframework/runtime/AbstractRunListener.java @@ -26,4 +26,5 @@ public void afterSpec(SpecInfo spec) {} public void error(ErrorInfo error) {} public void specSkipped(SpecInfo spec) {} public void featureSkipped(FeatureInfo feature) {} + public void block(String type, String description) {} } diff --git a/spock-core/src/main/java/org/spockframework/runtime/AsyncRunListener.java b/spock-core/src/main/java/org/spockframework/runtime/AsyncRunListener.java index e23ccfde97..7830d6b89d 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/AsyncRunListener.java +++ b/spock-core/src/main/java/org/spockframework/runtime/AsyncRunListener.java @@ -66,7 +66,11 @@ public void beforeSpec(final SpecInfo spec) { public void run() { delegate.beforeSpec(spec); } - }); + }); + } + + public void block(String type, String description) { + delegate.block(type, description); } public void beforeFeature(final FeatureInfo feature) { diff --git a/spock-core/src/main/java/org/spockframework/runtime/IRunListener.java b/spock-core/src/main/java/org/spockframework/runtime/IRunListener.java index 26d9e07f31..74fbfd39df 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/IRunListener.java +++ b/spock-core/src/main/java/org/spockframework/runtime/IRunListener.java @@ -30,6 +30,11 @@ public interface IRunListener { */ void beforeSpec(SpecInfo spec); + /** + * Called when a block is reached. + */ + void block(String type,String description); + /** * Called before each feature of a spec. */ @@ -71,7 +76,7 @@ public interface IRunListener { // IDEA: might be able to remove remaining two methods and // call before/after instead, since skip flag should be set on // SpecInfo/FeatureInfo anyway - + /** * Called if a spec is skipped, for example because it is marked * with @Ignore. diff --git a/spock-core/src/main/java/org/spockframework/runtime/MasterRunListener.java b/spock-core/src/main/java/org/spockframework/runtime/MasterRunListener.java index 25bba7d52f..5a21cd6d6a 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/MasterRunListener.java +++ b/spock-core/src/main/java/org/spockframework/runtime/MasterRunListener.java @@ -29,6 +29,12 @@ public void beforeSpec(SpecInfo spec) { } } + public void block(String type, String description) { + for (IRunListener listener : spec.getListeners()) { + listener.block(type, description); + } + } + public void beforeFeature(FeatureInfo feature) { for (IRunListener listener : spec.getListeners()) { listener.beforeFeature(feature); diff --git a/spock-specs/src/test/groovy/org/spockframework/smoke/extension/ReportLogExtensionSpec.groovy b/spock-specs/src/test/groovy/org/spockframework/smoke/extension/ReportLogExtensionSpec.groovy index 231733a93a..3cde9ca9de 100644 --- a/spock-specs/src/test/groovy/org/spockframework/smoke/extension/ReportLogExtensionSpec.groovy +++ b/spock-specs/src/test/groovy/org/spockframework/smoke/extension/ReportLogExtensionSpec.groovy @@ -58,6 +58,7 @@ So that bar then: "baz" println("out2") + and: "bazbaz" System.err.println("err2") } @@ -109,7 +110,6 @@ loadLogFile([{ def "write execution log for spec with failing feature"() { runner.throwFailure = false - when: runner.runWithImports( """ From bbf483715c2b98f6392a9bb2b55c4b15514e533b Mon Sep 17 00:00:00 2001 From: sebi Date: Tue, 4 Aug 2015 18:23:45 +0300 Subject: [PATCH 2/2] notify setup --- .../java/org/spockframework/compiler/SpecRewriter.java | 5 ++++- .../org/spockframework/runtime/AsyncRunListener.java | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java b/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java index 04541c6287..db13ca22ab 100755 --- a/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java +++ b/spock-core/src/main/java/org/spockframework/compiler/SpecRewriter.java @@ -356,7 +356,10 @@ private ForStatement getNotifyWhenThen(String blockType, Expression expr) { public void visitWhenBlock(WhenBlock block) throws Exception { updateNotify("when", block); + } + public void visitSetupBlock(SetupBlock block) throws Exception { + updateNotify("setup", block); } public void visitThenBlock(ThenBlock block) { @@ -604,7 +607,7 @@ private Expression createDefaultValueInitializer(DeclarationExpression expr) { for (Expression elementExpr : tupleExpr.getExpressions()) { Variable variable = (Variable) elementExpr; listExpr.addExpression(new ConstantExpression( - ReflectionUtil.getDefaultValue(variable.getOriginType().getTypeClass()))); + ReflectionUtil.getDefaultValue(variable.getOriginType().getTypeClass()))); } return listExpr; diff --git a/spock-core/src/main/java/org/spockframework/runtime/AsyncRunListener.java b/spock-core/src/main/java/org/spockframework/runtime/AsyncRunListener.java index 7830d6b89d..bf2f4128bc 100644 --- a/spock-core/src/main/java/org/spockframework/runtime/AsyncRunListener.java +++ b/spock-core/src/main/java/org/spockframework/runtime/AsyncRunListener.java @@ -68,9 +68,12 @@ public void run() { } }); } - - public void block(String type, String description) { - delegate.block(type, description); + public void block(final String type, final String description) { + addEvent(new Runnable() { + public void run() { + delegate.block(type, description); + } + }); } public void beforeFeature(final FeatureInfo feature) {