Presentation is loading. Please wait.

Presentation is loading. Please wait.

A Considerate Specification of the Composite Pattern

Similar presentations


Presentation on theme: "A Considerate Specification of the Composite Pattern"— Presentation transcript:

1 A Considerate Specification of the Composite Pattern
Alexander J. Summers Sophia Drossopoulou Imperial College London Imperial College London

2 Overview Specification of the Composite pattern
SAVCBS challenge problem last year Invariant protocol based on Middelkoop et. al. 2006 Idea: “Considerate Reasoning” (IWACO 2009) objects are concerned with each others’ invariants Implementation and verification in Boogie2 Encoding the invariant protocol Simplifying the resulting proof obligations Practical handling of quantified formulas

3 The Composite pattern A tree whose nodes preserve properties related to all their descendant leaves. Subtrees may be added directly without first visiting their parents. We ignore subclassing issues for this talk, and treat a single class Composite

4 The Composite pattern suggested as a specification/verification challenge by Mueller, Leavens and Poetzsch-Heffter Various solutions proposed at SACVBS’08 We describe its specification and verification using invariants, adapting approach suggested by Middelkoop et. al. What we’re going to talk about the effect of different connectives on term calculi Write this at the end, when all other slides are done.#

5 The Composite class class Composite int total; Composite parent;
Composite[] components; int count; void addComponent(Composite c); }

6 The Composite class 7 class Composite int total; Composite parent;
Composite[] components; int count; void addComponent(Composite c); } 4 3 2 2 2 1

7 The Composite class 7 class Composite int total; Composite parent; Composite[] components; int count; void addComponent(Composite c); } 4 3 2 2 2 1 The field parent points to the parent node. The fields components and count maintain pointers to all children – i.e., the inverse of parent.

8 The Composite - invariant
2 2 2 1

9 The Composite - invariant
Each node has a value which is the sum of the values of all its descendant leaves. 2 2 2 1

10 The Composite - invariant
Each node has a value which is the sum of the values of all its descendant leaves. 7 2 2 2 1

11 The Composite - invariant
Each node has a value which is the sum of the values of all its descendant leaves. 7 4 2 2 2 1

12 The Composite - invariant
Each node has a value which is the sum of the values of all its descendant leaves. 7 4 3 2 2 2 1

13 The Composite - invariant
Each node has a value which is the sum of the values of all its descendant leaves. P(n) <=> n.total =  (lf.total), where lf a leaf under n 7 4 3 2 2 2 1

14 The Composite - invariant
Each node has a value which is the sum of the values of all its descendant leaves. P(n) <=> n.total =  (lf.total), where lf a leaf under n 7 4 3 2 2 2 1

15 The Composite - invariant
Each node has a value which is the sum of the values of all its descendant leaves. P(n) <=> n.total =  (lf.total), where lf a leaf under n 7 4 3 2 2 2 1 P(n) is a non-local predicate

16 The Composite - invariant - local
Each node has a value which is the sum of the values of all its direct descendants. 2 2 2 1

17 The Composite - invariant - local
Each node has a value which is the sum of the values of all its direct descendants. Q(n) <=> n.total =  (n’.total), where n’.parent=this 2 2 2 1

18 The Composite - invariant - local
Each node has a value which is the sum of the values of all its direct descendants. Q(n) <=> n.total =  (n’.total), where n’.parent=this 4 2 2 2 1

19 The Composite - invariant - local
Each node has a value which is the sum of the values of all its direct descendants. Q(n) <=> n.total =  (n’.total), where n’.parent=this 4 3 2 2 2 1

20 The Composite - invariant - local
Each node has a value which is the sum of the values of all its direct descendants. Q(n) <=> n.total =  (n’.total), where n’.parent=this 7 4 3 2 2 2 1

21 Local invariants achieve as much
P(n)  n.total =  (lf.total), where lf a leaf under n P(n) is non-local Q(n)  n.total =  (n’.total), where n’.parent=this Q(n) is local P(n) is stronger than Q(n) n. P(n)  n. Q(n) We will be using Q(n) as the invariant for n InvTwo: total == 1 + Sum(i=0..count)::components[i].total

