Giter VIP home page Giter VIP logo

sismic's Introduction

Sismic for Python

https://github.com/AlexandreDecan/sismic/actions/workflows/test.yaml/badge.svg?branch=master https://coveralls.io/repos/AlexandreDecan/sismic/badge.svg?branch=master&service=github https://readthedocs.org/projects/sismic/badge/?version=latest

Sismic Interactive Statechart Model Interpreter and Checker

Sismic is a recursive acronym that stands for Sismic Interactive Statechart Model Interpreter and Checker.

Statecharts are a well-known visual modeling language for representing the executable behavior of complex reactive event-based systems. Sismic library for Python (version 3.6 or higher) provides a set of tools to define, validate, simulate, execute and test statecharts. More specifically, Sismic provides:

  • An easy way to define and to import statecharts, based on the human-friendly YAML markup language
  • A statechart interpreter offering a discrete, step-by-step, and fully observable simulation engine
  • Fully controllable simulation clock, with support for real and simulated time
  • Built-in support for expressing actions and guards using regular Python code, can be easily extended to other programming languages
  • Support for Design by Contract (DbC) for statecharts: contracts can be specified to express invariants, pre- and postconditions on states and transitions
  • Runtime monitoring of behavioral properties expressed as statecharts
  • Built-in support for behavior-driven development (BDD)
  • Support for communication between statecharts
  • Synchronous and asynchronous executions
  • Statechart visualization using PlantUML

Installation

Sismic requires Python >=3.7. Sismic can be installed using pip as usual: pip install sismic. This will install the latest stable version.

You can also install Sismic from this repository by cloning it.

Starting from release 1.0.0, Sismic adheres to a semantic versioning scheme.

Documentation

The documentation for the latest distributed version is available on sismic.readthedocs.io.

Many examples are available in docs/examples.

The documentation can also be directly built from the docs directory using Sphinx.

The scientific article A method for testing and validating executable statechart models presenting the method and techniques supported by Sismic for validating and testing statecharts, is published in Springer's Software and Systems modeling journal in 2018.

Changelog

See documentation's changelog.

Credits

The Sismic library for Python is mainly developed by Alexandre Decan at the Software Engineering Lab of the University of Mons with the help of many contributors.

Sismic is released as open source software under the GNU Lesser General Public Licence version 3.0 (LGPLv3).

You can cite the Sismic library using:

@article{sismic-article,
    title = "Sismicβ€”A Python library for statechart execution and testing",
    journal = "SoftwareX",
    volume = "12",
    pages = "100590",
    year = "2020",
    issn = "2352-7110",
    doi = "10.1016/j.softx.2020.100590",
    url = "https://doi.org/10.1016/j.softx.2020.100590",
    author = "Alexandre Decan and Tom Mens",
}

or

