Skip to content

Commit d2e7e94

Browse files
committed
added a concurrency test that shows that things work even under heavy concurrency
1 parent 314ad15 commit d2e7e94

2 files changed

Lines changed: 90 additions & 1 deletion

File tree

compiler/src/main/java/com/github/mustachejava/FallbackMustacheFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
* @author gw0 [http://gw.tnode.com/] <[email protected]>
1111
*/
12-
public class FallbackMustacheFactory extends DefaultMustacheFactory {
12+
public class FallbackMustacheFactory extends DefaultMustacheFactory {
1313

1414
/** List of fallback resource roots to search through. */
1515
private Object[] resourceRoots;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.github.mustachejava;
2+
3+
import org.junit.Test;
4+
5+
import java.io.IOException;
6+
import java.io.StringReader;
7+
import java.io.StringWriter;
8+
import java.security.SecureRandom;
9+
import java.util.Random;
10+
import java.util.concurrent.ExecutorService;
11+
import java.util.concurrent.Executors;
12+
import java.util.concurrent.Semaphore;
13+
import java.util.concurrent.atomic.AtomicInteger;
14+
15+
import static junit.framework.Assert.assertEquals;
16+
17+
/**
18+
* Inspired by an unconfirmed bug report.
19+
*/
20+
public class ConcurrencyTest {
21+
22+
static Random r = new SecureRandom();
23+
24+
private static class TestObject {
25+
final int a;
26+
final int b;
27+
final int c;
28+
29+
int aa() throws InterruptedException {
30+
Thread.sleep(r.nextInt(10));
31+
return a;
32+
}
33+
34+
int bb() throws InterruptedException {
35+
Thread.sleep(r.nextInt(10));
36+
return b;
37+
}
38+
39+
int cc() throws InterruptedException {
40+
Thread.sleep(r.nextInt(10));
41+
return c;
42+
}
43+
44+
private TestObject(int a, int b, int c) {
45+
this.a = a;
46+
this.b = b;
47+
this.c = c;
48+
}
49+
}
50+
51+
// Alternate render
52+
static String render(TestObject to) {
53+
return to.a + ":" + to.b + ":" + to.c;
54+
}
55+
56+
@Test
57+
public void testConcurrentExecution() throws InterruptedException {
58+
String template = "{{aa}}:{{bb}}:{{cc}}";
59+
final Mustache test = new DefaultMustacheFactory().compile(new StringReader(template), "test");
60+
ExecutorService es = Executors.newCachedThreadPool();
61+
final AtomicInteger total = new AtomicInteger();
62+
final Semaphore semaphore = new Semaphore(100);
63+
for (int i = 0; i < 100000; i++) {
64+
semaphore.acquire();
65+
es.submit(new Runnable() {
66+
@Override
67+
public void run() {
68+
try {
69+
TestObject testObject = new TestObject(r.nextInt(), r.nextInt(), r.nextInt());
70+
StringWriter sw = new StringWriter();
71+
test.execute(sw, testObject).flush();
72+
if (!render(testObject).equals(sw.toString())) {
73+
total.incrementAndGet();
74+
}
75+
} catch (IOException e) {
76+
// Can't fail
77+
e.printStackTrace();
78+
System.exit(1);
79+
} finally {
80+
semaphore.release();
81+
}
82+
}
83+
});
84+
}
85+
// Wait for them all to complete
86+
semaphore.acquire(100);
87+
assertEquals(0, total.intValue());
88+
}
89+
}

0 commit comments

Comments
 (0)