diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-05-16 16:04:17 +1000 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@typesafe.com> | 2016-05-16 08:04:17 +0200 |
commit | eac1af364e99a6712c5e54e257216027b2ab127e (patch) | |
tree | 7913340cff137466511c3d6ca4066fdd55d4aeb9 /test/junit/scala/tools/testing/ClearAfterClass.java | |
parent | 9e30bee0c9363f6cf36a7b65ddbaaa225b57d6a9 (diff) | |
download | scala-eac1af364e99a6712c5e54e257216027b2ab127e.tar.gz scala-eac1af364e99a6712c5e54e257216027b2ab127e.tar.bz2 scala-eac1af364e99a6712c5e54e257216027b2ab127e.zip |
Reduce boilerplate in compiler JUnit tests (#5158)
Many JUnit tests share a compiler instance between all
test cases in a class to reduce overhead.
This commit refactors the mechanism to reduce the boilerplate.
In the new scheme:
- Using the `@ClassRule` hook in JUnit, we create a per-class
map for each test class.
- Per-class values are registered from the test class itself
by calling `cached("someKey", () => mkExpensiveThing)`
- At the end of the test, the entries in this map are `close()`-ed
(if they implement `Closable`), and are released for
garbage collection.)
Diffstat (limited to 'test/junit/scala/tools/testing/ClearAfterClass.java')
-rw-r--r-- | test/junit/scala/tools/testing/ClearAfterClass.java | 47 |
1 files changed, 40 insertions, 7 deletions
diff --git a/test/junit/scala/tools/testing/ClearAfterClass.java b/test/junit/scala/tools/testing/ClearAfterClass.java index 232d459c4e..95e170ec13 100644 --- a/test/junit/scala/tools/testing/ClearAfterClass.java +++ b/test/junit/scala/tools/testing/ClearAfterClass.java @@ -1,20 +1,53 @@ package scala.tools.testing; -import org.junit.AfterClass; +import org.junit.ClassRule; +import org.junit.rules.TestRule; +import org.junit.runners.model.Statement; + +import java.io.Closeable; +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** - * Extend this class to use JUnit's @AfterClass. This annotation only works on static methods, + * Extend this class to use JUnit's @ClassRule. This annotation only works on static methods, * which cannot be written in Scala. * * Example: {@link scala.tools.nsc.backend.jvm.opt.InlinerTest} */ public class ClearAfterClass { - public static interface Clearable { - void clear(); + private static Map<Class<?>, Map<String, Object>> cache = new ConcurrentHashMap<>(); + + @ClassRule + public static TestRule clearClassCache() { + return (statement, desc) -> new Statement() { + @Override + public void evaluate() throws Throwable { + ConcurrentHashMap<String, Object> perClassCache = new ConcurrentHashMap<>(); + cache.put(desc.getTestClass(), perClassCache); + try { + statement.evaluate(); + } finally { + perClassCache.values().forEach(ClearAfterClass::closeIfClosable); + cache.remove(desc.getTestClass()); + } + } + }; } - public static Clearable stateToClear; + private static void closeIfClosable(Object o) { + if (o instanceof Closeable) { + try { + ((Closeable) o).close(); + } catch (IOException e) { + // ignore + } + } + } + + public <T> T cached(String key, scala.Function0<T> t) { + Map<String, Object> perClassCache = cache.get(getClass()); + return (T) perClassCache.computeIfAbsent(key, s -> t.apply()); + } - @AfterClass - public static void clearState() { stateToClear.clear(); } } |