@software{sismic,
  author = {Decan, Alexandre},
  title = {Sismic Interactive Statechart Model Interpreter and Checker},
  url = {https://github.com/AlexandreDecan/sismic},
}

You can cite the associated research article (PDF) using:

@article{sismic2018-sosym,
   author = {Mens, Tom and Decan, Alexandre and Spanoudakis, Nikolaos},
   journal = {Software and Systems Modeling},
   publisher = {Springer},
   year = 2018,
   title = {A method for testing and validating executable statechart models},
   doi = {10.1007/s10270-018-0676-3},
   url = {https://doi.org/10.1007/s10270-018-0676-3},
 }

External Resources

The following resources provide additional information about statecharts that may be of use, even if it is not immediately related to Sismic.

  • Yakindu Statechart tools: commercial software for visual simulation, debugging, testing and code generation from statecharts. A free academic licence can be obtained for universities.
  • A YouTube playlist providing a set of introductory tutorials about statechart modeling and simulation (based on the aforementioned Yakindu tool).

(If some of the links provided above turn out to be dead, or if you know other relevant resources that should be added here, please contact us.)

sismic's People

Contributors

alexandredecan avatar edwardbetts avatar gordonfierce avatar jnwtr avatar mcree avatar mgoeminne avatar sbidoul avatar tommens avatar zinoex avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sismic's Issues

Style checker for statecharts

Probably an issue request to the tagged under "utopia", or "nice to have", as it is not a priority for the moment, but nevertheless useful for people that would like to develop executable statecharts:

A "style checker" for statecharts would provide warnings if the statechart specification does not follow a nice "modelling style" or does not respect the common "modelling conventions" for statecharts. It would be the equivalent for the many style checkers that already exist for programming languages (e.g. PMD, CheckStyle, and many other static code analyser tools that aim to assess structural code quality).

A style checker goes beyond a statechart validation tool (which simply checks for syntactic correctness of the statechart): it should typically rule based, composed of a number of rules that verify if the modelling style and modelling conventions are respected. The user should be able to easily configure, enable or disable some rules, in order to customise the style checker to his own needs. It should also be easy to add and share new rules.

Unclear error when running sismic-bdd feature file for a simple cassette player statechart

When I run
sismic-bdd player.yaml --steps player_steps.py --features motor_human.feature
(I will give you the corresponding files in a separate mail)
I get an error in one of its scenarios, but the error message is not very clear "CodeEvaluationError", so I do not know how to deal with it.

Scenario: Motor turns off when stopped # motor_human.feature:25
Given I reproduce "Motor is on while playing" # ../myenv/lib/python3.6/site-packages/sismic/bdd/steps.py:12 0.004s
When I press stop button # ../myenv/lib/python3.6/site-packages/sismic/bdd/wrappers.py:38 0.001s
Assertion Failed: FAILED SUB-STEP: When I send event stop
Captured stdout:
HOOK-ERROR in after_step: CodeEvaluationError: The above exception occurred while executing:
sent('playReleased')

Then motor turns off # None
And play button is released # None

Failing scenarios:
motor_human.feature:25 Motor turns off when stopped

Implementing an Evaluator for a DSL

Hi,

I'm looking into integrating a DSL into Sismic. The DSL is based on Python Lark and would manage some abstractions we have in our system which need to be resolved at run-time. One possible advantage we might gain from that is that DSL commands which run in Sismic will also run interactively - let's see .... its at least likely that a DSL commands would, indirectly, raise Events in the same Sismic model that called the DSL (via a Redis PubSub Channel).

From what I case see in the Sismic code I would need to create an Evaluator class and then pass an instance of that to the Interpreter. For any DSL specific parameters or initialisation it seems that I could use the initial_context parameter of the Interpreter.

Would it be better to base the class on PythonEvaluator and then override the _evaluate_code() and _execute_code() methods (and similar)? That might keep the behavior consistent between the DSL and PythonEvaluator, and allow for the management of exposed_content in the DSL (i.e. active, send, meta, time ...).

Does that seem right?

Thanks, Tim.

validate()

validate() method was really handy for mutation, since I'm changing the internals of the mutants, and it was nice to have a method that detects inconsistencies. Is there anything in place of it that I can use instead?

Support for visualising statecharts

It would be great, some time in the future, to have support for statechart visualisation. This would/should include

  • Support for creating images of SISMIC-compatible statechart models using some generic graphical editing tool of choice (e.g. DIA), preferably with predefined templates that enforce the syntax to avoid making syntactic erros
  • Automatic support for importing YAML files from their corresponding visual model (in that case, of course, the visual model should not be a bitmap image, but it should be in a format from which the YAML file can be generated easily
  • Automatic support for exporting YAML files to a visual editor, in order to be able to (i) visualise them; (ii) generate an image from them; (iii) edit them
  • For all of the above, the intended visual support should take into account the new features of SISMIC, such as the ability to express contracts at different levels (in a nice and consistent visual way), and the ability to express multiple statecharts that communicate. For example, w.r.t. contracts we could either model them visually (at least for states) in the same way as entry/ and exit/ actions on states (i.e. by specifying one or more optional before/, after/, and always/ inside the state). For transitions we could do the same, but the notation would become a bit "heavy". So, alternatively, we could have some kind of "note" notation (similar to UML's note/comment notation) that can be attached to any model element, and in which we can formally describe the contract. This would make sense, as it is more or less "compatible" with the way in which additional OCL constrains can be expressed on UML model elements...

Multiple instances of a statechart reg

I have question . In the documentation elevator or stop watch statecharts are explained. What is the upper limit for statecharts , ex , how many elevators can i create or how many stop watches can i create ? I really like the idea of YAML , and all the features , My use case is more like - creating multiple state machines , each maintaining its own state and able to interact with these state machines also would like to retain the current state between crashes and restarts. For instance , i want to create 1k elevators or 10k elevators and interact with each elevator . Any suggestions?

Thanks

Move Story from "stories" to "interpreter.helpers"?

Stories are just list of events and pauses, and are currently mainly used as a convenience to send many events to an interpreter and to execute the interpreter after each event. As such, it seems more appropriate to move Story (and related functions, such as story_from_trace) to sismic.interpreter.helpers instead of sismic.stories.

This has a big of impact (on the code, on the tests, on the documentation, ...). It is also unclear where functions like random_stories_generator can be put (do we need to keep it? can we also put it in helpers?).

Restructure documentation

In the documentation, I would suggest to move out the part "Defining statecharts in Python" (from the "Defining statecharts" section), and move it to the "Advanced topics" section. It is not really the basic intended use of Sismic, so it fits more as advanced topic.
Before doing so, however, please integrate my previous pull request first, since it also makes changes to the "Defining statecharts" section...

A *todo* list of many "minor" changes (with big impact)

The main idea behind this quite huge refactoring is to separate the structure of a statechart from its content. The idea is to put the structural information of a statechart in a Statechart instance, and to make use of the other classes as data class.
This way, it will be a lot easier to construct and manipulate a statechart "in memory" (in contrast to its import from a YAML document).

These changes will help us to do statechart transformations and to implement a nice UI to create or edit statecharts.

Exceptions

Define a proper hierarchy of exceptions that are raised by Sismic (see #22 for the motivation).
Those exceptions will be available in sismic.exceptions:

  • A SismicError base exception at the top of the hierarchy.
  • A base InvalidStatechartError
  • A CodeEvaluationError (raised by a code.PythonEvaluator from any exception raised by exec or eval).
  • A base ExecutionErrorand that is extended by NonDeterminismError and ConflictingTransitionsError (both raised by Interpreter._sort_transitions)
  • A base ContractError (currently ConditionFailed) that is extended by InvariantError (currently InvariantFailedException), PreconditionError (currently PreconditionFailed) and Postcondition (currently PostconditionFailed).

Transitions

  • A Transition instance should not store an Event object, just its name.
  • The from_state and to_state of a transition should be made protected, and from_state and to_state properties should be made available.

Mixins

  • Make StateMixin.name protected and add a StateMixin.name property on it.
  • A CompositeStateMixin should not record its children. This information should be stored in a Statechart instance (as we currently do it for parent).
  • TransitionStateMixin should not store data about transitions, and should be a class whose purpose is only for type checking.
  • Add a RootState which inherits from ContractMixin, StateMixin, ActionStateMixin, CompositeStateMixin.

YAML

  • Add a context key on statechart element which has the semantic of the actual on entry.

Statechart

  • The Statechart class should not anymore inherit from any subclass of StateMixin. Instances of Statechart should be created with a root parameter which has to be a RootState (it is the only state that has no parent).
  • The constructor of a Statechart should accept an optional description parameter to be consistent with its YAML representation.

Statechart states

  • Add a state_for function that is a mapping from name to StateMixin instances.
  • Add a parent_for and a children_for methods that take a StateMixin or a name and returns StateMixin instances.
  • Add a children_for that accepts a StateMixin or a name and returns its children instances, if any.
  • Add a states property that returns a list of StateMixin.
  • Add an add_state which takes a StateMixin and a parent (name or StateMixin) parameter. It should ensures that a state with the same name does not exist (raises InvalidStatechartError), and that given parent accepts child states (raises InvalidStatechartError). If added state is an HistoryState, its parent must be a CompoundState (raises InvalidStatechartError, check C2).
  • A remove_state which takes a name or StateMixin and remove it. The removal can be done only if the state has no more children and no more (outgoing or incoming) transitions.

Statechart transitions

  • Use a transitions property that returns a list of Transition instances.
  • Add an add_transition which takes a Transition instance. The method checks that source state is a TransitionStateMixin and that target state exists.
  • Add transitions_from and transitions_to that take a StateMixin or a name and return a list of transitions.
  • Add a transitions_with that takes an event name or an Event instance and returns a list of transitions.
  • A remove_transition that takes a Transition instance and remove it.

Statechart utils

  • Adapt descendants_for, ancestors_for, leaf_for, depth_of (rename it depth_for to be consistent), least_common_ancestor, etc. such that these methods accept either a name or a StateMixin. These methods should return StateMixin instances.
  • Remove the @lru_cache or invalidate this cache when a change occurs in the statechart.

Statechart validation

  • Checks C1 to C6 should raise InvalidStatechartError with a code attribute reflecting the check that failed. Notice that C1 and C2 are already checked during construction.

IO

  • import_from_yaml and export_to_yaml must support the new YAML keys and the new exceptions hierarchy.

Interpreter

  • The configuration of an Interpreter instance now always contains the root state, except if it is in a final (ie. empty) configuration.
  • The configuration contains StateMixin instead of names.

Documentation

  • Adapt the documentation for the new YAML format (context key)
  • Adapt the examples (both in the documentation AND in its subdirectory examples)
  • Adapt the documentation for the "design by contract" (as there is no more a different behaviour for contracts of a statechart and contracts for a state. The "old" contracts for a statechart are now the "new" contracts for its root state).

(The list will be completed as soon as ideas come)

Changing the name

First I say this with the most respect. This is one of the best if not the best state machine library for python. The contract / behavior driven approach produces robust programs. It is however incredibly hard to find when searching on google. It doesn't even make the results with a simple "python statemachine" search. Search engines and keyboards want to auto-correct sismic to seismic. I really think more people would benefit from this library if it had a less cryptic name. I know your goal isn't recognition and you might not even care how many people use it. I just thought maybe you would consider a new name so that a larger portion of developers and beginners come across this library and benefit from it in the same way I have. Thanks for all the hard work in making this library!

Initial Update

Hi πŸ‘Š

This is my first visit to this fine repo, but it seems you have been working hard to keep all dependencies updated so far.

Once you have closed this issue, I'll create seperate pull requests for every update as soon as I find one.

That's it for now!

Happy merging! πŸ€–

Support type hinting from Python 3.5+

Python 3.5 introduces a new type hinting system that relies on parameter annotations (among other), see https://docs.python.org/3/library/typing.html

This kind of static typing is only useful for IDE (because Python does not make any asumption at runtime). While Sismic already uses annotations to declare variable types, this is done in a somewhat limited fashion and it could be very interesting to migrate from Python 3.4 to Python 3.5 to benefit from the new typing module.

JupyterLab Integration

This is for discussion of an idea to make an integration with JuypterLab (https://jupyterlab.readthedocs.io/en/stable/).

We currently run Sismic in a Docker environment, and would like to extend this further. One idea we are considering is to build an interactive editing and execution interface using JuypterLab. The Docker environment would provide the Interpreter and Code evaluators within the JupyterLab framework. Meanwhile, the Statecharts would be "remoted" to the JupyterLab Browser based GUI so that Statecharts can be developed and debugged in real-time.

How exactly to do this is unclear. Transparent Proxy's, Statechart's which can merge in updated/changed YAML, bindings to Javascript representations via a Websockets.

Allow the use of initial transition

In the SCXML specification the initial property can be a state or a transition. This allows for an action that might initialize specific contexts that a state might need. Could you add this feature or would you like me to look into adding it?

initial:
  - target: ready
    action: warmup()

Setting idle time after executing on entry code

With reference to the following code block:

def execute_on_entry(self, state: StateMixin) -> List[Event]:
     """
     Execute the on entry action for given state.
     This method is called for every state that is entered, even those with no *on_entry*.

     :param state: the considered state
     :return: a list of sent events
     """
     self._entry_time[state.name] = self._interpreter.time
     self._idle_time[state.name] = self._interpreter.time

     return self._execute_code(getattr(state, 'on_entry', None))

when the on_entry code takes some time both After(x) and Idle(x) in guard conditions operate from the same reference point. If the _idle_time were set after the on_entry code was executed then the Idle(x) time would provide a more useful measure of how long the state has been waiting since the on_entry code was executed - currently its not possible to achieve that.

For instance:

      self._entry_time[state.name] = self._interpreter.time
      foo = self._execute_code(getattr(state, 'on_entry', None))
      self._idle_time[state.name] = self._interpreter.time
      return foo

Possibly the same change is needed in execute_action() where again the idle time is set before executing the action code, which if that action code takes some time, the idle time is perhaps not correct (since it includes the time for executing the action).

Initial Update

Hi πŸ‘Š

This is my first visit to this fine repo, but it seems you have been working hard to keep all dependencies updated so far.

Once you have closed this issue, I'll create separate pull requests for every update as soon as I find one.

That's it for now!

Happy merging! πŸ€–

Possible confusion with *send* function

In the current version of Sismic, the send function is used in two different ways, which may cause confusion to users:

  • Within a statechart description, send can be used as an action to raise and send a new event. The syntax for this is, for example send('floorSelected', floor=4) if one wants to raise a parameterised event, or simply send('floorSelected') if it is a parameterless event.
  • Within a statechart Interpreter however, in order to send an event one has to use the following syntax: interpreter.send(Event('click’))

I understand why there is this difference, but it may nevertheless be confusing, especially because both functions are called send. To avoid this confusion, one could rename one of both sends. Here are 2 possibilities:

  • Use raise(...) instead of send(...) within the statechart descriptions, and keep send(...) within the statechart intepreter
  • Keep send() within the statechart descriptions, and use fire(...) or trigger(...) within the statechart interpreter.
  • other possibilities?
    I am not sure which renaming would be the most appropriate. Preferably one that is the closest to the SCXML syntax (for those SCXML users that would like to use our approach...)

Avoid using ``AssertionError`` in ``validate()``

The Statechart.validate() method currently raises an AssertionError if one of the provided check fails. There are two major improvements to be done:

  • Do not use AssertionError as this is clearly not an error related to an assertion, but more something like a StructuralError or MalformedStatechartError. It could be interesting to create a hierarchy of sismic's specific exceptions (including ConditionFailed, etc.).
  • The documentation enumerates the checks that are done using C1., C2., etc. Add this code as an attribute of the raised exception so an automatic handling can be done according to the check that failed.

As a complement (and somewhat related to #21), a validate module could be created with several checks (including structural errors, semantic errors, style warnings, etc.).

Alternative to pykwalify

Hi,

I noticed on the kwalify issue tracker that you had the exact same problem as me (check the other issues).

FYI that nasty experience, among other issues with kwalify and YAML, made me write this alternative: https://github.com/crdoconnor/strictyaml

It's still something of a work in progress (I'll be adding kwalify support soon, for instance), but it's working. Any comments appreciated.

story generator based on mutation

Story generator based on mutation testing is now working. However, the mutation operators are very simple for now, so the stories that are being generated are not that good. I will focus my efforts on developing all Fabbri mutation operators.

There's a slight issue in the way of completely automating the process:

We still need an item list to be submitted to the story generator. So far I used "events_for()" method to get all possible events. but this is not always working, because events usually need additional parameters (for example floor, in case of floorSelecting event). I'm still unclear how we can make this part automatic as well without some form of python parser. Maybe it is a good idea to introduce a DSL instead of python code, so that this part can be automated as well.

Signal-based hooks

(Discussion introduced in #72)

Another thing that I would like to change is the way we defined hooks and "notifications". Basically, in the current implementation, we have many direct hooks (like the many methods of PythonEvaluator that are called by the interpreter at specific points), "indirect hooks" (like the meta-events to support property statecharts) and "observable objects" (like the clock, the event queue, the trace, etc.). I would like to have a more uniform approach to deal with all these "hooks", and I'm currently looking into a signal-based communication between components (e.g. the interpreter defines signals like before execute, before step, after execute*, on state entered, on consumed event, etc., and other components can subscribe to those signals and attach callbacks to them). This will greatly simplify many parts of the current implementation, but will also contain a lot of breaking changes, e.g.:

  • Property statecharts could be implemented as a subclass of Interpreter, with an additional method listen(other_interpreter) that subscribes and reacts to these signals. As such, an observed interpreter won't know it's currently observed (which is something one can expect. In the current implement, the observed interpreter "attaches" property statecharts);
  • Bound callables could subscribe to the event sent signal. Similarly, the binding process will be inverted: a statechart will "listen" to another statechart, instead of binding a "listening statechart" to the current interpreter;
  • Clock could generates a time changed signal so that a ClockBasedRunner could listen to a clock and executes the statechart accordingly.
  • A debugger will simply listen to (nearly all) signals;
  • Event-based runner could subscribe to the event queued signal to jump to the next event;
  • An code evaluator won't have to implement such a complex interface (execute_on_entry and execute_on_exit were introduced only because we needed to be notified when a state is entered or exited);
    ...

Given the breaking nature of these changes, I'll reserve them for Sismic 2.0.0

Branch specs - get specifications from statechart

This branch implements some support to automatically get some information from the Python code contained in a statechart, such as the events that can be sent, the attributes that are accessed in the code, the type of the variables, and so on.

Persisting / restoring interpreter state

Hi,

I'm looking for a mechanism to persist / restore interpreter state.

My current approach is to persist Interpreter._configuration to database. To restore it I instantiate Interpreter wit a restored initial context, then set _configuration obtained from database. Of course, persisting _memory would be needed too if using history states.

Obviously, I'm using an non public API by accessing/restoring Interpreter._configuration directly.

This worked well until 1.3. It breaks with sismic 1.4 because of the TimedContextEvaluator which has it's own copy of the states _configuration. Since I don't restore it, it starts with an empty _configuration and it breaks when exiting state at

self._configuration.remove(event.state)
.

Pickle is not an option for us for many reasons, mostly because it does not lend itself to data migration (if we evolve the state machine, it is possible to update _configuration during data migration, while updating a pickle is not practical).

So I'd like to discuss if pausing a state machine by persisting it to database makes sense as a use case for Sismic? If yes, what could be a stable API for persisting/restoring interpreter state?

New exceptions hierarchy

Define a proper hierarchy of exceptions that are raised by Sismic (see #22 for the motivation).

Those exceptions will be available in sismic.exceptions:

  • A SismicError base exception at the top of the hierarchy.
  • A base InvalidStatechart (raised by Statechart.validate() and during the construction of a statechart).
  • A CodeEvaluationError (raised by a code.PythonEvaluator from any exception raised by exec or eval).
  • A base InterpreterExecutionErrorand that is extended by NonDeterministicChoice and ConflictingTransitions (both raised by Interpreter._sort_transitions)
  • A base ContractError (currently ConditionFailed) that inherits from InterpreterError (currently AssertionError) and that is extended by UnsatisfiedInvariant (currently InvariantFailedException), UnsatisfiedPrecondition (currently PreconditionFailed) and UnsatisfiedPostcondition (currently PostconditionFailed).

Provide a simple Python example, with GUI, using a sismic interpreter as backend

To illustrate the use of sismic, I would suggest to add (in the docs, or as a tutorial) something similar in spirit to what can be found here for SCXML:
https://commons.apache.org/proper/commons-scxml/usecases/scxml-stopwatch.html

The idea is to show a very simple example of a GUI in Python (with some button that trigger events), where the "backend" is basically simply a statechart that is being interpreted dynamically each time one of the buttons is pressed. (It does not have to be the stopwatch example, it can be any other example, as long as it is simple and illustrative.)

Such an example will illustrate to potential users how seismic can be integrated directly in user code, if desired. (Of course, in this example we should also add, as usual, the necessary contracts, and we could also write the necessary tests for it.)

Proper error message when using Python <3.4

When using Sismic on Python 2.7, a syntax error is raised due to the lack of support for annotations in Python 2.7. This could/should be replaced with an appropriate error message (via Exception) saying that this version is not supported by Sismic.

Duplicate transitions after copying from another statechart

The Statechart class method copy_from_statechart(...) in the module model.statechart adds all transitions between copied states twice.

target statechart - state active to be replaced:

target

source statechart - (root) state active to be copied:

source

result of copy_from_statechart(...):

result

I will send a pull request with a solution.

Kind regards,
Jan Wouter Versluis

Support for coverage metrics

Regardless of how a statechart is being executed, it would be useful to have support for coverage metrics in Sismic. This metrics should report: the number and percentage of states that were active at some point during the execution; the number and percentage of transitions that were active at some point during the execution. These metrics could also be extended with profiling-like metrics, to make it easier to find possible "bottlenecks" in the statechart: the number of distinct times any given state (or transition) has become active during the execution; the total time (and percentage of time) a state has been active during the execution.

Different ways of executing the statechart that should support coverage metrics are:

  • direct execution of the statechart in interactive mode (e.g. through a GUI)
  • batch execution by giving the statechart one or more scenarios to be executed
  • during testing by giving as input a number of statechart unit tests (i.e. stories containing one or more assertions)
  • during testing based on a BDD feature description
  • others?

Function ``story_from_trace`` should ignore internal events

Function story_from_trace currently builts a story based on a given interpreter trace.
If the statechart sends an internal event, this event is added to the trace and thus generates a new step in the resulting story.

This could be problematic as it may duplicate some events.
Consider a statechart whose context is x = 1 and which has a transition with event: A and action: send('B') and another transition with event: B and action: x += 1.

  • Base story: send A.
  • Events in the resulting trace: A then B
  • Value of x: 1

A call to story_from_trace will generates a story A then B.

  • Executed story: A then B.
  • Events in the resulting trace: A then B then B
  • Value of x: 2

One approach to solve this is to tag an event either as "Internal" or "External" and to ignore "Internal" in story_from_trace. But this change has many implications:

  • The Event class should accept an additional parameter internal and exposes a read-only property internal. This can be problematic, as it may shallow some event parameter. Another possibility is to define a subclass of Event, namely InternalEvent to make the distinction between internal and external ones.
  • Events that are sent by a code evaluator should be tagged as internal.
  • Interpreter.queue should not accept anymore an internal parameter, as this information will be contained in the received Event instance.
  • When propagating internal event, a new event should be created with the same name and the same content (but not tagged as external).
  • Documentation should be adapted.

Refactor of Bind mechanism to introduce concept of Bind_Interface

I'm trying to reconcile the recent changes to Bind(), along with my Adapter class for Distributed Statecharts, and the previously mentioned idea of creating a Proxy for the existing Bind Mechanism. Out of this analysis came a few ideas, which when combined, change the nature of the Bind Mechanism.

This is a further extension of the recent changes with an intention to create a flexible and stable interface. What I would really like to do is make the concept of Binding two Statecharts generic and have the parameters of the Bind() determine how the Bind is realised. Possibly also, the Bind() could be delegated to a Class- i.e. bind this Statechart to the Interpreter using this Bind_Class.

This is no different to the latest implementation, just further along.

What I would like to suggest is to turn the Bind Mechanism into something which represents a more generic subscription model. An Object, which implements the abstract Bind_Interface(), is able to be bound to an Interpreter, and in the process subscribes to the various meta-data-interfaces. The subscription can either be manually specified within the call to Bind(), or, specified by a Helper Class which implements the Bind_Interface and provides the predefined set of Subscriptions.

As a short conceptual example:

class BindInterface():
    subscribes = []
    execute():
        pass
    @property
    final():
       return foo
    queue():
        pass
    
class PropertyBind(BindInterface):
    subscribes = ['Meta', 'Execute']
   # and so on ...

class LocalBind(BindInterface):
    subscribes = ['Internal']
   # and so on ...
 
it.bind(LocalBind(some_other_chart))
it.bind(some_other_chart_interpreter) #if the Interpreter class inherits LocalBind (by default), then this works too!
it.bind(RemoteBind(some_other_chart)) # the Remote bind should override the LocalBind IIRC
it.bind(PropertyBind(import_from_yaml('foo')) # simple Propertychart

There is more to it that that πŸ˜‰ however at least that was one area which I can explain at least a bit. Much of the thinking behind this is that a bound Statechart and bound Property Statechart are actually the same thing, and so, by making the interface more generic, we get the chance to introduce new kinds of Binds ... which could be very interesting.

Further along, the actual implementation of the Bind (sending events, calling execute) could also be pushed into the HelperClass, allowing for even more possibilities. Then, the Interpreter need only call a method on each Bound Statechart, and have the Helper do the actual work. That might be the point where a remote Statechart could be bound ... i.e. where the transport/connectivity gets implemented.

In my distributed case, I might have:

it.bind(RedisBind(import_from_yaml('remote_foo'))
it.bind(PropertyBind(RedisBind(import_from_yaml('remote_foo'))) # perhaps even that will work, remote Property charts ...

I think it will be easier to implement than explain ... πŸ˜„ ... assuming things remain calm, I hope to spend some time this week on the concept. Again, there are several drivers here; distributed Statecharts, more generic and flexible bind() interface, and also looking at additional language support.

Post the article fulltext on Arxiv

I really like your repo, and I'd love to read your paper, but I would not love to pay Springer $40 for the pleasure. Can you post on Arxiv and reroute the link?

Obtaining statechart coverage information from a trace

Sismic currently proposes basic coverage data when scenarios are executed using sismic-behave.
As coverage is not tightly related to behavior-driven development, it could be interested to add a generic way to get coverage information.

For example, this could be related to a told Story, or could be directly computed from a trace (which allows to compute the set of visited states, but not the proportion of visited states, unless we have access to the statechart).

initial state change

It would be nice to have a method that can change the initial state of a statechart/ anything with a compositemixin.
I can change it myself from inside mutator, but I think this functionality is better suited for the model module, like the rest of the manipulator methods.

Join pseudostate

HI,

First of all, congratulations and many thanks for this excellent library.

I was wondering how to implement a join pseudostate? I did not find native support for it in Sismic, and I could not imagine a clean way to emulate it so far (perhaps there is one?).

Fork pseudo states are less of an issue as in most use cases we always use the same initial entry point in parallel states.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.