using System.Collections.Generic;
using System.Text;
using Microsoft.Modeling;
namespace ABP
{
public static class ABPclass
{
// State
static bool initializing = true;
static bool bit1 = false; // true when bit is 1, 0 to start 1st msg
static bool inFlight = false; // true when sending x, but no ack x yet
static bool SendEnabled(bool bit)
{
return (initializing
|| !initializing && bit == bit1);
}
[Action("Send(_, bit)")]
static void Send(bool bit)
{
Contracts.Requires(SendEnabled(bit));
if (!bit) initializing = false; // send bit 0 to leave initial state
if (!initializing) inFlight = true;
}
static bool AckEnabled(bool bit)
{
return (bit && initializing // initialy ack 1
|| bit && !initializing && inFlight
|| bit && !initializing && !inFlight && !bit1
|| !bit && !initializing && inFlight
|| !bit && !initializing && !inFlight && bit1);
}
[Action]
static void Ack(bool bit)
{
Contracts.Requires(AckEnabled(bit));
if (!initializing && bit == bit1)
{
bit1 = !bit1;
inFlight = false;
}
}
[AcceptingStateCondition]
static bool AcceptingState() { return (initializing || !inFlight); }
}
}
S0:initializing=true,bit1=false,inFlight=false
S4:initializing=false,bit1=false,inFlight=true
S10:initializing=false,bit1=true,inFlight=false
S14:initializing=false,bit1=true,inFlight=true
S19:initializing=false,bit1=false,inFlight=false
In addtion, these states are genelated automatically by Spec Explorer.
The key variable is inFlight which shows if the messege is flying(sending).
4.The [AcceptingStateCondition] indicates the states allowed.
The traces which are not ended with those state are not accepted.
5.[Action] indicates the action methods.
Each action method must express how the action changes the state (or leaves it unchanged). Usually, the body of an action method computes the next state from the current state, by assigning one or more state variables.
config Actions
{
// concrete actions so !?! composition works
action static void ABPImpl.Send(string msg, bool bit);
action static void ABPImpl.Ack(bool bit);
switch graphtimeout = 0;
}
main machine ABPContract(): Actions
{
construct model program from Actions where namespace = "ABP"
}
machine AllowedScenario(): Actions
{
Send(_,true);
Ack(true);
Send(_, false);
Ack(false);
Send(_, true);
Ack(true);
}
machine CheckAllowedScenario(): Actions
{
AllowedScenario || ABPContract;
}
machine ForbiddenScenario(): Actions
{
Send(_,true);
Ack(true);
Send(_, false);
Ack(false);
Send(_, false); // FORBIDDEN! Must send true after Ack(false)
Ack(true);
}
machine CheckForbiddenScenario(): Actions
{
ForbiddenScenario || ABPContract;
}
machine MessageScenario(): Actions
{
Send("Initializing",true);
Ack(true);
Send("Message1", false);
Ack(false);
Send("Message2", true);
Ack(true);
}
machine CheckMessageScenario(): Actions
{
MessageScenario || ABPContract;
}
config SendAction
{
action static void ABPImpl.Send(string msg, bool bit);
switch graphtimeout = 0;
}
machine MessageOnlyScenario(): SendAction
{
Send("Initializing", true);
Send("Message1", false);
Send("Message2", true);
}
machine CheckMessageOnlyScenario(): Actions
{
MessageOnlyScenario || ABPContract;
}
// Concrete actions are needed for this!
machine CheckMessageInterleaveScenario(): Actions
{
MessageOnlyScenario |?| ABPContract;
}
machine MessageResendScenario(): SendAction
{
Send("Initializing", true)+; // + means one or more
Send("Message1", false)+;
Send("Message2", true)+;
}
machine CheckMessageResendScenario(): Actions
{
MessageResendScenario |?| ABPContract;
}
actions must be declared before use.
2.machine: block describes behaviors
construct model program from Actions where namespace = "ABP"
Contract model program describes all allowed traces
machine AllowedScenario(): Actions
Scenario machine describes particular traces of interest (perhaps just one)
3.|| and |?|
Combines two (or more) machines. Combines can form composition of contract model program with scenario machine, the result is intersection of traces.
And combines can also checks whether contract model program can execute scenario (when intersection includes the entire scenario)
using System.Collections.Generic;
using System.Text;
using Microsoft.Modeling;
namespace CEP1Model
{
///<summary>
/// An example model program.
///</summary>
static class ModelProgram
{
static Set<int> idsUsed = new Set<int>();
static Set<int> pendingARequests = new Set<int>();
static Set<int> pendingBRequests = new Set<int>();
static bool isFinished = false;
static Set<int> pendingCancellations = new Set<int>();
static Set<int> completedCancellations = new Set<int>();
static int creditLimit = 0;
static int creditUsage = 0;
static Map<int, int> creditRequests = new Map<int, int>();
static bool RequestPossible(int x, int creditRequest)
{
return (0 <= x && x <= creditLimit &&
creditRequest >= 0 &&
((x == creditLimit || x == creditUsage) ? creditRequest > 0 : true));
}
static bool GrantPossible(int x, int creditGrant)
{
return creditGrant >= 0 &&
creditRequests.ContainsKey(x) &&
creditRequests[x] >= creditGrant &&
(creditUsage == creditLimit ? creditGrant > 0 : true);
}
static void UpdateCreditUsage(int x)
{
creditUsage = Math.Max(x, creditUsage);
}
static void UpdateCreditLimit(int creditGrant)
{
creditLimit += creditGrant;
}
[Action("ARequest(x, creditRequest)")]
static void ARequest(int x, int creditRequest)
{
Contracts.Requires(x >= 0 && !idsUsed.Contains(x));
Contracts.Requires(!isFinished);
Contracts.Requires(RequestPossible(x, creditRequest));
pendingARequests = pendingARequests.Add(x);
idsUsed = idsUsed.Add(x);
creditRequests = creditRequests.Add(x, creditRequest);
UpdateCreditUsage(x);
}
[Action("AResponse(x, creditGrant)")]
static void AResponse(int x, int creditGrant)
{
Contracts.Requires(pendingARequests.Contains(x));
Contracts.Requires(!isFinished);
Contracts.Requires(GrantPossible(x, creditGrant));
pendingARequests = pendingARequests.Remove(x);
pendingCancellations = pendingCancellations.Remove(x);
UpdateCreditLimit(creditGrant);
}
[Action("BRequest(x, creditRequest)")]
static void BRequest(int x, int creditRequest)
{
Contracts.Requires(x >= 0 && !idsUsed.Contains(x));
Contracts.Requires(!isFinished);
Contracts.Requires(RequestPossible(x, creditRequest));
pendingBRequests = pendingBRequests.Add(x);
idsUsed = idsUsed.Add(x);
creditRequests = creditRequests.Add(x, creditRequest);
UpdateCreditUsage(x);
}
[Action("BResponse(x, creditGrant)")]
static void BResponse(int x, int creditGrant)
{
Contracts.Requires(pendingBRequests.Contains(x));
Contracts.Requires(!isFinished);
Contracts.Requires(GrantPossible(x, creditGrant));
pendingBRequests = pendingBRequests.Remove(x);
pendingCancellations = pendingCancellations.Remove(x);
UpdateCreditLimit(creditGrant);
}
[Action("Cancel(x)")]
static void Cancel(int x)
{
Contracts.Requires(idsUsed.Contains(x));
Contracts.Requires(!pendingCancellations.Contains(x));
Contracts.Requires(!completedCancellations.Contains(x));
Contracts.Requires(!isFinished);
pendingCancellations = pendingCancellations.Add(x);
}
[Action("CancelCompleted(x, creditGrant)")]
static void CancelCompleted(int x, int creditGrant)
{
Contracts.Requires(pendingCancellations.Contains(x));
Contracts.Requires(!isFinished);
Contracts.Requires(GrantPossible(x, creditGrant));
pendingCancellations = pendingCancellations.Remove(x);
completedCancellations = completedCancellations.Add(x);
pendingARequests = pendingARequests.Remove(x);
pendingBRequests = pendingBRequests.Remove(x);
UpdateCreditLimit(creditGrant);
}
[Action("Finish(x, creditRequest)")]
static void Finish(int x, int creditRequest)
{
Contracts.Requires(x >= 0 && !idsUsed.Contains(x));
Contracts.Requires(!isFinished);
Contracts.Requires(RequestPossible(x, creditRequest));
isFinished = true;
}
[AcceptingStateCondition]
public static bool NoPendingRequests()
{
return (pendingARequests.Count == 0 &&
pendingBRequests.Count == 0);
}
[AcceptingStateCondition]
public static bool IsFinished()
{
return isFinished;
}
}
}
// Here you define configurations and machines describing the
// exploration task you want to perform.
using CEP1Implementation;
/// Contains actions of the model, bounds, and switches.
config Actions
{
action abstract static void Implementation.ARequest(int x, int creditRequest);
action abstract static void Implementation.AResponse(int x, int creditGrant);
action abstract static void Implementation.BRequest(int x, int creditRequest);
action abstract static void Implementation.BResponse(int x, int creditGrant);
action abstract static void Implementation.Cancel(int x);
action abstract static void Implementation.CancelCompleted(int x, int creditGrant);
action abstract static void Implementation.Finish(int x, int creditRequest);
bound steps = 128;
bound pathdepth = 128;
switch graphtimeout = 0;
}
/// Constructs a machine from the model program.
/// Since the model is not finite, this machine explodes
/// and exploration is stopped by a bound.
machine CEP2() : Actions
{
construct model program from Actions where namespace = "CEP1Model"
}
machine Trace1() : Actions
{
BRequest(0, 1);
BResponse(0, 1);
Cancel(0);
ARequest(1, 2);
AResponse(1, 2);
ARequest(3, 2);
Cancel(1);
AResponse(3, 1);
BRequest(4, 2);
BResponse(4, 0);
Finish(2, 2)
}
machine Trace1AndContract() : Actions
{
Trace1() || CEP2()
}