Permalink
Browse files

Removed OneTimeResourceLoader and made sure glue code is loaded only …

…once. The Backend.loadGlue method should ideally be removed, and the World and gluePaths passed to each Backend's constructor. Other TODOs on this branch: rename World to Glue. RuntimeGlue should not have a ref back to Runtime. Make Scala work again (disabled it because I don't have the required Scala fu)
  • Loading branch information...
1 parent fed7d3b commit bd0634ea5ee0d5ba72f7391eb1c2fb2e0ab5763e @aslakhellesoy aslakhellesoy committed Jan 18, 2012
Showing with 112 additions and 115 deletions.
  1. +2 −1 build.xml
  2. +6 −1 clojure/src/main/java/cucumber/runtime/clojure/ClojureBackend.java
  3. +1 −2 core/src/main/java/cucumber/cli/Main.java
  4. +1 −4 core/src/main/java/cucumber/io/ClasspathResourceLoader.java
  5. +0 −33 core/src/main/java/cucumber/io/OneTimeResourceLoader.java
  6. +6 −4 core/src/main/java/cucumber/runtime/Backend.java
  7. +6 −8 core/src/main/java/cucumber/runtime/Runtime.java
  8. +5 −1 core/src/main/java/cucumber/runtime/RuntimeWorld.java
  9. +3 −3 core/src/test/java/cucumber/formatter/HTMLFormatterTest.java
  10. +2 −2 core/src/test/java/cucumber/runtime/BackgroundTest.java
  11. +0 −20 core/src/test/java/cucumber/runtime/StubBackend.java
  12. +6 −1 core/src/test/java/cucumber/runtime/UndefinedStepsTrackerTest.java
  13. +4 −1 cucumber-jvm.ipr
  14. +5 −2 groovy/src/main/java/cucumber/runtime/groovy/GroovyBackend.java
  15. +5 −1 ioke/src/main/java/cucumber/runtime/ioke/IokeBackend.java
  16. +5 −1 java/src/main/java/cucumber/runtime/java/JavaBackend.java
  17. +2 −1 java/src/test/java/cucumber/runtime/java/JavaBackendTest.java
  18. +14 −8 java/src/test/java/cucumber/runtime/java/JavaHookTest.java
  19. +10 −4 java/src/test/java/cucumber/runtime/java/JavaStepDefinitionDependencyInjectionTest.java
  20. +10 −7 java/src/test/java/cucumber/runtime/java/JavaStepDefinitionTest.java
  21. +6 −3 jruby/src/main/java/cucumber/runtime/jruby/JRubyBackend.java
  22. +1 −2 junit/src/main/java/cucumber/junit/Cucumber.java
  23. +6 −2 jython/src/main/java/cucumber/runtime/jython/JythonBackend.java
  24. +6 −3 rhino/src/main/java/cucumber/runtime/rhino/RhinoBackend.java
