A Model-driven Methodology for Generating and Verifying CSP-based Java Code
Julio Mari˜ no 1 Ra´ ul N.N. Alborodo 2
1 Universidad Polit´
ecnica de Madrid Babel research group julio.marino@upm.es
2 IMDEA Software Institute
raul.alborodo@imdea.org
A Model-driven Methodology for Generating and Verifying CSP-based - - PowerPoint PPT Presentation
A Model-driven Methodology for Generating and Verifying CSP-based Java Code no 1 ul N.N. Alborodo 2 Julio Mari Ra 1 Universidad Polit 2 IMDEA Software Institute ecnica de Madrid Babel research group raul.alborodo@imdea.org
1 Universidad Polit´
ecnica de Madrid Babel research group julio.marino@upm.es
2 IMDEA Software Institute
raul.alborodo@imdea.org
the paper in a nutshell
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 2 / 31
workflows
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 3 / 31
why adding may be necessary for simplifying things
1
2
3
4
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 4 / 31
what is so relevant that deserves to be modeled
P1 P2 P3 R1 Op1 Op2 P4 P5 P6 Op1 R2 Op2 P7
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 5 / 31
readers & writers
BR AR BW AW
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 6 / 31
readers & writers
CADT ReadersWriters OPERATIONS ACTION BeforeRead;AfterRead;BeforeWrite;AfterWrite: SEMANTICS DOMAIN: STATE: (readers : N × writers : N) INVT: (readers > 0 ⇒ writers = 0) ∧
INITIAL: writers = 0 ∧ readers = 0 CPRE: writers = 0 ∧ readers = 0 BeforeWrite POST: writers = 1 PRE: writers = 1 CPRE: true AfterWrite POST: writers = 0 CPRE: writers = 0 BeforeRead POST: readers = 1 + readersin PRE: readers > 0 CPRE: true AfterRead POST: readers = readersin − 1
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 7 / 31
readers & writers
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 8 / 31
applying all of this to developing concurrent Java SW
SPECS
SR(s)
SR (JML interface)
.tla
KeY JML-annotated Java classfiles
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 9 / 31
a textual, convenient and ready-to-compile representation
1
2 3
4
5
6 7
8
9
10
11
12 13
14 15
16
17
18
19
20
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 10 / 31
a textual, convenient and ready-to-compile representation
1
2
3
4
5
6 7
8
9
10
11
12
13 14
15
16
17
18
19
20
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 11 / 31
client-server + RPC + . . .
OP1 OP2
P2 P3 P1 Wrapper
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 12 / 31
client-server + RPC + . . .
OP1 OP2
P2 P3 P1 Wrapper
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 13 / 31
the devil is in the CPREs
◮ channel replication: Instantiate CPREs with all their possible values, take classes modulo logical
equivalence, then assign a channel to each class. Enable channels according to each CPRE.
◮ deferred requests: one (always open) channel per operation, requests are stored in the server
until CPRE holds.
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 14 / 31
multibuffer
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 15 / 31
multibuffer
CPREput(2) CPREput(1) CPREget(1) CPREget(2)
Server Code
PUT GET
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 16 / 31
multibuffer
Server Code
PUT(obj) GET(n)
2 <= MAX − nData 1 <= MAX − nData 1 <= nData 2 <= nData
1 2 3
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 17 / 31
CPRE depends on some operation parameters x (Dx potentially infinite)
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 18 / 31
multibuffer
Server Code
PUT GET
putRequests getRequests
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 19 / 31
wrapper
1
2
3
4
5
1
2
3
4
5
6
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 20 / 31
proof obligations
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 21 / 31
prop cs preservation
int chosenService = 42; int[] services = {. . .}; boolean[] syncCond = new boolean[#rg(pe)]; while (chosenService != -1 ){
. . .
update syncCond array /*@ assert (\forall int j; @ 0<=j && j<syncCond.length; @ syncCond[j] == CPREi ); @*/ chosenService = fairSelect(syncCond,services); switch(chosenService){
. . .
case METHODl : //@ assert CPREl (chosenService);
. . .
break;
. . .
} } }
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 22 / 31
prop cs preservation
int chosenService = 42; int[] services = {. . .}; boolean[] syncCond = new boolean[#rg(pe)]; while (chosenService != -1 ){
. . .
update syncCond array /*@ assert (\forall int j; @ 0<=j && j<syncCond.length; @ syncCond[j] == CPREi ); @*/ chosenService = fairSelect(syncCond,services); switch(chosenService){
. . .
case METHODl : //@ assert CPREl (chosenService);
. . .
break;
. . .
} } }
public boolean cprePreservation; public boolean oneMessageProcessed;
. . .
//@ ensures cprePreservation; public void run(){
. . .
cprePreservation = true; int chosenService = 42; while (chosenService != -1){ chosenService = fairSelect(syncCond,services); switch(chosenService){
. . .
case METHODl : cprePreservation &= CPREl (chosenService);
. . .
break;
. . .
} } }
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 22 / 31
prop safe selection
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 23 / 31
prop safe selection
public void run(){ int chosenService = 42; int[] services = {. . .}; boolean[] syncCond = new boolean[#rg(pe)]; while (chosenService != -1 ){
. . .
update syncCond array /*@ assert (\forall int j; @ 0<=j && j<syncCond.length; @ syncCond[j] == CPREi ); @*/ chosenService = fairSelect(syncCond,services);
. . .
process a request onchosenService } }
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 24 / 31
prop safe selection
public void run(){ int chosenService = 42; int[] services = {. . .}; boolean[] syncCond = new boolean[#rg(pe)]; while (chosenService != -1 ){
. . .
update syncCond array /*@ assert (\forall int j; @ 0<=j && j<syncCond.length; @ syncCond[j] == CPREi ); @*/ chosenService = fairSelect(syncCond,services);
. . .
process a request onchosenService } }
//@ ensures wellFormedSyncCond; public void run(){ wellFormedSyncCond = true; int[] services = {. . .}; boolean[] syncCond = new boolean[#rg(pe)]; int chosenService = 42; while (chosenService != -1 ) {
. . .
update syncCond array for (int i =0 ; i < syncCond.length ; i++ ) { wellFormedSyncCond &= (syncCond[i] == CPREi ); } wellFormedSyncCond &= syncCond.length == guards.length; chosenService = JCSPKeY.fairSelect(syncCond, guards);
. . .
process a request onchosenService } }
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 24 / 31
prop safe selection
public void run(){ int chosenService = 42; int[] services = {. . .}; boolean[] syncCond = new boolean[#rg(pe)]; while (chosenService != -1 ){
. . .
update syncCond array /*@ assert (\forall int j; @ 0<=j && j<syncCond.length; @ syncCond[j] == CPREi ); @*/ chosenService = fairSelect(syncCond,services);
. . .
process a request onchosenService } }
//@ ensures wellFormedSyncCond; public void run(){ wellFormedSyncCond = true; int[] services = {. . .}; boolean[] syncCond = new boolean[#rg(pe)]; int chosenService = 42; while (chosenService != -1 ) {
. . .
update syncCond array for (int i =0 ; i < syncCond.length ; i++ ) { wellFormedSyncCond &= (syncCond[i] == CPREi ); } wellFormedSyncCond &= syncCond.length == guards.length; chosenService = JCSPKeY.fairSelect(syncCond, guards);
. . .
process a request onchosenService } }
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 24 / 31
prop only one request
public void run(){ int chosenService = 42; int[] services = {. . .}; boolean[] syncCond = new boolean[#rg(pe)]; while (chosenService != -1 ){
. . .
update syncCond array chosenService = fairSelect(syncCond,services); switch(chosenService){
. . .
case METHODl : //@ assert CPREl (chosenService);
. . .
break;
. . .
} } }
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 25 / 31
prop only one request
public void run(){ int chosenService = 42; int[] services = {. . .}; boolean[] syncCond = new boolean[#rg(pe)]; while (chosenService != -1 ){
. . .
update syncCond array chosenService = fairSelect(syncCond,services); switch(chosenService){
. . .
case METHODl : //@ assert CPREl (chosenService);
. . .
break;
. . .
} } }
public boolean oneMessageProcessed;
. . .
//@ ensures oneMessageProcessed; public void run(){
. . .
int chosenService = 42; while (chosenService != -1){ int processedMessages = 0;
. . .
update syncCond array chosenService = fairSelect(syncCond,services); switch(chosenService){
. . .
case METHODl :
. . .
processedMessages ++; break;
. . .
}
} }
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 25 / 31
prop only one request
public void run(){ int chosenService = 42; int[] services = {. . .}; boolean[] syncCond = new boolean[#rg(pe)]; while (chosenService != -1 ){
. . .
update syncCond array chosenService = fairSelect(syncCond,services); switch(chosenService){
. . .
case METHODl : //@ assert CPREl (chosenService);
. . .
break;
. . .
} } }
public boolean oneMessageProcessed;
. . .
//@ ensures oneMessageProcessed; public void run(){
. . .
int chosenService = 42; while (chosenService != -1){ int processedMessages = 0;
. . .
update syncCond array chosenService = fairSelect(syncCond,services); switch(chosenService){
. . .
case METHODl :
. . .
processedMessages ++; break;
. . .
}
} }
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 25 / 31
proof obligations
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 26 / 31
prop cs preservation
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 27 / 31
prop cs preservation
. . .
public void run(){
. . .
// process deferred requests for operation k for (int i = 0; i < operation_kRequest.size()) {
. . .
dequeue request item from operation k Request
. . .
extract operation k footprint from the request item if (condition_k (operation_k_footprint) { /*@ assert resource_Invariant && condition_k←
֓
(operation_k_footprint) @ ==> CPRE_k; @*/
. . .
extract the channel, innerChannel, from the request item
. . .
input remaining operation k parameters, if any, from innerChannel
. . .
apply operation k to the resource, using footprint and parameters //@ assume resource_Invariant && POST_k;
. . .
send operation k results (or null) down innerChannel } else {
. . .
enqueue item back on operation k Request } }
. . .
process deferred requests for all the other operations similarly }
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 28 / 31
prop cs preservation
. . .
public void run(){
. . .
// process deferred requests for operation k for (int i = 0; i < operation_kRequest.size()) {
. . .
dequeue request item from operation k Request
. . .
extract operation k footprint from the request item if (condition_k (operation_k_footprint) { /*@ assert resource_Invariant && condition_k←
֓
(operation_k_footprint) @ ==> CPRE_k; @*/
. . .
extract the channel, innerChannel, from the request item
. . .
input remaining operation k parameters, if any, from innerChannel
. . .
apply operation k to the resource, using footprint and parameters //@ assume resource_Invariant && POST_k;
. . .
send operation k results (or null) down innerChannel } else {
. . .
enqueue item back on operation k Request } }
. . .
process deferred requests for all the other operations similarly }
boolean cprePreservation;
. . .
//@ ensures cprePreservation; public void processDeferredRequests(){
. . .
// process deferred requests for operation k for (int i = 0; i < operation_kRequest.size()) {
. . .
dequeue request item from operation k Request
. . .
extract operation k footprint from the request item if (condition_k (operation_k_footprint) { /*@ assert resource_Invariant && condition_k←
֓
(operation_k_footprint) @ ==> CPRE_k; @*/ cprePreservation &= CPRE_k; // let’s see if←
֓
it’s true
. . .
extract the channel, innerChannel, from the request item
. . .
input remaining operation k parameters, if any, from innerChannel
. . .
apply operation k to the resource, using footprint and parameters //@ assume resource_Invariant && POST_k;
. . .
send operation k results (or null) down innerChannel } else {
. . .
enqueue item back on operation k Request } }
. . .
process deferred requests for all the other operations similarly }
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 28 / 31
prop completeness
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 29 / 31
prop completeness
CPRE does NOT depend on the input parameters
//prop_completeness //@ ensures
n
(methodi Requests > 0 ==> !CPREi );
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 29 / 31
prop completeness
CPRE does NOT depend on the input parameters
//prop_completeness //@ ensures
n
(methodi Requests > 0 ==> !CPREi );
CPRE DEPENDS on the input parameters
//prop_completeness //@ ensures
n
methodi Request.size() > 0 ==> completeness;
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 29 / 31
prop completeness
CPRE does NOT depend on the input parameters
//prop_completeness //@ ensures
n
(methodi Requests > 0 ==> !CPREi );
CPRE DEPENDS on the input parameters
//prop_completeness //@ ensures
n
methodi Request.size() > 0 ==> completeness;
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 29 / 31
using KeY to certify shared resource implementations
◮ implementations following the templates ◮ optimized versions of the previous implementations.
◮ Channel replication: ⋆ implementations with erroneous or incomplete update of the syncCond array. ⋆ missing break statements in switch code; ◮ Deferred requests: ⋆ incorrect optimizations on the code processing the pending requests ⋆ violations of protocol definitions. ⋆ not taking into account ping-pong effects J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 30 / 31
◮ Channel replication: CPRE depends on x (with Dx finite) ◮ Deferred requests: CPRE depends on x (with Dx potentially infinite)
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 31 / 31
◮ Channel replication: CPRE depends on x (with Dx finite) ◮ Deferred requests: CPRE depends on x (with Dx potentially infinite)
◮ Experience gained with instrumentation may serve to make KeY concurrency-aware
◮ for a subset of the shared resource syntax (codename razor)
◮ A collection of correct concurrent Java collections on the way J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 31 / 31
CPRE depends on some operation parameters
CPRE(opi (
x, y)) ≡ Ci
tautology Ci ⇔ true
depends only on resource state Ci = φ(S)
may depend on x : Ci = φ(S, x)
channel replication deferred requests
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 1 / 3
CPREopi Ci only depends on x
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 2 / 3
CPREopi Ci only depends on x
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 2 / 3
J.Mari˜ no & R.Alborodo (UPM & IMDEA) Model-based Code Generation Using JCSP CPA2015 3 / 3