22 The Composite - code void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal( c.total ); }

23 The Composite - code void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal( c.total ); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t);

24 The Composite - code this c void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal( c.total ); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this c

25 The Composite - code this c void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal( c.total ); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this c

26 The Composite - code this c void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal( c.total); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this c

27 The Composite - code this void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal( c.total); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this

28 The Composite - code this void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal( c.total); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this

29 The Composite - code this void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal( c.total); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this

30 The Composite - add a subtree
The Composite - code The Composite - add a subtree void addComponent(Composite c) { components[count]=c; count ++; c.parent = this; addToTotal( c.total); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this

31 The Composite - code this void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal(c.total); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this

32 The Composite - code this void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal(c.total); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this

33 The Composite - code this void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal(c.total); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this

34 The Composite - code this void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal(c.total); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this

35 The Composite - code this void addComponent(Composite c) {
components[count]=c; count ++; c.parent = this; addToTotal(c.total); } void addToTotal(int t){ total=total+t; if (parent!=null){ parent.addToTotal(t); this

36 The Composite class - invariant revisited
7 class Composite int total; Composite parent; Composite[] components; int count; } 4 3 2 2 2 1

37 The Composite class - invariant revisited
7 class Composite int total; Composite parent; Composite[] components; int count; } 4 3 2 2 2 1 InvOne: total > 0 && count ≥ 0

38 The Composite class - invariant revisited
7 class Composite int total; Composite parent; Composite[] components; int count; } 4 3 2 2 2 1 InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total

39 The Composite class - invariant revisited
7 class Composite int total; Composite parent; Composite[] components; int count; } 4 3 2 2 2 1 InvThree: i::components[i].parent == this

40 The Composite class - invariant revisited
7 class Composite int total; Composite parent; Composite[] components; int count; } 4 3 2 2 2 1 InvThree: i::components[i].parent == this InvFour: this.parent != null  i::this.parent.components[i] == this

41 The Composite class - invariant revisited
7 class Composite int total; Composite parent; Composite[] components; int count; } 4 3 2 2 2 1 InvThree: i::components[i].parent == this InvFour: this.parent != null  i::this.parent.components[i] == this Essentially, parent and components are inverses

42 Visible States Semantics
One basic philosophy for multi-object invariants Idea: invariants can be temporarily broken Must be fixed by the end of each method body Must also be fixed before making further calls In simplest form, all invariants hold at these points Many invariant protocols are based on this idea We use a variant based on Middelkoop et. al. First, basic visible states implemented in Boogie2

43 Visible State Semantics in Boogie2
public void addComponent(Composite c) { components[count] = c; count++; c.parent = this; this.addToTotal(c.total); }

44 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; this.addToTotal(c.total); }

45 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; this.addToTotal(c.total); }

46 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; this.addToTotal(c.total); } assume o :: InvOne(o)

47 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; this.addToTotal(c.total); } assume o :: InvOne(o) assume o :: InvTwo(o) assume o :: InvThree(o) assume o :: InvFour(o)

48 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; this.addToTotal(c.total); }

49 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; this.addToTotal(c.total); assert all invariants.. }

50 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; this.addToTotal(c.total); assert all invariants.. } assert o :: InvOne(o) assert o :: InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o)

51 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; this.addToTotal(c.total); assert all invariants.. }

52 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); }

53 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); }

54 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); }

55 Visible State Semantics in Boogie2
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); } But, addToTotal is meant to fix an invariant which is currently broken!

56 Handling “broken” invariants
We need to allow exceptions to visible states rules Want to allow an invariant to be broken for a call Idea: add a specification construct broken Method signatures can declare “broken” invariants: InvTwo(this) need not hold before calling However, must be established by the method end Related to the INC construct of Middelkoop et. al. // broken: InvTwo(this) private void addToTotal() { ...

57 Handling “broken” invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); }

58 Handling “broken” invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); }

59 Handling “broken” invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); } private void addToTotal() { ...

60 Handling “broken” invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); } // broken: InvTwo(this) private void addToTotal() { ...

