Skip to content

Commit

Permalink
Test from @drykovanov.
Browse files Browse the repository at this point in the history
This was fixed recently by @agentgt but I just wanted to double check that this
test now passes.

Closes #138.
  • Loading branch information
samskivert committed Nov 30, 2023
1 parent a697d1c commit 7922422
Showing 1 changed file with 82 additions and 0 deletions.
82 changes: 82 additions & 0 deletions src/test/java/com/samskivert/mustache/ThreadSafetyTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// JMustache - A Java implementation of the Mustache templating language
// http://github.com/samskivert/jmustache/blob/master/LICENSE

package com.samskivert.mustache;

import java.io.Reader;
import java.io.StringReader;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;

import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template;

import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class ThreadSafetyTest {

private static final String templateA = "Template A content\n{{> templateB}}";
private static final String templateB = "Template B content";

private static class CountingLoader implements Mustache.TemplateLoader {
private final AtomicInteger counter = new AtomicInteger(0);

@Override public Reader getTemplate (String name) throws Exception {
counter.incrementAndGet();
if (!"templateB".equals(name)) {
throw new IllegalArgumentException();
}
return new StringReader(templateB);
}

public int counter () {
return counter.get();
}
}

@Test
public void testTemplateLoading () throws InterruptedException {
// 4096 works but is disabled as it makes the test take a long time
for (int ii : new int[] { 1, 2, 4, 8, 16, 32, 256, 1024/* , 4096 */ }) {
templateLoadingIsThreadSafe(ii);
}
}

void templateLoadingIsThreadSafe (int nThreads) throws InterruptedException {
final CyclicBarrier barrier = new CyclicBarrier(nThreads);
final CountingLoader loader = new CountingLoader();
final Mustache.Compiler compiler = Mustache.compiler().withLoader(loader);
final Template template = compiler.compile(new StringReader(templateA));

final List<Thread> threads = new LinkedList<>();
for (int i = 0; i < nThreads; i++) {
final Thread thread = new Thread(() -> {
try {
barrier.await();
final String value = template.execute(Map.of());
if (!value.contains("Template A content\nTemplate B content")) {
fail("Invalid template result " + value);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
});

threads.add(thread);
thread.start();
}

for (Thread thread : threads) {
thread.join();
}

assertEquals(1, loader.counter());
}
}

0 comments on commit 7922422

Please sign in to comment.