Spec Explorer

来源:互联网 发布:云教学平台 - 为您优化 编辑:程序博客网 时间:2024/05/04 04:32
The training course of “Introduction to Protocol Modeling” held May 11, 2007 at the Microsoft ATC by Colin Campbell was finished this weekend. It is quiet a good experience to join such a class, the teacher is kind and talkative and the training content is helpful. I shall write a memo of this training for further usage.
Our first task is learning to use Spec Explorer. Spec Explorer is a software-development tool for advanced model-based specification and conformance testing. Spec Explorer can help software-development teams detect errors in the design, the specification, and the implementation of their systems. Using Spec Explorer we can:
We install some packages provided by Microsoft as follows: the plug-in Spec Explorer work together with visual studio 2005 and so on (I can’t remember exactly the file names in the list which is in http://sharepoint/sites/pt3/specexplorer, and I googled and got some links which might helpful: http://research.microsoft.com/specexplorer/)
After the installation we can use Spec Explorer to write models and we were fist given an example of Alternating Bit Protocol. (http://en.wikipedia.org/wiki/Alternating_bit_protocol)
 
using System; 
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); } 
    }
 
}
 
Now let me tell my own understanding of the code.
1. using Microsoft.Modeling;
We using Contracts.Requires(bool) later and it is in the namespace Microsoft.Modeling. If the  function parameter is not true, it will throw an exception so with this line get those conditions meet the requirements.
2. There are only three bool variables represent the state, so it is a finite model.
It is proved by Spec Explorer that there are 5 states as follows.
3.We can read the code better with the help of the picture displayed above.
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.
using ABP; 
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; 
}
 
 
Follows are my own understanding of the code.
1.config: block declares actions
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) 
 
1.This is the design mode of the code.
2.Double click the name of the machine or click the Explorer, the FSM is displayed in the exploration window.
3.The state window shows the state of all variables.
 
using System; 
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<intint> creditRequests = new Map<intint>(); 
        
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; 
        }
 
    }
 
}
 
1.This is a Infinite State Machine Example with Set<int> as variable.

// This is a Spec Explorer coordination script (Cord version 1.0). 
// 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(
01); 
   BResponse(
01); 
   Cancel(
0); 
   ARequest(
12); 
   AResponse(
12); 
   ARequest(
32); 
   Cancel(
1); 
   AResponse(
31); 
   BRequest(
42); 
   BResponse(
40); 
   Finish(
22
}
 
machine Trace1AndContract() : Actions 

   Trace1() 
|| CEP2() 
}
 
1.bound steps and pathdepth are usually used in infinite machines.
原创粉丝点击