61 Handling “broken” invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); } // broken: InvTwo(this) private void addToTotal() { ...

62 Handling “broken” invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); } // broken: InvTwo(this) private void addToTotal() { ... assert o :: InvOne(o) assert o :: InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o)

63 Handling “broken” invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); } // broken: InvTwo(this) private void addToTotal() { ... assert o :: InvOne(o) assert o :: InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o)

64 Handling “broken” invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all invariants.. this.addToTotal(c.total); } // broken: InvTwo(this) private void addToTotal() { ... assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o)

65 Handling “broken” invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); assert all invariants.. } assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o)

66 Handling “broken” invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); assert all invariants.. }

67 Problem: Quantifiers in Assertions
Asserting invariants for all objects is excessive Also, leaves a lot of work to the prover

68 Problem: Quantifiers in Assertions
Asserting invariants for all objects is excessive Also, leaves a lot of work to the prover void m() { // code.. }

69 Problem: Quantifiers in Assertions
Asserting invariants for all objects is excessive Also, leaves a lot of work to the prover void m() { // code.. } assume o :: Inv(o)

70 Problem: Quantifiers in Assertions
Asserting invariants for all objects is excessive Also, leaves a lot of work to the prover void m() { // code.. } assume o :: Inv(o) assert o :: Inv(o)

71 Problem: Quantifiers in Assertions
Asserting invariants for all objects is excessive Also, leaves a lot of work to the prover void m() { // code.. } assume o :: Inv(o) assert o :: Inv(o)

72 Problem: Quantifiers in Assertions
Asserting invariants for all objects is excessive Also, leaves a lot of work to the prover void m() { // code.. } assume o :: Inv(o) assert o :: Inv(o)

73 Problem: Quantifiers in Assertions
Asserting invariants for all objects is excessive Also, leaves a lot of work to the prover void m() { // code.. } assume o :: Inv(o) assert o :: Inv(o)

74 Problem: Quantifiers in Assertions
Asserting invariants for all objects is excessive Also, leaves a lot of work to the prover Which assertions trivial, and which require work? void m() { // code.. } assume o :: Inv(o) assert o :: Inv(o)

75 Coop-sets to track invariants
Idea: track which invariants depend on which fields Middelkoop et. al. – each field gets a “coop set” Declares which invariants may be broken by modifying this field Coop sets consist of pairs (I, P), where... I names an invariant which depends on the field P is a predicate describing when this invariant might be broken by modifying the field, in which: this denotes the object whose field is modified o denotes the object whose invariant may be broken

76 Coop-sets to track invariants

77 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0

78 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ...

79 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop:

80 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop:

81 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop: (InvOne,o==this)

82 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop: (InvOne,o==this)

83 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop: (InvOne,o==this)

84 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop: (InvOne,o==this), (InvTwo,o==this)

85 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop: (InvOne,o==this), (InvTwo,o==this)

86 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop: (InvOne,o==this), (InvTwo,o==this)

87 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop: (InvOne,o==this), (InvTwo,o==this) // (InvTwo, i :: o.components[i] == this)

88 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop: (InvOne,o==this), (InvTwo,o==this) // (InvTwo, i :: o.components[i] == this)

89 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop: (InvOne,o==this), (InvTwo,o==this) // (InvTwo, i :: o.components[i] == this) Use the coop-sets to calculate the vulnerable invariants

90 Coop-sets to track invariants
InvOne: total > 0 && count ≥ 0 InvTwo: total == 1 + Sum(i=0..count) :: components[i].total ... private int total; // coop: (InvOne,o==this), (InvTwo,o==this) // (InvTwo, i :: o.components[i] == this) Use the coop-sets to calculate the vulnerable invariants Note: the objects o are not obviously reachable from this

91 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); assert all invariants.. }

92 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); assert all invariants.. }

93 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total);

94 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total);

95 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants

96 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants

97 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private Composite[] components; Vulnerable Invariants

98 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private Composite[] components; // coop: (InvThree,o==this) // (InvFour,o.parent==this) Vulnerable Invariants

99 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private Composite[] components; // coop: (InvThree,o==this) // (InvFour,o.parent==this) Vulnerable Invariants InvThree(this)

100 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private Composite[] components; // coop: (InvThree,o==this) // (InvFour,o.parent==this) Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o)

101 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private Composite[] components; // coop: (InvThree,o==this) // (InvFour,o.parent==this) Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o) Note: coop wrong

102 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o)

