Skip to content

Commit 419a6d8

Browse files
committed
Merge branch 'bradleyhart-master'
2 parents 8e6f9d2 + 1d8353d commit 419a6d8

File tree

4 files changed

+62
-7
lines changed

4 files changed

+62
-7
lines changed

groovy/src/main/code_generator/I18n.groovy.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import java.util.regex.Pattern;
88
public class ${i18n.underscoredIsoCode.toUpperCase()} {
99
<% i18n.codeKeywords.each { kw -> %>
1010
public static void ${kw}(Pattern regexp, Closure body) throws Throwable {
11-
GroovyBackend.instance.addStepDefinition(regexp, 0, body);
11+
GroovyBackend.getInstance().addStepDefinition(regexp, 0, body);
1212
}
1313

1414
public static void ${java.text.Normalizer.normalize(kw, java.text.Normalizer.Form.NFC)}(Pattern regexp, long timeoutMillis, Closure body) throws Throwable {
15-
GroovyBackend.instance.addStepDefinition(regexp, timeoutMillis, body);
15+
GroovyBackend.getInstance().addStepDefinition(regexp, timeoutMillis, body);
1616
}
1717
<% } %>
1818
}

groovy/src/main/java/cucumber/api/groovy/Hooks.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
public class Hooks {
1111
public static void World(Closure body) throws Throwable {
12-
GroovyBackend.instance.registerWorld(body);
12+
GroovyBackend.getInstance().registerWorld(body);
1313
}
1414

1515
public static void Before(Object... args) throws Throwable {
@@ -37,9 +37,9 @@ private static void addHook(Object[] tagsExpressionsAndBody, boolean before) {
3737

3838
TagExpression tagExpression = new TagExpression(tagExpressions);
3939
if (before) {
40-
GroovyBackend.instance.addBeforeHook(tagExpression, timeoutMillis, body);
40+
GroovyBackend.getInstance().addBeforeHook(tagExpression, timeoutMillis, body);
4141
} else {
42-
GroovyBackend.instance.addAfterHook(tagExpression, timeoutMillis, body);
42+
GroovyBackend.getInstance().addAfterHook(tagExpression, timeoutMillis, body);
4343
}
4444
}
4545
}

groovy/src/main/java/cucumber/runtime/groovy/GroovyBackend.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import static cucumber.runtime.io.MultiLoader.packageName;
3131

3232
public class GroovyBackend implements Backend {
33-
public static GroovyBackend instance;
33+
public static ThreadLocal<GroovyBackend> instanceThreadLocal = new ThreadLocal<GroovyBackend>();
3434
private final Set<Class> scripts = new HashSet<Class>();
3535
private final SnippetGenerator snippetGenerator = new SnippetGenerator(new GroovySnippet());
3636
private final ResourceLoader resourceLoader;
@@ -41,6 +41,10 @@ public class GroovyBackend implements Backend {
4141
private Object world;
4242
private Glue glue;
4343

44+
public static GroovyBackend getInstance(){
45+
return instanceThreadLocal.get();
46+
}
47+
4448
private static GroovyShell createShell() {
4549
CompilerConfiguration compilerConfig = new CompilerConfiguration();
4650
// Probably not needed:
@@ -55,7 +59,7 @@ public GroovyBackend(ResourceLoader resourceLoader) {
5559
public GroovyBackend(GroovyShell shell, ResourceLoader resourceLoader) {
5660
this.shell = shell;
5761
this.resourceLoader = resourceLoader;
58-
instance = this;
62+
instanceThreadLocal.set(this);
5963
classFinder = new ResourceLoaderClassFinder(resourceLoader, shell.getClassLoader());
6064
}
6165

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package cucumber.runtime.groovy;
2+
3+
import cucumber.runtime.io.ResourceLoader;
4+
import groovy.lang.Closure;
5+
import org.junit.Test;
6+
import org.junit.runner.RunWith;
7+
import org.mockito.Mock;
8+
import org.mockito.runners.MockitoJUnitRunner;
9+
10+
11+
@RunWith(MockitoJUnitRunner.class)
12+
public class ParallelTest {
13+
@Mock
14+
ResourceLoader resourceLoader;
15+
@Mock
16+
Closure closure;
17+
18+
@Test(expected = RuntimeException.class)
19+
public void exception_throw_when_world_already_set_on_same_thread() {
20+
GroovyBackend groovyBackend = new GroovyBackend(resourceLoader);
21+
groovyBackend.registerWorld(closure);
22+
groovyBackend.registerWorld(closure);
23+
}
24+
25+
@Test
26+
public void can_have_a_new_backend_on_a_different_thread() {
27+
new GroovyBackend(resourceLoader);
28+
Thread interactWithBackendThread = new Thread(new Runnable(){
29+
@Override
30+
public void run() {
31+
try {
32+
GroovyBackend.getInstance().registerWorld(closure);
33+
} catch (NullPointerException e){
34+
// This is what we want as there should be no GroovyBackend on this thread
35+
}
36+
}
37+
});
38+
runAndWait(interactWithBackendThread);
39+
GroovyBackend.getInstance().registerWorld(closure);
40+
}
41+
42+
private void runAndWait(Thread interactWithBackendThread) {
43+
interactWithBackendThread.start();
44+
try {
45+
interactWithBackendThread.join();
46+
} catch (InterruptedException e) {
47+
throw new RuntimeException("Doh");
48+
}
49+
}
50+
51+
}

0 commit comments

Comments
 (0)