diff --git a/processing/src/test/java/io/druid/segment/filter/BaseFilterTest.java b/processing/src/test/java/io/druid/segment/filter/BaseFilterTest.java index 76b7b08a6195..dfbc5ad255eb 100644 --- a/processing/src/test/java/io/druid/segment/filter/BaseFilterTest.java +++ b/processing/src/test/java/io/druid/segment/filter/BaseFilterTest.java @@ -23,7 +23,6 @@ import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.metamx.common.Pair; import com.metamx.common.guava.Sequence; @@ -53,7 +52,6 @@ import io.druid.segment.incremental.IncrementalIndex; import io.druid.segment.incremental.IncrementalIndexStorageAdapter; import org.joda.time.Interval; -import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TemporaryFolder; @@ -61,7 +59,9 @@ import java.io.Closeable; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -77,14 +77,31 @@ public abstract class BaseFilterTest protected StorageAdapter adapter; protected Closeable closeable; protected boolean optimize; + protected final String testName; + + // JUnit creates a new test instance for every test method call. + // For filter tests, the test setup creates a segment. + // Creating a new segment for every test method call is pretty slow, so cache the StorageAdapters. + // Each thread gets its own map. + protected static ThreadLocal>>> adapterCache = + new ThreadLocal>>>() + { + @Override + protected Map>> initialValue() + { + return new HashMap<>(); + } + }; public BaseFilterTest( + String testName, List rows, IndexBuilder indexBuilder, Function> finisher, boolean optimize ) { + this.testName = testName; this.rows = rows; this.indexBuilder = indexBuilder; this.finisher = finisher; @@ -94,17 +111,37 @@ public BaseFilterTest( @Before public void setUp() throws Exception { - final Pair pair = finisher.apply( - indexBuilder.tmpDir(temporaryFolder.newFolder()).add(rows) - ); + String className = getClass().getName(); + Map> adaptersForClass = adapterCache.get().get(className); + if (adaptersForClass == null) { + adaptersForClass = new HashMap<>(); + adapterCache.get().put(className, adaptersForClass); + } + + Pair pair = adaptersForClass.get(testName); + if (pair == null) { + pair = finisher.apply( + indexBuilder.tmpDir(temporaryFolder.newFolder()).add(rows) + ); + adaptersForClass.put(testName, pair); + } + this.adapter = pair.lhs; this.closeable = pair.rhs; + } - @After - public void tearDown() throws Exception + public static void tearDown(String className) throws Exception { - closeable.close(); + Map> adaptersForClass = adapterCache.get().get(className); + + if (adaptersForClass != null) { + for (Map.Entry> entry : adaptersForClass.entrySet()) { + Closeable closeable = entry.getValue().rhs; + closeable.close(); + } + adapterCache.get().put(className, null); + } } @Parameterized.Parameters(name = "{0}") @@ -215,41 +252,6 @@ public void close() throws IOException return constructors; } - /** - * Selects elements from "selectColumn" from rows matching a filter. selectColumn must be a single valued dimension. - */ - protected List selectColumnValuesMatchingFilter(final DimFilter filter, final String selectColumn) - { - final Cursor cursor = makeCursor(Filters.toFilter(maybeOptimize(filter))); - final List values = Lists.newArrayList(); - final DimensionSelector selector = cursor.makeDimensionSelector( - new DefaultDimensionSpec(selectColumn, selectColumn) - ); - - for (; !cursor.isDone(); cursor.advance()) { - final IndexedInts row = selector.getRow(); - Preconditions.checkState(row.size() == 1); - values.add(selector.lookupName(row.get(0))); - } - - return values; - } - - protected long selectCountUsingFilteredAggregator(final DimFilter filter) - { - final Cursor cursor = makeCursor(null); - final Aggregator agg = new FilteredAggregatorFactory( - new CountAggregatorFactory("count"), - maybeOptimize(filter) - ).factorize(cursor); - - for (; !cursor.isDone(); cursor.advance()) { - agg.aggregate(); - } - - return agg.getLong(); - } - private DimFilter maybeOptimize(final DimFilter dimFilter) { if (dimFilter == null) { @@ -258,7 +260,7 @@ private DimFilter maybeOptimize(final DimFilter dimFilter) return optimize ? dimFilter.optimize() : dimFilter; } - private Cursor makeCursor(final Filter filter) + private Sequence makeCursorSequence(final Filter filter) { final Sequence cursors = adapter.makeCursors( filter, @@ -266,6 +268,66 @@ private Cursor makeCursor(final Filter filter) QueryGranularities.ALL, false ); - return Iterables.getOnlyElement(Sequences.toList(cursors, Lists.newArrayList())); + + return cursors; + } + + /** + * Selects elements from "selectColumn" from rows matching a filter. selectColumn must be a single valued dimension. + */ + protected List selectColumnValuesMatchingFilter(final DimFilter filter, final String selectColumn) + { + final Sequence cursors = makeCursorSequence(Filters.toFilter(maybeOptimize(filter))); + Sequence> seq = Sequences.map( + cursors, + new Function>() + { + @Override + public List apply(Cursor input) + { + final DimensionSelector selector = input.makeDimensionSelector( + new DefaultDimensionSpec(selectColumn, selectColumn) + ); + + final List values = Lists.newArrayList(); + + while (!input.isDone()) { + IndexedInts row = selector.getRow(); + Preconditions.checkState(row.size() == 1); + values.add(selector.lookupName(row.get(0))); + input.advance(); + } + + return values; + } + } + ); + return Sequences.toList(seq, new ArrayList>()).get(0); + } + + protected long selectCountUsingFilteredAggregator(final DimFilter filter) + { + final Sequence cursors = makeCursorSequence(Filters.toFilter(maybeOptimize(filter))); + Sequence aggSeq = Sequences.map( + cursors, + new Function() + { + @Override + public Aggregator apply(Cursor input) + { + Aggregator agg = new FilteredAggregatorFactory( + new CountAggregatorFactory("count"), + maybeOptimize(filter) + ).factorize(input); + + for (; !input.isDone(); input.advance()) { + agg.aggregate(); + } + + return agg; + } + } + ); + return Sequences.toList(aggSeq, new ArrayList()).get(0).getLong(); } } diff --git a/processing/src/test/java/io/druid/segment/filter/BoundFilterTest.java b/processing/src/test/java/io/druid/segment/filter/BoundFilterTest.java index a8a7524e9a3d..00b5a9a95d6e 100644 --- a/processing/src/test/java/io/druid/segment/filter/BoundFilterTest.java +++ b/processing/src/test/java/io/druid/segment/filter/BoundFilterTest.java @@ -37,6 +37,7 @@ import io.druid.segment.IndexBuilder; import io.druid.segment.StorageAdapter; import org.joda.time.DateTime; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -74,7 +75,13 @@ public BoundFilterTest( boolean optimize ) { - super(ROWS, indexBuilder, finisher, optimize); + super(testName, ROWS, indexBuilder, finisher, optimize); + } + + @AfterClass + public static void tearDown() throws Exception + { + BaseFilterTest.tearDown(BoundFilterTest.class.getName()); } @Test diff --git a/processing/src/test/java/io/druid/segment/filter/InFilterTest.java b/processing/src/test/java/io/druid/segment/filter/InFilterTest.java index b5f1b912f7a6..77350cca5575 100644 --- a/processing/src/test/java/io/druid/segment/filter/InFilterTest.java +++ b/processing/src/test/java/io/druid/segment/filter/InFilterTest.java @@ -45,6 +45,7 @@ import io.druid.segment.IndexBuilder; import io.druid.segment.StorageAdapter; import org.joda.time.DateTime; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -79,12 +80,6 @@ public class InFilterTest extends BaseFilterTest PARSER.parse(ImmutableMap.of("dim0", "f", "dim1", "abc")) ); - @Parameterized.Parameters(name = "{0}") - public static Collection constructorFeeder() throws IOException - { - return makeConstructors(); - } - public InFilterTest( String testName, IndexBuilder indexBuilder, @@ -92,17 +87,13 @@ public InFilterTest( boolean optimize ) { - super(ROWS, indexBuilder, finisher, optimize); + super(testName, ROWS, indexBuilder, finisher, optimize); } - @Before - public void setUp() throws IOException + @AfterClass + public static void tearDown() throws Exception { - final Pair pair = finisher.apply( - indexBuilder.tmpDir(temporaryFolder.newFolder()).add(ROWS) - ); - this.adapter = pair.lhs; - this.closeable = pair.rhs; + BaseFilterTest.tearDown(InFilterTest.class.getName()); } @Test diff --git a/processing/src/test/java/io/druid/segment/filter/JavaScriptFilterTest.java b/processing/src/test/java/io/druid/segment/filter/JavaScriptFilterTest.java index 3d64733197e8..e502e0751e13 100644 --- a/processing/src/test/java/io/druid/segment/filter/JavaScriptFilterTest.java +++ b/processing/src/test/java/io/druid/segment/filter/JavaScriptFilterTest.java @@ -39,6 +39,7 @@ import io.druid.segment.IndexBuilder; import io.druid.segment.StorageAdapter; import org.joda.time.DateTime; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -80,7 +81,13 @@ public JavaScriptFilterTest( boolean optimize ) { - super(ROWS, indexBuilder, finisher, optimize); + super(testName, ROWS, indexBuilder, finisher, optimize); + } + + @AfterClass + public static void tearDown() throws Exception + { + BaseFilterTest.tearDown(JavaScriptFilterTest.class.getName()); } private final String jsNullFilter = "function(x) { return(x === null) }"; diff --git a/processing/src/test/java/io/druid/segment/filter/NotFilterTest.java b/processing/src/test/java/io/druid/segment/filter/NotFilterTest.java index 395578acc700..c584b74c87eb 100644 --- a/processing/src/test/java/io/druid/segment/filter/NotFilterTest.java +++ b/processing/src/test/java/io/druid/segment/filter/NotFilterTest.java @@ -35,6 +35,7 @@ import io.druid.segment.IndexBuilder; import io.druid.segment.StorageAdapter; import org.joda.time.DateTime; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -72,7 +73,13 @@ public NotFilterTest( boolean optimize ) { - super(ROWS, indexBuilder, finisher, optimize); + super(testName, ROWS, indexBuilder, finisher, optimize); + } + + @AfterClass + public static void tearDown() throws Exception + { + BaseFilterTest.tearDown(NotFilterTest.class.getName()); } @Test diff --git a/processing/src/test/java/io/druid/segment/filter/RegexFilterTest.java b/processing/src/test/java/io/druid/segment/filter/RegexFilterTest.java index d503d727d80c..0f7c8e386fd9 100644 --- a/processing/src/test/java/io/druid/segment/filter/RegexFilterTest.java +++ b/processing/src/test/java/io/druid/segment/filter/RegexFilterTest.java @@ -37,6 +37,7 @@ import io.druid.segment.IndexBuilder; import io.druid.segment.StorageAdapter; import org.joda.time.DateTime; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -78,7 +79,13 @@ public RegexFilterTest( boolean optimize ) { - super(ROWS, indexBuilder, finisher, optimize); + super(testName, ROWS, indexBuilder, finisher, optimize); + } + + @AfterClass + public static void tearDown() throws Exception + { + BaseFilterTest.tearDown(RegexFilterTest.class.getName()); } @Test diff --git a/processing/src/test/java/io/druid/segment/filter/SearchQueryFilterTest.java b/processing/src/test/java/io/druid/segment/filter/SearchQueryFilterTest.java index 147b6c01f23a..dc5fe242b8ca 100644 --- a/processing/src/test/java/io/druid/segment/filter/SearchQueryFilterTest.java +++ b/processing/src/test/java/io/druid/segment/filter/SearchQueryFilterTest.java @@ -40,6 +40,7 @@ import io.druid.segment.IndexBuilder; import io.druid.segment.StorageAdapter; import org.joda.time.DateTime; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -81,7 +82,13 @@ public SearchQueryFilterTest( boolean optimize ) { - super(ROWS, indexBuilder, finisher, optimize); + super(testName, ROWS, indexBuilder, finisher, optimize); + } + + @AfterClass + public static void tearDown() throws Exception + { + BaseFilterTest.tearDown(SearchQueryFilterTest.class.getName()); } private SearchQuerySpec specForValue(String value) diff --git a/processing/src/test/java/io/druid/segment/filter/SelectorFilterTest.java b/processing/src/test/java/io/druid/segment/filter/SelectorFilterTest.java index adbd5dc82b3f..861b20702a67 100644 --- a/processing/src/test/java/io/druid/segment/filter/SelectorFilterTest.java +++ b/processing/src/test/java/io/druid/segment/filter/SelectorFilterTest.java @@ -40,6 +40,7 @@ import io.druid.segment.IndexBuilder; import io.druid.segment.StorageAdapter; import org.joda.time.DateTime; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -82,7 +83,13 @@ public SelectorFilterTest( boolean optimize ) { - super(ROWS, indexBuilder, finisher, optimize); + super(testName, ROWS, indexBuilder, finisher, optimize); + } + + @AfterClass + public static void tearDown() throws Exception + { + BaseFilterTest.tearDown(SelectorFilterTest.class.getName()); } @Test