From 9a2dfd074412c3547264d998d3640037dd2875b2 Mon Sep 17 00:00:00 2001 From: Andrea Burattin <andrea.burattin@gmail.com> Date: Tue, 15 Mar 2022 22:23:57 +0100 Subject: [PATCH] Started working on thorough testing --- pom.xml | 37 ++++- .../beamline/exceptions/EventException.java | 10 ++ .../ExcludeOnCaseAttributeEqualityFilter.java | 9 -- .../RetainOnCaseAttributeEqualityFilter.java | 9 -- .../java/beamline/sources/CSVLogSource.java | 20 +-- .../java/beamline/sources/MQTTXesSource.java | 17 +-- src/main/java/beamline/tester/Tester.java | 136 ++++++++++++++++++ src/main/java/beamline/tester/Tester2.java | 35 +++++ src/main/java/beamline/tester/Tester3.java | 71 +++++++++ src/main/java/beamline/utils/EventUtils.java | 107 ++++++++++++++ .../java/beamline/utils/package-info.java | 4 + src/test/java/DONTDELETEME | 0 .../java/beamline/tests/AlgorithmTests.java | 65 +++++++++ .../java/beamline/tests/FiltersTests.java | 123 ++++++++++++++++ src/test/java/beamline/tests/UtilsTests.java | 102 +++++++++++++ 15 files changed, 693 insertions(+), 52 deletions(-) create mode 100644 src/main/java/beamline/exceptions/EventException.java create mode 100644 src/main/java/beamline/tester/Tester.java create mode 100644 src/main/java/beamline/tester/Tester2.java create mode 100644 src/main/java/beamline/tester/Tester3.java create mode 100644 src/main/java/beamline/utils/EventUtils.java create mode 100644 src/main/java/beamline/utils/package-info.java delete mode 100644 src/test/java/DONTDELETEME create mode 100644 src/test/java/beamline/tests/AlgorithmTests.java create mode 100644 src/test/java/beamline/tests/FiltersTests.java create mode 100644 src/test/java/beamline/tests/UtilsTests.java diff --git a/pom.xml b/pom.xml index 62764fb..caf98d0 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,4 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +<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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>beamline</groupId> @@ -10,7 +9,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> - + <repositories> <repository> <id>ApromoreCore_SupportLibs</id> @@ -22,7 +21,7 @@ <url>https://jitpack.io</url> </repository> </repositories> - + <dependencies> <dependency> <groupId>javax.xml.bind</groupId> @@ -57,12 +56,38 @@ <dependency> <groupId>com.github.beamline</groupId> <artifactId>graphviz</artifactId> - <version>0.0.2</version> + <version>master-SNAPSHOT</version> </dependency> <dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.6</version> </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <version>5.8.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.platform</groupId> + <artifactId>junit-platform-suite-api</artifactId> + <version>1.8.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest</artifactId> + <version>2.2</version> + </dependency> </dependencies> -</project> \ No newline at end of file + + <build> + <plugins> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.22.2</version> + </plugin> + </plugins> + </build> +</project> diff --git a/src/main/java/beamline/exceptions/EventException.java b/src/main/java/beamline/exceptions/EventException.java new file mode 100644 index 0000000..f8f71fa --- /dev/null +++ b/src/main/java/beamline/exceptions/EventException.java @@ -0,0 +1,10 @@ +package beamline.exceptions; + +public class EventException extends Exception { + + private static final long serialVersionUID = 5835305478001040595L; + + public EventException(String message) { + super(message); + } +} diff --git a/src/main/java/beamline/filters/ExcludeOnCaseAttributeEqualityFilter.java b/src/main/java/beamline/filters/ExcludeOnCaseAttributeEqualityFilter.java index ebeb443..55157bd 100644 --- a/src/main/java/beamline/filters/ExcludeOnCaseAttributeEqualityFilter.java +++ b/src/main/java/beamline/filters/ExcludeOnCaseAttributeEqualityFilter.java @@ -37,15 +37,6 @@ public class ExcludeOnCaseAttributeEqualityFilter<T extends XAttribute> implemen this.attributeValues = new HashSet<T>(Arrays.asList(values)); } - /** - * Adds the value to the list of values to be considered for removal - * - * @param value value - */ - public void addValue(T value) { - this.attributeValues.add(value); - } - @Override public boolean test(@NonNull XTrace t) throws Throwable { return !attributeValues.contains(t.getAttributes().get(attributeName)); diff --git a/src/main/java/beamline/filters/RetainOnCaseAttributeEqualityFilter.java b/src/main/java/beamline/filters/RetainOnCaseAttributeEqualityFilter.java index 10637ec..485e622 100644 --- a/src/main/java/beamline/filters/RetainOnCaseAttributeEqualityFilter.java +++ b/src/main/java/beamline/filters/RetainOnCaseAttributeEqualityFilter.java @@ -37,15 +37,6 @@ public class RetainOnCaseAttributeEqualityFilter<T extends XAttribute> implement this.attributeValues = new HashSet<T>(Arrays.asList(values)); } - /** - * Adds the value to the list of values to be considered for retention - * - * @param value value - */ - public void addValue(T value) { - this.attributeValues.add(value); - } - @Override public boolean test(@NonNull XTrace t) throws Throwable { return attributeValues.contains(t.getAttributes().get(attributeName)); diff --git a/src/main/java/beamline/sources/CSVLogSource.java b/src/main/java/beamline/sources/CSVLogSource.java index 85a09f9..bdf876b 100644 --- a/src/main/java/beamline/sources/CSVLogSource.java +++ b/src/main/java/beamline/sources/CSVLogSource.java @@ -3,17 +3,17 @@ package beamline.sources; import java.io.Reader; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.LinkedList; +import java.util.List; -import org.deckfour.xes.extension.std.XConceptExtension; -import org.deckfour.xes.factory.XFactory; -import org.deckfour.xes.factory.XFactoryNaiveImpl; -import org.deckfour.xes.model.XEvent; +import org.apache.commons.lang3.tuple.Pair; import org.deckfour.xes.model.XTrace; import com.opencsv.CSVParser; import com.opencsv.CSVReader; import com.opencsv.CSVReaderBuilder; +import beamline.utils.EventUtils; import io.reactivex.rxjava3.annotations.NonNull; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.ObservableEmitter; @@ -27,7 +27,6 @@ import io.reactivex.rxjava3.core.ObservableOnSubscribe; */ public class CSVLogSource implements XesSource { - private static XFactory xesFactory = new XFactoryNaiveImpl(); private CSVReader csvReader; private String filename; private int caseIdColumn; @@ -80,16 +79,11 @@ public class CSVLogSource implements XesSource { public void subscribe(@NonNull ObservableEmitter<@NonNull XTrace> emitter) throws Throwable { String[] line; while ((line = csvReader.readNext()) != null) { - XTrace eventWrapper = xesFactory.createTrace(); - XEvent newEvent = xesFactory.createEvent(); - XConceptExtension.instance().assignName(eventWrapper, line[caseIdColumn]); - XConceptExtension.instance().assignName(newEvent, line[activityNameColumn]); + List<Pair<String, String>> attributes = new LinkedList<Pair<String, String>>(); for (int i = 0; i < line.length; i++) { - String attributeName = "attribute_" + i; - newEvent.getAttributes().put(attributeName, xesFactory.createAttributeLiteral(attributeName, line[i], null)); + attributes.add(Pair.of("attribute_" + i, line[i])); } - eventWrapper.add(newEvent); - emitter.onNext(eventWrapper); + emitter.onNext(EventUtils.create(line[activityNameColumn], line[caseIdColumn], null, attributes)); } emitter.onComplete(); } diff --git a/src/main/java/beamline/sources/MQTTXesSource.java b/src/main/java/beamline/sources/MQTTXesSource.java index 930fcba..d7a10ee 100644 --- a/src/main/java/beamline/sources/MQTTXesSource.java +++ b/src/main/java/beamline/sources/MQTTXesSource.java @@ -1,13 +1,7 @@ package beamline.sources; -import java.util.Date; import java.util.UUID; -import org.deckfour.xes.extension.std.XConceptExtension; -import org.deckfour.xes.extension.std.XTimeExtension; -import org.deckfour.xes.factory.XFactory; -import org.deckfour.xes.factory.XFactoryNaiveImpl; -import org.deckfour.xes.model.XEvent; import org.deckfour.xes.model.XTrace; import org.eclipse.paho.client.mqttv3.IMqttClient; import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; @@ -16,6 +10,7 @@ import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttMessage; +import beamline.utils.EventUtils; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.subjects.PublishSubject; @@ -37,7 +32,6 @@ import io.reactivex.rxjava3.subjects.PublishSubject; */ public class MQTTXesSource implements XesSource { - private static XFactory xesFactory = new XFactoryNaiveImpl(); private String processName; private String brokerHost; private String topicBase; @@ -77,14 +71,7 @@ public class MQTTXesSource implements XesSource { String partBeforeActName = topic.substring(0, posLastSlash); String activityName = topic.substring(posLastSlash + 1); String caseId = partBeforeActName.substring(partBeforeActName.lastIndexOf("/") + 1); - - XEvent event = xesFactory.createEvent(); - XConceptExtension.instance().assignName(event, activityName); - XTimeExtension.instance().assignTimestamp(event, new Date()); - XTrace eventWrapper = xesFactory.createTrace(); - XConceptExtension.instance().assignName(eventWrapper, caseId); - eventWrapper.add(event); - ps.onNext(eventWrapper); + ps.onNext(EventUtils.create(activityName, caseId)); } @Override diff --git a/src/main/java/beamline/tester/Tester.java b/src/main/java/beamline/tester/Tester.java new file mode 100644 index 0000000..b4289f0 --- /dev/null +++ b/src/main/java/beamline/tester/Tester.java @@ -0,0 +1,136 @@ +package beamline.tester; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.deckfour.xes.extension.std.XConceptExtension; +import org.deckfour.xes.extension.std.XTimeExtension; +import org.deckfour.xes.in.XParser; +import org.deckfour.xes.in.XesXmlParser; +import org.deckfour.xes.model.XEvent; +import org.deckfour.xes.model.XLog; +import org.deckfour.xes.model.XTrace; + +import beamline.filters.ExcludeActivitiesFilter; +import beamline.filters.RetainActivitiesFilter; +import beamline.mappers.DirectlyFollowsRelation; +import beamline.mappers.InfiniteSizeDirectlyFollowsMapper; +import beamline.models.algorithms.HookEventProcessing; +import beamline.models.algorithms.StreamMiningAlgorithm; +import beamline.models.responses.GraphvizResponse; +import beamline.sources.MQTTXesSource; +import beamline.sources.XesLogSource; +import beamline.sources.XesSource; +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.ObservableEmitter; +import io.reactivex.rxjava3.core.ObservableOnSubscribe; +import io.reactivex.rxjava3.core.ObservableSource; +import io.reactivex.rxjava3.functions.Consumer; +import io.reactivex.rxjava3.functions.Function; +import io.reactivex.rxjava3.functions.Predicate; +import jdk.jshell.execution.StreamingExecutionControl; + +public class Tester { + + public static void main(String[] args) throws Exception { + System.out.println("start"); + + XParser p = new XesXmlParser(); + XLog l = p.parse(new File("C:\\Users\\andbur\\Desktop\\input.xes")).get(0); +// XesSource source = new XesLogSource(l); + XesSource source = new MQTTXesSource("tcp://broker.hivemq.com:1883", "pmcep", "test"); + source.prepare(); + +// DiscoveryMiner miner = new DiscoveryMiner(); +// miner.setMinDependency(0.3); +// miner.setModelRefreshRate(1); +// miner.setOnAfterEvent(new HookEventProcessing() { +// @Override +// public void trigger() { +// if (miner.getProcessedEvents() % 100 == 0) { +// try { +// GraphvizResponse resp = miner.getLatestResponse(); +// resp.generateDot().exportToSvg(new File("C:\\Users\\andbur\\Desktop\\output-" + miner.getProcessedEvents() + ".svg")); +// } catch (IOException e) { } +// } +// } +// }); + + Observable<XTrace> obs = source.getObservable(); + obs +// .filter(new RetainActivitiesFilter("A", "B", "C", "dummy-retain")) +// .filter(new ExcludeActivitiesFilter("A", "dummy-exclude")) +// .map(new DirectSuccessionMapper()) +// .combine(new SlidingWindow(1000)) +// .map(new Miner(1, 0.5)) +// .subscribe(miner); +// .mapOptional(new Function<XTrace, Optional<Pair<String, String>>>() { +// +// @Override +// public @NonNull Optional<Pair<String, String>> apply(@NonNull XTrace t) throws Throwable { +// // TODO Auto-generated method stub +// return null; +// } +// }); +// .map(new Function<XTrace, DirectlyFollowRelation>() { +// Map<String, String> map = new HashMap<String, String>(); +// +// @Override +// public @NonNull DirectlyFollowRelation apply(@NonNull XTrace t) throws Throwable { +// String caseId = XConceptExtension.instance().extractName(t); +// String act = XConceptExtension.instance().extractName(t.get(0)); +// DirectlyFollowRelation toRet = new DirectlyFollowRelation(); +// if (map.containsKey(caseId)) { +// String prevAct = map.get(caseId); +// toRet.first = prevAct; +// toRet.second = act; +// toRet.caseId = caseId; +// } +// map.put(caseId, act); +// +// return toRet; +// } +// }) +// .filter(new Predicate<DirectlyFollowRelation>() { +// @Override +// public boolean test(@NonNull DirectlyFollowRelation t) throws Throwable { +// return t.first != null && t.second != null; +// } +// }) + .flatMap(new InfiniteSizeDirectlyFollowsMapper()) + .subscribe(new Consumer<DirectlyFollowsRelation>() { + + @Override + public void accept(@NonNull DirectlyFollowsRelation t) throws Throwable { + System.out.println( + XConceptExtension.instance().extractName(t.getFirst()) + " -> " + + XConceptExtension.instance().extractName(t.getSecond()) + " for case " + t.getCaseId()); + } + }); + + + +// .subscribe(new Consumer<XTrace>() { +// @Override +// public void accept(@NonNull XTrace t) throws Throwable { +// System.out.println( +// XConceptExtension.instance().extractName(t) + " - " + +// XConceptExtension.instance().extractName(t.get(0)) + " - " + +// XTimeExtension.instance().extractTimestamp(t.get(0)) +// ); +// } +// }); + +// miner.getLatestResponse().generateDot().exportToSvg(new File("C:\\Users\\andbur\\Desktop\\output.svg")); + + System.out.println("done"); + } + +} diff --git a/src/main/java/beamline/tester/Tester2.java b/src/main/java/beamline/tester/Tester2.java new file mode 100644 index 0000000..9eca93b --- /dev/null +++ b/src/main/java/beamline/tester/Tester2.java @@ -0,0 +1,35 @@ +package beamline.tester; + +import java.io.IOException; + +import org.deckfour.xes.extension.std.XConceptExtension; +import org.deckfour.xes.model.XTrace; + +import beamline.sources.CSVLogSource; +import beamline.sources.XesSource; +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.functions.Consumer; + +public class Tester2 { + + public static void main(String[] args) throws Exception { + String f = "C:\\Users\\andbur\\OneDrive - Danmarks Tekniske Universitet\\uni\\publishing\\papers\\conferences\\2022-caise\\material\\data\\synthetic\\event streams\\sudden_time_noise0_500_pm_simple.csv"; + XesSource source = new CSVLogSource(f, 1, 2); + source.prepare(); + + Observable<XTrace> obs = source.getObservable(); + obs.subscribe(new Consumer<XTrace>() { + @Override + public void accept(@NonNull XTrace t) throws Throwable { + System.out.println( + XConceptExtension.instance().extractName(t) + " - " + + XConceptExtension.instance().extractName(t.get(0)) + " - " + + t.get(0).getAttributes() + ); + } + }); + + System.out.println("done"); + } +} diff --git a/src/main/java/beamline/tester/Tester3.java b/src/main/java/beamline/tester/Tester3.java new file mode 100644 index 0000000..168c338 --- /dev/null +++ b/src/main/java/beamline/tester/Tester3.java @@ -0,0 +1,71 @@ +package beamline.tester; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import org.deckfour.xes.extension.std.XConceptExtension; +import org.deckfour.xes.factory.XFactory; +import org.deckfour.xes.factory.XFactoryNaiveImpl; +import org.deckfour.xes.model.XEvent; +import org.deckfour.xes.model.XTrace; + +import beamline.mappers.DirectlyFollowsRelation; +import io.reactivex.rxjava3.annotations.NonNull; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.ObservableSource; +import io.reactivex.rxjava3.core.Observer; +import io.reactivex.rxjava3.functions.Consumer; +import io.reactivex.rxjava3.functions.Function; + +public class Tester3 { + + public static void main(String[] args) { + + String fileName = "C:\\Users\\andbur\\Desktop\\log.txt"; + XFactory factory = new XFactoryNaiveImpl(); + + Observable<String> stramOfStrings = Observable.defer(() -> new ObservableSource<String>() { + @Override + public void subscribe(@NonNull Observer<? super @NonNull String> observer) { + try { + Files.lines(Paths.get(fileName)).forEach(observer::onNext); + observer.onComplete(); + } catch (IOException e) { + observer.onError(e); + } + } + }); + + + Observable<XTrace> streamOfXTraces = stramOfStrings.flatMap(new Function<String, ObservableSource<XTrace>>() { + @Override + public @NonNull ObservableSource<XTrace> apply(@NonNull String t) throws Throwable { + String caseId = t.substring(0, 3); + String activityName = t.substring(3); + + XTrace wrapper = factory.createTrace(); + XEvent event = factory.createEvent(); + + XConceptExtension.instance().assignName(wrapper, caseId); + XConceptExtension.instance().assignName(event, activityName); + + wrapper.add(event); + + return Observable.just(wrapper); + } + }); + + + streamOfXTraces.subscribe(new Consumer<XTrace>() { + @Override + public void accept(@NonNull XTrace t) throws Throwable { + System.out.println( + XConceptExtension.instance().extractName(t) + " - " + + XConceptExtension.instance().extractName(t.get(0)) + " - " + + t.get(0).getAttributes() + ); + } + }); + } +} diff --git a/src/main/java/beamline/utils/EventUtils.java b/src/main/java/beamline/utils/EventUtils.java new file mode 100644 index 0000000..e60da3d --- /dev/null +++ b/src/main/java/beamline/utils/EventUtils.java @@ -0,0 +1,107 @@ +package beamline.utils; + +import java.util.Collection; +import java.util.Date; + +import org.apache.commons.lang3.tuple.Pair; +import org.deckfour.xes.extension.std.XConceptExtension; +import org.deckfour.xes.extension.std.XTimeExtension; +import org.deckfour.xes.factory.XFactory; +import org.deckfour.xes.factory.XFactoryNaiveImpl; +import org.deckfour.xes.model.XEvent; +import org.deckfour.xes.model.XTrace; +import org.deckfour.xes.model.impl.XAttributeLiteralImpl; + +import beamline.exceptions.EventException; + +/** + * This class contains some utility methods useful to handle and process events. + * + * @author Andrea Burattin + */ +public class EventUtils { + + private static final XFactory xesFactory = new XFactoryNaiveImpl(); + + /** + * Creates a new {@link XTrace} referring to one event + * + * @param activityName the name of the activity + * @param caseId the identifier of the process instance + * @param time the time when the event has happened + * @param eventAttributes a collection of string attributes for the event + * @return the new event + * @throws EventException this exception is thrown is incomplete information + * is provided + */ + public static XTrace create(String activityName, String caseId, Date time, Collection<Pair<String, String>> eventAttributes) throws EventException { + if (activityName == null || caseId == null) { + throw new EventException("Activity name or case id missing"); + } + + XEvent event = xesFactory.createEvent(); + XConceptExtension.instance().assignName(event, activityName); + if (time == null) { + XTimeExtension.instance().assignTimestamp(event, new Date()); + } else { + XTimeExtension.instance().assignTimestamp(event, time); + } + if (eventAttributes != null) { + for(Pair<String, String> a : eventAttributes) { + event.getAttributes().put(a.getLeft(), new XAttributeLiteralImpl(a.getLeft(), a.getRight())); + } + } + XTrace eventWrapper = xesFactory.createTrace(); + XConceptExtension.instance().assignName(eventWrapper, caseId); + eventWrapper.add(event); + return eventWrapper; + } + + /** + * Creates a new {@link XTrace} referring to one event + * + * @param activityName the name of the activity + * @param caseId the identifier of the process instance + * @param time the time when the event has happened + * @return the new event + * @throws EventException this exception is thrown is incomplete information + * is provided + */ + public static XTrace create(String activityName, String caseId, Date time) throws EventException { + return create(activityName, caseId, time, null); + } + + /** + * Creates a new {@link XTrace} referring to one event. The time of the + * event is set to the current time + * + * @param activityName the name of the activity + * @param caseId the identifier of the process instance + * @return the new event + * @throws EventException this exception is thrown is incomplete information + * is provided + */ + public static XTrace create(String activityName, String caseId) throws EventException { + return create(activityName, caseId, null, null); + } + + /** + * Extracts the activity name + * + * @param event the event + * @return the activity name + */ + public static String getActivityName(XTrace event) { + return XConceptExtension.instance().extractName(event.get(0)); + } + + /** + * Extracts the case id + * + * @param event the event + * @return the case id + */ + public static String getCaseId(XTrace event) { + return XConceptExtension.instance().extractName(event); + } +} diff --git a/src/main/java/beamline/utils/package-info.java b/src/main/java/beamline/utils/package-info.java new file mode 100644 index 0000000..6db5f83 --- /dev/null +++ b/src/main/java/beamline/utils/package-info.java @@ -0,0 +1,4 @@ +/** + * This package contains utility classes to be used throughout the framework. + */ +package beamline.utils; \ No newline at end of file diff --git a/src/test/java/DONTDELETEME b/src/test/java/DONTDELETEME deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/java/beamline/tests/AlgorithmTests.java b/src/test/java/beamline/tests/AlgorithmTests.java new file mode 100644 index 0000000..ae9b401 --- /dev/null +++ b/src/test/java/beamline/tests/AlgorithmTests.java @@ -0,0 +1,65 @@ +package beamline.tests; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItems; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import beamline.models.algorithms.StreamMiningAlgorithm; +import io.reactivex.rxjava3.core.Observable; + +public class AlgorithmTests { + + Observable<Integer> o = Observable.just(3, 7, 11, 13); + + @Test + public void test_result() { + StreamMiningAlgorithm<Integer, Integer> m = new StreamMiningAlgorithm<Integer, Integer>() { + public Integer product = 1; + + @Override + public Integer ingest(Integer event) { + product *= event; + setLatestResponse(-product); + return product; + } + }; + + o.subscribe(m); + assertEquals(4, m.getProcessedEvents()); + assertEquals(3003, m.getLatestResponse()); + } + + @Test + public void test_hooks() { + StreamMiningAlgorithm<Integer, Integer> m = new StreamMiningAlgorithm<Integer, Integer>() { + public Integer product = 1; + + @Override + public Integer ingest(Integer event) { + product *= event; + setLatestResponse(-product); + return product; + } + }; + + List<Integer> resultsBefore = new ArrayList<Integer>(); + m.setOnBeforeEvent(() -> { + resultsBefore.add(m.getProcessedEvents()); + }); + + List<Integer> resultsAfter = new ArrayList<Integer>(); + m.setOnAfterEvent(() -> { + resultsAfter.add(m.getProcessedEvents()); + }); + + o.subscribe(m); + + assertThat(resultsBefore, hasItems(0,1,2,3)); + assertThat(resultsAfter, hasItems(1,2,3,4)); + } +} diff --git a/src/test/java/beamline/tests/FiltersTests.java b/src/test/java/beamline/tests/FiltersTests.java new file mode 100644 index 0000000..efc1224 --- /dev/null +++ b/src/test/java/beamline/tests/FiltersTests.java @@ -0,0 +1,123 @@ +package beamline.tests; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItems; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.deckfour.xes.model.XTrace; +import org.deckfour.xes.model.impl.XAttributeLiteralImpl; +import org.junit.jupiter.api.Test; + +import beamline.exceptions.EventException; +import beamline.filters.ExcludeActivitiesFilter; +import beamline.filters.ExcludeOnCaseAttributeEqualityFilter; +import beamline.filters.RetainActivitiesFilter; +import beamline.filters.RetainOnCaseAttributeEqualityFilter; +import beamline.utils.EventUtils; +import io.reactivex.rxjava3.core.Observable; + +public class FiltersTests { + + EventUtils e = new EventUtils(); + + @Test + public void test_exclude_activities_on_name_filter() { + List<String> results = new ArrayList<String>(); + generateObservableSameCaseId() + .filter(new ExcludeActivitiesFilter("A")) + .subscribe((t) -> results.add(EventUtils.getActivityName(t))); + assertEquals(3, results.size()); + assertThat(results, hasItems("K","B","C")); + } + + @Test + public void test_retain_activities_on_name_filter() { + List<String> results = new ArrayList<String>(); + generateObservableSameCaseId() + .filter(new RetainActivitiesFilter("A","B")) + .subscribe((t) -> results.add(EventUtils.getActivityName(t))); + assertEquals(3, results.size()); + assertThat(results, hasItems("A","B","A")); + } + + @Test + public void test_retain_activities_on_case_attribute_filter_1() { + List<String> results = new ArrayList<String>(); + generateObservableSameCaseId() + .filter(new RetainOnCaseAttributeEqualityFilter<XAttributeLiteralImpl>( + "a1", + new XAttributeLiteralImpl("a1", "v1"))) + .subscribe((t) -> results.add(EventUtils.getActivityName(t))); + assertEquals(1, results.size()); + assertThat(results, hasItems("A")); + } + + @Test + public void test_retain_activities_on_case_attribute_filter_2() { + List<String> results = new ArrayList<String>(); + generateObservableSameCaseId() + .filter(new RetainOnCaseAttributeEqualityFilter<XAttributeLiteralImpl>( + "a1", + new XAttributeLiteralImpl("a1", "v1"), + new XAttributeLiteralImpl("a1", "v4"))) + .subscribe((t) -> results.add(EventUtils.getActivityName(t))); + assertEquals(2, results.size()); + assertThat(results, hasItems("A","C")); + } + + @Test + public void test_exclude_activities_on_case_attribute_filter_1() { + List<String> results = new ArrayList<String>(); + generateObservableSameCaseId() + .filter(new ExcludeOnCaseAttributeEqualityFilter<XAttributeLiteralImpl>( + "a1", + new XAttributeLiteralImpl("a1", "v1"))) + .subscribe((t) -> results.add(EventUtils.getActivityName(t))); + assertEquals(4, results.size()); + assertThat(results, hasItems("K","B","A","C")); + } + + @Test + public void test_exclude_activities_on_case_attribute_filter_2() { + List<String> results = new ArrayList<String>(); + generateObservableSameCaseId() + .filter(new ExcludeOnCaseAttributeEqualityFilter<XAttributeLiteralImpl>( + "a1", + new XAttributeLiteralImpl("a1", "v1"), + new XAttributeLiteralImpl("a1", "v4"))) + .subscribe((t) -> results.add(EventUtils.getActivityName(t))); + assertEquals(3, results.size()); + assertThat(results, hasItems("K","B","A")); + } + + /* + * Generate a streams with these events: + * - K + * - A / trace attribute: (a1,v1) + * - B + * - A + * - C / trace attribute: (a1,v4) + */ + private Observable<XTrace> generateObservableSameCaseId() { + XTrace[] events = null; + try { + events = new XTrace[] { + EventUtils.create("K", "c"), + EventUtils.create("A", "c"), + EventUtils.create("B", "c"), + EventUtils.create("A", "c"), + EventUtils.create("C", "c") + }; + } catch (EventException e) { + e.printStackTrace(); + } + events[1].getAttributes().put("a1", new XAttributeLiteralImpl("a1", "v1")); + events[2].get(0).getAttributes().put("a2", new XAttributeLiteralImpl("a2", "v3")); + events[3].get(0).getAttributes().put("a2", new XAttributeLiteralImpl("a2", "v2")); + events[4].getAttributes().put("a1", new XAttributeLiteralImpl("a1", "v4")); + return Observable.fromArray(events); + } +} diff --git a/src/test/java/beamline/tests/UtilsTests.java b/src/test/java/beamline/tests/UtilsTests.java new file mode 100644 index 0000000..47c2005 --- /dev/null +++ b/src/test/java/beamline/tests/UtilsTests.java @@ -0,0 +1,102 @@ +package beamline.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.sql.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.commons.lang3.tuple.Pair; +import org.deckfour.xes.extension.std.XConceptExtension; +import org.deckfour.xes.extension.std.XTimeExtension; +import org.deckfour.xes.model.XTrace; +import org.junit.jupiter.api.Test; + +import beamline.exceptions.EventException; +import beamline.utils.EventUtils; + +public class UtilsTests { + + @Test + public void test_create_event() { + String activityName = UUID.randomUUID().toString(); + String caseId = UUID.randomUUID().toString(); + XTrace t = null; + try { + t = EventUtils.create(activityName, caseId); + } catch (EventException e) { } + + assertNotNull(t); + assertEquals(XConceptExtension.instance().extractName(t), caseId); + assertEquals(XConceptExtension.instance().extractName(t.get(0)), activityName); + } + + @Test + public void test_create_event_time() { + String activityName = UUID.randomUUID().toString(); + String caseId = UUID.randomUUID().toString(); + Date date = Date.valueOf("1996-01-23"); + XTrace t = null; + try { + t = EventUtils.create(activityName, caseId, date); + } catch (EventException e) { } + + assertNotNull(t); + assertEquals(XConceptExtension.instance().extractName(t), caseId); + assertEquals(XConceptExtension.instance().extractName(t.get(0)), activityName); + assertEquals(XTimeExtension.instance().extractTimestamp(t.get(0)), date); + } + + @Test + public void test_create_event_attributes() { + String activityName = UUID.randomUUID().toString(); + String caseId = UUID.randomUUID().toString(); + Date date = Date.valueOf("1996-01-23"); + List<Pair<String, String>> attributes = new LinkedList<Pair<String, String>>(); + Map<String, String> values = new HashMap<String, String>(); + for (int i = 0; i < 10; i++) { + String attributeName = "attr-" + i; + String attributeValue = UUID.randomUUID().toString(); + values.put(attributeName, attributeValue); + attributes.add(Pair.of(attributeName, attributeValue)); + } + XTrace t = null; + try { + t = EventUtils.create(activityName, caseId, date, attributes); + } catch (EventException e) { } + + assertNotNull(t); + assertEquals(XConceptExtension.instance().extractName(t), caseId); + assertEquals(XConceptExtension.instance().extractName(t.get(0)), activityName); + assertEquals(XTimeExtension.instance().extractTimestamp(t.get(0)), date); + for(String name : t.get(0).getAttributes().keySet()) { + if (name.startsWith("attr-")) { + assertEquals(t.get(0).getAttributes().get(name).toString(), values.get(name)); + } + } + } + + @Test + public void test_no_activityname() { + assertThrows(EventException.class, () -> { + EventUtils.create(null, ""); + }); + assertThrows(EventException.class, () -> { + EventUtils.create("", null); + }); + } + + @Test + public void test_extract_name_case() throws EventException { + String activityName = UUID.randomUUID().toString(); + String caseId = UUID.randomUUID().toString(); + XTrace t = EventUtils.create(activityName, caseId); + assertEquals(activityName, EventUtils.getActivityName(t)); + assertEquals(caseId, EventUtils.getCaseId(t)); + } +} -- GitLab