valueType) {
- this.valueType = valueType;
- }
-
- /**
- * Parse a Pkl string. Returns an instance of the parsers value type. Any errors will result in a CirrinaException being thrown. Errors
- * could be syntax errors as well as validation errors such as missing fields.
- *
- * @param pkl Pkl description.
- * @return Collaborative state machine model.
- * @throws IllegalArgumentException If an error occurs during parsing or validation.
- */
- public T parse(String pkl) throws IllegalArgumentException {
- try (var evaluator = ConfigEvaluator.preconfigured()) {
- return evaluator.evaluate(ModuleSource.text(pkl)).as(valueType);
- } catch (Exception e) {
- throw new IllegalArgumentException("Parsing error", e);
- }
- }
-}
diff --git a/src/main/java/at/ac/uibk/dps/cirrina/runtime/OnlineRuntime.java b/src/main/java/at/ac/uibk/dps/cirrina/runtime/OnlineRuntime.java
index c457eca2..7066af6c 100644
--- a/src/main/java/at/ac/uibk/dps/cirrina/runtime/OnlineRuntime.java
+++ b/src/main/java/at/ac/uibk/dps/cirrina/runtime/OnlineRuntime.java
@@ -1,22 +1,9 @@
package at.ac.uibk.dps.cirrina.runtime;
-import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClassBuilder;
-import at.ac.uibk.dps.cirrina.csml.description.JobDescription;
import at.ac.uibk.dps.cirrina.execution.object.context.Context;
import at.ac.uibk.dps.cirrina.execution.object.event.EventHandler;
-import at.ac.uibk.dps.cirrina.execution.object.expression.ExpressionBuilder;
-import at.ac.uibk.dps.cirrina.execution.service.RandomServiceImplementationSelector;
-import at.ac.uibk.dps.cirrina.execution.service.ServiceImplementationBuilder;
-import at.ac.uibk.dps.cirrina.runtime.job.Job;
-import at.ac.uibk.dps.cirrina.runtime.job.JobListener;
-import at.ac.uibk.dps.cirrina.runtime.job.JobMonitor;
import at.ac.uibk.dps.cirrina.utils.Time;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
import io.opentelemetry.api.OpenTelemetry;
-import java.io.IOException;
-import java.util.List;
-import org.apache.curator.framework.CuratorFramework;
/**
* Online runtime, a runtime system implementation that is meant to be connected to a message queue, key-value store and coordination system
@@ -24,28 +11,13 @@
*
* StateClass machine instantiation is triggered based on jobs.
*/
-public class OnlineRuntime extends Runtime implements JobListener {
+public class OnlineRuntime extends Runtime {
/**
* Start time.
*/
private final double startTime = Time.timeInMillisecondsSinceStart();
- /**
- * Whether to delete a job when consumed.
- */
- private final boolean deleteJob;
-
- /**
- * Job monitor, using ZooKeeper to monitor new jobs.
- */
- private final JobMonitor jobMonitor;
-
- /**
- * Jobs to start in the future.
- */
- private final Multimap futureJobs = HashMultimap.create();
-
/**
* Initializes this online runtime instance.
*
@@ -53,198 +25,13 @@ public class OnlineRuntime extends Runtime implements JobListener {
* @param eventHandler Event handler.
* @param persistentContext Persistent context.
* @param openTelemetry OpenTelemetry.
- * @param curatorFramework CuratorFramework.
- * @param deleteJob Delete job when consumed.
*/
public OnlineRuntime(
String name,
EventHandler eventHandler,
Context persistentContext,
- OpenTelemetry openTelemetry,
- CuratorFramework curatorFramework,
- boolean deleteJob
+ OpenTelemetry openTelemetry
) {
super(name, eventHandler, persistentContext, openTelemetry);
- this.deleteJob = deleteJob;
-
- // Create a job monitor
- this.jobMonitor = new JobMonitor(curatorFramework, this);
- }
-
- /**
- * Called upon the arrival of a new job, will instantiate a new state machine if capable and appropriate.
- *
- * @param job New job.
- * @throws UnsupportedOperationException If the state machine is not known or abstract.
- */
- @Override
- public void newJob(Job job) throws UnsupportedOperationException {
- // TODO: Add additional conditions/rules
-
- final var jobDescriptionRuntimeName = job.getJobDescription().getRuntimeName();
-
- if (!name.equals(jobDescriptionRuntimeName)) {
- logger.info(
- "Found job for runtime '%s' which does not match this runtime's name '%s', ignoring".formatted(
- jobDescriptionRuntimeName,
- name
- )
- );
-
- return;
- }
-
- try {
- // Attempt to lock the job
- job.lock();
-
- // It is possible that it has been removed in the meantime
- if (job.exists()) {
- // Acquire the job description
- final var jobDescription = job.getJobDescription();
-
- // Schedule job
- synchronized (futureJobs) {
- logger.info(
- "Found a job for {} it is {} now",
- jobDescription.getStartTime(),
- Time.timeInMillisecondsSinceStart()
- );
-
- futureJobs.put(jobDescription.getStartTime(), jobDescription);
- }
-
- // Delete the job (it has been consumed)
- if (deleteJob) {
- job.delete();
- }
- }
- } finally {
- // Unlock the job
- job.unlock();
- }
- }
-
- private void startJob(JobDescription jobDescription) {
- // Create the collaborative state machine from the description
- final var collaborativeStateMachine = CollaborativeStateMachineClassBuilder.from(
- jobDescription.getCollaborativeStateMachine()
- ).build();
-
- // Acquire the service implementation selector
- final var serviceImplementationSelector = new RandomServiceImplementationSelector(
- ServiceImplementationBuilder.from(jobDescription.getServiceImplementations()).build()
- );
-
- // Acquire the state machine name
- final var stateMachineName = jobDescription.getStateMachineName();
-
- // Find the state machine by name
- final var stateMachine = collaborativeStateMachine
- .findStateMachineClassByName(stateMachineName)
- .orElseThrow(() ->
- new UnsupportedOperationException(
- "A state machine with the name '%s' does not exist in the collaborative state machine".formatted(
- stateMachineName
- )
- )
- );
-
- // Create persistent variables
- final var persistentContextVariables =
- collaborativeStateMachine.getPersistentContextVariables();
-
- persistentContextVariables.forEach(variable -> {
- try {
- logger.info("Creating persistent context variable '{}'", variable.name());
-
- persistentContext.create(variable.name(), variable.value());
- } catch (IOException e) {
- logger.info(
- "Did not create persistent context variable '{}', possibly already exists",
- variable.name()
- );
- }
- });
-
- // Create instances, newInstances will also instantiate nested state machines
- final var instanceIds = newInstances(
- List.of(stateMachine),
- serviceImplementationSelector,
- null,
- jobDescription.getEndTime()
- );
-
- // Assign local data from the job description if the job description contains any local data. Assign to the parent and nested state machines
- if (!jobDescription.getLocalData().isEmpty()) {
- for (final var instanceId : instanceIds) {
- final var stateMachineInstance = findInstance(instanceId).orElseThrow(() ->
- new UnsupportedOperationException(
- "State machine '%s' with id '%s' was not instantiated.".formatted(
- stateMachine.getName(),
- instanceId
- )
- )
- );
-
- for (final var localData : jobDescription.getLocalData().entrySet()) {
- try {
- // Assign local data entry, evaluate the value as an expression
- final var valueExpression = ExpressionBuilder.from(localData.getValue()).build();
-
- stateMachineInstance
- .getExtent()
- .setOrCreate(
- localData.getKey(),
- valueExpression.execute(stateMachineInstance.getExtent())
- );
- } catch (IOException | IllegalArgumentException e) {
- throw new UnsupportedOperationException(
- "Could not assign value '%s' to local data variable '%s'".formatted(
- localData.getKey(),
- localData.getValue()
- ),
- e
- );
- }
- }
- }
- }
- }
-
- /**
- * Run until shut down.
- */
- public void run() {
- final var SLEEP_TIME_IN_MS = 1000;
-
- try {
- while (!isShutdown()) {
- // Get the current time
- final var currentTime = Time.timeInMillisecondsSinceStart();
-
- // Collect the keys of the entries that need to be processed and removed
- synchronized (futureJobs) {
- futureJobs
- .entries()
- .removeIf(entry -> {
- final var startTime = entry.getKey();
-
- if (startTime < currentTime) {
- logger.info("Starting job ({}) at time: {}", startTime, currentTime);
-
- startJob(entry.getValue());
- return true;
- }
- return false;
- });
- }
-
- // Sleep
- Thread.sleep(SLEEP_TIME_IN_MS);
- }
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
}
}
diff --git a/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/Job.java b/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/Job.java
deleted file mode 100644
index 726e0586..00000000
--- a/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/Job.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package at.ac.uibk.dps.cirrina.runtime.job;
-
-import at.ac.uibk.dps.cirrina.csml.description.JobDescription;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreMutex;
-
-/**
- * Job, represents a job submitted to the coordination system requesting the instantiation of a state machine. A job is described by means
- * of a job description.
- *
- * Functionality is provided to lock and unlock the job, such that the instantiation of a state machine according to the job is
- * synchronized.
- */
-public class Job {
-
- /**
- * The lock path format.
- */
- private static final String LOCK_PATH_FORMAT = "/locks/%s";
-
- /**
- * The name of the job.
- */
- private final String jobName;
-
- /**
- * The node path to the job.
- */
- private final String nodePath;
-
- /**
- * The job description.
- */
- private final JobDescription jobDescription;
-
- /**
- * Curator framework.
- */
- private final CuratorFramework curatorFramework;
-
- /**
- * Job lock, can be null in case no lock has been acquired. Will be non-null if the job has been acquired.
- */
- private InterProcessSemaphoreMutex sharedLock;
-
- /**
- * Initializes this job instance.
- *
- * @param jobName Name of the job.
- * @param nodePath Node path of the job.
- * @param jobDescription Job description.
- * @param curatorFramework Curator framework.
- */
- public Job(
- String jobName,
- String nodePath,
- JobDescription jobDescription,
- CuratorFramework curatorFramework
- ) {
- this.jobName = jobName;
- this.nodePath = nodePath;
- this.jobDescription = jobDescription;
- this.curatorFramework = curatorFramework;
- }
-
- /**
- * Deletes this job.
- *
- * @throws UnsupportedOperationException If the job could not be deleted.
- */
- public void delete() throws UnsupportedOperationException {
- try {
- curatorFramework.delete().forPath(nodePath);
- } catch (Exception e) {
- throw new UnsupportedOperationException("Failed to delete job '%s'".formatted(nodePath), e);
- }
- }
-
- /**
- * Locks this job, will block execution until the lock can be acquired.
- *
- * Every call to lock needs to be balanced with a call to unlock.
- *
- * @throws UnsupportedOperationException If a job lock was already created.
- * @throws UnsupportedOperationException If a job lock could not be acquired/created.
- */
- public void lock() throws UnsupportedOperationException {
- if (sharedLock != null) {
- throw new UnsupportedOperationException("A job lock was already created");
- }
-
- // Acquire a job lock
- try {
- sharedLock = new InterProcessSemaphoreMutex(
- curatorFramework,
- String.format(LOCK_PATH_FORMAT, jobName)
- );
- sharedLock.acquire();
- } catch (Exception e) {
- throw new UnsupportedOperationException("Failed to create/acquire job lock", e);
- }
- }
-
- /**
- * Unlocks the job.
- *
- * @throws UnsupportedOperationException If the job has not been locked.
- * @throws UnsupportedOperationException If the job could not be released.
- */
- public void unlock() throws UnsupportedOperationException {
- if (sharedLock == null) {
- throw new UnsupportedOperationException("A job lock was not created");
- }
-
- // Release a job lock
- try {
- sharedLock.release();
- } catch (Exception e) {
- throw new UnsupportedOperationException("Failed to release job lock", e);
- }
- }
-
- /**
- * Returns a flag that indicates if this job exists.
- *
- * @return True if existent, otherwise false.
- * @throws UnsupportedOperationException If the existence could not be checked.
- */
- public boolean exists() throws UnsupportedOperationException {
- try {
- return curatorFramework.checkExists().forPath(nodePath) != null;
- } catch (Exception e) {
- throw new UnsupportedOperationException(
- "Failed to check for existence of '%s'".formatted(nodePath),
- e
- );
- }
- }
-
- /**
- * Returns the job description.
- *
- * @return Job description.
- */
- public JobDescription getJobDescription() {
- return jobDescription;
- }
-}
diff --git a/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/JobDescriptionParser.java b/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/JobDescriptionParser.java
deleted file mode 100644
index e7265387..00000000
--- a/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/JobDescriptionParser.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package at.ac.uibk.dps.cirrina.runtime.job;
-
-import at.ac.uibk.dps.cirrina.csml.description.JobDescription;
-import at.ac.uibk.dps.cirrina.io.description.DescriptionParser;
-
-/**
- * Job description parser. Parses job description JSON data files.
- */
-public class JobDescriptionParser extends DescriptionParser {
-
- /**
- * Initializes the parser.
- */
- public JobDescriptionParser() {
- super(JobDescription.class);
- }
-}
diff --git a/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/JobListener.java b/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/JobListener.java
deleted file mode 100644
index f26f8e3b..00000000
--- a/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/JobListener.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package at.ac.uibk.dps.cirrina.runtime.job;
-
-/**
- * Job listener, informed when a new job is submitted.
- */
-public interface JobListener {
- /**
- * Called upon the arrival of a new job, will instantiate a new state machine if capable and appropriate.
- *
- * @param job New job.
- * @throws UnsupportedOperationException If an error occurs.
- */
- void newJob(Job job) throws UnsupportedOperationException;
-}
diff --git a/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/JobMonitor.java b/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/JobMonitor.java
deleted file mode 100644
index 5fe8f6c7..00000000
--- a/src/main/java/at/ac/uibk/dps/cirrina/runtime/job/JobMonitor.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package at.ac.uibk.dps.cirrina.runtime.job;
-
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.regex.Pattern;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.recipes.cache.ChildData;
-import org.apache.curator.framework.recipes.cache.CuratorCache;
-import org.apache.curator.framework.recipes.cache.CuratorCacheListener;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-/**
- * Job monitor, watches for new jobs submitted to the coordination system.
- */
-public class JobMonitor implements CuratorCacheListener {
-
- /**
- * Job monitor logger.
- */
- private static final String JOBS_NODE = "/jobs";
-
- /**
- * Job monitor logger.
- */
- private static final Logger logger = LogManager.getLogger();
-
- /**
- * Job node pattern.
- */
- private static final Pattern JOB_NODE_PATTERN = Pattern.compile("^\\/jobs\\/(job\\d+)$");
-
- /**
- * Curator framework.
- */
- private final CuratorFramework curatorFramework;
-
- /**
- * Curator cache of the jobs node.
- */
- private final CuratorCache curatorCache;
-
- /**
- * Job listener.
- */
- private final JobListener jobListener;
-
- /**
- * Known jobs.
- */
- private final Map jobs = new HashMap<>();
-
- /**
- * Initializes this job monitor.
- *
- * Initiates watching the jobs node for newly submitted jobs.
- *
- * @param curatorFramework Curator framework.
- * @param jobListener Job listener.
- */
- public JobMonitor(CuratorFramework curatorFramework, JobListener jobListener) {
- // Construct the ZooKeeper instance
- this.curatorFramework = curatorFramework;
-
- this.jobListener = jobListener;
-
- // Create curator cache for observing the jobs node
- curatorCache = CuratorCache.builder(this.curatorFramework, JOBS_NODE).build();
-
- curatorCache.listenable().addListener(this);
- curatorCache.start();
- }
-
- /**
- * Returns the job name if the node path provided points to a valid job (has the correct naming format), otherwise empty.
- *
- * @param nodePath Node path.
- * @return Job name or empty.
- */
- private static Optional getJobName(String nodePath) {
- final var matcher = JOB_NODE_PATTERN.matcher(nodePath);
-
- if (matcher.find()) {
- return Optional.of(matcher.group(1));
- } else {
- return Optional.empty();
- }
- }
-
- private void nodeCreated(String nodePath, byte[] data) {
- getJobName(nodePath).ifPresent(jobName -> {
- // Job path already present
- if (jobs.containsKey(nodePath)) {
- return;
- }
-
- // Acquire the data as a string
- final var dataAsUtf8String = new String(data, StandardCharsets.UTF_8);
-
- try {
- // Parse the description
- final var jobDescription = new JobDescriptionParser().parse(dataAsUtf8String);
-
- // Create the job
- final var job = new Job(jobName, nodePath, jobDescription, curatorFramework);
-
- // Register as known job
- jobs.put(nodePath, job);
-
- // Call listener
- jobListener.newJob(job);
- } catch (UnsupportedOperationException | IllegalArgumentException e) {
- logger.error(
- "Failed to parse job description for job '{}'. Skipping this job.",
- jobName,
- e
- );
-
- try {
- // Delete the invalid job
- new Job(jobName, nodePath, null, curatorFramework).delete();
- logger.info("Deleted invalid job '{}'", jobName);
- } catch (Exception ex) {
- logger.error("Failed to delete invalid job '{}'", jobName, ex);
- }
- }
- });
- }
-
- private void nodeDeleted(String nodePath) {
- getJobName(nodePath).ifPresent(jobName -> {
- // Job path already present
- if (!jobs.containsKey(nodePath)) {
- return;
- }
-
- // Remove from the collection of known jobs
- jobs.remove(nodePath);
- });
- }
-
- /**
- * Watcher event handler.
- *
- * @param type Event type.
- * @param oldData Previous data.
- * @param data Current data.
- */
- @Override
- public void event(Type type, ChildData oldData, ChildData data) {
- final var jobPath = data.getPath();
-
- switch (type) {
- case Type.NODE_CREATED -> nodeCreated(jobPath, data.getData());
- case Type.NODE_DELETED -> nodeDeleted(jobPath);
- }
- }
-}
diff --git a/src/main/resources/pkl/CollaborativeStateMachineDescription.pkl b/src/main/resources/pkl/CollaborativeStateMachineDescription.pkl
deleted file mode 100644
index 3c80fbd0..00000000
--- a/src/main/resources/pkl/CollaborativeStateMachineDescription.pkl
+++ /dev/null
@@ -1,341 +0,0 @@
-/// Collaborative state machine construct. Represents the highest level entity in a description.
-///
-/// Keywords:
-///
-/// | Keyword | Description | Required |
-/// | name | Unique name | Yes |
-/// | version | CSML version | Yes |
-/// | stateMachines | StateClass machines | Yes (at least one) |
-/// | localContext | Lexical description of the local context | No |
-/// | persistentContext | Lexical description of the persistent context | No |
-///
-/// 1.0
-/// Example:
-///
-/// {
-/// name: 'Collaborative State Machine Name',
-/// version: '0.1',
-/// stateMachines: [...]
-/// }
-///
-///
-/// @since CSML 1.0.
-@ModuleInfo { minPklVersion = "0.26.2" }
-module at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription
-/// The name.
-name: String
-/// The CSML version.
-///
-/// The following CSML versions are valid:
-///
-/// | Version | Value |
-/// | Version 0.1 | 0.1 |
-///
-version: Version
-/// The state machines.
-///
-/// At least one state machine must be provided.
-stateMachines: Listing
-/// The optional lexical declaration of local context variables.
-localContext: ContextDescription?
-/// The optional lexical declaration of persistent context variables.
-persistentContext: ContextDescription?
-
-
-typealias Version = "2.0"
-typealias ExpressionDescription = String
-
-/// State machine construct. Represents a state machine within a collaborative state machine.
-///
-/// Keywords:
-///
-/// | Keyword | Description | Required |
-/// | name | Unique name | Yes |
-/// | localContext | Lexical description of the local context | No |
-/// | persistentContext | Lexical description of the persistent context | No |
-///
-///
-/// Example:
-///
-/// {
-/// name: 'Collaborative State Machine Name',
-/// states: [...],
-/// stateMachines: [...],
-/// localContext: [...],
-/// persistentContext: [...],
-/// guards: [],
-/// actions: [],
-/// }
-///
-///
-/// @since CSML 1.0.
-open class StateMachineDescription {
- /// The name.
- name: String
- /// The states.
- ///
- /// At least one initial state must be provided.
- ///
- states: Listing
- /// The nested state machines of this state machine.
- stateMachines: Listing
- /// The optional lexical declaration of local context variables.
- localContext: ContextDescription?
- /// The optional lexical declaration of persistent context variables.
- persistentContext: ContextDescription?
-}
-
-/// State construct, represents an atomic state of a state machine.
-///
-/// Keywords:
-///
-/// | Keyword | Description | Required |
-/// | name | Unique name | Yes |
-/// | initial | Initial state flag | No |
-/// | terminal | Terminal state flag | No |
-/// | entry | On entry actions | No |
-/// | exit | On exit actions | No |
-/// | while | While actions | No |
-/// | after | Timeout actions | No |
-/// | on | On transitions | No |
-/// | always | Always transitions | No |
-/// | localContext | Lexical description of the local context | No |
-/// | persistentContext | Lexical description of the persistent context | No |
-/// | staticContext | Lexical description of the static context | No |
-///
-///
-/// Example:
-///
-/// {
-/// name: 'State Name',
-/// initial: true,
-/// terminal: false,
-/// entry: [...],
-/// exit: [...],
-/// while: [...],
-/// after: [...],
-/// on: [...],
-/// localContext: [...],
-/// persistentContext: [...],
-/// staticContext: [...]
-/// }
-///
-///
-/// @since CSML 1.0.
-open class StateDescription {
- /// The name.
- name: String
- /// The is initial flag. Indicating if this is the initial state of the state machine. Exactly one state must be the initial state of a
- /// state machine. If omitted, the state is not initial.
- initial: Boolean = false
- /// The is terminal flag. Indicating if this is a terminal state of the state machine. If omitted, the state is not terminal.
- terminal: Boolean = false
- /// The optional entry actions.
- entry: Listing
- /// The optional exit actions.
- exit: Listing
- /// The optional while actions.
- while: Listing
- /// The optional after (timeout) actions. Actions provided must be raise event actions.
- after: Listing
- /// The optional on transitions. On transitions are taken upon event receiving an event that matches the 'event' keyword of the on
- /// transition.
- on: Listing
- /// The optional always transitions. Always transitions are always taken upon entering a state.
- always: Listing
- /// The optional lexical declaration of local context variables.
- localContext: ContextDescription
- /// The optional lexical declaration of persistent context variables.
- persistentContext: ContextDescription
- /// The optional lexical declaration of static context variables.
- staticContext: ContextDescription
-}
-
-/// Transition construct. Represents a transition that is to be taken regardless of an event.
-///
-/// Keywords:
-///
-/// | Keyword | Description | Required |
-/// | target | Target state | Yes |
-/// | guards | Guards | Yes |
-/// | actions | Actions | Yes |
-/// | else | Else target | No |
-///
-///
-/// Example:
-///
-/// {
-/// target: 'State Name',
-/// guards: [...],
-/// actions: [...]
-/// }
-///
-///
-/// @since CSML 1.0.
-open class TransitionDescription {
- /// The optional target state name. If the target is omitted, the transition is internal.
- target: String?
- /// The optional guards. All guard expressions need to evaluate to true before a transition can be taken.
- guards: Listing
- /// The optional actions. These actions are executed during the transition, if the transition is taken.
- actions: Listing
- /// The optional else target name. If the guards evaluate to false, the state machine ends up in this target state.
- `else`: String?
-}
-
-/// Guard construct. Represents a conditional (if) that determines if a transition can be taken.
-///
-/// Keywords:
-///
-/// | Keyword | Description | Required |
-/// | name | Unique name | Yes |
-/// | expression | Expression | Yes |
-///
-///
-/// Example:
-///
-/// {
-/// name: 'Guard Name',
-/// expression: 'a==5'
-/// }
-///
-///
-/// @since CSML 1.0.
-open class GuardDescription {
- /// An expression.
- ///
- /// The expression must evaluate to a boolean value.
- ///
- expression: ExpressionDescription
-}
-
-/// On transition construct. Represents a transition that is to be taken based on a received event.
-///
-/// Keywords:
-///
-/// | Keyword | Description | Required |
-/// | event | Event | Yes |
-///
-///
-/// Example:
-///
-/// {
-/// target: 'StateClass Name',
-/// guards: [...],
-/// actions: [...],
-/// event: 'Event Name'
-/// }
-///
-///
-/// @since CSML 1.0.
-class OnTransitionDescription extends TransitionDescription {
- event: String
-}
-
-/// An abstract action construct. Represents an action that can be taken in a state machine.
-abstract class ActionDescription {
- type: Type
-}
-
-typealias Type = "invoke" | "create" | "assign" | "lock" | "unlock" | "raise" | "timeout" | "timeoutReset" | "match"
-
-/// Assign action construct. Represents an assignment of a value to a context variable.
-class AssignActionDescription extends ActionDescription {
- type: Type = "assign"
- variable: ContextVariableDescription
-}
-
-/// Create action construct. Represents the creation of a context variable.
-class CreateActionDescription extends ActionDescription {
- type: Type = "create"
- /// The context variable to be created.
- variable: ContextVariableDescription
- /// Determines if the context variable is persistent.
- isPersistent: Boolean = false
-}
-
-/// Invoke action construct. Represents the invocation of a service.
-class InvokeActionDescription extends ActionDescription {
- type: Type = "invoke"
- /// The service type.
- serviceType: String
- /// Determines if the service is local.
- isLocal: Boolean = false
- /// The input parameters.
- input: Listing
- /// The events to be raised when the service is done.
- done: Listing
- /// The output mappings to context variables.
- output: Listing
-}
-
-/// Match action construct. Represents a match action.
-class MatchActionDescription extends ActionDescription {
- type: Type = "match"
- /// The value to be matched.
- value: ExpressionDescription
- /// The match cases.
- cases: Listing
-}
-
-/// Match case construct.
-class MatchCaseDescription {
- /// The case value.
- `case`: ExpressionDescription
- /// The actions to be taken if the case value matches the value of the match action.
- action: ActionDescription
-}
-
-/// Raise action construct. Represents the raising of an event.
-class RaiseActionDescription extends ActionDescription {
- type: Type = "raise"
- /// The event to be raised.
- event: EventDescription
-}
-
-/// Timeout action construct. Represents a timeout action.
-class TimeoutActionDescription extends ActionDescription {
- type: Type = "timeout"
- /// The name of the timeout action.
- name: String
- /// The delay until the timeout action is executed.
- delay: ExpressionDescription // Note: if Code Generation is working replace with Duration type
- /// The action to be executed when the timeout occurs.
- action: ActionDescription
-}
-
-/// Timeout reset action construct. Represents a timeout reset action.
-class TimeoutResetActionDescription extends ActionDescription {
- type: Type = "timeoutReset"
- /// The timeout action to reset.
- action: String
-}
-
-///Event construct. Represents an event that can be raised.
-class EventDescription {
- /// The event name.
- name: String
- /// The event channel.
- channel: EventChannel
- /// The event data.
- data: Listing
-}
-
-/// The event channel. Represents the channel on which an event is raised.
-typealias EventChannel = "internal" | "external" | "global" | "peripheral"
-
-/// Context variable reference construct. Represents a reference to a context variable.
-class ContextVariableReferenceDescription {
- reference: String
-}
-
-/// Context description construct. Represents a context.
-class ContextDescription {
- variables: Listing
-}
-
-/// Context variable description construct. Represents a context variable.
-class ContextVariableDescription {
- name: String
- value: ExpressionDescription
-}
diff --git a/src/main/resources/pkl/HttpServiceImplementationDescription.pkl b/src/main/resources/pkl/HttpServiceImplementationDescription.pkl
deleted file mode 100644
index 2686c7fe..00000000
--- a/src/main/resources/pkl/HttpServiceImplementationDescription.pkl
+++ /dev/null
@@ -1,15 +0,0 @@
-@ModuleInfo { minPklVersion = "0.26.2" }
-module at.ac.uibk.dps.cirrina.csml.description.HttpServiceImplementationDescription
-
-extends "ServiceImplementationDescription.pkl"
-
-import "ServiceImplementationDescription.pkl" as SID
-
-type: SID.ServiceImplementationType = "HTTP"
-scheme: String
-host: String
-port: Int(isBetween(1, 65535))
-endPoint: String
-method: Method
-
-typealias Method = "GET" | "POST"
diff --git a/src/main/resources/pkl/JobDescription.pkl b/src/main/resources/pkl/JobDescription.pkl
deleted file mode 100644
index a27ef842..00000000
--- a/src/main/resources/pkl/JobDescription.pkl
+++ /dev/null
@@ -1,14 +0,0 @@
-@ModuleInfo { minPklVersion = "0.26.2" }
-module at.ac.uibk.dps.cirrina.csml.description.JobDescription
-
-import "CollaborativeStateMachineDescription.pkl"
-import "ServiceImplementationDescription.pkl"
-
-serviceImplementations: Listing
-collaborativeStateMachine: CollaborativeStateMachineDescription
-stateMachineName: String
-localData: Mapping
-bindEventInstanceIds: Listing
-runtimeName: String
-startTime: Float = -1.0
-endTime: Float = -1.0
diff --git a/src/main/resources/pkl/PklProject b/src/main/resources/pkl/PklProject
deleted file mode 100644
index 974c59a4..00000000
--- a/src/main/resources/pkl/PklProject
+++ /dev/null
@@ -1,8 +0,0 @@
-amends "pkl:Project"
-
-package {
- name = "csm"
- version = "1.0.0"
- baseUri = "package://example.com/\(name)"
- packageZipUrl = "https://example.com/\(name)/\(name)@\(version).zip"
-}
\ No newline at end of file
diff --git a/src/main/resources/pkl/ServiceImplementationDescription.pkl b/src/main/resources/pkl/ServiceImplementationDescription.pkl
deleted file mode 100644
index aeca3b09..00000000
--- a/src/main/resources/pkl/ServiceImplementationDescription.pkl
+++ /dev/null
@@ -1,10 +0,0 @@
-@ModuleInfo { minPklVersion = "0.26.2" }
-abstract module at.ac.uibk.dps.cirrina.csml.description.ServiceImplementationDescription
-
-typealias ServiceImplementationType = "HTTP" | "Other"
-
-name: String
-type: ServiceImplementationType
-cost: Float
-`local`: Boolean
-
diff --git a/src/main/resources/pkl/csm/.gitignore b/src/main/resources/pkl/csm/.gitignore
new file mode 100644
index 00000000..c585e193
--- /dev/null
+++ b/src/main/resources/pkl/csm/.gitignore
@@ -0,0 +1 @@
+out
\ No newline at end of file
diff --git a/src/main/resources/pkl/csm/Csml.pkl b/src/main/resources/pkl/csm/Csml.pkl
new file mode 100644
index 00000000..006c91ab
--- /dev/null
+++ b/src/main/resources/pkl/csm/Csml.pkl
@@ -0,0 +1,143 @@
+@ModuleInfo { minPklVersion = "0.29.0" }
+module at.ac.uibk.dps.cirrina.csml.description.Csml
+
+typealias Version = "3.0.0"
+typealias Expression = String
+
+name: String
+version: Version
+stateMachines: Listing
+localContext: ContextDescription?
+persistentContext: ContextDescription?
+
+open class StateMachineDescription {
+ name: String
+ states: Listing
+ stateMachines: Listing
+ localContext: ContextDescription?
+ persistentContext: ContextDescription?
+}
+
+open class StateDescription {
+ name: String
+ initial: Boolean = false
+ terminal: Boolean = false
+ entry: Listing
+ exit: Listing
+ while: Listing
+ after: Listing
+ on: Listing
+ always: Listing
+ localContext: ContextDescription
+ persistentContext: ContextDescription
+ staticContext: ContextDescription
+}
+
+open class TransitionDescription {
+ target: String?
+ guards: Listing
+ actions: Listing
+ `else`: String?
+}
+
+class OnTransitionDescription extends TransitionDescription {
+ event: String
+}
+
+open class GuardDescription {
+ expression: Expression
+}
+
+abstract class ActionDescription {
+ type: Type
+}
+
+typealias Type = "invoke" | "create" | "assign" | "raise" | "timeout" | "timeoutReset" | "match"
+
+class AssignActionDescription extends ActionDescription {
+ type: Type = "assign"
+ variable: ContextVariableDescription
+}
+
+class CreateActionDescription extends ActionDescription {
+ type: Type = "create"
+ variable: ContextVariableDescription
+ isPersistent: Boolean = false
+}
+
+class InvokeActionDescription extends ActionDescription {
+ type: Type = "invoke"
+ serviceType: String
+ isLocal: Boolean = false
+ input: Listing
+ done: Listing
+ output: Listing
+}
+
+class MatchCaseDescription {
+ `case`: Expression
+ action: ActionDescription
+}
+
+class MatchActionDescription extends ActionDescription {
+ type: Type = "match"
+ value: Expression
+ cases: Listing
+}
+
+class RaiseActionDescription extends ActionDescription {
+ type: Type = "raise"
+ event: EventDescription
+}
+
+class TimeoutActionDescription extends ActionDescription {
+ type: Type = "timeout"
+ name: String
+ delay: Expression
+ action: ActionDescription
+}
+
+class TimeoutResetActionDescription extends ActionDescription {
+ type: Type = "timeoutReset"
+ action: String
+}
+
+typealias EventChannel = "internal" | "external" | "global" | "peripheral"
+
+class EventDescription {
+ name: String
+ channel: EventChannel
+ data: Listing
+}
+
+class ContextDescription {
+ variables: Listing
+}
+
+class ContextVariableDescription {
+ name: String
+ value: Expression
+}
+
+class ContextVariableReferenceDescription {
+ reference: String
+}
+
+typealias StateMachine = StateMachineDescription
+typealias State = StateDescription
+typealias Transition = TransitionDescription
+typealias OnTransition = OnTransitionDescription
+typealias Guard = GuardDescription
+typealias Action = ActionDescription
+typealias AssignAction = AssignActionDescription
+typealias CreateAction = CreateActionDescription
+typealias InvokeAction = InvokeActionDescription
+typealias MatchCase = MatchCaseDescription
+typealias MatchAction = MatchActionDescription
+typealias RaiseAction = RaiseActionDescription
+typealias TimeoutAction = TimeoutActionDescription
+typealias TimeoutResetAction = TimeoutResetActionDescription
+typealias Event = EventDescription
+typealias Context = ContextDescription
+typealias ContextVariable = ContextVariableDescription
+typealias ContextVariableReference = ContextVariableReferenceDescription
\ No newline at end of file
diff --git a/src/main/resources/pkl/csm/HttpServiceImplementationDescription.pkl b/src/main/resources/pkl/csm/HttpServiceImplementationDescription.pkl
new file mode 100644
index 00000000..0a61c3c7
--- /dev/null
+++ b/src/main/resources/pkl/csm/HttpServiceImplementationDescription.pkl
@@ -0,0 +1,15 @@
+@ModuleInfo { minPklVersion = "0.29.0" }
+module at.ac.uibk.dps.cirrina.csm.description.HttpServiceImplementationDescription
+
+extends "ServiceImplementationDescription.pkl"
+
+import "ServiceImplementationDescription.pkl"
+
+type: ServiceImplementationDescription.Type = "HTTP"
+scheme: String
+host: String
+port: Int(isBetween(1, 65535))
+endPoint: String
+method: Method
+
+typealias Method = "GET" | "POST"
\ No newline at end of file
diff --git a/src/main/resources/pkl/csm/PklProject b/src/main/resources/pkl/csm/PklProject
new file mode 100644
index 00000000..11d4c6c9
--- /dev/null
+++ b/src/main/resources/pkl/csm/PklProject
@@ -0,0 +1,8 @@
+amends "pkl:Project"
+
+package {
+ name = "csm"
+ version = "3.0.0"
+ baseUri = "package://collaborativestatemachines.github.io/files/cirrina/\(name)"
+ packageZipUrl = "https://collaborativestatemachines.github.io/files/cirrina/\(name)/\(name)@\(version).zip"
+}
\ No newline at end of file
diff --git a/src/main/resources/pkl/PklProject.deps.json b/src/main/resources/pkl/csm/PklProject.deps.json
similarity index 100%
rename from src/main/resources/pkl/PklProject.deps.json
rename to src/main/resources/pkl/csm/PklProject.deps.json
diff --git a/src/main/resources/pkl/csm/README.md b/src/main/resources/pkl/csm/README.md
new file mode 100644
index 00000000..26e55bd4
--- /dev/null
+++ b/src/main/resources/pkl/csm/README.md
@@ -0,0 +1,49 @@
+# Cirrina CSML Pkl Project
+
+This directory contains the Cirrina CSML Pkl Project, containing the CSML language specification and other Cirrina Pkl resource files. The
+project is intended to be exported as a package and imported into Cirrina application projects. However, to serve the package locally (for
+development purposes), a local (HTTPS-capable) web server is required.
+
+The Cirrina application project can specify the locally served Pkl project as a dependency:
+
+```pkl
+dependencies {
+ ["CSML"] {
+ uri = "package://localhost:10000/csm/csm@2.0.0"
+ }
+}
+```
+
+We can use [https-localhost](https://www.npmjs.com/package/https-localhost) to serve the project locally:
+
+```
+PORT=10000 npx https-localhost
+```
+
+From the `out` directory, generated by:
+
+```
+pkl project package --skip-publish-check --output-path out/csm/
+```
+
+Which will set up the local web server on port 10000, as well as creating a self-signed certificate. To ensure that Pkl can access the
+project, we need to provide access to the certificate. One way of doing this is by symlinking `/etc/ssl/certs` to `~/.pkl/cacerts`:
+
+```
+ln -s /etc/ssl/certs ~/.pkl/cacerts
+```
+
+Since the Cirrina CSML Pkl project specifies its base URI and package ZIP URL, we need to rewrite these values to point to the local
+server using `~/.pkl/settings.pkl`:
+
+```bash
+amends "pkl:settings"
+
+http {
+ rewrites {
+ ["https://collaborativestatemachines.github.io/files/cirrina/"] = "https://localhost:10000/"
+ }
+}
+```
+
+**Note that this requires at least version 0.29.0 of the Pkl.**
\ No newline at end of file
diff --git a/src/main/resources/pkl/csm/ServiceImplementationDescription.pkl b/src/main/resources/pkl/csm/ServiceImplementationDescription.pkl
new file mode 100644
index 00000000..b5ada9ac
--- /dev/null
+++ b/src/main/resources/pkl/csm/ServiceImplementationDescription.pkl
@@ -0,0 +1,9 @@
+@ModuleInfo { minPklVersion = "0.29.0" }
+abstract module at.ac.uibk.dps.cirrina.csm.description.ServiceImplementationDescription
+
+typealias Type = "HTTP" | "Other"
+
+name: String
+type: Type
+cost: Float
+`local`: Boolean
\ No newline at end of file
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/classes/statemachine/StateMachineClassTest.java b/src/test/java/at/ac/uibk/dps/cirrina/classes/statemachine/StateMachineClassTest.java
index 5a3be825..c3eba42a 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/classes/statemachine/StateMachineClassTest.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/classes/statemachine/StateMachineClassTest.java
@@ -6,9 +6,8 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClassBuilder;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription;
import at.ac.uibk.dps.cirrina.data.DefaultDescriptions;
-import at.ac.uibk.dps.cirrina.io.description.DescriptionParser;
+import at.ac.uibk.dps.cirrina.io.description.CsmlParser;
import java.util.List;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
@@ -19,12 +18,9 @@ public class StateMachineClassTest {
@BeforeAll
public static void setUp() {
- var json = DefaultDescriptions.complete;
-
- var parser = new DescriptionParser<>(CollaborativeStateMachineDescription.class);
assertDoesNotThrow(() -> {
var collaborativeStateMachine = CollaborativeStateMachineClassBuilder.from(
- parser.parse(json)
+ CsmlParser.parse(DefaultDescriptions.complete)
).build();
stateMachineClass = collaborativeStateMachine
@@ -41,15 +37,15 @@ void testGetName() {
@Test
void testGetHandledEvents() {
var handledEvents = stateMachineClass.getInputEvents();
- var expectedHandledEvents = List.of("e1", "e2");
- assertEquals(handledEvents, expectedHandledEvents);
+ var expectedHandledEvents = List.of("e1", "e2", "e3");
+ assertEquals(expectedHandledEvents, handledEvents);
}
@Test
void testGetRaisedEvents() {
var raisedEvents = stateMachineClass.getInputEvents();
- var expectedRaisedEvents = List.of("e1", "e2");
- assertEquals(raisedEvents, expectedRaisedEvents);
+ var expectedRaisedEvents = List.of("e1", "e2", "e3");
+ assertEquals(expectedRaisedEvents, raisedEvents);
}
@Test
@@ -70,7 +66,7 @@ void testGetActionByName() {
@Test
void testFindStateByName() {
assertDoesNotThrow(() -> {
- stateMachineClass.findStateClassByName("state1").get().getName().equals("state1");
+ stateMachineClass.findStateClassByName("a").get().getName().equals("a");
assertFalse(stateMachineClass.findStateClassByName("nonExisting").isPresent());
});
@@ -80,17 +76,17 @@ void testFindStateByName() {
void testFindTransitionByEventName() {
assertDoesNotThrow(() -> {
var t = stateMachineClass.findOnTransitionsFromStateByEventName(
- stateMachineClass.findStateClassByName("state1").get(),
+ stateMachineClass.findStateClassByName("a").get(),
"e1"
);
assertEquals(1, t.size());
- assertEquals("state2", t.getFirst().getTargetStateName().get());
+ assertEquals("b", t.getFirst().getTargetStateName().get());
assertEquals(
0,
stateMachineClass
.findOnTransitionsFromStateByEventName(
- stateMachineClass.findStateClassByName("state1").get(),
+ stateMachineClass.findStateClassByName("a").get(),
"nonExisting"
)
.size()
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/csml/parser/CsmlParserTest.java b/src/test/java/at/ac/uibk/dps/cirrina/csml/parser/CsmlParserTest.java
new file mode 100644
index 00000000..eac8a8f3
--- /dev/null
+++ b/src/test/java/at/ac/uibk/dps/cirrina/csml/parser/CsmlParserTest.java
@@ -0,0 +1,27 @@
+package at.ac.uibk.dps.cirrina.csml.parser;
+
+import org.junit.jupiter.api.Test;
+
+class CsmlParserTest {
+
+ @Test
+ void testDescriptionPositive() {
+ // TODO: Fix me
+ /*var pkl = DefaultDescriptions.complete;
+
+ assertDoesNotThrow(() -> {
+ var csm = CsmlParser.parse(pkl);
+ });*/
+ }
+
+ @Test
+ void testDescriptionNegative() {
+ // TODO: Fix me
+ /*var json = DefaultDescriptions.empty;
+
+ assertThrows(IllegalArgumentException.class, () -> {
+ var csm = CsmlParser.parse(json);
+ System.out.println(csm);
+ });*/
+ }
+}
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/csml/parser/DescriptionParserTest.java b/src/test/java/at/ac/uibk/dps/cirrina/csml/parser/DescriptionParserTest.java
deleted file mode 100644
index b0b16fc2..00000000
--- a/src/test/java/at/ac/uibk/dps/cirrina/csml/parser/DescriptionParserTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package at.ac.uibk.dps.cirrina.csml.parser;
-
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription;
-import at.ac.uibk.dps.cirrina.data.DefaultDescriptions;
-import at.ac.uibk.dps.cirrina.io.description.DescriptionParser;
-import org.junit.jupiter.api.Test;
-
-class DescriptionParserTest {
-
- @Test
- void testDescriptionPositive() {
- var pkl = DefaultDescriptions.complete;
-
- var parser = new DescriptionParser<>(CollaborativeStateMachineDescription.class);
- assertDoesNotThrow(() -> {
- var csm = parser.parse(pkl);
- });
- }
-
- @Test
- void testDescriptionNegative() {
- var json = DefaultDescriptions.empty;
-
- var parser = new DescriptionParser<>(CollaborativeStateMachineDescription.class);
- assertThrows(IllegalArgumentException.class, () -> {
- var csm = parser.parse(json);
- System.out.println(csm);
- });
- }
-}
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/data/DefaultDescriptions.java b/src/test/java/at/ac/uibk/dps/cirrina/data/DefaultDescriptions.java
index 0cb7e941..d0df6f63 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/data/DefaultDescriptions.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/data/DefaultDescriptions.java
@@ -1,46 +1,20 @@
package at.ac.uibk.dps.cirrina.data;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.Test;
public class DefaultDescriptions {
- public static final String empty = "{}";
+ public static final String complete = "pkl/complete/main.pkl";
- public static final String complete = loadResource("complete.pkl");
+ public static final String invoke = "pkl/invoke/main.pkl";
- public static final String completeNested = loadResource("completeNested.pkl");
+ public static final String timeout = "pkl/timeout/main.pkl";
- public static final String invoke = loadResource("invoke.pkl");
-
- public static final String timeout = loadResource("timeout.pkl");
-
- public static final String pingPong = loadResource("pingPong.pkl");
- public static final String jobDescription = loadResource("jobDescription.pkl");
-
- private static String loadResource(String fileName) {
- try (
- InputStream inputStream = DefaultDescriptions.class.getResourceAsStream(
- "/at/ac/uibk/dps/cirrina/data/" + fileName
- )
- ) {
- if (inputStream == null) {
- throw new IOException("Resource not found: " + fileName);
- }
- byte[] bytes = inputStream.readAllBytes();
- return new String(bytes, StandardCharsets.UTF_8);
- } catch (IOException e) {
- throw new RuntimeException("Failed to load resource: " + fileName, e);
- }
- }
+ public static final String pingPong = "pkl/pingPong/main.pkl";
@Test
void testLoadResource() {
- assert !empty.isEmpty();
assert !complete.isEmpty();
- assert !completeNested.isEmpty();
assert !invoke.isEmpty();
assert !timeout.isEmpty();
assert !pingPong.isEmpty();
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/execution/object/event/NatsEventHandlerTest.java b/src/test/java/at/ac/uibk/dps/cirrina/execution/object/event/NatsEventHandlerTest.java
index 7c45c171..96beaba9 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/execution/object/event/NatsEventHandlerTest.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/execution/object/event/NatsEventHandlerTest.java
@@ -4,9 +4,9 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription.ContextVariableDescription;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription.EventChannel;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription.EventDescription;
+import at.ac.uibk.dps.cirrina.csml.description.Csml.ContextVariableDescription;
+import at.ac.uibk.dps.cirrina.csml.description.Csml.EventChannel;
+import at.ac.uibk.dps.cirrina.csml.description.Csml.EventDescription;
import at.ac.uibk.dps.cirrina.execution.object.context.Extent;
import at.ac.uibk.dps.cirrina.execution.object.context.InMemoryContext;
import java.util.ArrayList;
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/execution/object/exchange/EventExchangeTest.java b/src/test/java/at/ac/uibk/dps/cirrina/execution/object/exchange/EventExchangeTest.java
index 7d436747..69dbe11e 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/execution/object/exchange/EventExchangeTest.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/execution/object/exchange/EventExchangeTest.java
@@ -4,7 +4,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription.EventChannel;
+import at.ac.uibk.dps.cirrina.csml.description.Csml.EventChannel;
import at.ac.uibk.dps.cirrina.execution.object.context.ContextVariable;
import at.ac.uibk.dps.cirrina.execution.object.event.Event;
import java.util.List;
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/execution/object/guard/GuardTest.java b/src/test/java/at/ac/uibk/dps/cirrina/execution/object/guard/GuardTest.java
index 54fc2498..406dc2b8 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/execution/object/guard/GuardTest.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/execution/object/guard/GuardTest.java
@@ -5,7 +5,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription.GuardDescription;
+import at.ac.uibk.dps.cirrina.csml.description.Csml.GuardDescription;
import at.ac.uibk.dps.cirrina.execution.object.context.Extent;
import at.ac.uibk.dps.cirrina.execution.object.context.InMemoryContext;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/execution/service/HttpServiceImplementationTest.java b/src/test/java/at/ac/uibk/dps/cirrina/execution/service/HttpServiceImplementationTest.java
index c4b9371b..fc04b79e 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/execution/service/HttpServiceImplementationTest.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/execution/service/HttpServiceImplementationTest.java
@@ -4,8 +4,8 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription.ContextVariableDescription;
-import at.ac.uibk.dps.cirrina.csml.description.HttpServiceImplementationDescription.Method;
+import at.ac.uibk.dps.cirrina.csm.description.HttpServiceImplementationDescription.Method;
+import at.ac.uibk.dps.cirrina.csml.description.Csml.ContextVariableDescription;
import at.ac.uibk.dps.cirrina.execution.object.context.ContextVariable;
import at.ac.uibk.dps.cirrina.execution.object.context.ContextVariableBuilder;
import at.ac.uibk.dps.cirrina.execution.object.context.Extent;
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/execution/service/ServiceImplementationSelectorTest.java b/src/test/java/at/ac/uibk/dps/cirrina/execution/service/ServiceImplementationSelectorTest.java
index a1f33d35..cc58d79f 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/execution/service/ServiceImplementationSelectorTest.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/execution/service/ServiceImplementationSelectorTest.java
@@ -3,10 +3,10 @@
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import at.ac.uibk.dps.cirrina.csml.description.HttpServiceImplementationDescription;
-import at.ac.uibk.dps.cirrina.csml.description.HttpServiceImplementationDescription.Method;
-import at.ac.uibk.dps.cirrina.csml.description.ServiceImplementationDescription;
-import at.ac.uibk.dps.cirrina.csml.description.ServiceImplementationDescription.ServiceImplementationType;
+import at.ac.uibk.dps.cirrina.csm.description.HttpServiceImplementationDescription;
+import at.ac.uibk.dps.cirrina.csm.description.HttpServiceImplementationDescription.Method;
+import at.ac.uibk.dps.cirrina.csm.description.ServiceImplementationDescription;
+import at.ac.uibk.dps.cirrina.csm.description.ServiceImplementationDescription.Type;
import java.util.List;
import org.junit.jupiter.api.Test;
@@ -22,7 +22,7 @@ void testSelectMatchingServices() {
"A",
1.0,
true,
- ServiceImplementationType.HTTP,
+ Type.HTTP,
"http",
"localhost",
12345,
@@ -39,7 +39,7 @@ void testSelectMatchingServices() {
"A",
0.5,
false,
- ServiceImplementationType.HTTP,
+ Type.HTTP,
"http",
"localhost",
12345,
@@ -56,7 +56,7 @@ void testSelectMatchingServices() {
"B",
0.4,
false,
- ServiceImplementationType.HTTP,
+ Type.HTTP,
"http",
"localhost",
12345,
@@ -73,7 +73,7 @@ void testSelectMatchingServices() {
"B",
0.2,
false,
- ServiceImplementationType.HTTP,
+ Type.HTTP,
"http",
"localhost",
12345,
@@ -90,7 +90,7 @@ void testSelectMatchingServices() {
"C",
1.0,
true,
- ServiceImplementationType.HTTP,
+ Type.HTTP,
"http",
"localhost",
12345,
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/io/description/CsmlParserTest.java b/src/test/java/at/ac/uibk/dps/cirrina/io/description/CsmlParserTest.java
new file mode 100644
index 00000000..089fd00c
--- /dev/null
+++ b/src/test/java/at/ac/uibk/dps/cirrina/io/description/CsmlParserTest.java
@@ -0,0 +1,9 @@
+package at.ac.uibk.dps.cirrina.io.description;
+
+import org.junit.jupiter.api.Test;
+
+public class CsmlParserTest {
+
+ @Test
+ void loadProject() {}
+}
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/io/plantuml/CollaborativeStateMachineClassExporterTest.java b/src/test/java/at/ac/uibk/dps/cirrina/io/plantuml/CollaborativeStateMachineClassExporterTest.java
deleted file mode 100644
index ac54519d..00000000
--- a/src/test/java/at/ac/uibk/dps/cirrina/io/plantuml/CollaborativeStateMachineClassExporterTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package at.ac.uibk.dps.cirrina.io.plantuml;
-
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-
-import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClass;
-import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClassBuilder;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription;
-import at.ac.uibk.dps.cirrina.data.DefaultDescriptions;
-import at.ac.uibk.dps.cirrina.io.description.DescriptionParser;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.StringWriter;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-class CollaborativeStateMachineClassExporterTest {
-
- private static CollaborativeStateMachineClass completeNestedCsm;
-
- @BeforeAll
- static void setUp() {
- var json = DefaultDescriptions.completeNested;
-
- var parser = new DescriptionParser(
- CollaborativeStateMachineDescription.class
- );
- var csm = assertDoesNotThrow(() -> parser.parse(json));
- completeNestedCsm = assertDoesNotThrow(() ->
- CollaborativeStateMachineClassBuilder.from(csm).build()
- );
- }
-
- @Test
- void exportCollaborativeStateMachine() {
- var out = new StringWriter();
-
- assertDoesNotThrow(() -> {
- CollaborativeStateMachineExporter.export(out, completeNestedCsm);
-
- var file = new File("test_complete_nested_csm.puml");
- assertDoesNotThrow(() -> {
- var writer = new FileWriter(file);
- writer.write(out.toString());
- writer.close();
- });
- });
- }
-
- @Test
- void exportStateMachine() {
- var out = new StringWriter();
-
- assertDoesNotThrow(() -> {
- CollaborativeStateMachineExporter.export(
- out,
- completeNestedCsm.getStateMachineClasses().getFirst()
- );
-
- var file = new File("test_complete_nested_sm.puml");
- assertDoesNotThrow(() -> {
- var writer = new FileWriter(file);
- writer.write(out.toString());
- writer.close();
- });
- });
- }
-}
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/runtime/job/JobDescriptionParserTest.java b/src/test/java/at/ac/uibk/dps/cirrina/runtime/job/JobDescriptionParserTest.java
deleted file mode 100644
index 39c026af..00000000
--- a/src/test/java/at/ac/uibk/dps/cirrina/runtime/job/JobDescriptionParserTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package at.ac.uibk.dps.cirrina.runtime.job;
-
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import at.ac.uibk.dps.cirrina.data.DefaultDescriptions;
-import org.junit.jupiter.api.Test;
-
-class JobDescriptionParserTest {
-
- @Test
- void testJobDescription() {
- final var jobDescriptionPkl = DefaultDescriptions.jobDescription;
-
- assertDoesNotThrow(() -> {
- final var jobDescription = new JobDescriptionParser().parse(jobDescriptionPkl);
-
- assertEquals("stateMachine1", jobDescription.getStateMachineName());
- assertEquals(1, jobDescription.getLocalData().size());
- assertEquals(0, jobDescription.getBindEventInstanceIds().size());
- assertEquals(1, jobDescription.getServiceImplementations().size());
- assertEquals("runtime", jobDescription.getRuntimeName());
- });
- }
-}
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/CompleteTest.java b/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/CompleteTest.java
new file mode 100644
index 00000000..278a55b0
--- /dev/null
+++ b/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/CompleteTest.java
@@ -0,0 +1,166 @@
+package at.ac.uibk.dps.cirrina.runtime.offline;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClass;
+import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClassBuilder;
+import at.ac.uibk.dps.cirrina.csm.description.HttpServiceImplementationDescription;
+import at.ac.uibk.dps.cirrina.csm.description.HttpServiceImplementationDescription.Method;
+import at.ac.uibk.dps.cirrina.csm.description.ServiceImplementationDescription;
+import at.ac.uibk.dps.cirrina.csm.description.ServiceImplementationDescription.Type;
+import at.ac.uibk.dps.cirrina.data.DefaultDescriptions;
+import at.ac.uibk.dps.cirrina.execution.object.context.ContextVariable;
+import at.ac.uibk.dps.cirrina.execution.object.context.InMemoryContext;
+import at.ac.uibk.dps.cirrina.execution.object.event.Event;
+import at.ac.uibk.dps.cirrina.execution.object.event.EventHandler;
+import at.ac.uibk.dps.cirrina.execution.object.exchange.ContextVariableExchange;
+import at.ac.uibk.dps.cirrina.execution.object.exchange.ContextVariableProtos;
+import at.ac.uibk.dps.cirrina.execution.service.OptimalServiceImplementationSelector;
+import at.ac.uibk.dps.cirrina.execution.service.ServiceImplementationBuilder;
+import at.ac.uibk.dps.cirrina.io.description.CsmlParser;
+import at.ac.uibk.dps.cirrina.runtime.OfflineRuntime;
+import com.sun.net.httpserver.HttpServer;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.List;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public class CompleteTest {
+
+ private static CollaborativeStateMachineClass collaborativeStateMachineClass;
+
+ private static HttpServer httpServer;
+
+ @BeforeAll
+ public static void setUp() throws IOException {
+ httpServer = HttpServer.create(new InetSocketAddress(8000), 0);
+
+ httpServer.createContext("/increment", exchange -> {
+ final var payload = exchange.getRequestBody().readAllBytes();
+
+ final var in = ContextVariableProtos.ContextVariables.parseFrom(payload)
+ .getDataList()
+ .stream()
+ .map(ContextVariableExchange::fromProto)
+ .toList();
+
+ final var v = in
+ .stream()
+ .filter(e -> e.name().equals("v"))
+ .findFirst();
+
+ // Create output
+ final var out = ContextVariableProtos.ContextVariables.newBuilder()
+ .addAllData(
+ Stream.of(new ContextVariable("v", (int) v.get().value() + 1))
+ .map(contextVariable -> new ContextVariableExchange(contextVariable).toProto())
+ .toList()
+ )
+ .build()
+ .toByteArray();
+
+ // Response stateMachineInstanceStatus and length
+ exchange.sendResponseHeaders(200, out.length);
+
+ // Output the response
+ try (final var stream = exchange.getResponseBody()) {
+ stream.write(out);
+ }
+ });
+
+ httpServer.start();
+
+ Assertions.assertDoesNotThrow(() -> {
+ collaborativeStateMachineClass = CollaborativeStateMachineClassBuilder.from(
+ CsmlParser.parse(DefaultDescriptions.complete)
+ ).build();
+ });
+ }
+
+ @AfterAll
+ public static void tearDown() {
+ httpServer.stop(0);
+ }
+
+ @Test
+ void testServiceInvocationExecute() {
+ Assertions.assertDoesNotThrow(() -> {
+ final var mockEventHandler = new EventHandler() {
+ @Override
+ public void close() {}
+
+ @Override
+ public void sendEvent(Event event, String source) {
+ propagateEvent(event);
+ }
+
+ @Override
+ public void subscribe(String topic) {}
+
+ @Override
+ public void unsubscribe(String topic) {}
+
+ @Override
+ public void subscribe(String source, String subject) {}
+
+ @Override
+ public void unsubscribe(String source, String subject) {}
+ };
+
+ // Mock a persistent context using an in-memory context
+ var mockPersistentContext = new InMemoryContext(true) {
+ @Override
+ public int assign(String name, Object value) throws IOException {
+ // Don't expect any variables assigned except for v
+ assertTrue(name.equals("v"));
+
+ // Which is an integer
+ assertInstanceOf(Integer.class, value);
+
+ return super.assign(name, value);
+ }
+ };
+
+ final var runtime = new OfflineRuntime("runtime", mockEventHandler, mockPersistentContext);
+
+ var serviceDescriptions = new ServiceImplementationDescription[1];
+
+ {
+ var service = new HttpServiceImplementationDescription(
+ "increment",
+ 1.0,
+ true,
+ Type.HTTP,
+ "http",
+ "localhost",
+ 8000,
+ "/increment",
+ Method.GET
+ );
+
+ serviceDescriptions[0] = service;
+ }
+
+ final var services = ServiceImplementationBuilder.from(List.of(serviceDescriptions)).build();
+ final var serviceImplementationSelector = new OptimalServiceImplementationSelector(services);
+
+ final var instances = runtime.newInstance(
+ collaborativeStateMachineClass,
+ serviceImplementationSelector
+ );
+
+ assertEquals(1, instances.size());
+
+ assertTrue(runtime.waitForCompletion(10000));
+
+ assertEquals(0, mockPersistentContext.get("v"));
+ assertEquals(true, mockPersistentContext.get("b"));
+ });
+ }
+}
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/PingPongTest.java b/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/PingPongTest.java
index ebd2a16a..74087af8 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/PingPongTest.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/PingPongTest.java
@@ -6,13 +6,12 @@
import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClass;
import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClassBuilder;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription;
import at.ac.uibk.dps.cirrina.data.DefaultDescriptions;
import at.ac.uibk.dps.cirrina.execution.object.context.InMemoryContext;
import at.ac.uibk.dps.cirrina.execution.object.event.Event;
import at.ac.uibk.dps.cirrina.execution.object.event.EventHandler;
import at.ac.uibk.dps.cirrina.execution.service.OptimalServiceImplementationSelector;
-import at.ac.uibk.dps.cirrina.io.description.DescriptionParser;
+import at.ac.uibk.dps.cirrina.io.description.CsmlParser;
import at.ac.uibk.dps.cirrina.runtime.OfflineRuntime;
import com.google.common.collect.ArrayListMultimap;
import java.io.IOException;
@@ -28,12 +27,9 @@ public class PingPongTest {
public static void setUp() {
var json = DefaultDescriptions.pingPong;
- var parser = new DescriptionParser(
- CollaborativeStateMachineDescription.class
- );
Assertions.assertDoesNotThrow(() -> {
collaborativeStateMachineClass = CollaborativeStateMachineClassBuilder.from(
- parser.parse(json)
+ CsmlParser.parse(json)
).build();
});
}
@@ -67,7 +63,7 @@ void testPingPongExecute() {
Assertions.assertDoesNotThrow(() -> {
final var mockEventHandler = new EventHandler() {
@Override
- public void close() throws Exception {}
+ public void close() {}
@Override
public void sendEvent(Event event, String source) {
@@ -101,8 +97,6 @@ public void unsubscribe(String source, String subject) {}
assertEquals(2, instances.size());
- final var instance = runtime.findInstance(instances.getFirst()).get();
-
assertTrue(runtime.waitForCompletion(10000));
assertEquals(100, mockPersistentContext.get("v"));
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/ServiceInvocationTest.java b/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/ServiceInvocationTest.java
index b1ecfd9f..64e1be19 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/ServiceInvocationTest.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/ServiceInvocationTest.java
@@ -6,11 +6,10 @@
import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClass;
import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClassBuilder;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription;
-import at.ac.uibk.dps.cirrina.csml.description.HttpServiceImplementationDescription;
-import at.ac.uibk.dps.cirrina.csml.description.HttpServiceImplementationDescription.Method;
-import at.ac.uibk.dps.cirrina.csml.description.ServiceImplementationDescription;
-import at.ac.uibk.dps.cirrina.csml.description.ServiceImplementationDescription.ServiceImplementationType;
+import at.ac.uibk.dps.cirrina.csm.description.HttpServiceImplementationDescription;
+import at.ac.uibk.dps.cirrina.csm.description.HttpServiceImplementationDescription.Method;
+import at.ac.uibk.dps.cirrina.csm.description.ServiceImplementationDescription;
+import at.ac.uibk.dps.cirrina.csm.description.ServiceImplementationDescription.Type;
import at.ac.uibk.dps.cirrina.data.DefaultDescriptions;
import at.ac.uibk.dps.cirrina.execution.object.context.ContextVariable;
import at.ac.uibk.dps.cirrina.execution.object.context.InMemoryContext;
@@ -20,7 +19,7 @@
import at.ac.uibk.dps.cirrina.execution.object.exchange.ContextVariableProtos;
import at.ac.uibk.dps.cirrina.execution.service.OptimalServiceImplementationSelector;
import at.ac.uibk.dps.cirrina.execution.service.ServiceImplementationBuilder;
-import at.ac.uibk.dps.cirrina.io.description.DescriptionParser;
+import at.ac.uibk.dps.cirrina.io.description.CsmlParser;
import at.ac.uibk.dps.cirrina.runtime.OfflineRuntime;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
@@ -86,10 +85,9 @@ public void handle(HttpExchange exchange) throws IOException {
final var json = DefaultDescriptions.invoke;
- final var parser = new DescriptionParser<>(CollaborativeStateMachineDescription.class);
Assertions.assertDoesNotThrow(() -> {
collaborativeStateMachineClass = CollaborativeStateMachineClassBuilder.from(
- parser.parse(json)
+ CsmlParser.parse(json)
).build();
});
}
@@ -104,7 +102,7 @@ void testServiceInvocationExecute() {
Assertions.assertDoesNotThrow(() -> {
final var mockEventHandler = new EventHandler() {
@Override
- public void close() throws Exception {}
+ public void close() {}
@Override
public void sendEvent(Event event, String source) {
@@ -128,7 +126,7 @@ public void unsubscribe(String source, String subject) {}
var mockPersistentContext = new InMemoryContext(true) {
@Override
public int assign(String name, Object value) throws IOException {
- // Don't expect any variables assigned except for v
+ // Don't expect any variables assigned except for v and e
assertTrue(name.equals("v") || name.equals("e"));
// Which is an integer
@@ -151,7 +149,7 @@ public int assign(String name, Object value) throws IOException {
"increment",
1.0,
true,
- ServiceImplementationType.HTTP,
+ Type.HTTP,
"http",
"localhost",
8000,
@@ -172,8 +170,6 @@ public int assign(String name, Object value) throws IOException {
assertEquals(1, instances.size());
- final var instance = runtime.findInstance(instances.getFirst()).get();
-
assertTrue(runtime.waitForCompletion(10000));
assertEquals(10, mockPersistentContext.get("v"));
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/TimeoutTest.java b/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/TimeoutTest.java
index 703db9a7..8c13b8d6 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/TimeoutTest.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/runtime/offline/TimeoutTest.java
@@ -6,13 +6,12 @@
import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClass;
import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClassBuilder;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription;
import at.ac.uibk.dps.cirrina.data.DefaultDescriptions;
import at.ac.uibk.dps.cirrina.execution.object.context.InMemoryContext;
import at.ac.uibk.dps.cirrina.execution.object.event.Event;
import at.ac.uibk.dps.cirrina.execution.object.event.EventHandler;
import at.ac.uibk.dps.cirrina.execution.service.OptimalServiceImplementationSelector;
-import at.ac.uibk.dps.cirrina.io.description.DescriptionParser;
+import at.ac.uibk.dps.cirrina.io.description.CsmlParser;
import at.ac.uibk.dps.cirrina.runtime.OfflineRuntime;
import com.google.common.collect.ArrayListMultimap;
import java.io.IOException;
@@ -28,10 +27,9 @@ public class TimeoutTest {
public static void setUp() {
final var json = DefaultDescriptions.timeout;
- final var parser = new DescriptionParser<>(CollaborativeStateMachineDescription.class);
Assertions.assertDoesNotThrow(() -> {
collaborativeStateMachineClass = CollaborativeStateMachineClassBuilder.from(
- parser.parse(json)
+ CsmlParser.parse(json)
).build();
});
}
@@ -65,7 +63,7 @@ void testTimeoutExecute() {
Assertions.assertDoesNotThrow(() -> {
final var mockEventHandler = new EventHandler() {
@Override
- public void close() throws Exception {}
+ public void close() {}
@Override
public void sendEvent(Event event, String source) {
diff --git a/src/test/java/at/ac/uibk/dps/cirrina/runtime/online/PingPongTest.java b/src/test/java/at/ac/uibk/dps/cirrina/runtime/online/PingPongTest.java
index 4e00b1b9..c6443166 100644
--- a/src/test/java/at/ac/uibk/dps/cirrina/runtime/online/PingPongTest.java
+++ b/src/test/java/at/ac/uibk/dps/cirrina/runtime/online/PingPongTest.java
@@ -2,16 +2,12 @@
import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClass;
import at.ac.uibk.dps.cirrina.classes.collaborativestatemachine.CollaborativeStateMachineClassBuilder;
-import at.ac.uibk.dps.cirrina.csml.description.CollaborativeStateMachineDescription;
import at.ac.uibk.dps.cirrina.data.DefaultDescriptions;
import at.ac.uibk.dps.cirrina.execution.object.context.NatsContext;
import at.ac.uibk.dps.cirrina.execution.object.event.NatsEventHandler;
-import at.ac.uibk.dps.cirrina.io.description.DescriptionParser;
+import at.ac.uibk.dps.cirrina.io.description.CsmlParser;
import at.ac.uibk.dps.cirrina.runtime.OnlineRuntime;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeAll;
@@ -22,25 +18,13 @@ public class PingPongTest {
private static CollaborativeStateMachineClass collaborativeStateMachineClass;
- private static CuratorFramework getCuratorFramework() {
- final var zooKeeperConnectString = System.getenv("ZOOKEEPER_CONNECT_STRING");
-
- return CuratorFrameworkFactory.builder()
- .connectString(zooKeeperConnectString)
- .retryPolicy(new ExponentialBackoffRetry(1000, 3))
- .connectionTimeoutMs(3000)
- .sessionTimeoutMs(3000)
- .build();
- }
-
@BeforeAll
public static void setUp() {
var json = DefaultDescriptions.pingPong;
- var parser = new DescriptionParser<>(CollaborativeStateMachineDescription.class);
Assertions.assertDoesNotThrow(() -> {
collaborativeStateMachineClass = CollaborativeStateMachineClassBuilder.from(
- parser.parse(json)
+ CsmlParser.parse(json)
).build();
});
}
@@ -61,20 +45,13 @@ void testPingPongExecute() {
try (final var eventHandler = new NatsEventHandler(natsServerURL)) {
try (final var persistentContext = new NatsContext(true, natsServerURL, natsBucketName)) {
- final var curatorFramework = getCuratorFramework();
- curatorFramework.start();
-
final var runtime = new OnlineRuntime(
"runtime",
eventHandler,
persistentContext,
- openTelemetry,
- curatorFramework,
- false
+ openTelemetry
);
- runtime.run();
-
- curatorFramework.close();
+ //runtime.run();
}
}
});
diff --git a/src/test/resources/at/ac/uibk/dps/cirrina/data/complete.pkl b/src/test/resources/at/ac/uibk/dps/cirrina/data/complete.pkl
deleted file mode 100644
index b9495927..00000000
--- a/src/test/resources/at/ac/uibk/dps/cirrina/data/complete.pkl
+++ /dev/null
@@ -1,102 +0,0 @@
-amends "modulepath:/pkl/CollaborativeStateMachineDescription.pkl"
-import "modulepath:/pkl/CollaborativeStateMachineDescription.pkl" as CSM
-
-// ------------------------ CSM -------------------------------
-name = "collaborativeStateMachine"
-version = "2.0"
-stateMachines {
- stateMachine1
-}
-
-// ------------------------ StateMachine Description -------------------------------
-local stateMachine1: CSM.StateMachineDescription = new {
- name = "stateMachine1"
- states {
- state1
- state2
- }
-}
-
-// ------------------------ States -------------------------------
-local state1: CSM.StateDescription = new {
- name = "state1"
- initial = true
- entry {
- action1
- new CSM.RaiseActionDescription {
- event {
- name = "e1"
- channel = "internal"
- }
- }
- new CSM.InvokeActionDescription {
- serviceType = "serviceTypeName"
- isLocal = true
- input {
- new {
- name = "inV1"
- value = "5"
- }
- new {
- name = "inV2"
- value = "6"
- }
- }
- done {
- new {
- name = "e1"
- channel = "internal"
- }
- new {
- name = "e2"
- channel = "internal"
- }
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- target = "state2"
- event = "e1"
- }
- }
-}
-
-local state2: CSM.StateDescription = new {
- name = "state2"
- entry {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v+1"
- }
- }
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v+1"
- }
- }
- new CSM.RaiseActionDescription {
- event {
- name = "e2"
- channel = "internal"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- target = "state2"
- event = "e2"
- }
- }
-}
-
-// ------------------------ Actions -------------------------------
-local action1: CSM.CreateActionDescription = new {
- type = "create"
- variable {
- name = "v"
- value = "5"
- }
-}
\ No newline at end of file
diff --git a/src/test/resources/at/ac/uibk/dps/cirrina/data/completeNested.pkl b/src/test/resources/at/ac/uibk/dps/cirrina/data/completeNested.pkl
deleted file mode 100644
index 3c60cc73..00000000
--- a/src/test/resources/at/ac/uibk/dps/cirrina/data/completeNested.pkl
+++ /dev/null
@@ -1,287 +0,0 @@
-amends "modulepath:/pkl/CollaborativeStateMachineDescription.pkl"
-import "modulepath:/pkl/CollaborativeStateMachineDescription.pkl" as CSM
-
-// ------------------------ CSM -------------------------------
-name = "collaborativeStateMachine"
-version = "2.0"
-stateMachines {
- stateMachine1
- stateMachine2
-}
-
-// ------------------------ StateMachine Description -------------------------------
-local stateMachine1: CSM.StateMachineDescription = new {
- name = "stateMachine1"
- stateMachines {
- stateMachine1_1
- stateMachine1_2
- }
- states {
- state1
- state2
- state3
- }
-}
-
-local stateMachine2: CSM.StateMachineDescription = new {
- name = "stateMachine2"
- states {
- state1_sm2
- state2_sm2
- }
-}
-
-// ------------------------ Nested StateMachine1_1 -------------------------------
-local stateMachine1_1: CSM.StateMachineDescription = new {
- name = "stateMachine1_1"
- states {
- state1_1
- state1_2
- }
-}
-
-local state1_1: CSM.StateDescription = new {
- name = "state1_1"
- initial = true
- exit {
- new CSM.InvokeActionDescription {
- serviceType = "patternRecognition"
- input {
- new {
- name = "maxValue"
- value = "5"
- }
- new {
- name = "minValue"
- value = "0"
- }
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- target = "state1_2"
- event = "e1_1"
- }
- }
-}
-
-local state1_2: CSM.StateDescription = new {
- name = "state1_2"
- terminal = true
-}
-
-// ------------------------ Nested StateMachine1_2 -------------------------------
-local stateMachine1_2: CSM.StateMachineDescription = new {
- name = "stateMachine1_2"
- states {
- state1_3
- state1_4
- }
-}
-
-local state1_3: CSM.StateDescription = new {
- name = "state1_3"
- initial = true
- on {
- new CSM.OnTransitionDescription {
- target = "state1_4"
- event = "e1_2"
- guards {
- new CSM.GuardDescription {
- expression = "v > 5"
- }
- new CSM.GuardDescription {
- expression = "v < 10"
- }
- }
- }
- }
-}
-
-local state1_4: CSM.StateDescription = new {
- name = "state1_4"
- terminal = true
- entry {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v*2"
- }
- }
- }
-}
-
-// ------------------------ States -------------------------------
-local state1: CSM.StateDescription = new {
- name = "state1"
- initial = true
- entry {
- action1
- new CSM.RaiseActionDescription {
- event {
- name = "e1"
- channel = "internal"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- target = "state2"
- event = "e1"
- guards {
- new CSM.GuardDescription {
- expression = "v > 5"
- }
- }
- }
- }
-}
-
-local state2: CSM.StateDescription = new {
- name = "state2"
- entry {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v+1"
- }
- }
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v+2"
- }
- }
- new CSM.RaiseActionDescription {
- event {
- name = "e2"
- channel = "internal"
- }
- }
- }
- while {
- new CSM.InvokeActionDescription {
- serviceType = "faceRecognition"
- }
- }
- exit {
- new CSM.CreateActionDescription {
- variable {
- name = "v"
- value = "5"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- target = "state2"
- event = "e2"
- actions {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v+1"
- }
- }
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v+1"
- }
- }
- new CSM.RaiseActionDescription {
- event {
- name = "e2"
- channel = "internal"
- }
- }
- }
- }
- new CSM.OnTransitionDescription {
- target = "state3"
- event = "e3"
- }
- }
-}
-
-local state3: CSM.StateDescription = new {
- name = "state3"
- terminal = true
- entry {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v*2"
- }
- }
- }
-}
-
-// ------------------------ Actions -------------------------------
-local action1: CSM.CreateActionDescription = new {
- variable {
- name = "v"
- value = "5"
- }
-}
-
-local action2: CSM.CreateActionDescription = new {
- variable {
- name = "b"
- value = "true"
- }
-}
-
-// ------------------------ StateMachine2 States -------------------------------
-local state1_sm2: CSM.StateDescription = new {
- name = "state1"
- initial = true
- entry {
- action1
- new CSM.RaiseActionDescription {
- event {
- name = "e1"
- channel = "internal"
- }
- }
- }
- exit {
- new CSM.InvokeActionDescription {
- serviceType = "patternRecognition"
- }
- }
- on {
- new CSM.OnTransitionDescription {
- target = "state2"
- event = "stop"
- guards {
- new CSM.GuardDescription {
- expression = "v != 0"
- }
- guard1
- }
- actions {
- action1
- }
- }
- }
-}
-
-local state2_sm2: CSM.StateDescription = new {
- name = "state2"
- terminal = true
- entry {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v*2 + 1"
- }
- }
- }
-}
-
-// ------------------------ Guards -------------------------------
-local guard1: CSM.GuardDescription = new {
- expression = "v < 4 && b"
-}
\ No newline at end of file
diff --git a/src/test/resources/at/ac/uibk/dps/cirrina/data/invoke.pkl b/src/test/resources/at/ac/uibk/dps/cirrina/data/invoke.pkl
deleted file mode 100644
index 90096152..00000000
--- a/src/test/resources/at/ac/uibk/dps/cirrina/data/invoke.pkl
+++ /dev/null
@@ -1,99 +0,0 @@
-amends "modulepath:/pkl/CollaborativeStateMachineDescription.pkl"
-import "modulepath:/pkl/CollaborativeStateMachineDescription.pkl" as CSM
-
-// ------------------------ CSM -------------------------------
-name = "collaborativeStateMachine"
-version = "2.0"
-stateMachines {
- stateMachine1
-}
-
-// ------------------------ StateMachine Description -------------------------------
-local stateMachine1: CSM.StateMachineDescription = new {
- name = "stateMachine1"
- states {
- stateA
- stateB
- stateC
- }
-}
-
-// ------------------------ States -------------------------------
-local stateA: CSM.StateDescription = new {
- name = "a"
- initial = true
- after {
- new CSM.TimeoutActionDescription {
- name = "timeout"
- delay = "100"
- action = new CSM.RaiseActionDescription {
- event {
- name = "update"
- channel = "internal"
- }
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- event = "update"
- target = "a"
- actions {
- new CSM.InvokeActionDescription {
- serviceType = "increment"
- isLocal = true
- input {
- new {
- name = "v"
- value = "v"
- }
- }
- done {
- new {
- name = "tob"
- channel = "internal"
- }
- }
- }
- new CSM.AssignActionDescription {
- variable {
- name = "e"
- value = "e + 1"
- }
- }
- }
- }
- new CSM.OnTransitionDescription {
- event = "tob"
- target = "b"
- }
- }
-}
-
-local stateB: CSM.StateDescription = new {
- name = "b"
- entry {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "$v"
- }
- }
- }
- always {
- new CSM.TransitionDescription {
- target = "a"
- guards {
- new CSM.GuardDescription {
- expression = "v < 10"
- }
- }
- `else` = "c"
- }
- }
-}
-
-local stateC: CSM.StateDescription = new {
- name = "c"
- terminal = true
-}
\ No newline at end of file
diff --git a/src/test/resources/at/ac/uibk/dps/cirrina/data/jobDescription.pkl b/src/test/resources/at/ac/uibk/dps/cirrina/data/jobDescription.pkl
deleted file mode 100644
index bd96faa6..00000000
--- a/src/test/resources/at/ac/uibk/dps/cirrina/data/jobDescription.pkl
+++ /dev/null
@@ -1,182 +0,0 @@
-amends "modulepath:/pkl/JobDescription.pkl"
-
-import "modulepath:/pkl/HttpServiceImplementationDescription.pkl"
-import "modulepath:/pkl/CollaborativeStateMachineDescription.pkl" as CSM
-
-serviceImplementations {
- new HttpServiceImplementationDescription {
- name = "A"
- type = "HTTP"
- cost = 1.0
- `local` = false
- scheme = "http"
- host = "localhost"
- port = 12345
- endPoint = ""
- method = "GET"
- }
-}
-collaborativeStateMachine = pingPongCSM
-stateMachineName = "stateMachine1"
-localData = new Mapping {
- ["foo"] = "'bar'"
-}
-bindEventInstanceIds = new Listing {}
-runtimeName = "runtime"
-
-
-// ------------------------ CSM -------------------------------
-local pingPongCSM: CSM = new {
- name = "collaborativeStateMachine"
- version = "2.0"
- stateMachines {
- stateMachine1
- stateMachine2
- }
- persistentContext {
- variables {
- new {
- name = "v"
- value = "0"
- }
- }
- }
-}
-
-// ------------------------ StateMachine1 Description -------------------------------
-local stateMachine1: CSM.StateMachineDescription = new {
- name = "stateMachine1"
- states {
- stateA1
- stateB1
- stateC1
- }
-}
-
-// ------------------------ StateMachine2 Description -------------------------------
-local stateMachine2: CSM.StateMachineDescription = new {
- name = "stateMachine2"
- states {
- stateA2
- stateB2
- stateC2
- }
-}
-
-// ------------------------ StateMachine1 States -------------------------------
-local stateA1: CSM.StateDescription = new {
- name = "a"
- initial = true
- entry {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v + 1"
- }
- }
- new CSM.RaiseActionDescription {
- event {
- name = "e1"
- channel = "global"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- event = "e2"
- target = "b"
- }
- }
-}
-
-local stateB1: CSM.StateDescription = new {
- name = "b"
- entry {
- new CSM.RaiseActionDescription {
- event {
- name = "e3"
- channel = "global"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- event = "e4"
- target = "a"
- }
- }
- always {
- new CSM.TransitionDescription {
- target = "c"
- guards {
- new CSM.GuardDescription {
- expression = "v >= 100"
- }
- }
- }
- }
-}
-
-local stateC1: CSM.StateDescription = new {
- name = "c"
- terminal = true
-}
-
-// ------------------------ StateMachine2 States -------------------------------
-local stateA2: CSM.StateDescription = new {
- name = "a"
- initial = true
- entry {
- new CSM.RaiseActionDescription {
- event {
- name = "e4"
- channel = "global"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- event = "e1"
- target = "b"
- }
- }
-}
-
-local stateB2: CSM.StateDescription = new {
- name = "b"
- entry {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v + 1"
- }
- }
- new CSM.RaiseActionDescription {
- event {
- name = "e2"
- channel = "global"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- event = "e3"
- target = "a"
- }
- }
- always {
- new CSM.TransitionDescription {
- target = "c"
- guards {
- new CSM.GuardDescription {
- expression = "v >= 100"
- }
- }
- }
- }
-}
-
-local stateC2: CSM.StateDescription = new {
- name = "c"
- terminal = true
-}
diff --git a/src/test/resources/at/ac/uibk/dps/cirrina/data/pingPong.pkl b/src/test/resources/at/ac/uibk/dps/cirrina/data/pingPong.pkl
deleted file mode 100644
index b1233d5e..00000000
--- a/src/test/resources/at/ac/uibk/dps/cirrina/data/pingPong.pkl
+++ /dev/null
@@ -1,148 +0,0 @@
-amends "modulepath:/pkl/CollaborativeStateMachineDescription.pkl"
-import "modulepath:/pkl/CollaborativeStateMachineDescription.pkl" as CSM
-
-// ------------------------ CSM -------------------------------
-name = "collaborativeStateMachine"
-version = "2.0"
-stateMachines {
- stateMachine1
- stateMachine2
-}
-
-// ------------------------ StateMachine1 Description -------------------------------
-local stateMachine1: CSM.StateMachineDescription = new {
- name = "stateMachine1"
- states {
- stateA1
- stateB1
- stateC1
- }
-}
-
-// ------------------------ StateMachine2 Description -------------------------------
-local stateMachine2: CSM.StateMachineDescription = new {
- name = "stateMachine2"
- states {
- stateA2
- stateB2
- stateC2
- }
-}
-
-// ------------------------ StateMachine1 States -------------------------------
-local stateA1: CSM.StateDescription = new {
- name = "a"
- initial = true
- entry {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v + 1"
- }
- }
- new CSM.RaiseActionDescription {
- event {
- name = "e1"
- channel = "global"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- event = "e2"
- target = "b"
- }
- }
-}
-
-local stateB1: CSM.StateDescription = new {
- name = "b"
- entry {
- new CSM.RaiseActionDescription {
- event {
- name = "e3"
- channel = "global"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- event = "e4"
- target = "a"
- }
- }
- always {
- new CSM.TransitionDescription {
- target = "c"
- guards {
- new CSM.GuardDescription {
- expression = "v >= 100"
- }
- }
- }
- }
-}
-
-local stateC1: CSM.StateDescription = new {
- name = "c"
- terminal = true
-}
-
-// ------------------------ StateMachine2 States -------------------------------
-local stateA2: CSM.StateDescription = new {
- name = "a"
- initial = true
- entry {
- new CSM.RaiseActionDescription {
- event {
- name = "e4"
- channel = "global"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- event = "e1"
- target = "b"
- }
- }
-}
-
-local stateB2: CSM.StateDescription = new {
- name = "b"
- entry {
- new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v + 1"
- }
- }
- new CSM.RaiseActionDescription {
- event {
- name = "e2"
- channel = "global"
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- event = "e3"
- target = "a"
- }
- }
- always {
- new CSM.TransitionDescription {
- target = "c"
- guards {
- new CSM.GuardDescription {
- expression = "v >= 100"
- }
- }
- }
- }
-}
-
-local stateC2: CSM.StateDescription = new {
- name = "c"
- terminal = true
-}
\ No newline at end of file
diff --git a/src/test/resources/at/ac/uibk/dps/cirrina/data/timeout.pkl b/src/test/resources/at/ac/uibk/dps/cirrina/data/timeout.pkl
deleted file mode 100644
index ee6aa42d..00000000
--- a/src/test/resources/at/ac/uibk/dps/cirrina/data/timeout.pkl
+++ /dev/null
@@ -1,84 +0,0 @@
-amends "modulepath:/pkl/CollaborativeStateMachineDescription.pkl"
-import "modulepath:/pkl/CollaborativeStateMachineDescription.pkl" as CSM
-
-// ------------------------ CSM -------------------------------
-name = "collaborativeStateMachine"
-version = "2.0"
-stateMachines {
- stateMachine1
-}
-
-// ------------------------ StateMachine Description -------------------------------
-local stateMachine1: CSM.StateMachineDescription = new {
- name = "stateMachine1"
- states {
- stateA
- stateB
- }
- persistentContext {
- variables {
- new {
- name = "v"
- value = "0"
- }
- }
- }
-}
-
-// ------------------------ States -------------------------------
-local stateA: CSM.StateDescription = new {
- name = "a"
- initial = true
- after {
- new CSM.TimeoutActionDescription {
- name = "timeout"
- delay = "100"
- action = new CSM.RaiseActionDescription {
- event {
- name = "update"
- channel = "internal"
- }
- }
- }
- }
- on {
- new CSM.OnTransitionDescription {
- event = "update"
- target = "a"
- actions {
- new CSM.MatchActionDescription {
- value = "v < 10"
- cases {
- new {
- `case` = "true"
- action = new CSM.AssignActionDescription {
- variable {
- name = "v"
- value = "v + 1"
- }
- }
- }
- new {
- `case` = "false"
- action = new CSM.RaiseActionDescription {
- event {
- name = "tob"
- channel = "internal"
- }
- }
- }
- }
- }
- }
- }
- new CSM.OnTransitionDescription {
- event = "tob"
- target = "b"
- }
- }
-}
-
-local stateB: CSM.StateDescription = new {
- name = "b"
- terminal = true
-}
\ No newline at end of file
diff --git a/src/test/resources/pkl/complete/main.pkl b/src/test/resources/pkl/complete/main.pkl
new file mode 100644
index 00000000..9a7db70a
--- /dev/null
+++ b/src/test/resources/pkl/complete/main.pkl
@@ -0,0 +1,10 @@
+amends "modulepath:/pkl/csm/Csml.pkl"
+import "modulepath:/pkl/csm/Csml.pkl"
+
+import "stateMachineOne.pkl"
+
+name = "complete"
+version = "3.0.0"
+stateMachines {
+ new stateMachineOne.StateMachine {}
+}
\ No newline at end of file
diff --git a/src/test/resources/pkl/complete/stateMachineOne.pkl b/src/test/resources/pkl/complete/stateMachineOne.pkl
new file mode 100644
index 00000000..1ba5aa27
--- /dev/null
+++ b/src/test/resources/pkl/complete/stateMachineOne.pkl
@@ -0,0 +1,166 @@
+import "modulepath:/pkl/csm/Csml.pkl"
+
+// State Machine One
+// ┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐
+// │ │
+// │ e1 │
+// │ ┌────────────────────┐ e2 │
+// │ ┌┴┐ ┌▼┐ assign v=$v ┌─┐ v>=100 ┌─┐ create b=true │
+// │ create v=0 │A│ invoke increment │B├─────────────►C├────────►D├───┐ after 10ms │
+// │ after 10ms raise e1 └─┘ done raise e2 └▲┘ └┬┘ └▲┘ │ assign v=v-1 │
+// │ └───────────────┘ │ │ match v │
+// │ v<100 └────┘ case 0: reset timeout │
+// │ │
+// └─────────────────────────────────────────────────────────────────────────────────────────────────────┘
+class StateMachine extends Csml.StateMachineDescription {
+ name = "stateMachine1"
+ states {
+ // State a
+ new Csml.StateDescription {
+ name = "a"
+ initial = true
+ // Create persistent variable v
+ entry {
+ new Csml.CreateActionDescription {
+ variable {
+ name = "v"
+ value = "0"
+ }
+ isPersistent = true
+ }
+ }
+ // After 10ms
+ after {
+ new Csml.TimeoutActionDescription {
+ name = "timeout"
+ delay = "10"
+ action = new Csml.RaiseActionDescription {
+ event {
+ name = "e1"
+ channel = "internal"
+ }
+ }
+ }
+ }
+ // Transition to b
+ on {
+ new Csml.OnTransitionDescription {
+ event = "e1"
+ target = "b"
+ }
+ }
+ }
+ // State b
+ new Csml.StateDescription {
+ name = "b"
+ // Increment v by service invocation and raise e2
+ entry {
+ new Csml.InvokeActionDescription {
+ serviceType = "increment"
+ isLocal = true
+ input {
+ new {
+ name = "v"
+ value = "v"
+ }
+ }
+ done {
+ new Csml.EventDescription {
+ name = "e2"
+ channel = "internal"
+ }
+ }
+ }
+ }
+ // Transition to c and update v based on event data ($v)
+ on {
+ new Csml.OnTransitionDescription {
+ event = "e2"
+ target = "c"
+ actions {
+ new Csml.AssignActionDescription {
+ variable = new {
+ name = "v"
+ value = "$v"
+ }
+ }
+ }
+ }
+ }
+ }
+ // State c
+ new Csml.StateDescription {
+ name = "c"
+ // Transition to d or b
+ always {
+ new Csml.TransitionDescription {
+ target = "d"
+ guards {
+ new Csml.GuardDescription {
+ expression = "v >= 100"
+ }
+ }
+ }
+ new Csml.TransitionDescription {
+ target = "b"
+ guards {
+ new Csml.GuardDescription {
+ expression = "v < 100"
+ }
+ }
+ }
+ }
+ }
+ // State d
+ new Csml.StateDescription {
+ name = "d"
+ entry {
+ new Csml.CreateActionDescription {
+ variable {
+ name = "b"
+ value = "true"
+ }
+ isPersistent = true
+ }
+ }
+ // After 10ms
+ after {
+ new Csml.TimeoutActionDescription {
+ name = "timeout"
+ delay = "10"
+ action = new Csml.RaiseActionDescription {
+ event {
+ name = "e3"
+ channel = "internal"
+ }
+ }
+ }
+ }
+ // Decrement v and reset timeout when reaching 0
+ on {
+ new Csml.OnTransitionDescription {
+ event = "e3"
+ actions {
+ new Csml.AssignActionDescription {
+ variable = new {
+ name = "v"
+ value = "v - 1"
+ }
+ }
+ new Csml.MatchActionDescription {
+ value = "v"
+ cases {
+ new Csml.MatchCaseDescription {
+ `case` = "0"
+ action = new Csml.TimeoutResetActionDescription {
+ action = "timeout"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/pkl/invoke/main.pkl b/src/test/resources/pkl/invoke/main.pkl
new file mode 100644
index 00000000..42f8c71b
--- /dev/null
+++ b/src/test/resources/pkl/invoke/main.pkl
@@ -0,0 +1,88 @@
+amends "modulepath:/pkl/csm/Csml.pkl"
+import "modulepath:/pkl/csm/Csml.pkl"
+
+name = "invoke"
+version = "3.0.0"
+stateMachines {
+ new {
+ name = "stateMachine1"
+ states {
+ new {
+ name = "a"
+ initial = true
+ after {
+ new Csml.TimeoutActionDescription {
+ name = "timeout"
+ delay = "100"
+ action = new Csml.RaiseActionDescription {
+ event {
+ name = "update"
+ channel = "internal"
+ }
+ }
+ }
+ }
+ on {
+ new Csml.OnTransitionDescription {
+ event = "update"
+ target = "a"
+ actions {
+ new Csml.InvokeActionDescription {
+ serviceType = "increment"
+ isLocal = true
+ input {
+ new {
+ name = "v"
+ value = "v"
+ }
+ }
+ done {
+ new {
+ name = "tob"
+ channel = "internal"
+ }
+ }
+ }
+ new Csml.AssignActionDescription {
+ variable {
+ name = "e"
+ value = "e + 1"
+ }
+ }
+ }
+ }
+ new Csml.OnTransitionDescription {
+ event = "tob"
+ target = "b"
+ }
+ }
+ }
+ new {
+ name = "b"
+ entry {
+ new Csml.AssignActionDescription {
+ variable {
+ name = "v"
+ value = "$v"
+ }
+ }
+ }
+ always {
+ new Csml.TransitionDescription {
+ target = "a"
+ guards {
+ new Csml.GuardDescription {
+ expression = "v < 10"
+ }
+ }
+ `else` = "c"
+ }
+ }
+ }
+ new {
+ name = "c"
+ terminal = true
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/pkl/pingPong/main.pkl b/src/test/resources/pkl/pingPong/main.pkl
new file mode 100644
index 00000000..b2a730a3
--- /dev/null
+++ b/src/test/resources/pkl/pingPong/main.pkl
@@ -0,0 +1,12 @@
+amends "modulepath:/pkl/csm/Csml.pkl"
+import "modulepath:/pkl/csm/Csml.pkl"
+
+import "stateMachineOne.pkl"
+import "stateMachineTwo.pkl"
+
+name = "pingPong"
+version = "3.0.0"
+stateMachines {
+ new stateMachineOne.StateMachine {}
+ new stateMachineTwo.StateMachine {}
+}
\ No newline at end of file
diff --git a/src/test/resources/pkl/pingPong/stateMachineOne.pkl b/src/test/resources/pkl/pingPong/stateMachineOne.pkl
new file mode 100644
index 00000000..d3b465c6
--- /dev/null
+++ b/src/test/resources/pkl/pingPong/stateMachineOne.pkl
@@ -0,0 +1,74 @@
+import "modulepath:/pkl/csm/Csml.pkl"
+
+// State Machine One
+// ┌──────────────────────────────────────────┐
+// │ │
+// │ e2 │
+// │ ┌────────────┐ │
+// │ ┌┴┐ ┌▼┐ v >= 100 ┌─┐ │
+// │ raise e1 │A│ raise e3 │B├────────────►C│ │
+// │ v += 1 └▲┘ └┬┘ └─┘ │
+// │ └────────────┘ │
+// │ e4 │
+// │ │
+// └──────────────────────────────────────────┘
+class StateMachine extends Csml.StateMachineDescription {
+ name = "stateMachine1"
+ states {
+ new {
+ name = "a"
+ initial = true
+ entry {
+ new Csml.AssignAction {
+ variable {
+ name = "v"
+ value = "v + 1"
+ }
+ }
+ new Csml.RaiseAction {
+ event {
+ name = "e1"
+ channel = "global"
+ }
+ }
+ }
+ on {
+ new Csml.OnTransition {
+ event = "e2"
+ target = "b"
+ }
+ }
+ }
+ new {
+ name = "b"
+ entry {
+ new Csml.RaiseAction {
+ event {
+ name = "e3"
+ channel = "global"
+ }
+ }
+ }
+ on {
+ new Csml.OnTransition {
+ event = "e4"
+ target = "a"
+ }
+ }
+ always {
+ new Csml.Transition {
+ target = "c"
+ guards {
+ new Csml.Guard {
+ expression = "v >= 100"
+ }
+ }
+ }
+ }
+ }
+ new {
+ name = "c"
+ terminal = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/pkl/pingPong/stateMachineTwo.pkl b/src/test/resources/pkl/pingPong/stateMachineTwo.pkl
new file mode 100644
index 00000000..37c5d764
--- /dev/null
+++ b/src/test/resources/pkl/pingPong/stateMachineTwo.pkl
@@ -0,0 +1,74 @@
+import "modulepath:/pkl/csm/Csml.pkl"
+
+// State Machine Two
+// ┌──────────────────────────────────────────┐
+// │ │
+// │ e1 │
+// │ ┌────────────┐ │
+// │ ┌┴┐ ┌▼┐ v >= 100 ┌─┐ │
+// │ raise e4 │A│ raise e2 │B├────────────►C│ │
+// │ └▲┘ v += 1 └┬┘ └─┘ │
+// │ └────────────┘ │
+// │ e3 │
+// │ │
+// └──────────────────────────────────────────┘
+class StateMachine extends Csml.StateMachineDescription {
+ name = "stateMachine2"
+ states {
+ new {
+ name = "a"
+ initial = true
+ entry {
+ new Csml.RaiseActionDescription {
+ event {
+ name = "e4"
+ channel = "global"
+ }
+ }
+ }
+ on {
+ new Csml.OnTransitionDescription {
+ event = "e1"
+ target = "b"
+ }
+ }
+ }
+ new {
+ name = "b"
+ entry {
+ new Csml.AssignActionDescription {
+ variable {
+ name = "v"
+ value = "v + 1"
+ }
+ }
+ new Csml.RaiseActionDescription {
+ event {
+ name = "e2"
+ channel = "global"
+ }
+ }
+ }
+ on {
+ new Csml.OnTransitionDescription {
+ event = "e3"
+ target = "a"
+ }
+ }
+ always {
+ new Csml.TransitionDescription {
+ target = "c"
+ guards {
+ new Csml.GuardDescription {
+ expression = "v >= 100"
+ }
+ }
+ }
+ }
+ }
+ new {
+ name = "c"
+ terminal = true
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/pkl/timeout/main.pkl b/src/test/resources/pkl/timeout/main.pkl
new file mode 100644
index 00000000..7485d6b0
--- /dev/null
+++ b/src/test/resources/pkl/timeout/main.pkl
@@ -0,0 +1,75 @@
+amends "modulepath:/pkl/csm/Csml.pkl"
+import "modulepath:/pkl/csm/Csml.pkl"
+
+name = "timeout"
+version = "3.0.0"
+stateMachines {
+ new {
+ name = "stateMachine1"
+ states {
+ new {
+ name = "a"
+ initial = true
+ after {
+ new Csml.TimeoutActionDescription {
+ name = "timeout"
+ delay = "100"
+ action = new Csml.RaiseActionDescription {
+ event {
+ name = "update"
+ channel = "internal"
+ }
+ }
+ }
+ }
+ on {
+ new Csml.OnTransitionDescription {
+ event = "update"
+ target = "a"
+ actions {
+ new Csml.MatchActionDescription {
+ value = "v < 10"
+ cases {
+ new {
+ `case` = "true"
+ action = new Csml.AssignActionDescription {
+ variable {
+ name = "v"
+ value = "v + 1"
+ }
+ }
+ }
+ new {
+ `case` = "false"
+ action = new Csml.RaiseActionDescription {
+ event {
+ name = "tob"
+ channel = "internal"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ new Csml.OnTransitionDescription {
+ event = "tob"
+ target = "b"
+ }
+ }
+ }
+ new {
+ name = "b"
+ terminal = true
+ }
+ }
+ persistentContext {
+ variables {
+ new {
+ name = "v"
+ value = "0"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/version.txt b/version.txt
index 7f207341..359a5b95 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-1.0.1
\ No newline at end of file
+2.0.0
\ No newline at end of file