Skip to content

A module for experimenting with new stuff, things we think might be cool to try out, but not reelly considered as production ready.

Notifications You must be signed in to change notification settings

GraphWalker/graphwalker-labs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

14 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The FsmFactory is inspired by the NModel project from Microsoft Research, https://nmodel.codeplex.com/, which later developed into the SpecExplorer. FsmFactory does only one thing: It creates a finite state chart from a class using the @Transition annotation.

The concept is:

  • a class implements Serializable.
  • Annotates methods that represents transitions using the @Transition. A transition is when some state changes. Some properties are changing values.
  • In a stateful system, transitions are only allowed under certain circumstances. This is done by accompanying guard methods to the transition method. They share the same method name, except that the guard has a the word On prefixed to the name.

Consider following code: (See also book Model-based Software Testing and Analysis with C#, the example with Client and Server. http://www.cambridge.org/se/academic/subjects/computer-science/software-engineering-and-development/model-based-software-testing-and-analysis-c?format=PB)

        FsmFactory factory = new FsmFactory();
        Model model = factory.create(new ClientServer());
        System.out.println(DotFileFactory.createDot(model));

and where the ClientServer class looks like:

public class ClientServer implements Serializable {

    public enum Socket { None, Created, Bound, Listening, Connecting,
        Connected, Disconnected, Closed }

    public enum Phase { Send, ServerReceive, ClientReceive }

    // Control state
    public Socket serverSocket = Socket.None;
    public Socket clientSocket = Socket.None;
    public Phase phase = Phase.Send;

    // Server enabling conditions and actions
    public boolean OnServerSocket() {
        return (serverSocket == Socket.None);
    }

    @Transition
    public void ServerSocket() {
        serverSocket = Socket.Created;
    }

    public boolean OnServerBind() {
        return (serverSocket == Socket.Created);
    }

    @Transition
    public void ServerBind()
    {
        serverSocket = Socket.Bound;
    }

    public boolean OnServerListen()
    {
        return (serverSocket == Socket.Bound);
    }

    @Transition
    public void ServerListen()
    {
        serverSocket = Socket.Listening;
    }

    public boolean OnServerAccept()
    {
        return (serverSocket == Socket.Listening
            && clientSocket == Socket.Connecting);
    }

    @Transition
    public void ServerAccept()
    {
        serverSocket = Socket.Connected; clientSocket = Socket.Connected;
    }

    public boolean OnServerReceive()
    {
        return (serverSocket == Socket.Connected
            && phase == Phase.ServerReceive);
    }


    // No parameter needed here, client always sends same thing
    @Transition
    public void ServerReceive()
    {
        phase = Phase.Send;
    }

    public boolean OnServerSend()
    {
        return (serverSocket == Socket.Connected
            && phase == Phase.Send
            && clientSocket == Socket.Connected);
    }

    // Parameter here, server can send different temperatures
    @Transition
    public void ServerSend()
    {
        phase = Phase.ClientReceive;
    }

    public boolean OnServerCloseConnection()
    {
        return (serverSocket == Socket.Connected);
    }

    @Transition
    public void ServerCloseConnection()
    {
        serverSocket = Socket.Disconnected;
    }

    // Prevent Client crashing - does sending to closed partner crash?
    public boolean OnServerClose()
    {
        return (serverSocket != Socket.None
            // && serverSocket != Socket.Listening
            && serverSocket != Socket.Connected
            && serverSocket != Socket.Closed);
    }

    @Transition
    public void ServerClose()
    {
        serverSocket = Socket.Closed;
    }

    // Client enabling conditions and actions

    public boolean OnClientSocket()
    {
        return (clientSocket == Socket.None);
    }

    @Transition
    public void ClientSocket()
    {
        clientSocket = Socket.Created;
    }

    public boolean OnClientConnect()
    {
        return (clientSocket == Socket.Created
            && serverSocket == Socket.Listening);
    }

    @Transition
    public void ClientConnect()
    {
        clientSocket = Socket.Connecting;
    }

    public boolean OnClientSend()
    {
        return (clientSocket == Socket.Connected
            && phase == Phase.Send);
    }

    // No parameter needed here, client always sends the same thing
    @Transition
    public void ClientSend()
    {
        phase = Phase.ServerReceive;
    }

    public boolean OnClientReceive()
    {
        return (clientSocket == Socket.Connected
            && phase == Phase.ClientReceive);
    }

    // Return value needed here, server sends different values
    @Transition
    public void ClientReceive()
    {
        phase = Phase.Send;
    }

    public boolean OnClientClose()
    {
        return (clientSocket == Socket.Connected
            && phase == Phase.Send);
    }

    @Transition
    public void ClientClose() {
        clientSocket = Socket.Closed;
    }
}

The FsmFactory will create a state chart, when written and visialized by graphviz and dot, will look like: (using dot -Tsvg clientserver.dot > login.svg) Alt text

About

A module for experimenting with new stuff, things we think might be cool to try out, but not reelly considered as production ready.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published