View
@@ -1,5 +1,6 @@
<project name="cucumber-jvm" default="publish-local">
- <property name="modules" value="core:junit:java:picocontainer:spring:guice:groovy:ioke:rhino:clojure:jruby:jython:scala:openejb:weld"/>
+ <!-- TODO: put scala back -->
+ <property name="modules" value="core:junit:java:picocontainer:spring:guice:groovy:ioke:rhino:clojure:jruby:jython:openejb:weld"/>
<target name="publish-local">
<subant target="publish-local" buildpath="${modules}"/>
@@ -29,13 +29,18 @@ public ClojureBackend(ResourceLoader resourceLoader) {
}
@Override
- public void buildWorld(List<String> gluePaths, World world) {
+ public void loadGlue(World world, List<String> gluePaths) {
this.world = world;
for (String gluePath : gluePaths) {
for (Resource resource : resourceLoader.resources(gluePath, ".clj")) {
loadScript(resource);
}
}
+
+ }
+
+ @Override
+ public void buildWorld() {
}
private void loadScript(String path) {
@@ -3,7 +3,6 @@
import cucumber.formatter.FormatterFactory;
import cucumber.formatter.MultiFormatter;
import cucumber.io.FileResourceLoader;
-import cucumber.io.OneTimeResourceLoader;
import cucumber.runtime.Runtime;
import cucumber.runtime.snippets.SummaryPrinter;
import gherkin.formatter.Formatter;
@@ -72,7 +71,7 @@ public static void main(String[] argv) throws Throwable {
System.exit(1);
}
- Runtime runtime = new Runtime(gluePaths, new OneTimeResourceLoader(new FileResourceLoader()), isDryRun);
+ Runtime runtime = new Runtime(gluePaths, new FileResourceLoader(), isDryRun);
if (dotCucumber != null) {
writeDotCucumber(featurePaths, dotCucumber, runtime);
@@ -45,10 +45,7 @@
Collection<T> result = new HashSet<T>();
for (Class<? extends T> clazz : getDescendants(parentType, packagePath)) {
if (Utils.isInstantiable(clazz)) {
- try {
- result.add(newInstance(constructorParams, constructorArgs, clazz));
- } catch (CucumberException ignore) {
- }
+ result.add(newInstance(constructorParams, constructorArgs, clazz));
}
}
return result;
@@ -1,33 +0,0 @@
-package cucumber.io;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * A wrapper for the existing resource loaders to ensure that
- * they're only loaded one time.
- * This allows the other resource loaders to still be used, for whatever purpose they've got
- * whilst in special cases preventing things from being loaded multiple times.
- */
-public class OneTimeResourceLoader implements ResourceLoader {
-
- private Set<String> loadedResourcePaths = new HashSet<String>();
- private ResourceLoader nestedLoader;
-
- public OneTimeResourceLoader(ResourceLoader loader) {
- this.nestedLoader = loader;
- }
-
- @Override
- public Iterable<Resource> resources(String path, String suffix) {
- Set<Resource> resourcesToLoad = new HashSet<Resource>();
-
- for (Resource resource : nestedLoader.resources(path, suffix)) {
- if (loadedResourcePaths.add(resource.getPath())) {
- resourcesToLoad.add(resource);
- }
- }
-
- return resourcesToLoad;
- }
-}
@@ -6,13 +6,15 @@
public interface Backend {
/**
+ * Invoked once before all features. This is where stepdefs and hooks should be loaded.
+ */
+ void loadGlue(World world, List<String> gluePaths);
+
+ /**
* Invoked before a new scenario starts. Implementations should do any necessary
* setup of new, isolated state here.
- *
- * @param gluePaths where to load from
- * @param world into where
*/
- void buildWorld(List<String> gluePaths, World world);
+ void buildWorld();
void disposeWorld();
@@ -29,13 +29,11 @@
public class Runtime {
private static final byte ERRORS = 0x1;
private static final List<Object> NO_FILTERS = emptyList();
- private static final Collection<String> NO_TAGS = emptyList();
private final UndefinedStepsTracker tracker;
private final List<Throwable> errors = new ArrayList<Throwable>();
private final Collection<? extends Backend> backends;
private final boolean isDryRun;
- private final List<String> gluePaths;
private final ResourceLoader resourceLoader;
private World world;
@@ -49,13 +47,15 @@ public Runtime(List<String> gluePaths, ResourceLoader resourceLoader, boolean is
}
public Runtime(List<String> gluePaths, ResourceLoader resourceLoader, Collection<? extends Backend> backends, boolean isDryRun) {
- this.gluePaths = gluePaths;
this.backends = backends;
this.resourceLoader = resourceLoader;
this.isDryRun = isDryRun;
this.tracker = new UndefinedStepsTracker(backends);
this.world = new RuntimeWorld(this);
+ for (Backend backend : backends) {
+ backend.loadGlue(world, gluePaths);
+ }
}
private static Collection<? extends Backend> loadBackends(ResourceLoader resourceLoader) {
@@ -89,9 +89,9 @@ public void run(CucumberFeature cucumberFeature, Formatter formatter, Reporter r
formatter.eof();
}
- public void buildBackendWorlds(World world) {
+ public void buildBackendWorlds() {
for (Backend backend : backends) {
- backend.buildWorld(gluePaths, world);
+ backend.buildWorld();
}
tracker.reset();
}
@@ -111,9 +111,7 @@ public void disposeBackendWorlds() {
*/
public void writeStepdefsJson(List<String> featurePaths, File dotCucumber) throws IOException {
List<CucumberFeature> features = load(resourceLoader, featurePaths, NO_FILTERS);
- //TODO: ensure that tagging still works
- //World world = new RuntimeWorld(this, NO_TAGS);
- buildBackendWorlds(world);
+ buildBackendWorlds();
List<StepDefinition> stepDefs = world.getStepDefinitions();
List<MetaStepdef> metaStepdefs = new StepdefGenerator().generate(stepDefs, features);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
@@ -14,6 +14,9 @@
private static final Object DUMMY_ARG = new Object();
// TODO - it's expensive to create a new LocalizedXStreams for each scenario - reuse a global one. (heh, except world is being recreated each time!)
+ /*
+ In the light of how this class is now used - one instance - purpose is to store glue code - I think we should rename it to RuntimeGlue implements Glue.
+ */
private final LocalizedXStreams localizedXStreams = new LocalizedXStreams();
private final List<StepDefinition> stepDefinitions = new ArrayList<StepDefinition>();
private final List<HookDefinition> beforeHooks = new ArrayList<HookDefinition>();
@@ -26,12 +29,13 @@
public RuntimeWorld(Runtime runtime) {
//TODO: does the runtime world need to see the runtime?
+ // AH: No, it shouldn't - it's a cyclic dependency we should get rid of
this.runtime = runtime;
}
@Override
public void buildBackendContextAndRunBeforeHooks(Reporter reporter, Set<String> tags) {
- runtime.buildBackendWorlds(this);
+ runtime.buildBackendWorlds();
Collections.sort(beforeHooks, new HookComparator(true));
runHooks(beforeHooks, reporter, tags);
}
@@ -1,8 +1,8 @@
package cucumber.formatter;
import cucumber.io.ClasspathResourceLoader;
+import cucumber.runtime.Backend;
import cucumber.runtime.Runtime;
-import cucumber.runtime.StubBackend;
import cucumber.runtime.model.CucumberFeature;
import org.junit.Test;
import org.mozilla.javascript.Context;
@@ -14,11 +14,11 @@
import java.io.IOException;
import java.util.List;
-import static gherkin.util.FixJava.readReader;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
public class HTMLFormatterTest {
@Test
@@ -28,7 +28,7 @@ public void writes_proper_html() throws IOException {
ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader();
List<CucumberFeature> features = CucumberFeature.load(resourceLoader, asList("cucumber/formatter/HTMLFormatterTest.feature"), emptyList());
List<String> gluePaths = emptyList();
- Runtime runtime = new Runtime(gluePaths, resourceLoader, asList(new StubBackend()), false);
+ Runtime runtime = new Runtime(gluePaths, resourceLoader, asList(mock(Backend.class)), false);
runtime.run(features.get(0), f, f);
f.done();
@@ -11,12 +11,12 @@
import static cucumber.runtime.TestHelper.feature;
import static java.util.Arrays.asList;
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
public class BackgroundTest {
@Test
public void should_run_background() throws IOException {
- Backend backend = new StubBackend();
- Runtime runtime = new Runtime(new ArrayList<String>(), new ClasspathResourceLoader(), asList(backend), false);
+ Runtime runtime = new Runtime(new ArrayList<String>(), new ClasspathResourceLoader(), asList(mock(Backend.class)), false);
CucumberFeature feature = feature("test.feature", "" +
"Feature:\n" +
" Background:\n" +
@@ -1,20 +0,0 @@
-package cucumber.runtime;
-
-import gherkin.formatter.model.Step;
-
-import java.util.List;
-
-public class StubBackend implements Backend {
- @Override
- public void buildWorld(List<String> gluePaths, World world) {
- }
-
- @Override
- public void disposeWorld() {
- }
-
- @Override
- public String getSnippet(Step step) {
- return "SNIP";
- }
-}
@@ -52,7 +52,12 @@ public void star_keyword_becomes_given_when_no_previous_step() {
private class TestBackend implements Backend {
@Override
- public void buildWorld(List<String> gluePaths, World world) {
+ public void loadGlue(World world, List<String> gluePaths) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void buildWorld() {
throw new UnsupportedOperationException();
}
View
@@ -21,6 +21,10 @@
<entry name="?*.tld" />
<entry name="?*.ftl" />
<entry name="?*.feature" />
+ <entry name="?*.rb" />
+ <entry name="?*.groovy" />
+ <entry name="?*.py" />
+ <entry name="?*.ik" />
</wildcardResourcePatterns>
<annotationProcessing enabled="false" useClasspath="true" />
</component>
@@ -282,7 +286,6 @@
<module fileurl="file://$PROJECT_DIR$/openejb/cucumber-openejb.iml" filepath="$PROJECT_DIR$/openejb/cucumber-openejb.iml" />
<module fileurl="file://$PROJECT_DIR$/picocontainer/cucumber-picocontainer.iml" filepath="$PROJECT_DIR$/picocontainer/cucumber-picocontainer.iml" />
<module fileurl="file://$PROJECT_DIR$/rhino/cucumber-rhino.iml" filepath="$PROJECT_DIR$/rhino/cucumber-rhino.iml" />
- <module fileurl="file://$PROJECT_DIR$/scala/cucumber-scala.iml" filepath="$PROJECT_DIR$/scala/cucumber-scala.iml" />
<module fileurl="file://$PROJECT_DIR$/spring/cucumber-spring.iml" filepath="$PROJECT_DIR$/spring/cucumber-spring.iml" />
<module fileurl="file://$PROJECT_DIR$/weld/cucumber-weld.iml" filepath="$PROJECT_DIR$/weld/cucumber-weld.iml" />
</modules>
@@ -40,7 +40,7 @@ public GroovyBackend(GroovyShell shell, ResourceLoader resourceLoader) {
}
@Override
- public void buildWorld(List<String> gluePaths, World world) {
+ public void loadGlue(World world, List<String> gluePaths) {
this.world = world;
final Binding context = new Binding();
@@ -53,7 +53,10 @@ public void buildWorld(List<String> gluePaths, World world) {
}
}
}
-
+ }
+
+ @Override
+ public void buildWorld() {
}
private Script parse(Resource resource) {
@@ -41,7 +41,7 @@ public IokeBackend(ResourceLoader resourceLoader) {
}
@Override
- public void buildWorld(List<String> gluePaths, World world) {
+ public void loadGlue(World world, List<String> gluePaths) {
this.world = world;
for (String gluePath : gluePaths) {
@@ -52,6 +52,10 @@ public void buildWorld(List<String> gluePaths, World world) {
}
}
+ @Override
+ public void buildWorld() {
+ }
+
private void evaluate(Resource resource) {
try {
String path = resource.getPath().replace('\\', '/'); // Need forward paths, even whn on Windows
@@ -47,9 +47,13 @@ public JavaBackend(ObjectFactory objectFactory) {
}
@Override
- public void buildWorld(List<String> gluePaths, World world) {
+ public void loadGlue(World world, List<String> gluePaths) {
this.world = world;
classpathMethodScanner.scan(this, gluePaths);
+ }
+
+ @Override
+ public void buildWorld() {
objectFactory.createInstances();
}
@@ -23,7 +23,8 @@ public void finds_step_definitions_by_scanning_for_annotations() {
ObjectFactory factory = new DefaultJavaObjectFactory();
JavaBackend backend = new JavaBackend(factory);
WorldStub world = new WorldStub();
- backend.buildWorld(asList("cucumber/runtime/java/test"), world);
+ backend.loadGlue(world, asList("cucumber/runtime/java/test"));
+ backend.buildWorld();
assertEquals(Stepdefs.class, factory.getInstance(Stepdefs.class).getClass());
}
Oops, something went wrong.

0 comments on commit bd0634e

Please sign in to comment.