This is an automated email from the ASF dual-hosted git repository.
zehnder pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to refs/heads/dev by this push:
new d69504c915 feat(#2374): Add suggestion to test processing elements
(#2375)
d69504c915 is described below
commit d69504c91540b4f93be267910d41d1dae44abfd1
Author: Philipp Zehnder <[email protected]>
AuthorDate: Thu May 2 08:38:14 2024 +0200
feat(#2374): Add suggestion to test processing elements (#2375)
* feat(#2374): Add suggestion to test processing elements
* #2374 refactored unit tests to use ProcessingElementTestExecutor
* #2374 cleanup
* #2374 cleanup
* #2374 updated test executor to non-static methods
* #2374 updated test executor to non-static methods
* test(#2374): provide a framework to easily unit test processing elements
(#2730)
* #2374 refactored unit tests to use ProcessingElementTestExecutor
* #2374 cleanup
* #2374 cleanup
* #2374 updated test executor to non-static methods
* #2374 updated test executor to non-static methods
* #2374 Added test configuration builder and resolved selector prefixes
* #2374 Moved test executor to a new package
* feat(#2374): Fix cyclic dependencies and checkstyle
* feat(#2374): Fix checkstyle
* #2374 extracted TestConfigurationBuilder into a separate file
---------
Co-authored-by: Isaak <[email protected]>
---
pom.xml | 1 +
.../streampipes-processors-filters-jvm/pom.xml | 2 +-
.../numericalfilter/NumericalFilterProcessor.java | 6 +-
.../booleanfilter/TestBooleanFilterProcessor.java | 118 +++----
.../processor/compose/TestComposeProcessor.java | 208 ++++++-------
.../processor/merge/TestMergeByTimeProcessor.java | 276 +++++++++--------
.../NumericalFilterProcessorTest.java | 83 +++++
.../TestSwingingDoorTrendingFilterProcessor.java | 339 +++++++++++++--------
.../textfilter/TestTextFilterProcessor.java | 188 ++++++------
.../template/PipelineElementTemplateVisitor.java | 5 +-
.../pom.xml | 51 ++--
.../streampipes/test/executors/PrefixStrategy.java | 23 ++
.../executors/ProcessingElementTestExecutor.java | 190 ++++++++++++
.../test/executors/TestConfiguration.java | 47 +++
.../test/executors/TestConfigurationBuilder.java | 62 ++++
15 files changed, 1012 insertions(+), 587 deletions(-)
diff --git a/pom.xml b/pom.xml
index f1ceafa3e6..967ff16e7b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -868,6 +868,7 @@
<module>streampipes-storage-couchdb</module>
<module>streampipes-storage-management</module>
<module>streampipes-test-utils</module>
+ <module>streampipes-test-utils-executors</module>
<module>streampipes-user-management</module>
<module>streampipes-vocabulary</module>
<module>streampipes-wrapper</module>
diff --git a/streampipes-extensions/streampipes-processors-filters-jvm/pom.xml
b/streampipes-extensions/streampipes-processors-filters-jvm/pom.xml
index ed05e4cbc5..536e4c9929 100644
--- a/streampipes-extensions/streampipes-processors-filters-jvm/pom.xml
+++ b/streampipes-extensions/streampipes-processors-filters-jvm/pom.xml
@@ -62,7 +62,7 @@
</dependency>
<dependency>
<groupId>org.apache.streampipes</groupId>
- <artifactId>streampipes-test-utils</artifactId>
+ <artifactId>streampipes-test-utils-executors</artifactId>
<version>0.95.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
diff --git
a/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/numericalfilter/NumericalFilterProcessor.java
b/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/numericalfilter/NumericalFilterProcessor.java
index 14062127cb..5f9a030d5a 100644
---
a/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/numericalfilter/NumericalFilterProcessor.java
+++
b/streampipes-extensions/streampipes-processors-filters-jvm/src/main/java/org/apache/streampipes/processors/filters/jvm/processor/numericalfilter/NumericalFilterProcessor.java
@@ -39,9 +39,9 @@ import org.apache.streampipes.sdk.utils.Assets;
public class NumericalFilterProcessor implements IStreamPipesDataProcessor {
- private static final String NUMBER_MAPPING = "number-mapping";
- private static final String VALUE = "value";
- private static final String OPERATION = "operation";
+ protected static final String NUMBER_MAPPING = "number-mapping";
+ protected static final String VALUE = "value";
+ protected static final String OPERATION = "operation";
private double threshold;
private NumericalOperator numericalOperator;
diff --git
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/booleanfilter/TestBooleanFilterProcessor.java
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/booleanfilter/TestBooleanFilterProcessor.java
index 3f473f6f61..a6d1a73727 100644
---
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/booleanfilter/TestBooleanFilterProcessor.java
+++
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/booleanfilter/TestBooleanFilterProcessor.java
@@ -18,106 +18,80 @@
package org.apache.streampipes.processors.filters.jvm.processor.booleanfilter;
-import
org.apache.streampipes.extensions.api.pe.context.EventProcessorRuntimeContext;
-import org.apache.streampipes.model.runtime.Event;
-import org.apache.streampipes.model.runtime.EventFactory;
-import org.apache.streampipes.model.runtime.SchemaInfo;
-import org.apache.streampipes.model.runtime.SourceInfo;
-import
org.apache.streampipes.sdk.extractor.ProcessingElementParameterExtractor;
-import org.apache.streampipes.test.extensions.api.StoreEventCollector;
-import org.apache.streampipes.wrapper.params.compat.ProcessorParams;
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.TestConfiguration;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
public class TestBooleanFilterProcessor {
- private static final String STREAM_PREFIX = "s0::";
- private static final Logger LOG =
LoggerFactory.getLogger(TestBooleanFilterProcessor.class);
+ BooleanFilterProcessor processor;
+ private static final String FIELD_NAME = "Test";
- static Stream<Arguments> data() {
- return Stream.of(
- Arguments.of("True", Arrays.asList(true, true, false, true, false,
true, false, true), 5),
- Arguments.of("True", Arrays.asList(true, true, true), 3),
- Arguments.of("True", Arrays.asList(false, false, false), 0),
- Arguments.of("True", Collections.emptyList(), 0),
- Arguments.of("False", Arrays.asList(true, false, true, false, true,
false, true, false, true), 4),
- Arguments.of("False", Arrays.asList(true, true, true), 0),
- Arguments.of("False", Arrays.asList(false, false, false), 3),
- Arguments.of("False", Collections.emptyList(), 0)
- );
+ @BeforeEach
+ public void setup(){
+ processor = new BooleanFilterProcessor();
}
-
@ParameterizedTest
@MethodSource("data")
- public void testBoolenFilter(
+ public void test(
String boolToKeep,
List<Boolean> eventBooleans,
- int expectedFilteredBooleanCount
+ List<Boolean> outputEventBooleans
) {
- var fieldName = "Test";
- var processorParams = mock(ProcessorParams.class);
- var eventProcessorRuntimeContext =
mock(EventProcessorRuntimeContext.class);
+ TestConfiguration configuration = TestConfiguration.builder()
+ .configWithDefaultPrefix(BooleanFilterProcessor.BOOLEAN_MAPPING,
FIELD_NAME)
+ .config(BooleanFilterProcessor.VALUE, boolToKeep)
+ .build();
- var processor = new BooleanFilterProcessor();
- var extractor = mock(ProcessingElementParameterExtractor.class);
- when(processorParams.extractor()).thenReturn(extractor);
-
when(extractor.mappingPropertyValue(BooleanFilterProcessor.BOOLEAN_MAPPING)).thenReturn(STREAM_PREFIX
+ fieldName);
- when(extractor.selectedSingleValue(BooleanFilterProcessor.VALUE,
String.class)).thenReturn(boolToKeep);
+ List<Map<String, Object>> events = new ArrayList<>();
+ eventBooleans.forEach(bool->events.add(Map.of(FIELD_NAME, bool)));
- var collector = new StoreEventCollector();
- processor.onInvocation(processorParams, collector,
eventProcessorRuntimeContext);
+ List<Map<String, Object>> outputEvents = new ArrayList<>();
+ outputEventBooleans.forEach(bool->outputEvents.add(Map.of(FIELD_NAME,
bool)));
- sendEvents(processor, collector, eventBooleans, fieldName);
+ ProcessingElementTestExecutor testExecutor = new
ProcessingElementTestExecutor(processor, configuration);
- assertEquals(expectedFilteredBooleanCount, collector.getEvents().size());
+ testExecutor.run(events, outputEvents);
}
- private void sendEvents(
- BooleanFilterProcessor processor,
- StoreEventCollector collector,
- List<Boolean> eventBooleans,
- String fieldName) {
- List<Event> events = makeEvents(eventBooleans, fieldName);
- for (Event event : events) {
- LOG.info("Sending event with value "
- + event.getFieldBySelector(STREAM_PREFIX + fieldName)
- .getAsPrimitive()
- .getAsBoolean());
- processor.onEvent(event, collector);
-
- }
- }
-
- private List<Event> makeEvents(List<Boolean> eventBooleans, String
fieldName) {
- List<Event> events = new ArrayList<>();
- for (Boolean eventSetting : eventBooleans) {
- events.add(makeEvent(eventSetting, fieldName));
- }
- return events;
- }
-
- private Event makeEvent(Boolean value, String fieldName) {
- Map<String, Object> map = new HashMap<>();
- map.put(fieldName, value);
- return EventFactory.fromMap(map, new SourceInfo("test" + "-topic", "s0"),
- new SchemaInfo(null, new ArrayList<>())
+ static Stream<Arguments> data() {
+ return Stream.of(
+ Arguments.of("True",
+ Arrays.asList(true, true, false, true, false, true, false, true),
+ Arrays.asList(true, true, true, true, true)),
+ Arguments.of("True",
+ Arrays.asList(true, true, true),
+ Arrays.asList(true, true, true)),
+ Arguments.of("True",
+ Arrays.asList(false, false, false),
+ Collections.emptyList()),
+ Arguments.of("True",
+ Collections.emptyList(),
+ Collections.emptyList()),
+ Arguments.of("False",
+ Arrays.asList(true, false, true, false, true, false, true, false,
true),
+ Arrays.asList(false, false, false, false)),
+ Arguments.of("False",
+ Arrays.asList(true, true, true),
+ Collections.emptyList()),
+ Arguments.of("False",
+ Arrays.asList(false, false, false),
+ Arrays.asList(false, false, false)),
+ Arguments.of("False",
+ Collections.emptyList(),
+ Collections.emptyList())
);
}
}
diff --git
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/compose/TestComposeProcessor.java
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/compose/TestComposeProcessor.java
index fd56bb23ee..05bf18cccd 100644
---
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/compose/TestComposeProcessor.java
+++
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/compose/TestComposeProcessor.java
@@ -18,124 +18,98 @@
package org.apache.streampipes.processors.filters.jvm.processor.compose;
-//@RunWith(Parameterized.class)
+import org.apache.streampipes.model.graph.DataProcessorInvocation;
+import org.apache.streampipes.model.output.CustomOutputStrategy;
+import org.apache.streampipes.model.output.OutputStrategy;
+import org.apache.streampipes.test.executors.PrefixStrategy;
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.TestConfiguration;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
public class TestComposeProcessor {
-//
-// private static final Logger LOG =
LoggerFactory.getLogger(TestComposeProcessor.class);
-//
-// @org.junit.runners.Parameterized.Parameter
-// public String testName;
-//
-// @org.junit.runners.Parameterized.Parameter(1)
-// public List<Map<String, Object>> eventMaps;
-//
-// @org.junit.runners.Parameterized.Parameter(2)
-// public List<String> selectorPrefixes;
-//
-// @org.junit.runners.Parameterized.Parameter(3)
-// public int expectedNumOfEvents;
-//
-// @org.junit.runners.Parameterized.Parameter(4)
-// public int expectedEventSize;
-//
-// private static final String outputKeySelector1 = "key-selector1";
-// private static final String outputKeySelector2 = "key-selector2";
-//
-// @org.junit.runners.Parameterized.Parameters
-// public static Iterable<Object[]> data() {
-// Map<String, Object> mapWithFirstOutputSelector = new HashMap<>();
-// mapWithFirstOutputSelector.put(outputKeySelector1, new Object());
-//
-// Map<String, Object> mapWithSecondOutputSelector = new HashMap<>();
-// mapWithSecondOutputSelector.put(outputKeySelector2, new Object());
-//
-// Map<String, Object> mapWithInvalidOutputSelector = new HashMap<>();
-// mapWithInvalidOutputSelector.put("invalid-selector", new Object());
-//
-// List<Map<String, Object>> singleMap = new ArrayList<>();
-// singleMap.add(mapWithFirstOutputSelector);
-//
-// List<Map<String, Object>> twoMapsMatching = new ArrayList<>();
-// twoMapsMatching.add(mapWithFirstOutputSelector);
-// twoMapsMatching.add(mapWithSecondOutputSelector);
-//
-// List<Map<String, Object>> twoMapsOneMatching = new ArrayList<>();
-// twoMapsOneMatching.add(mapWithFirstOutputSelector);
-// twoMapsOneMatching.add(mapWithInvalidOutputSelector);
-//
-// List<Map<String, Object>> twoMapsNoneMatching = new ArrayList<>();
-// twoMapsNoneMatching.add(mapWithInvalidOutputSelector);
-// twoMapsNoneMatching.add(new HashMap<>(mapWithInvalidOutputSelector));
-//
-// return Arrays.asList(new Object[][]{
-// {"testWithOneEvent", singleMap, List.of("s0"), 0, 0},
-// {"testWithTwoEventsSamePrefix", twoMapsMatching, List.of("s0",
"s0"), 0, 0},
-// {"testWithTwoEvents", twoMapsMatching, List.of("s0", "s1"), 1,
2},
-// {"testWithTwoEventsAnd1InvalidSelector", twoMapsOneMatching,
List.of("s0", "s1"), 1, 1},
-// {"testWithTwoEventsWithInvalidSelectors", twoMapsNoneMatching,
List.of("s0", "s1"), 1, 0}
-// });
-// }
-//
-//
-//
-// @Test
-// public void testComposeProcessor() {
-// LOG.info("Executing test: {}", testName);
-// var processor = new ComposeProcessor();
-// var originalGraph = processor.declareModel();
-//
originalGraph.setSupportedGrounding(EventGroundingGenerator.makeDummyGrounding());
-//
-// var graph = InvocationGraphGenerator.makeEmptyInvocation(originalGraph);
-// List<OutputStrategy> outputStrategies = new ArrayList<>();
-// outputStrategies.add(new CustomOutputStrategy(List.of("s0::" +
outputKeySelector1, "s1::" + outputKeySelector2)));
-// graph.setOutputStrategies(outputStrategies);
-// var params = new ProcessorParams(graph);
-//
-// var eventCollector = new StoreEventCollector();
-// processor.onInvocation(params, eventCollector, null);
-//
-// List<Event> collectedEvents = sendEvents(processor, eventCollector);
-//
-// LOG.info("Expected collected event count is: {}", expectedNumOfEvents);
-// LOG.info("Actual collected event count is: {}", collectedEvents.size());
-// assertEquals(expectedNumOfEvents, collectedEvents.size());
-//
-// if (!collectedEvents.isEmpty()){
-// int eventSize = collectedEvents.get(0).getFields().size();
-//
-// LOG.info("Expected event size is: {}", expectedEventSize);
-// LOG.info("Actual event size is: {}", eventSize);
-// assertEquals(expectedEventSize, eventSize);
-// }
-// }
-//
-// private List<Event> sendEvents(ComposeProcessor processor,
StoreEventCollector collector) {
-// List<Event> events = makeEvents();
-// for (Event event : events) {
-// LOG.info("Sending event with map: " + event.getFields()
-// + ", and prefix selector: " +
event.getSourceInfo().getSelectorPrefix());
-// processor.onEvent(event, collector);
-// try {
-// Thread.sleep(100);
-// } catch (InterruptedException e) {
-// e.printStackTrace();
-// }
-// }
-// return collector.getEvents();
-// }
-// private List<Event> makeEvents() {
-// List<Event> events = new ArrayList<>();
-// for (int i = 0; i < eventMaps.size(); i++) {
-// events.add(makeEvent(eventMaps.get(i), selectorPrefixes.get(i)));
-// }
-// return events;
-// }
-//
-// private Event makeEvent(Map<String, Object> eventMap, String
selectorPrefix) {
-// return EventFactory.fromMap(eventMap, new SourceInfo("test" + "-topic",
selectorPrefix),
-// new SchemaInfo(null, new ArrayList<>()));
-// }
-}
+ ComposeProcessor processor;
+ private static final String SELECTOR_1 = "key-selector1";
+ private static final String SELECTOR_2 = "key-selector2";
+ private static final String INVALID_SELECTOR = "invalid-selector";
+ private static final String S0_PREFIX = "s0::";
+ private static final String S1_PREFIX = "s1::";
+
+ @BeforeEach
+ public void setup(){
+ processor = new ComposeProcessor();
+ }
+
+ @ParameterizedTest
+ @MethodSource("data")
+ public void test(List<Map<String, Object>> events,
+ List<Map<String, Object>> outputEvents,
+ PrefixStrategy prefixStrategy) {
+ Consumer<DataProcessorInvocation> invocationConfig = (invocation->{
+ List<OutputStrategy> outputStrategies = new ArrayList<>();
+ outputStrategies.add(new CustomOutputStrategy(List.of(S0_PREFIX +
SELECTOR_1, S1_PREFIX + SELECTOR_2)));
+ invocation.setOutputStrategies(outputStrategies);
+ });
+ TestConfiguration configuration =
TestConfiguration.builder().prefixStrategy(prefixStrategy).build();
+
+ ProcessingElementTestExecutor testExecutor =
+ new ProcessingElementTestExecutor(processor, configuration,
invocationConfig);
+
+ testExecutor.run(events, outputEvents);
+ }
+ static Stream<Arguments> data() {
+
+ var object1 = new Object();
+ var object2 = new Object();
+
+ return Stream.of(
+ Arguments.of(
+ List.of(
+ Map.of(SELECTOR_1, object1)),
+ List.of(),
+ PrefixStrategy.SAME_PREFIX),
+ Arguments.of(
+ List.of(
+ Map.of(SELECTOR_1, object1),
+ Map.of(SELECTOR_2, object2)),
+ List.of(),
+ PrefixStrategy.SAME_PREFIX),
+ Arguments.of(
+ List.of(
+ Map.of(SELECTOR_1, object1),
+ Map.of(SELECTOR_2, object2)),
+ List.of(
+ Map.of(SELECTOR_1, object1, SELECTOR_2, object2)
+ ),
+ PrefixStrategy.ALTERNATE),
+ Arguments.of(
+ List.of(
+ Map.of(SELECTOR_1, object1),
+ Map.of(INVALID_SELECTOR, object2)),
+ List.of(
+ Map.of(SELECTOR_1, object1)
+ ),
+ PrefixStrategy.ALTERNATE),
+ Arguments.of(
+ List.of(
+ Map.of(INVALID_SELECTOR, object1),
+ Map.of(INVALID_SELECTOR, object2)),
+ List.of(
+ Map.of()
+ ),
+ PrefixStrategy.ALTERNATE)
+ );
+ }
+}
diff --git
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/merge/TestMergeByTimeProcessor.java
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/merge/TestMergeByTimeProcessor.java
index 2c4334fb00..953080fb68 100644
---
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/merge/TestMergeByTimeProcessor.java
+++
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/merge/TestMergeByTimeProcessor.java
@@ -17,145 +17,141 @@
*/
package org.apache.streampipes.processors.filters.jvm.processor.merge;
-//@RunWith(Parameterized.class)
+import org.apache.streampipes.model.graph.DataProcessorInvocation;
+import org.apache.streampipes.model.output.CustomOutputStrategy;
+import org.apache.streampipes.test.executors.PrefixStrategy;
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.TestConfiguration;
+import org.apache.streampipes.test.executors.TestConfigurationBuilder;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+
public class TestMergeByTimeProcessor {
-//
-// private static final Logger LOG =
LoggerFactory.getLogger(TestMergeByTimeProcessor.class);
-//
-// private static final Integer timeInterval = 100;
-// @org.junit.runners.Parameterized.Parameter
-// public String testName;
-// @org.junit.runners.Parameterized.Parameter(1)
-// public List<String> eventStrings;
-// @org.junit.runners.Parameterized.Parameter(2)
-// public List<String> expectedValue;
-//
-// @org.junit.runners.Parameterized.Parameters
-// public static Iterable<Object[]> data() {
-// return Arrays.asList(new Object[][]{
-// {"testWithInInterval", Arrays.asList("s0:0", "s1:90"),
List.of("(90,0)")},
-// {"testNotWithInInterval", Arrays.asList("s0:0", "s1:110"),
List.of()},
-// {"testWithInAndNotWithInInterval", Arrays.asList("s0:0", "s1:80",
"s0:110", "s1:500"),
-// List.of("(80,0)")},
-// {"testFigGvnInDocs",
-// Arrays.asList("s1:0", "s0:10", "s0:110", "s1:115", "s0:120",
"s1:230", "s0:340", "s0:500",
-// "s1:510"),
-// Arrays.asList("(0,10)", "(115,110)", "(510,500)")}
-// });
-// }
-//
-// @Test
-// public void testMergeByTimeProcessor() {
-// MergeByTimeProcessor mergeByTimeProcessor = new MergeByTimeProcessor();
-// DataProcessorDescription originalGraph =
mergeByTimeProcessor.declareModel();
-//
originalGraph.setSupportedGrounding(EventGroundingGenerator.makeDummyGrounding());
-//
-// DataProcessorInvocation graph =
InvocationGraphGenerator.makeEmptyInvocation(originalGraph);
-// graph.setInputStreams(Arrays.asList(
-//
EventStreamGenerator.makeStreamWithProperties(Collections.singletonList("in-stram0")),
-//
EventStreamGenerator.makeStreamWithProperties(Collections.singletonList("in-stream1"))
-// ));
-//
-// graph.setOutputStream(
-//
EventStreamGenerator.makeStreamWithProperties(Collections.singletonList("out-stream"))
-// );
-//
graph.getOutputStream().getEventGrounding().getTransportProtocol().getTopicDefinition()
-// .setActualTopicName("output-topic");
-//
-// List<String> outputKeySelectors = graph.getOutputStrategies()
-// .stream()
-// .filter(CustomOutputStrategy.class::isInstance)
-// .map(o -> (CustomOutputStrategy) o)
-// .findFirst()
-// .map(CustomOutputStrategy::getSelectedPropertyKeys)
-// .orElse(new ArrayList<>());
-// outputKeySelectors.add("s0::timestamp_mapping_stream_1");
-// outputKeySelectors.add("s1::timestamp_mapping_stream_2");
-//
-// List<MappingPropertyUnary> mappingPropertyUnaries =
graph.getStaticProperties()
-// .stream()
-// .filter(p -> p instanceof MappingPropertyUnary)
-// .map((p -> (MappingPropertyUnary) p))
-// .filter(p -> Arrays.asList(
-// MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
-// MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY)
-// .contains(p.getInternalName()))
-// .collect(Collectors.toList());
-//
-// assert mappingPropertyUnaries.size() == 2;
-// mappingPropertyUnaries.get(0)
-// .setSelectedProperty("s0::" +
MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY);
-// mappingPropertyUnaries.get(1)
-// .setSelectedProperty("s1::" +
MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY);
-//
-// FreeTextStaticProperty fsp = graph.getStaticProperties().stream()
-// .filter(p -> p instanceof FreeTextStaticProperty)
-// .map((p -> (FreeTextStaticProperty) p))
-// .filter(p ->
p.getInternalName().equals(MergeByTimeProcessor.TIME_INTERVAL))
-// .findFirst().orElse(null);
-// assert fsp != null;
-// fsp.setValue(String.valueOf(timeInterval));
-//
-// ProcessorParams params = new ProcessorParams(graph);
-//
-// StoreEventCollector collector = new StoreEventCollector();
-//
-// mergeByTimeProcessor.onInvocation(params, collector, null);
-// sendEvents(mergeByTimeProcessor, collector);
-//
-// List<String> actualCollectedEvents = collector.getEvents().stream()
-// .map(e -> formatMergedEvent(e))
-// .collect(Collectors.toList());
-//
-// LOG.info("Expected merged event is {}", expectedValue);
-// LOG.info("Actual merged event is {}", actualCollectedEvents);
-// assertTrue(eventsEquals(expectedValue, actualCollectedEvents));
-// }
-//
-// private boolean eventsEquals(List<String> expectedValue, List<String>
actualCollectedEvents) {
-// if (expectedValue.size() != actualCollectedEvents.size()) {
-// return false;
-// }
-// for (int i = 0; i < expectedValue.size(); i++) {
-// if
(!expectedValue.get(i).equalsIgnoreCase(actualCollectedEvents.get(i))) {
-// return false;
-// }
-// }
-// return true;
-// }
-//
-// private String formatMergedEvent(Event mergedEvent) {
-// return String.format("(%s)", mergedEvent.getFields().values().stream()
-// .map(m ->
m.getAsPrimitive().getAsString()).collect(Collectors.joining(",")));
-// }
-//
-// private void sendEvents(MergeByTimeProcessor mergeByTimeProcessor,
StoreEventCollector spOut) {
-// List<Event> events = makeEvents();
-// for (Event event : events) {
-// mergeByTimeProcessor.onEvent(event, spOut);
-// }
-//
-// }
-//
-// private List<Event> makeEvents() {
-// List<Event> events = Lists.newArrayList();
-// for (String eventString : eventStrings) {
-// events.add(makeEvent(eventString));
-// }
-// return events;
-// }
-//
-// private Event makeEvent(String eventString) {
-// Map<String, Object> map = Maps.newHashMap();
-// String streamId = eventString.split(":")[0];
-// String timestamp = eventString.split(":")[1];
-// if (streamId.equals("s0")) {
-// map.put(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
timestamp);
-// } else {
-// map.put(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY,
timestamp);
-// }
-// return EventFactory.fromMap(map,
-// new SourceInfo("test", streamId),
-// new SchemaInfo(null, Lists.newArrayList()));
-// }
+
+ private static final String S0_PREFIX = "s0";
+ private static final String S1_PREFIX = "s1";
+ private static final Integer timeInterval = 100;
+
+ MergeByTimeProcessor processor;
+
+ @BeforeEach
+ public void setup(){
+ processor = new MergeByTimeProcessor();
+ }
+ @ParameterizedTest
+ @MethodSource("data")
+ public void test(List<Map<String, Object>> events,
+ List<Map<String, Object>> outputEvents,
+ PrefixStrategy prefixStrategy,
+ List<String> customPrefixes){
+
+
+ TestConfigurationBuilder configurationBuilder = TestConfiguration.builder()
+ .config(MergeByTimeProcessor.TIME_INTERVAL, timeInterval)
+ .configWithPrefix(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY, S0_PREFIX)
+ .configWithPrefix(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY,
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY, S1_PREFIX);
+
+ if (customPrefixes != null){
+ configurationBuilder.customPrefixStrategy(customPrefixes);
+ } else {
+ configurationBuilder.prefixStrategy(prefixStrategy);
+ }
+
+
+ Consumer<DataProcessorInvocation> invocationConfig = (invocation->{
+ List<String> outputKeySelectors = invocation.getOutputStrategies()
+ .stream()
+ .filter(CustomOutputStrategy.class::isInstance)
+ .map(o -> (CustomOutputStrategy) o)
+ .findFirst()
+ .map(CustomOutputStrategy::getSelectedPropertyKeys)
+ .orElse(new ArrayList<>());
+ outputKeySelectors.add(S0_PREFIX + "::" +
MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY);
+ outputKeySelectors.add(S1_PREFIX + "::" +
MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY);
+ });
+
+ ProcessingElementTestExecutor testExecutor =
+ new ProcessingElementTestExecutor(processor,
configurationBuilder.build(), invocationConfig);
+
+ testExecutor.run(events, outputEvents);
+ }
+
+ static Stream<Arguments> data() {
+ return Stream.of(
+ Arguments.of(
+ List.of(
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
"0"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY,
"90")
+ ),
+ List.of(
+ Map.of(
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY, "90",
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY, "0"
+ )),
+ PrefixStrategy.ALTERNATE,
+ null),
+ Arguments.of(
+ List.of(
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY, "0"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY, "110")
+ ),
+ List.of(),
+ PrefixStrategy.ALTERNATE,
+ null),
+ Arguments.of(
+ List.of(
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
"0"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY,
"80"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
"110"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY,
"500")
+ ),
+ List.of(
+ Map.of(
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY, "80",
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY, "0"
+ )),
+ PrefixStrategy.ALTERNATE,
+ null),
+ Arguments.of(
+ List.of(
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY,
"0"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
"10"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
"110"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY,
"115"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
"120"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY,
"230"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
"340"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY,
"500"),
+ Map.of(MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY,
"510")
+ ),
+ List.of(
+ Map.of(
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY, "0",
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY, "10"
+ ),
+ Map.of(
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY, "115",
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY, "110"
+ ),
+ Map.of(
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_2_KEY, "510",
+ MergeByTimeProcessor.TIMESTAMP_MAPPING_STREAM_1_KEY, "500"
+ )
+ ),
+ null,
+ List.of(S1_PREFIX, S0_PREFIX, S0_PREFIX, S1_PREFIX, S0_PREFIX,
S1_PREFIX, S0_PREFIX, S0_PREFIX, S1_PREFIX))
+ );
+ }
}
\ No newline at end of file
diff --git
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/numericalfilter/NumericalFilterProcessorTest.java
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/numericalfilter/NumericalFilterProcessorTest.java
new file mode 100644
index 0000000000..ed08eecd9f
--- /dev/null
+++
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/numericalfilter/NumericalFilterProcessorTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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
org.apache.streampipes.processors.filters.jvm.processor.numericalfilter;
+
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.TestConfiguration;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.Map;
+
+public class NumericalFilterProcessorTest {
+
+ private static final String PROPERTY_NAME = "propertyName";
+ private NumericalFilterProcessor processor;
+
+
+ @BeforeEach
+ public void setup() {
+ processor = new NumericalFilterProcessor();
+ }
+
+ @Test
+ public void testLowerThenOperatorFilterNotApplied() {
+
+ TestConfiguration configuration = TestConfiguration.builder()
+ .configWithDefaultPrefix(NumericalFilterProcessor.NUMBER_MAPPING,
PROPERTY_NAME)
+ .config(NumericalFilterProcessor.VALUE, 10.0)
+ .config(NumericalFilterProcessor.OPERATION, "<")
+ .build();
+
+ List<Map<String, Object>> inputEvents = List.of(
+ Map.of(PROPERTY_NAME, 1.0f)
+ );
+
+ List<Map<String, Object>> outputEvents = List.of(
+ Map.of(PROPERTY_NAME, 1.0f)
+ );
+
+ ProcessingElementTestExecutor testExecutor = new
ProcessingElementTestExecutor(processor, configuration);
+
+ testExecutor.run(inputEvents, outputEvents);
+ }
+
+ @Test
+ public void testLowerThenOperatorFilterApplied() {
+
+ TestConfiguration configuration = TestConfiguration.builder()
+ .configWithDefaultPrefix(NumericalFilterProcessor.NUMBER_MAPPING,
PROPERTY_NAME)
+ .config(NumericalFilterProcessor.VALUE, 10.0)
+ .config(NumericalFilterProcessor.OPERATION, "<")
+ .build();
+
+ List<Map<String, Object>> inputEvents = List.of(
+ Map.of(PROPERTY_NAME, 11.0f)
+ );
+
+ List<Map<String, Object>> outputEvents = List.of();
+
+ ProcessingElementTestExecutor testExecutor = new
ProcessingElementTestExecutor(processor, configuration);
+
+ testExecutor.run(inputEvents, outputEvents);
+ }
+
+}
\ No newline at end of file
diff --git
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/sdt/TestSwingingDoorTrendingFilterProcessor.java
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/sdt/TestSwingingDoorTrendingFilterProcessor.java
index 3a5dbf2288..07f14e2ad5 100644
---
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/sdt/TestSwingingDoorTrendingFilterProcessor.java
+++
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/sdt/TestSwingingDoorTrendingFilterProcessor.java
@@ -18,133 +18,216 @@
package org.apache.streampipes.processors.filters.jvm.processor.sdt;
-//@RunWith(Parameterized.class)
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.TestConfiguration;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
public class TestSwingingDoorTrendingFilterProcessor {
-//
-// private static final Logger LOG =
LoggerFactory.getLogger(TestSwingingDoorTrendingFilterProcessor.class);
-//
-// @org.junit.runners.Parameterized.Parameter
-// public String testName;
-// @org.junit.runners.Parameterized.Parameter(1)
-// public String sdtCompressionDeviation;
-// @org.junit.runners.Parameterized.Parameter(2)
-// public String sdtCompressionMinTimeInterval;
-// @org.junit.runners.Parameterized.Parameter(3)
-// public String sdtCompressionMaxTimeInterval;
-// @org.junit.runners.Parameterized.Parameter(4)
-// public int expectedFilteredCount;
-// @org.junit.runners.Parameterized.Parameter(5)
-// public List<Pair<Long, Double>> eventSettings;
-// @org.junit.runners.Parameterized.Parameter(6)
-// public boolean expectException;
-// @org.junit.runners.Parameterized.Parameter(7)
-// public String expectedErrorMessage;
-//
-// private final String sdtTimestampField = "sdtTimestampField";
-// private final String sdtValueField = "sdtValueField";
-//
-// @org.junit.runners.Parameterized.Parameters
-// public static Iterable<Object[]> data() {
-//
-// return Arrays.asList(new Object[][]{
-// {"testWithOneEvent", "10.0", "100", "500", 1, List.of(Pair.of(9,
50.0)), false, ""},
-// {"testFullFilter", "10.0", "100", "500", 4, List.of(
-// Pair.of(0, 50.0), //true
-// Pair.of(50, 50.0), //false
-// Pair.of(200, 100.0), //false
-// Pair.of(270, 140.0), //false
-// Pair.of(300, 250.0), //true
-// Pair.of(900, 500.0), //true
-// Pair.of(1100, 800.0), //false
-// Pair.of(1250, 1600.0) //true
-// )
-// , false, ""},
-// {"testWithNegativeCompressionDeviation", "-10.0", "100", "500",
1, new ArrayList<>(), true
-// , "Compression Deviation should be positive!"},
-// {"testWithNegativeMinInterval", "10.0", "-100", "500", 1, new
ArrayList<>(), true
-// , "Compression Minimum Time Interval should be >= 0!"},
-// {"testWithMinInterval>MaxInterval", "10.0", "1000", "500", 1,
new ArrayList<>(), true
-// , "Compression Minimum Time Interval should be <
Compression Maximum Time Interval!"}
-// });
-// }
-//
-// @Rule
-// public ExpectedException exceptionRule = ExpectedException.none();
-//
-// @Test
-// public void testSdtFilter() {
-// LOG.info("Executing test: {}", testName);
-// SwingingDoorTrendingFilterProcessor processor = new
SwingingDoorTrendingFilterProcessor();
-// DataProcessorDescription originalGraph = processor.declareModel();
-//
originalGraph.setSupportedGrounding(EventGroundingGenerator.makeDummyGrounding());
-//
-// DataProcessorInvocation graph =
-// InvocationGraphGenerator.makeEmptyInvocation(originalGraph);
-//
-// ProcessorParams params = new ProcessorParams(graph);
-//
params.extractor().getStaticPropertyByName(SwingingDoorTrendingFilterProcessor.SDT_TIMESTAMP_FIELD_KEY
-// , MappingPropertyUnary.class)
-// .setSelectedProperty("test::" + sdtTimestampField);
-//
params.extractor().getStaticPropertyByName(SwingingDoorTrendingFilterProcessor.SDT_VALUE_FIELD_KEY
-// , MappingPropertyUnary.class)
-// .setSelectedProperty("test::" + sdtValueField);
-//
params.extractor().getStaticPropertyByName(SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_DEVIATION_KEY
-// , FreeTextStaticProperty.class)
-// .setValue(sdtCompressionDeviation);
-//
params.extractor().getStaticPropertyByName(SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_MIN_INTERVAL_KEY
-// , FreeTextStaticProperty.class)
-// .setValue(sdtCompressionMinTimeInterval);
-//
params.extractor().getStaticPropertyByName(SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_MAX_INTERVAL_KEY
-// , FreeTextStaticProperty.class)
-// .setValue(sdtCompressionMaxTimeInterval);
-//
-// if (expectException){
-// LOG.info("Expecting Error Message: {}", expectedErrorMessage);
-// exceptionRule.expect(SpRuntimeException.class);
-// exceptionRule.expectMessage(expectedErrorMessage);
-// }
-//
-// StoreEventCollector eventCollector = new StoreEventCollector();
-// processor.onInvocation(params, eventCollector, null);
-//
-// int result = sendEvents(processor, eventCollector);
-//
-// LOG.info("Expected SDT filtered count is: {}", expectedFilteredCount);
-// LOG.info("Actual SDT filtered count is: {}", result);
-// assertEquals(expectedFilteredCount, result);
-// }
-//
-//
-// private int sendEvents(SwingingDoorTrendingFilterProcessor processor,
StoreEventCollector collector) {
-// List<Event> events = makeEvents();
-// for (Event event : events) {
-// LOG.info("Sending event with timestamp: "
-// + event.getFieldBySelector("test::" +
sdtTimestampField).getAsPrimitive().getAsLong()
-// + ", and value: "
-// + event.getFieldBySelector("test::" +
sdtValueField).getAsPrimitive().getAsFloat());
-// processor.onEvent(event, collector);
-// try {
-// Thread.sleep(100);
-// } catch (InterruptedException e) {
-// e.printStackTrace();
-// }
-// }
-// return collector.getEvents().size();
-// }
-//
-// private List<Event> makeEvents() {
-// List<Event> events = new ArrayList<>();
-// for (Pair<Long, Double> eventSetting: eventSettings) {
-// events.add(makeEvent(eventSetting));
-// }
-// return events;
-// }
-//
-// private Event makeEvent(Pair<Long, Double> eventSetting) {
-// Map<String, Object> map = new HashMap<>();
-// map.put(sdtTimestampField, eventSetting.getKey());
-// map.put(sdtValueField, eventSetting.getValue());
-// return EventFactory.fromMap(map, new SourceInfo("test" + "-topic",
"test"),
-// new SchemaInfo(null, new ArrayList<>()));
-// }
+
+ private final String sdtTimestampField = "sdtTimestampField";
+ private final String sdtValueField = "sdtValueField";
+
+ private SwingingDoorTrendingFilterProcessor processor;
+
+ @BeforeEach
+ public void setup() {
+ processor = new SwingingDoorTrendingFilterProcessor();
+ }
+
+ @Test
+ public void test() {
+ TestConfiguration configuration = TestConfiguration
+ .builder()
+
.configWithDefaultPrefix(SwingingDoorTrendingFilterProcessor.SDT_TIMESTAMP_FIELD_KEY,
sdtTimestampField)
+
.configWithDefaultPrefix(SwingingDoorTrendingFilterProcessor.SDT_VALUE_FIELD_KEY,
sdtValueField)
+
.config(SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_DEVIATION_KEY,
"10.0")
+
.config(SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_MIN_INTERVAL_KEY,
"100")
+
.config(SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_MAX_INTERVAL_KEY,
"500")
+ .build();
+
+ List<Map<String, Object>> inputEvents = List.of(
+ Map.of(sdtTimestampField, 0,
+ sdtValueField, 50.0
+ ),
+ Map.of(sdtTimestampField, 50,
+ sdtValueField, 50.0
+ ),
+ Map.of(sdtTimestampField, 200,
+ sdtValueField, 100.0
+ ),
+ Map.of(sdtTimestampField, 270,
+ sdtValueField, 140.0
+ ),
+ Map.of(sdtTimestampField, 300,
+ sdtValueField, 250.0
+ ),
+ Map.of(sdtTimestampField, 900,
+ sdtValueField, 500.0
+ ),
+ Map.of(sdtTimestampField, 1100,
+ sdtValueField, 800.0
+ ),
+ Map.of(sdtTimestampField, 1250,
+ sdtValueField, 1600.0
+ )
+ );
+
+ List<Map<String, Object>> outputEvents = List.of(
+ Map.of(sdtTimestampField, 0,
+ sdtValueField, 50.0
+ ),
+ Map.of(sdtTimestampField, 270,
+ sdtValueField, 140.0
+ ),
+ Map.of(sdtTimestampField, 900,
+ sdtValueField, 500.0
+ ),
+ Map.of(sdtTimestampField, 1100,
+ sdtValueField, 800.0
+ )
+ );
+
+ ProcessingElementTestExecutor testExecutor = new
ProcessingElementTestExecutor(processor, configuration);
+
+ testExecutor.run(inputEvents, outputEvents);
+ }
+
+ @Test
+ public void testInvalidDeviationKey() {
+ TestConfiguration configuration = TestConfiguration
+ .builder()
+ .configWithDefaultPrefix(
+ SwingingDoorTrendingFilterProcessor.SDT_TIMESTAMP_FIELD_KEY,
+ sdtTimestampField
+ )
+ .configWithDefaultPrefix(
+ SwingingDoorTrendingFilterProcessor.SDT_VALUE_FIELD_KEY,
+ sdtValueField
+ )
+ .config(
+ SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_DEVIATION_KEY,
+ "-10.0"
+ )
+ .config(
+
SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_MIN_INTERVAL_KEY,
+ "100"
+ )
+ .config(
+
SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_MAX_INTERVAL_KEY,
+ "500"
+ )
+ .build();
+
+ List<Map<String, Object>> inputEvents = new ArrayList<>();
+
+ List<Map<String, Object>> outputEvents = new ArrayList<>();
+
+ Exception expectedException = new SpRuntimeException("Compression
Deviation should be positive!");
+
+ ProcessingElementTestExecutor testExecutor = new
ProcessingElementTestExecutor(processor, configuration);
+
+ Exception exception = assertThrows(expectedException.getClass(), () -> {
+ testExecutor.run(inputEvents, outputEvents);
+ });
+ String expectedMessage = expectedException.getMessage();
+ String actualMessage = exception.getMessage();
+ assertTrue(actualMessage.contains(expectedMessage));
+
+ }
+
+ @Test
+ public void testNegativeMinimumTime() {
+ TestConfiguration configuration = TestConfiguration
+ .builder()
+ .configWithDefaultPrefix(
+ SwingingDoorTrendingFilterProcessor.SDT_TIMESTAMP_FIELD_KEY,
+ sdtTimestampField
+ )
+ .configWithDefaultPrefix(
+ SwingingDoorTrendingFilterProcessor.SDT_VALUE_FIELD_KEY,
+ sdtValueField
+ )
+ .config(
+ SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_DEVIATION_KEY,
+ "10.0"
+ )
+ .config(
+
SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_MIN_INTERVAL_KEY,
+ "-100"
+ )
+ .config(
+
SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_MAX_INTERVAL_KEY,
+ "500"
+ )
+ .build();
+
+ List<Map<String, Object>> inputEvents = new ArrayList<>();
+
+ List<Map<String, Object>> outputEvents = new ArrayList<>();
+
+ Exception expectedException = new SpRuntimeException("Compression Minimum
Time Interval should be >= 0!");
+
+ ProcessingElementTestExecutor testExecutor = new
ProcessingElementTestExecutor(processor, configuration);
+
+ Exception exception = assertThrows(expectedException.getClass(), () -> {
+ testExecutor.run(inputEvents, outputEvents);
+ });
+ String expectedMessage = expectedException.getMessage();
+ String actualMessage = exception.getMessage();
+ assertTrue(actualMessage.contains(expectedMessage));
+ }
+
+ @Test
+ public void testInvalidTimeInterval() {
+ TestConfiguration configuration = TestConfiguration
+ .builder()
+ .configWithDefaultPrefix(
+ SwingingDoorTrendingFilterProcessor.SDT_TIMESTAMP_FIELD_KEY,
+ sdtTimestampField
+ )
+ .configWithDefaultPrefix(
+ SwingingDoorTrendingFilterProcessor.SDT_VALUE_FIELD_KEY,
+ sdtValueField
+ )
+ .config(
+ SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_DEVIATION_KEY,
+ "10.0"
+ )
+ .config(
+
SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_MIN_INTERVAL_KEY,
+ "1000"
+ )
+ .config(
+
SwingingDoorTrendingFilterProcessor.SDT_COMPRESSION_MAX_INTERVAL_KEY,
+ "500"
+ )
+ .build();
+
+ List<Map<String, Object>> inputEvents = new ArrayList<>();
+
+ List<Map<String, Object>> outputEvents = new ArrayList<>();
+
+ Exception expectedException = new
+ SpRuntimeException("Compression Minimum Time Interval should be <
Compression Maximum Time Interval!");
+
+ ProcessingElementTestExecutor testExecutor = new
ProcessingElementTestExecutor(processor, configuration);
+
+ Exception exception = assertThrows(expectedException.getClass(), () -> {
+ testExecutor.run(inputEvents, outputEvents);
+ });
+ String expectedMessage = expectedException.getMessage();
+ String actualMessage = exception.getMessage();
+ assertTrue(actualMessage.contains(expectedMessage));
+ }
}
\ No newline at end of file
diff --git
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/textfilter/TestTextFilterProcessor.java
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/textfilter/TestTextFilterProcessor.java
index 54dc91129a..d283eb04ce 100644
---
a/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/textfilter/TestTextFilterProcessor.java
+++
b/streampipes-extensions/streampipes-processors-filters-jvm/src/test/java/org/apache/streampipes/processors/filters/jvm/processor/textfilter/TestTextFilterProcessor.java
@@ -18,101 +18,99 @@
package org.apache.streampipes.processors.filters.jvm.processor.textfilter;
-//@RunWith(Parameterized.class)
+import org.apache.streampipes.test.executors.ProcessingElementTestExecutor;
+import org.apache.streampipes.test.executors.TestConfiguration;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
public class TestTextFilterProcessor {
-// private static final Logger LOG =
LoggerFactory.getLogger(TestTextFilterProcessor.class);
-//
-// @org.junit.runners.Parameterized.Parameters
-// public static Iterable<Object[]> data() {
-// return Arrays.asList(new Object[][] {
-// {"TestLowerCaseMatch", "keyword", StringOperator.MATCHES,
Arrays.asList("keyword", "KeyWord", "KEYWORD"), 1},
-// {"TestUpperCaseMatch", "KEYWORD", StringOperator.MATCHES,
Arrays.asList("keyword", "KeyWord", "KEYWORD"), 1},
-// {"TestMixMatch", "KeyWord", StringOperator.MATCHES,
Arrays.asList("keyword", "KeyWord", "KEYWORD"), 1},
-// {"TestEmptyMatch", "keYWord", StringOperator.MATCHES,
Arrays.asList("keyword", "KeyWord", "KEYWORD"), 0},
-// {"TestMultipleMatch", "KeyWord", StringOperator.MATCHES,
-// Arrays.asList("keyword", "KeyWord", "KEYWORD", "KeyWord"), 2},
-//
-// {"TestContainsWord", "keyword", StringOperator.CONTAINS,
-// Arrays.asList("text contains keyword", "text doesn't have
word"), 1},
-// {"TestNotContainsWord", "keyword", StringOperator.CONTAINS,
-// Arrays.asList("text is empty", "text doesn't have word"), 0},
-// });
-// }
-//
-// @org.junit.runners.Parameterized.Parameter
-// public String selectedFieldName;
-//
-// @org.junit.runners.Parameterized.Parameter(1)
-// public String keyword;
-//
-// @org.junit.runners.Parameterized.Parameter(2)
-// public StringOperator stringOperator;
-//
-// @org.junit.runners.Parameterized.Parameter(3)
-// public List<String> eventStrings;
-//
-// @org.junit.runners.Parameterized.Parameter(4)
-// public int expectedFilteredTextCount;
-//
-// @Test
-// public void testTextFilter() {
-// TextFilterProcessor textFilterProcessor = new TextFilterProcessor();
-// DataProcessorDescription originalGraph =
textFilterProcessor.declareModel();
-//
originalGraph.setSupportedGrounding(EventGroundingGenerator.makeDummyGrounding());
-//
-// DataProcessorInvocation graph =
InvocationGraphGenerator.makeEmptyInvocation(originalGraph);
-// graph.setInputStreams(Collections
-// .singletonList(EventStreamGenerator
-//
.makeStreamWithProperties(Collections.singletonList(selectedFieldName))));
-// graph.setOutputStream(EventStreamGenerator
-// .makeStreamWithProperties(Collections.singletonList(selectedFieldName)));
-//
graph.getOutputStream().getEventGrounding().getTransportProtocol().getTopicDefinition()
-// .setActualTopicName("output-topic");
-//
-// graph.getStaticProperties().stream()
-// .filter(p -> p instanceof MappingPropertyUnary)
-// .map(p -> (MappingPropertyUnary) p)
-// .filter(p ->
p.getInternalName().equals(TextFilterProcessor.MAPPING_PROPERTY_ID))
-// .findFirst().get().setSelectedProperty("s0::" + selectedFieldName);
-// ProcessorParams params = new ProcessorParams(graph);
-//
params.extractor().getStaticPropertyByName(TextFilterProcessor.OPERATION_ID,
OneOfStaticProperty.class)
-// .getOptions()
-// .stream().filter(o ->
o.getName().equals(stringOperator.name())).findFirst().get().setSelected(true);
-//
params.extractor().getStaticPropertyByName(TextFilterProcessor.KEYWORD_ID,
FreeTextStaticProperty.class)
-// .setValue(keyword);
-// StoreEventCollector collector = new StoreEventCollector();
-//
-// textFilterProcessor.onInvocation(params, collector, null);
-// int result = sendEvents(textFilterProcessor, collector);
-//
-// LOG.info("Expected filtered text count is {}",
expectedFilteredTextCount);
-// LOG.info("Actual filtered text count is {}", result);
-// assertEquals(expectedFilteredTextCount, result);
-//
-// }
-//
-// private int sendEvents(TextFilterProcessor textFilterProcessor,
StoreEventCollector collector) {
-// List<Event> events = makeEvents();
-// for (Event e : events) {
-// textFilterProcessor.onEvent(e, collector);
-// }
-// return collector.getEvents().size();
-// }
-//
-// private List<Event> makeEvents() {
-// List<Event> events = new ArrayList<>();
-// for (String eventString : eventStrings) {
-// events.add(makeEvent(eventString));
-// }
-// return events;
-// }
-//
-// private Event makeEvent(String eventString) {
-// Map<String, Object> map = Maps.newHashMap();
-// map.put(selectedFieldName, eventString);
-// return EventFactory.fromMap(map,
-// new SourceInfo("test", "s0"),
-// new SchemaInfo(null, Lists.newArrayList()));
-// }
+ TextFilterProcessor processor;
+
+ public static final String FIELD_NAME = "selectedField";
+
+ @BeforeEach
+ public void setup(){
+ processor = new TextFilterProcessor();
+ }
+
+ @ParameterizedTest
+ @MethodSource("data")
+ public void test(String keyword,
+ StringOperator stringOperator,
+ List<String> eventValues,
+ List<String> outputEventValues){
+
+ TestConfiguration configuration = TestConfiguration.builder()
+ .configWithDefaultPrefix(TextFilterProcessor.MAPPING_PROPERTY_ID,
FIELD_NAME)
+ .config(TextFilterProcessor.OPERATION_ID, stringOperator)
+ .config(TextFilterProcessor.KEYWORD_ID, keyword)
+ .build();
+
+ List<Map<String, Object>> events = new ArrayList<>();
+ eventValues.forEach(value->events.add(Map.of(FIELD_NAME, value)));
+
+ List<Map<String, Object>> outputEvents = new ArrayList<>();
+ outputEventValues.forEach(value->outputEvents.add(Map.of(FIELD_NAME,
value)));
+
+ ProcessingElementTestExecutor testExecutor = new
ProcessingElementTestExecutor(processor, configuration);
+
+ testExecutor.run(events, outputEvents);
+ }
+
+
+ static Stream<Arguments> data() {
+ return Stream.of(
+ Arguments.of(
+ "keyword",
+ StringOperator.MATCHES,
+ List.of("keyword", "KeyWord", "KEYWORD"),
+ List.of("keyword")
+ ),
+ Arguments.of(
+ "KEYWORD",
+ StringOperator.MATCHES,
+ List.of("keyword", "KeyWord", "KEYWORD"),
+ List.of("KEYWORD")
+ ),
+ Arguments.of(
+ "KeyWord",
+ StringOperator.MATCHES,
+ List.of("keyword", "KeyWord", "KEYWORD"),
+ List.of("KeyWord")
+ ),
+ Arguments.of(
+ "keYWord",
+ StringOperator.MATCHES,
+ List.of("keyword", "KeyWord", "KEYWORD"),
+ List.of()
+ ),
+ Arguments.of(
+ "KeyWord",
+ StringOperator.MATCHES,
+ List.of("keyword", "KeyWord", "KEYWORD", "KeyWord"),
+ List.of("KeyWord", "KeyWord")
+ ),
+ Arguments.of(
+ "keyword",
+ StringOperator.CONTAINS,
+ List.of("text contains keyword", "text doesn't have word"),
+ List.of("text contains keyword")
+ ),
+ Arguments.of(
+ "keyword",
+ StringOperator.CONTAINS,
+ List.of("text is empty", "text doesn't have word"),
+ List.of()
+ )
+ );
+ }
}
diff --git
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
index 627eedb250..742417ddd8 100644
---
a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
+++
b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/template/PipelineElementTemplateVisitor.java
@@ -116,7 +116,10 @@ public class PipelineElementTemplateVisitor implements
StaticPropertyVisitor {
@Override
public void visit(MappingPropertyUnary mappingPropertyUnary) {
- // Do nothing, not supported by pipeline element templates
+ if (hasKey(mappingPropertyUnary)) {
+ var selectedProperty = getAsString(mappingPropertyUnary);
+ mappingPropertyUnary.setSelectedProperty(selectedProperty);
+ }
}
@Override
diff --git a/streampipes-extensions/streampipes-processors-filters-jvm/pom.xml
b/streampipes-test-utils-executors/pom.xml
similarity index 71%
copy from streampipes-extensions/streampipes-processors-filters-jvm/pom.xml
copy to streampipes-test-utils-executors/pom.xml
index ed05e4cbc5..8004169299 100644
--- a/streampipes-extensions/streampipes-processors-filters-jvm/pom.xml
+++ b/streampipes-test-utils-executors/pom.xml
@@ -19,65 +19,56 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
- <artifactId>streampipes-extensions</artifactId>
+ <artifactId>streampipes-parent</artifactId>
<groupId>org.apache.streampipes</groupId>
<version>0.95.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>streampipes-processors-filters-jvm</artifactId>
+ <artifactId>streampipes-test-utils-executors</artifactId>
<dependencies>
- <!-- StreamPipes dependencies -->
- <dependency>
- <groupId>org.apache.streampipes</groupId>
- <artifactId>streampipes-extensions-management</artifactId>
- <version>0.95.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.apache.streampipes</groupId>
- <artifactId>streampipes-wrapper-standalone</artifactId>
- <version>0.95.0-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>org.quartz-scheduler</groupId>
- <artifactId>quartz</artifactId>
- </dependency>
-
<!-- Test dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
- <scope>test</scope>
+ <scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
- <scope>test</scope>
+ <scope>compile</scope>
</dependency>
<dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-params</artifactId>
- <scope>test</scope>
+ <groupId>org.apache.streampipes</groupId>
+ <artifactId>streampipes-pipeline-management</artifactId>
+ <version>0.95.0-SNAPSHOT</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.objenesis</groupId>
+ <artifactId>objenesis</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.apache.streampipes</groupId>
<artifactId>streampipes-test-utils</artifactId>
<version>0.95.0-SNAPSHOT</version>
- <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
</dependency>
</dependencies>
-
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
- <configuration>
- <propertyExpansion>
-
checkstyle.config.base.path=${project.parent.parent.basedir}/tools/maven
- </propertyExpansion>
- </configuration>
</plugin>
</plugins>
</build>
diff --git
a/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/PrefixStrategy.java
b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/PrefixStrategy.java
new file mode 100644
index 0000000000..3cc2a1ee60
--- /dev/null
+++
b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/PrefixStrategy.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.streampipes.test.executors;
+
+public enum PrefixStrategy {
+ SAME_PREFIX, ALTERNATE
+}
diff --git
a/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/ProcessingElementTestExecutor.java
b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/ProcessingElementTestExecutor.java
new file mode 100644
index 0000000000..f2d87197ad
--- /dev/null
+++
b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/ProcessingElementTestExecutor.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.streampipes.test.executors;
+
+import org.apache.streampipes.extensions.api.pe.IStreamPipesDataProcessor;
+import org.apache.streampipes.extensions.api.pe.param.IDataProcessorParameters;
+import org.apache.streampipes.extensions.api.pe.routing.SpOutputCollector;
+import org.apache.streampipes.manager.template.DataProcessorTemplateHandler;
+import org.apache.streampipes.model.graph.DataProcessorInvocation;
+import org.apache.streampipes.model.runtime.Event;
+import org.apache.streampipes.model.runtime.EventFactory;
+import org.apache.streampipes.model.runtime.SchemaInfo;
+import org.apache.streampipes.model.runtime.SourceInfo;
+import org.apache.streampipes.model.template.PipelineElementTemplate;
+import org.apache.streampipes.model.template.PipelineElementTemplateConfig;
+import
org.apache.streampipes.sdk.extractor.ProcessingElementParameterExtractor;
+import org.apache.streampipes.test.generator.EventStreamGenerator;
+
+import org.junit.jupiter.api.Assertions;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.IntStream;
+
+
+public class ProcessingElementTestExecutor {
+
+ private final IStreamPipesDataProcessor processor;
+ private TestConfiguration testConfiguration;
+ private Iterator<String> selectorPrefixes;
+ private Consumer<DataProcessorInvocation> invocationConfig;
+
+ public ProcessingElementTestExecutor(IStreamPipesDataProcessor processor,
TestConfiguration testConfiguration,
+ Consumer<DataProcessorInvocation>
invocationConfig) {
+ this.processor = processor;
+ this.testConfiguration = testConfiguration;
+ this.selectorPrefixes = testConfiguration.getPrefixes().iterator();
+ this.invocationConfig = invocationConfig;
+ }
+
+ public ProcessingElementTestExecutor(IStreamPipesDataProcessor processor,
TestConfiguration testConfiguration) {
+ this.processor = processor;
+ this.testConfiguration = testConfiguration;
+ this.selectorPrefixes = testConfiguration.getPrefixes().iterator();
+ }
+
+ public ProcessingElementTestExecutor(IStreamPipesDataProcessor processor,
+ Consumer<DataProcessorInvocation>
invocationConfig) {
+ this.processor = processor;
+ this.invocationConfig = invocationConfig;
+ this.selectorPrefixes = List.of("").iterator();
+ }
+
+
+ /**
+ * This method is used to run a data processor with a given configuration
and a list of input events.
+ * It then verifies the output events against the expected output events.
+ *
+ * @param inputEvents The list of input events to be processed.
+ * @param expectedOutputEvents The list of expected output events.
+ */
+ public void run(
+ List<Map<String, Object>> inputEvents,
+ List<Map<String, Object>> expectedOutputEvents
+ ) {
+
+
+ // initialize the extractor with the provided configuration of the user
input
+ var dataProcessorInvocation = getProcessorInvocation();
+ if (invocationConfig != null){
+ invocationConfig.accept(dataProcessorInvocation);
+ }
+
+ var e = getProcessingElementParameterExtractor(dataProcessorInvocation);
+ var mockParams = Mockito.mock(IDataProcessorParameters.class);
+
+ Mockito.when(mockParams.getModel()).thenReturn(dataProcessorInvocation);
+ Mockito.when(mockParams.extractor()).thenReturn(e);
+
+ // calls the onPipelineStarted method of the processor to initialize it
+ processor.onPipelineStarted(mockParams, null, null);
+
+ // mock the output collector to capture the output events and validate the
results later
+ var mockCollector = Mockito.mock(SpOutputCollector.class);
+ var spOutputCollectorCaptor = ArgumentCaptor.forClass(Event.class);
+
+
+ // Iterate over all input events and call the onEvent method of the
processor
+ for (Map<String, Object> inputRawEvent : inputEvents) {
+ processor.onEvent(getEvent(inputRawEvent), mockCollector);
+ }
+
+ // Validate the output of the processor
+ Mockito.verify(mockCollector,
+
Mockito.times(expectedOutputEvents.size())).collect(spOutputCollectorCaptor.capture());
+ var resultingEvents = spOutputCollectorCaptor.getAllValues();
+ IntStream.range(0, expectedOutputEvents.size())
+ .forEach(i -> Assertions.assertEquals(
+ expectedOutputEvents.get(i),
+ resultingEvents.get(i)
+ .getRaw()
+ ));
+
+ // validate that the processor is stopped correctly
+ processor.onPipelineStopped();
+ }
+
+ private static ProcessingElementParameterExtractor
getProcessingElementParameterExtractor(
+ DataProcessorInvocation dataProcessorInvocation
+ ) {
+ return ProcessingElementParameterExtractor.from(dataProcessorInvocation);
+ }
+
+ private DataProcessorInvocation getProcessorInvocation() {
+ var pipelineElementTemplate = getPipelineElementTemplate();
+
+ var invocation = new DataProcessorInvocation(
+ processor
+ .declareConfig()
+ .getDescription()
+ );
+
+ invocation.setOutputStream(EventStreamGenerator.makeEmptyStream());
+
+
+ return new DataProcessorTemplateHandler(
+ pipelineElementTemplate,
+ invocation,
+ true
+ )
+ .applyTemplateOnPipelineElement();
+ }
+
+ private PipelineElementTemplate getPipelineElementTemplate() {
+ var staticProperties = processor
+ .declareConfig()
+ .getDescription()
+ .getStaticProperties();
+
+
+ var configs = new HashMap<String, PipelineElementTemplateConfig>();
+
+ staticProperties.forEach(staticProperty -> {
+ var value =
testConfiguration.getFieldConfiguration().get(staticProperty.getInternalName());
+ configs.put(
+ staticProperty.getInternalName(),
+ new PipelineElementTemplateConfig(true, true, value)
+ );
+ });
+
+ return new PipelineElementTemplate("name", "description", configs);
+ }
+
+ private Event getEvent(Map<String, Object> rawEvent) {
+
+ if (!selectorPrefixes.hasNext()){
+ selectorPrefixes = testConfiguration.getPrefixes().iterator();
+ }
+
+ String selectorPrefix = selectorPrefixes.next();
+
+
+ var sourceInfo = new SourceInfo("", selectorPrefix);
+ var schemaInfo = new SchemaInfo(null, new ArrayList<>());
+
+ return EventFactory.fromMap(rawEvent, sourceInfo, schemaInfo);
+ }
+}
diff --git
a/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/TestConfiguration.java
b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/TestConfiguration.java
new file mode 100644
index 0000000000..fb2270f3a4
--- /dev/null
+++
b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/TestConfiguration.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.streampipes.test.executors;
+
+import java.util.List;
+import java.util.Map;
+
+public class TestConfiguration {
+
+ private final Map<String, Object> fieldConfiguration;
+
+ private final List<String> prefixes;
+
+ public TestConfiguration(Map<String, Object> fieldConfiguration,
+ List<String> eventPrefixes) {
+ this.fieldConfiguration = fieldConfiguration;
+ this.prefixes = eventPrefixes;
+ }
+
+ public Map<String, Object> getFieldConfiguration() {
+ return fieldConfiguration;
+ }
+
+ public List<String> getPrefixes() {
+ return prefixes;
+ }
+
+ public static TestConfigurationBuilder builder() {
+ return new TestConfigurationBuilder();
+ }
+}
diff --git
a/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/TestConfigurationBuilder.java
b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/TestConfigurationBuilder.java
new file mode 100644
index 0000000000..e2260c5366
--- /dev/null
+++
b/streampipes-test-utils-executors/src/main/java/org/apache/streampipes/test/executors/TestConfigurationBuilder.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.streampipes.test.executors;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class TestConfigurationBuilder{
+ private Map<String, Object> fieldConfiguration = new HashMap<>();
+ private List<String> eventPrefixes = List.of("");
+
+ public TestConfigurationBuilder config(String key, Object value){
+ this.fieldConfiguration.put(key, value);
+ return this;
+ }
+ public TestConfigurationBuilder configWithPrefix(String key, Object value,
String prefix){
+ this.fieldConfiguration.put(key, prefix + "::" + value);
+ return this;
+ }
+
+ public TestConfigurationBuilder configWithDefaultPrefix(String key, Object
value){
+ return this.configWithPrefix(key, value, "");
+ }
+
+ public TestConfigurationBuilder config(Map<String, Object> config){
+ this.fieldConfiguration = config;
+ return this;
+ }
+
+ public TestConfigurationBuilder prefixStrategy(PrefixStrategy strategy){
+ this.eventPrefixes = switch (strategy){
+ case SAME_PREFIX -> List.of("s0");
+ case ALTERNATE -> List.of("s0", "s1");
+ };
+ return this;
+ }
+
+ public TestConfigurationBuilder customPrefixStrategy(List<String>
eventPrefixes) {
+ this.eventPrefixes = eventPrefixes;
+ return this;
+ }
+
+ public TestConfiguration build(){
+ return new TestConfiguration(this.fieldConfiguration, this.eventPrefixes);
+ }
+}
\ No newline at end of file