[java-metadata-aggregator] 02/02: MDA-275 - Default stage configurations should not create daemon threads
Ian Young
ian at iay.org.uk
Wed Feb 1 17:10:30 UTC 2023
This is an automated email from the git hooks/post-receive script.
iay pushed a commit to branch main
in repository java-metadata-aggregator.
View the commit online:
http://git.shibboleth.net/view/?p=java-metadata-aggregator.git;a=commit;h=5f6a97b0292e7b9a93ecaf93b8c4a6f4f98d14e3
commit 5f6a97b0292e7b9a93ecaf93b8c4a6f4f98d14e3
Author: Ian Young <ian at iay.org.uk>
AuthorDate: Wed Feb 1 16:48:54 2023 +0000
MDA-275 - Default stage configurations should not create daemon threads
Change API of three stages from an ExecutorService to an Executor.
This simplification allows a switch to a DirectExecutor by default,
which just executes tasks on the calling thread. This means we don't
allocate any thread pools by default, leaving that to the caller if it
is to be done. It also means we're not creating any non-daemon threads
by default.
https://shibboleth.atlassian.net/browse/MDA-275
---
.../pipeline/PipelineDemultiplexerStage.java | 93 +++++++++++++++++-----
.../metadata/pipeline/PipelineMergeStage.java | 74 ++++++++++++++---
.../metadata/pipeline/SplitMergeStage.java | 64 ++++++++++++---
.../metadata/pipeline/impl/DirectExecutor.java | 35 ++++++++
.../pipeline/PipelineDemultiplexerStageTest.java | 8 ++
.../metadata/pipeline/PipelineMergeStageTest.java | 18 +++++
.../metadata/pipeline/SplitMergeStageTest.java | 8 ++
7 files changed, 259 insertions(+), 41 deletions(-)
diff --git a/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/PipelineDemultiplexerStage.java b/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/PipelineDemultiplexerStage.java
index 0c9e71c..6da7606 100644
--- a/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/PipelineDemultiplexerStage.java
+++ b/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/PipelineDemultiplexerStage.java
@@ -19,9 +19,10 @@ package net.shibboleth.metadata.pipeline;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
import java.util.function.Predicate;
import java.util.function.Supplier;
@@ -31,6 +32,7 @@ import javax.annotation.concurrent.ThreadSafe;
import net.shibboleth.metadata.Item;
import net.shibboleth.metadata.SimpleItemCollectionFactory;
+import net.shibboleth.metadata.pipeline.impl.DirectExecutor;
import net.shibboleth.metadata.pipeline.impl.FutureSupport;
import net.shibboleth.metadata.pipeline.impl.PipelineCallable;
import net.shibboleth.shared.annotation.constraint.NonnullElements;
@@ -38,13 +40,19 @@ import net.shibboleth.shared.annotation.constraint.Unmodifiable;
import net.shibboleth.shared.collection.Pair;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.DeprecationSupport;
+import net.shibboleth.shared.primitive.DeprecationSupport.ObjectType;
/**
* A stage which, given an item collection and a list of {@link Pipeline} and {@link Predicate} pairs, sends the
- * collection of item copies selected by the predicate to the associated pipeline. This stage is similar to
+ * collection of item copies selected by the predicate to the associated pipeline.
+ *
+ * <p>
+ * This stage is similar to
* {@link SplitMergeStage} but a given item, or more precisely a copy of it, may end up going to more than one pipeline
* (or no pipeline).
- *
+ * </p>
+ *
* <p>
* This stage requires the following properties be set prior to initialization:
* <ul>
@@ -52,22 +60,31 @@ import net.shibboleth.shared.logic.Constraint;
* </ul>
*
* <p>
- * If no {@link #executorService} is provided, one will be created using {@link Executors#newFixedThreadPool(int)} with
- * 6 threads.
- *
+ * If an {@link #executor} is provided, it will be used to execute the pipelines,
+ * potentially concurrently. By default, the pipelines will be executed sequentially
+ * on the calling thread.
+ * </p>
+ *
+ * <p>
+ * The caller is responsible for the lifecycle of any provided {@link Executor},
+ * including the lifecycle of any threads or thread pools associated with it.
+ * </p>
+ *
+ * <p>
* If no {@link #collectionFactory} is given, then {@link SimpleItemCollectionFactory} is used.
- *
+ * </p>
+ *
* @param <T> type of items upon which this stage operates
*/
@ThreadSafe
public class PipelineDemultiplexerStage<T> extends AbstractStage<T> {
- /** Service used to execute the selected and/or non-selected item pipelines. */
+ /** {@link Executor} used to execute the selected and/or non-selected item pipelines. */
@Nonnull @GuardedBy("this")
- private ExecutorService executorService = Executors.newSingleThreadExecutor();
+ private Executor executor = new DirectExecutor();
/**
- * Whether this child waits for all the invoked pipelines to complete before proceeding.
+ * Whether this stage waits for all the invoked pipelines to complete before proceeding.
*
* Default: <code>true</code>.
*/
@@ -81,23 +98,56 @@ public class PipelineDemultiplexerStage<T> extends AbstractStage<T> {
@Nonnull @NonnullElements @Unmodifiable @GuardedBy("this")
private List<Pair<Pipeline<T>, Predicate<Item<T>>>> pipelineAndStrategies = List.of();
+ /**
+ * Gets the executor used to run the selected and non-selected item pipelines.
+ *
+ * @return executor used to run the selected and non-selected item pipelines
+ *
+ * @since 0.10.0
+ */
+ @Nonnull public final synchronized Executor getExecutor() {
+ return executor;
+ }
+
/**
* Gets the executor service used to run the selected and non-selected item pipelines.
*
* @return executor service used to run the selected and non-selected item pipelines
+ *
+ * @deprecated
*/
- @Nonnull public final synchronized ExecutorService getExecutorService() {
- return executorService;
+ @Deprecated(since="0.10.0", forRemoval=true)
+ @Nonnull public final synchronized Executor getExecutorService() {
+ DeprecationSupport.warnOnce(ObjectType.METHOD, "getExecutorService",
+ "PipelineDemultiplexerStage", "getExecutor");
+ return executor;
+ }
+
+ /**
+ * Sets the executor used to run the selected and non-selected item pipelines.
+ *
+ * @param service executor used to run the selected and non-selected item pipelines
+ *
+ * @since 0.10.0
+ */
+ public synchronized void setExecutor(@Nonnull final Executor exec) {
+ checkSetterPreconditions();
+ executor = Constraint.isNotNull(exec, "executor can not be null");
}
/**
* Sets the executor service used to run the selected and non-selected item pipelines.
*
* @param service executor service used to run the selected and non-selected item pipelines
+ *
+ * @deprecated
*/
+ @Deprecated(since="0.10.0", forRemoval=true)
public synchronized void setExecutorService(@Nonnull final ExecutorService service) {
+ DeprecationSupport.warnOnce(ObjectType.METHOD, "setExecutorService",
+ "PipelineDemultiplexerStage", "setExecutor");
checkSetterPreconditions();
- executorService = Constraint.isNotNull(service, "ExecutorService can not be null");
+ executor = Constraint.isNotNull(service, "ExecutorService can not be null");
}
/**
@@ -168,26 +218,27 @@ public class PipelineDemultiplexerStage<T> extends AbstractStage<T> {
@Override
protected void doExecute(@Nonnull @NonnullElements final List<Item<T>> items)
throws StageProcessingException {
- final ArrayList<Future<List<Item<T>>>> pipelineFutures = new ArrayList<>();
+ final @Nonnull @NonnullElements List<Future<List<Item<T>>>> pipelineFutures = new ArrayList<>();
for (final Pair<Pipeline<T>, Predicate<Item<T>>> pipelineAndStrategy : getPipelineAndSelectionStrategies()) {
- final Pipeline<T> pipeline = pipelineAndStrategy.getFirst();
- final Predicate<Item<T>> selectionStrategy = pipelineAndStrategy.getSecond();
- final List<Item<T>> selectedItems = getCollectionFactory().get();
+ final @Nonnull Pipeline<T> pipeline = pipelineAndStrategy.getFirst();
+ final @Nonnull Predicate<Item<T>> selectionStrategy = pipelineAndStrategy.getSecond();
+ final @Nonnull List<Item<T>> selectedItems = getCollectionFactory().get();
for (final Item<T> item : items) {
if (selectionStrategy.test(item)) {
-// @SuppressWarnings("unchecked") final ItemType copied = (ItemType) item.copy();
-// selectedItems.add(copied);
selectedItems.add(item.copy());
}
}
- pipelineFutures.add(getExecutorService().submit(new PipelineCallable<>(pipeline, selectedItems)));
+ final @Nonnull var callable = new PipelineCallable<T>(pipeline, selectedItems);
+ final @Nonnull var future = new FutureTask<List<Item<T>>>(callable);
+ getExecutor().execute(future);
+ pipelineFutures.add(future);
}
if (isWaitingForPipelines()) {
- for (final Future<List<Item<T>>> pipelineFuture : pipelineFutures) {
+ for (final @Nonnull Future<List<Item<T>>> pipelineFuture : pipelineFutures) {
FutureSupport.futureItems(pipelineFuture);
}
}
diff --git a/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/PipelineMergeStage.java b/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/PipelineMergeStage.java
index 9e882bf..93b16ec 100644
--- a/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/PipelineMergeStage.java
+++ b/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/PipelineMergeStage.java
@@ -19,9 +19,10 @@ package net.shibboleth.metadata.pipeline;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
import java.util.function.Supplier;
import javax.annotation.Nonnull;
@@ -32,30 +33,46 @@ import net.shibboleth.metadata.CollectionMergeStrategy;
import net.shibboleth.metadata.Item;
import net.shibboleth.metadata.SimpleCollectionMergeStrategy;
import net.shibboleth.metadata.SimpleItemCollectionFactory;
+import net.shibboleth.metadata.pipeline.impl.DirectExecutor;
import net.shibboleth.metadata.pipeline.impl.FutureSupport;
import net.shibboleth.metadata.pipeline.impl.PipelineCallable;
import net.shibboleth.shared.annotation.constraint.NonnullElements;
import net.shibboleth.shared.annotation.constraint.Unmodifiable;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.DeprecationSupport;
+import net.shibboleth.shared.primitive.DeprecationSupport.ObjectType;
/**
* This {@link Stage} allows the merging of multiple pipeline outputs into a single {@link List} that can then be
* used as the input source for another pipeline.
*
+ * <p>
* This source works producing a {@link List} by means of the registered {@link Supplier} . Then each of its
* registered {@link Pipeline} is invoked in turn (no ordering is guaranteed and pipelines may execute concurrently).
* After each pipeline has completed the results are merged in to the Item collection given to this stage by means of
* the an {@link CollectionMergeStrategy}.
+ * </p>
*
+ * <p>
+ * If an {@link #executor} is provided, it will be used to execute the pipelines,
+ * potentially concurrently. By default, the pipelines will be executed sequentially
+ * on the calling thread.
+ * </p>
+ *
+ * <p>
+ * The caller is responsible for the lifecycle of any provided {@link Executor},
+ * including the lifecycle of any threads or thread pools associated with it.
+ * </p>
+ *
* @param <T> the type of items processed by the stage
*/
@ThreadSafe
public class PipelineMergeStage<T> extends AbstractStage<T> {
- /** Service used to execute the pipelines whose results will be merged. */
+ /** {@link Executor} used to execute the selected and/or non-selected item pipelines. */
@Nonnull @GuardedBy("this")
- private ExecutorService executorService = Executors.newSingleThreadExecutor();
+ private Executor executor = new DirectExecutor();
/**
* The factory used to create the item returned by this source. Default implementation is
@@ -72,23 +89,56 @@ public class PipelineMergeStage<T> extends AbstractStage<T> {
@Nonnull @NonnullElements @Unmodifiable @GuardedBy("this")
private List<Pipeline<T>> mergedPipelines = List.of();
+ /**
+ * Gets the executor used to run the selected and non-selected item pipelines.
+ *
+ * @return executor used to run the selected and non-selected item pipelines
+ *
+ * @since 0.10.0
+ */
+ @Nonnull public final synchronized Executor getExecutor() {
+ return executor;
+ }
+
/**
* Gets the executor service used to run the selected and non-selected item pipelines.
*
* @return executor service used to run the selected and non-selected item pipelines
+ *
+ * @deprecated
*/
- @Nonnull public final synchronized ExecutorService getExecutorService() {
- return executorService;
+ @Deprecated(since="0.10.0", forRemoval=true)
+ @Nonnull public final synchronized Executor getExecutorService() {
+ DeprecationSupport.warnOnce(ObjectType.METHOD, "getExecutorService",
+ "PipelineMergeStage", "getExecutor");
+ return executor;
+ }
+
+ /**
+ * Sets the executor used to run the selected and non-selected item pipelines.
+ *
+ * @param service executor used to run the selected and non-selected item pipelines
+ *
+ * @since 0.10.0
+ */
+ public synchronized void setExecutor(@Nonnull final Executor exec) {
+ checkSetterPreconditions();
+ executor = Constraint.isNotNull(exec, "executor can not be null");
}
/**
* Sets the executor service used to run the selected and non-selected item pipelines.
*
* @param service executor service used to run the selected and non-selected item pipelines
+ *
+ * @deprecated
*/
+ @Deprecated(since="0.10.0", forRemoval=true)
public synchronized void setExecutorService(@Nonnull final ExecutorService service) {
+ DeprecationSupport.warnOnce(ObjectType.METHOD, "setExecutorService",
+ "PipelineMergeStage", "setExecutor");
checkSetterPreconditions();
- executorService = Constraint.isNotNull(service, "ExecutorService can not be null");
+ executor = Constraint.isNotNull(service, "ExecutorService can not be null");
}
/**
@@ -154,14 +204,16 @@ public class PipelineMergeStage<T> extends AbstractStage<T> {
@Override
protected void doExecute(@Nonnull @NonnullElements final List<Item<T>> items)
throws StageProcessingException {
- final ArrayList<Future<List<Item<T>>>> pipelineResultFutures = new ArrayList<>();
+ final @Nonnull List<Future<List<Item<T>>>> pipelineResultFutures = new ArrayList<>();
- for (final Pipeline<T> pipeline : getMergedPipelines()) {
- pipelineResultFutures.add(getExecutorService().submit(
- new PipelineCallable<>(pipeline, getCollectionFactory().get())));
+ for (final @Nonnull Pipeline<T> pipeline : getMergedPipelines()) {
+ final @Nonnull var callable = new PipelineCallable<T>(pipeline, getCollectionFactory().get());
+ final @Nonnull var future = new FutureTask<List<Item<T>>>(callable);
+ getExecutor().execute(future);
+ pipelineResultFutures.add(future);
}
- final ArrayList<List<Item<T>>> pipelineResults = new ArrayList<>();
+ final List<List<Item<T>>> pipelineResults = new ArrayList<>();
for (final Future<List<Item<T>>> future : pipelineResultFutures) {
pipelineResults.add(FutureSupport.futureItems(future));
}
diff --git a/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/SplitMergeStage.java b/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/SplitMergeStage.java
index c712f10..f943752 100644
--- a/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/SplitMergeStage.java
+++ b/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/SplitMergeStage.java
@@ -20,9 +20,10 @@ package net.shibboleth.metadata.pipeline;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
import java.util.function.Predicate;
import java.util.function.Supplier;
@@ -38,18 +39,21 @@ import net.shibboleth.metadata.CollectionMergeStrategy;
import net.shibboleth.metadata.Item;
import net.shibboleth.metadata.SimpleCollectionMergeStrategy;
import net.shibboleth.metadata.SimpleItemCollectionFactory;
+import net.shibboleth.metadata.pipeline.impl.DirectExecutor;
import net.shibboleth.metadata.pipeline.impl.FutureSupport;
import net.shibboleth.metadata.pipeline.impl.PipelineCallable;
import net.shibboleth.shared.annotation.constraint.NonnullElements;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.DeprecationSupport;
+import net.shibboleth.shared.primitive.DeprecationSupport.ObjectType;
/**
* A stage which splits a given collection according to a provided selection strategy
* and passes selected items to one pipeline and non-selected items to another.
*
* <p>
- * The selected and non-selected item pipelines are executed via the set {@link ExecutorService}.
+ * The selected and non-selected item pipelines are executed via the set {@link #executor}.
* </p>
*
* <p>
@@ -66,7 +70,14 @@ import net.shibboleth.shared.logic.Constraint;
* </ul>
*
* <p>
- * If no {@link #executorService} is provided, one will be created using {@link Executors#newSingleThreadExecutor()}.
+ * If an {@link #executor} is provided, it will be used to execute the pipelines,
+ * potentially concurrently. By default, the pipelines will be executed sequentially
+ * on the calling thread.
+ * </p>
+ *
+ * <p>
+ * The caller is responsible for the lifecycle of any provided {@link Executor},
+ * including the lifecycle of any threads or thread pools associated with it.
* </p>
*
* <p>
@@ -85,9 +96,9 @@ public class SplitMergeStage<T> extends AbstractStage<T> {
/** Class logger. */
private final Logger log = LoggerFactory.getLogger(SplitMergeStage.class);
- /** Service used to execute the selected and/or non-selected item pipelines. */
+ /** {@link Executor} used to execute the pipelines. */
@Nonnull @GuardedBy("this")
- private ExecutorService executorService = Executors.newSingleThreadExecutor();
+ private Executor executor = new DirectExecutor();
/** Factory used to create the Item collection that is then given to the pipelines. */
@Nonnull @GuardedBy("this")
@@ -109,23 +120,56 @@ public class SplitMergeStage<T> extends AbstractStage<T> {
@Nonnull @GuardedBy("this")
private CollectionMergeStrategy mergeStrategy = new SimpleCollectionMergeStrategy();
+ /**
+ * Gets the executor used to run the selected and non-selected item pipelines.
+ *
+ * @return executor used to run the selected and non-selected item pipelines
+ *
+ * @since 0.10.0
+ */
+ @Nonnull public final synchronized Executor getExecutor() {
+ return executor;
+ }
+
/**
* Gets the executor service used to run the selected and non-selected item pipelines.
*
* @return executor service used to run the selected and non-selected item pipelines
+ *
+ * @deprecated
*/
- @Nonnull public final synchronized ExecutorService getExecutorService() {
- return executorService;
+ @Deprecated(since="0.10.0", forRemoval=true)
+ @Nonnull public final synchronized Executor getExecutorService() {
+ DeprecationSupport.warnOnce(ObjectType.METHOD, "getExecutorService",
+ "SplitMergeStage", "getExecutor");
+ return executor;
+ }
+
+ /**
+ * Sets the executor used to run the selected and non-selected item pipelines.
+ *
+ * @param service executor used to run the selected and non-selected item pipelines
+ *
+ * @since 0.10.0
+ */
+ public synchronized void setExecutor(@Nonnull final Executor exec) {
+ checkSetterPreconditions();
+ executor = Constraint.isNotNull(exec, "executor can not be null");
}
/**
* Sets the executor service used to run the selected and non-selected item pipelines.
*
* @param service executor service used to run the selected and non-selected item pipelines
+ *
+ * @deprecated
*/
+ @Deprecated(since="0.10.0", forRemoval=true)
public synchronized void setExecutorService(@Nonnull final ExecutorService service) {
+ DeprecationSupport.warnOnce(ObjectType.METHOD, "setExecutorService",
+ "SplitMergeStage", "setExecutor");
checkSetterPreconditions();
- executorService = Constraint.isNotNull(service, "ExecutorService can not be null");
+ executor = Constraint.isNotNull(service, "ExecutorService can not be null");
}
/**
@@ -274,7 +318,9 @@ public class SplitMergeStage<T> extends AbstractStage<T> {
}
final PipelineCallable<T> callable = new PipelineCallable<>(pipeline, items);
- return getExecutorService().submit(callable);
+ final @Nonnull var future = new FutureTask<List<Item<T>>>(callable);
+ getExecutor().execute(future);
+ return future;
}
@Override
diff --git a/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/impl/DirectExecutor.java b/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/impl/DirectExecutor.java
new file mode 100644
index 0000000..7941703
--- /dev/null
+++ b/mda-framework/src/main/java/net/shibboleth/metadata/pipeline/impl/DirectExecutor.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.metadata.pipeline.impl;
+
+import java.util.concurrent.Executor;
+
+/**
+ * A degenerate {@link Executor} which executes everything on
+ * the calling thread.
+ *
+ * @since 0.10.0
+ */
+public class DirectExecutor implements Executor {
+
+ @Override
+ public void execute(Runnable command) {
+ command.run();
+ }
+
+}
diff --git a/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/PipelineDemultiplexerStageTest.java b/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/PipelineDemultiplexerStageTest.java
index 07c80d0..1bed8f3 100644
--- a/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/PipelineDemultiplexerStageTest.java
+++ b/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/PipelineDemultiplexerStageTest.java
@@ -52,6 +52,14 @@ public class PipelineDemultiplexerStageTest {
Assert.assertEquals(stage.getExecutorService(), executor);
}
+ @Test public void testExecutor() {
+ PipelineDemultiplexerStage<Object> stage = new PipelineDemultiplexerStage<>();
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ stage.setExecutor(executor);
+ Assert.assertEquals(stage.getExecutor(), executor);
+ }
+
@Test public void testPipelineAndSelectionStrategies() {
PipelineDemultiplexerStage<Object> stage = new PipelineDemultiplexerStage<>();
diff --git a/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/PipelineMergeStageTest.java b/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/PipelineMergeStageTest.java
index 01c5b7f..150336c 100644
--- a/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/PipelineMergeStageTest.java
+++ b/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/PipelineMergeStageTest.java
@@ -20,6 +20,8 @@ package net.shibboleth.metadata.pipeline;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import net.shibboleth.metadata.DeduplicatingItemIdMergeStrategy;
import net.shibboleth.metadata.Item;
@@ -44,6 +46,22 @@ public class PipelineMergeStageTest {
list.add(element2);
return list;
}
+
+ @Test public void testExecutorService() {
+ PipelineMergeStage<Object> stage = new PipelineMergeStage<>();
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ stage.setExecutorService(executor);
+ Assert.assertEquals(stage.getExecutorService(), executor);
+ }
+
+ @Test public void testExecutor() {
+ PipelineMergeStage<Object> stage = new PipelineMergeStage<>();
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ stage.setExecutor(executor);
+ Assert.assertEquals(stage.getExecutor(), executor);
+ }
@Test public void test() throws Exception {
Item<String> md1 = new MockItem("one");
diff --git a/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/SplitMergeStageTest.java b/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/SplitMergeStageTest.java
index 2092508..c6f9db5 100644
--- a/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/SplitMergeStageTest.java
+++ b/mda-framework/src/test/java/net/shibboleth/metadata/pipeline/SplitMergeStageTest.java
@@ -51,6 +51,14 @@ public class SplitMergeStageTest {
Assert.assertEquals(stage.getExecutorService(), executor);
}
+ @Test public void testExecutor() {
+ SplitMergeStage<Object> stage = new SplitMergeStage<>();
+
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ stage.setExecutor(executor);
+ Assert.assertEquals(stage.getExecutor(), executor);
+ }
+
@Test public void testNonselectedItemPipeline() {
SplitMergeStage<Object> stage = new SplitMergeStage<>();
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list