103 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o)

104 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private int count; // coop: (InvOne,o==this) // (InvTwo,o==this) // (InvThree,o==this) // (InvFour,o.parent==this) Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o)

105 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private int count; // coop: (InvOne,o==this) // (InvTwo,o==this) // (InvThree,o==this) // (InvFour,o.parent==this) Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this)

106 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private int count; // coop: (InvOne,o==this) // (InvTwo,o==this) // (InvThree,o==this) // (InvFour,o.parent==this) Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this)

107 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private int count; // coop: (InvOne,o==this) // (InvTwo,o==this) // (InvThree,o==this) // (InvFour,o.parent==this) Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvThree(this)

108 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private int count; // coop: (InvOne,o==this) // (InvTwo,o==this) // (InvThree,o==this) // (InvFour,o.parent==this) Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvThree(this), o :: o.parent==this  InvFour(o)

109 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvThree(this), o :: o.parent==this  InvFour(o)

110 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvThree(this), o :: o.parent==this  InvFour(o)

111 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvThree(this)

112 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvThree(this)

113 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this)

114 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this)

115 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private Composite parent; // coop: (InvFour,o==this) // (InvThree,(i :: this==o.components[i])) Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this)

116 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private Composite parent; // coop: (InvFour,o==this) // (InvThree,(i :: this==o.components[i])) Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvFour(c)

117 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); private Composite parent; // coop: (InvFour,o==this) // (InvThree,(i :: this==o.components[i])) Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvFour(c), o :: (i :: c==o.components[i])  InvThree(o)

118 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvFour(c), o :: (i :: c==o.components[i])  InvThree(o)

119 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvFour(c), o :: (i :: c==o.components[i])  InvThree(o)

120 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvTwo(this), InvFour(c), o :: (i :: c==o.components[i])  InvThree(o)

121 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants InvThree(this), o :: o.parent==this  InvFour(o), InvOne(this), InvFour(c), o :: (i :: c==o.components[i])  InvThree(o)

122 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants aInvThree(this), ao :: o.parent==this  InvFour(o), aInvOne(this), aInvFour(c), ao :: (i :: c==o.components[i])  InvThree(o)

123 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants asInvThree(this), aso :: o.parent==this  InvFour(o), asInvOne(this), asInvFour(c), aso :: (i :: c==o.components[i])  InvThree(o)

124 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assInvThree(this), asso :: o.parent==this  InvFour(o), assInvOne(this), assInvFour(c), asso :: (i :: c==o.components[i])  InvThree(o)

125 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants asseInvThree(this), asseo :: o.parent==this  InvFour(o), asseInvOne(this), asseInvFour(c), asseo :: (i :: c==o.components[i])  InvThree(o)

126 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants asserInvThree(this), assero :: o.parent==this  InvFour(o), asserInvOne(this), asserInvFour(c), assero :: (i :: c==o.components[i])  InvThree(o)

127 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assertInvThree(this), asserto :: o.parent==this  InvFour(o), assertInvOne(this), assertInvFour(c), asserto :: (i :: c==o.components[i])  InvThree(o)

128 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

129 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert all except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

130 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

131 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o) Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

132 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o) Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

133 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o) Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

134 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o) Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

135 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o) FEWER INVARIANTS ASSERTED Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

136 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o) FEWER INVARIANTS ASSERTED Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

137 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o) Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

138 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o) Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

139 Calculating vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); assert o :: InvOne(o) assert o :: o!=this  InvTwo(o) assert o :: InvThree(o) assert o :: InvFour(o) Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

140 Refining vulnerable invariants
InvThree and InvFour express that components and parent are “inverses” If we use this information, we can refine assertions For example: assert o :: (i :: c==o.components[i])  InvThree(o) “those objects which have c in their components” The only possible such object is c.parent : assert (c.parent != null)  InvThree(c.parent) This assertion concerns a (single) object to which we have direct field access This reduces the burden of work on the prover

141 Refining vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

142 Refining vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

143 Refining vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); o.parent==this othis.components Vulnerable Invariants assert InvThree(this), assert o :: o.parent==this  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

144 Refining vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); o.parent==this othis.components Vulnerable Invariants assert InvThree(this), assert (i :: o==this.components[i])  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

145 Refining vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assert InvThree(this), assert (i :: o==this.components[i])  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

146 Refining vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assert InvThree(this), assert (i :: o==this.components[i])  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

147 Refining vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); co.components c.parent == o Vulnerable Invariants assert InvThree(this), assert (i :: o==this.components[i])  InvFour(o), assert InvOne(this), assert InvFour(c), assert o :: (i :: c==o.components[i])  InvThree(o)

148 Refining vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); co.components c.parent == o Vulnerable Invariants assert InvThree(this), assert (i :: o==this.components[i])  InvFour(o), assert InvOne(this), assert InvFour(c), assert (c.parent != null)  InvThree(c.parent)

149 Refining vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assert InvThree(this), assert (i :: o==this.components[i])  InvFour(o), assert InvOne(this), assert InvFour(c), assert (c.parent != null)  InvThree(c.parent)

150 Refining vulnerable invariants
public void addComponent(Composite c) { assume all invariants.. components[count] = c; count++; c.parent = this; assert vulnerable except “broken” invariants.. this.addToTotal(c.total); Vulnerable Invariants assert InvThree(this), assert (i :: o==this.components[i])  InvFour(o), assert InvOne(this), assert InvFour(c), assert (c.parent != null)  InvThree(c.parent)

151 Quantifiers in assumptions
Assuming all invariants is logically very powerful However, in practice this can give too much information to the theorem prover assume o :: InvOne(o) .... InvOne(this)

152 Quantifiers in assumptions
Assuming all invariants is logically very powerful However, in practice this can give too much information to the theorem prover assume o :: InvOne(o) .... InvOne(this), InvOne(this.parent)

153 Quantifiers in assumptions
Assuming all invariants is logically very powerful However, in practice this can give too much information to the theorem prover assume o :: InvOne(o) .... InvOne(this), InvOne(this.parent), InvOne(this.parent.parent)... We can use “triggers” on quantified formulas to control when the prover instantiates them Rule: the prover has to “know about” a term which matches the trigger, to be allowed to instantiate

154 Quantifiers in assumptions
Without choosing appropriate triggers, we get looping and unpredictable results Invariant definitions are guarded by triggers: The invariant name, e.g. InvOne(o) Some additional triggers: hint when it might be useful Invariants assumed/asserted in code are also guarded: Only instantiate if the invariant is determined to be relevant at some point in the method body. This can be by explicitly mentioning it, or because its definition is triggered as above. Resulting specification is well-behaved!

155 Results Our specification in Boogie encodes our intended invariant-based argument naturally and precisely The specification verifies (in about 5 seconds) No additional assertions are needed in the code: only those specified by the invariant protocol The calculation of vulnerable invariants from coop-sets could be easily automated The calculation of coop-sets themselves is by hand, but we believe could be partially automated The essential simplification is gained by knowing “inverse” relationships between fields

156 Conclusions and Future Work
Invariant-based approach handles this example Resulting specification is simple, compared with “direct” approaches, and could be automated Simplifications of vulnerable invariants require some extra work The approach extends to other more-complex examples (with cycles etc.). The treatment of invariants we have used does not extend easily to client-provider relationships A combination with other approaches (e.g., ownership) would be more flexible

157 Finally…

158 Any questions? Thank you for listening! What we’re going to talk about
the effect of different connectives on term calculi Write this at the end, when all other slides are done.#


Download ppt "A Considerate Specification of the Composite Pattern"

Similar presentations


Ads by Google