Mike Barnett RSDE Microsoft Research Nikolai Tillmann RSDE Microsoft Research TL51
Mike Barnett RSDE Microsoft Research Nikolai Tillmann RSDE Microsoft Research
Contract Library in.NET 4.0 Coming soon: Tools for contracts at
string GetDescription(int x); /// /// should be greater than zero /// /// non-null string /// string GetDescription(int x); /// /// should be greater than zero /// /// non-null string /// string GetDescription(int x); string s = o.GetDescription(i); … s.Length … string s = o.GetDescription(i); … s.Length …
string GetDescription(int x) { Contract.Requires( 0 < x ); Contract.Ensures( Contract.Result () != null ); … } string GetDescription(int x) { Contract.Requires( 0 < x ); Contract.Ensures( Contract.Result () != null ); … } Design-by-Contract meets.NET!
Mike Barnett RSDE Research in Software Engineering
class Rational { public Rational(int n, int d) { Contract.Requires( 0 < d ); this.N = n; this.D = d; } } DocumentationDocumentation Runtime Checking Static Checking Test Generation ( Pex ) Test Generation ( Pex )
void ObjectInvariant() { Contract.Invariant( items != null ); } Features Declarative Language expression syntax Type checking / IDE Special Encodings Result and OldValue public virtual int Add(object value) { Contract.Requires( value != null ); Contract.Ensures( Count == Contract.OldValue(Count) + 1 ); Contract.Ensures( Contract.Result () == Contract.OldValue(Count) ); if (count == items.Length) EnsureCapacity(count + 1); items[count] = value; return count++; }
Mike Barnett RSDE Research in Software Engineering
.method public hidebysig newslot virtual instance int32 Add(object 'value') cil managed { ldarg.1 ldnull ceq ldc.i4.0 ceq call void [Microsoft.Contracts]Microsoft.Contracts.Contract::Requires(bool) ldarg.0 call instance int32 TabDemo.BaseList::get_Count() ldarg.0 call instance int32 TabDemo.BaseList::get_Count() call !!0 [Microsoft.Contracts]Microsoft.Contracts.Contract::Old (!!0) ldc.i4.1 add ceq call void [Microsoft.Contracts]Microsoft.Contracts.Contract::Ensures(bool) call !!0 [Microsoft.Contracts]Microsoft.Contracts.Contract::Result () ldarg.0 call instance int32 TabDemo.BaseList::get_Count() call !!0 [Microsoft.Contracts]Microsoft.Contracts.Contract::Old (!!0) ceq call void [Microsoft.Contracts]Microsoft.Contracts.Contract::Ensures(bool) ldarg.0 ldfld int32 TabDemo.BaseList::count ldarg.0 ldfld object[] TabDemo.BaseList::items ldlen conv.i4 ceq ldc.i4.0 ceq stloc.1 ldloc.1 brtrue.s IL_0069 ldarg.0 ldfld int32 TabDemo.BaseList::count ldc.i4.1 add call instance void TabDemo.BaseList::EnsureCapacity(int32) ldarg.0 ldfld object[] TabDemo.BaseList::items ldarg.0 ldfld int32 TabDemo.BaseList::count ldarg.1 stelem.ref ldarg.0 dup ldfld int32 TabDemo.BaseList::count dup stloc.2 ldc.i4.1 add stfld int32 TabDemo.BaseList::count ldloc.2 stloc.0 br.s IL_008b ldloc.0 ret } // end of method BaseList::Add csc/vbc/….method public hidebysig newslot virtual instance int32 Add(object 'value') cil managed { ldarg.0 ldfld int32 TabDemo.BaseList::count ldarg.0 ldfld object[] TabDemo.BaseList::items ldlen conv.i4 ceq ldc.i4.0 ceq stloc.1 ldloc.1 brtrue.s IL_0029 ldarg.0 ldfld int32 TabDemo.BaseList::count ldc.i4.1 add call instance void TabDemo.BaseList::EnsureCapacity(int32) ldarg.0 ldfld object[] TabDemo.BaseList::items ldarg.0 ldfld int32 TabDemo.BaseList::count ldarg.1 stelem.ref ldarg.0 dup ldfld int32 TabDemo.BaseList::count dup stloc.2 ldc.i4.1 add stfld int32 TabDemo.BaseList::count ldloc.2 stloc.0 br.s IL_004b ldloc.0 ret } Release Compile /d:CONTRACTS_FULL ccrewrite Inheritance Style checks Executable Runtime Contract Checking public virtual int Add(object value){ Contract.Requires( value != null ); Contract.Ensures( Count == Contract.OldValue(Count) + 1 ); Contract.Ensures( Contract.Result () == Contract.OldValue(Count) ); if (_size == _items.Length) EnsureCapacity(_size+1); _items[_size] = value; return _size++; }.method public hidebysig newslot virtual instance int32 Add(object 'value') cil managed {.locals init (int32 'Contract.Old(Count)', int32 'Contract.Result ()') ldarg.0 call instance int32 TabDemo.BaseList::get_Count() stloc.3 ldarg.1 ldnull ceq ldc.i4.0 ceq ldstr "value != null" call void __RewriterMethods::RewriterRequires$PST (bool, string) ldarg.0 ldfld int32 TabDemo.BaseList::count ldarg.0 ldfld object[] TabDemo.BaseList::items ldlen conv.i4 ceq ldc.i4.0 ceq stloc.1 ldloc.1 brtrue IL_004d nop ldarg.0 ldfld int32 TabDemo.BaseList::count ldc.i4.1 add call instance void TabDemo.BaseList::EnsureCapacity(int32) nop ldarg.0 ldfld object[] TabDemo.BaseList::items ldarg.0 ldfld int32 TabDemo.BaseList::count ldarg.1 stelem.ref ldarg.0 dup ldfld int32 TabDemo.BaseList::count dup stloc.2 ldc.i4.1 add stfld int32 TabDemo.BaseList::count ldloc.2 stloc.0 br IL_0072 ldloc.0 stloc.s 'Contract.Result ()' br IL_007a ldarg.0 call instance int32 TabDemo.BaseList::get_Count() ldloc.3 ldc.i4.1 add ceq ldstr "Count == Contract.Old(Count) + 1" call void __RewriterMethods::RewriterEnsures$PST B(bool, string) ldloc.s 'Contract.Result ()' ldloc.s V_4 ceq ldstr "Contract.Result () == Contract.Old(Count)" call void __RewriterMethods::RewriterEnsures$PST B(bool, string) ldloc.s 'Contract.Result ()' ret }
src PowerLib.dll (minimal runtime checks) PowerLib.Contracts.dll All contracts, no code + Release Assemblies Contract Reference Assemblies
Compile /d:CONTRACTS_FULL ccRefGen.method public hidebysig newslot virtual instance int32 Add(object 'value') cil managed { ldarg.1 ldnull ceq ldc.i4.0 ceq call void [Microsoft.Contracts]Microsoft.Contracts.Contract::Requires(bool) ldarg.0 call instance int32 TabDemo.BaseList::get_Count() ldarg.0 call instance int32 TabDemo.BaseList::get_Count() call !!0 [Microsoft.Contracts]Microsoft.Contracts.Contract::Old (!!0) ldc.i4.1 add ceq call void [Microsoft.Contracts]Microsoft.Contracts.Contract::Ensures(bool) call !!0 [Microsoft.Contracts]Microsoft.Contracts.Contract::Result () ldarg.0 call instance int32 TabDemo.BaseList::get_Count() call !!0 [Microsoft.Contracts]Microsoft.Contracts.Contract::Old (!!0) ceq call void [Microsoft.Contracts]Microsoft.Contracts.Contract::Ensures(bool) ldarg.0 ldfld int32 TabDemo.BaseList::count ldarg.0 ldfld object[] TabDemo.BaseList::items ldlen conv.i4 ceq ldc.i4.0 ceq stloc.1 ldloc.1 brtrue.s IL_0069 ldarg.0 ldfld int32 TabDemo.BaseList::count ldc.i4.1 add call instance void TabDemo.BaseList::EnsureCapacity(int32) ldarg.0 ldfld object[] TabDemo.BaseList::items ldarg.0 ldfld int32 TabDemo.BaseList::count ldarg.1 stelem.ref ldarg.0 dup ldfld int32 TabDemo.BaseList::count dup stloc.2 ldc.i4.1 add stfld int32 TabDemo.BaseList::count ldloc.2 stloc.0 br.s IL_008b ldloc.0 ret } // end of method BaseList::Add Contract Reference Assembly.method public hidebysig newslot virtual instance int32 Add(object 'value') cil managed { ldarg.1 ldnull ceq ldc.i4.0 ceq call void [Microsoft.Contracts]Microsoft.Contracts.Contract::Requires(bool) ldarg.0 call instance int32 TabDemo.BaseList::get_Count() ldarg.0 call instance int32 TabDemo.BaseList::get_Count() call !!0 [Microsoft.Contracts]Microsoft.Contracts.Contract::Old (!!0) ldc.i4.1 add ceq call void [Microsoft.Contracts]Microsoft.Contracts.Contract::Ensures(bool) call !!0 [Microsoft.Contracts]Microsoft.Contracts.Contract::Result () ldarg.0 call instance int32 TabDemo.BaseList::get_Count() call !!0 [Microsoft.Contracts]Microsoft.Contracts.Contract::Old (!!0) ceq call void [Microsoft.Contracts]Microsoft.Contracts.Contract::Ensures(bool) } // end of method BaseList::Add public virtual int Add(object value){ Contract.Requires( value != null ); Contract.Ensures( Count == Contract.OldValue(Count) + 1 ); Contract.Ensures( Contract.Result () == Contract.OldValue(Count) ); if (_size == _items.Length) EnsureCapacity(_size+1); _items[_size] = value; return _size++; }
[ContractClass(typeof(CloneableContract))] public interface ICloneable { object Clone(); } [ContractClass(typeof(CloneableContract))] public interface ICloneable { object Clone(); } [ContractClassFor(typeof(ICloneable))] public class CloneableContract : ICloneable { public object Clone() { Contract.Ensures( Contract.Result () != null ); … } } [ContractClassFor(typeof(ICloneable))] public class CloneableContract : ICloneable { public object Clone() { Contract.Ensures( Contract.Result () != null ); … } } All classes implementing the interface inherit the contract
Get Pex for Visual Studio 2010 at Pex
Dont give up, Pex has arrived. Dont give up, Pex has arrived.
Nikolai Tillmann RSDE Microsoft Research Pex
Nikolai Tillmann RSDE Microsoft Research Pex
[TestMethod] void AddZeroTest() { var r = new Rational(1,2); var q = r + 0; Assert(r == p); } [TestMethod] void AddZeroTest() { var r = new Rational(1,2); var q = r + 0; Assert(r == p); } Handwritten
[PexMethod] void AddZeroTest( Rational r) { var q = r + 0; Assert(r == p); } [PexMethod] void AddZeroTest( Rational r) { var q = r + 0; Assert(r == p); } [TestMethod] void AddZeroTest01() { var r = new Rational(1,2); this.AddZeroTest(r); } [TestMethod] void AddZeroTest01() { var r = new Rational(1,2); this.AddZeroTest(r); } Pex calls Automatically generated Handwritten
27
[PexAllowedException(typeof(ArgumentException))] [TestClass] public partial class ResourceReaderTest { [PexMethod] public void ReadEntries(byte[] data) { if (data == null) return; fixed (byte* p = data) using (var stream = new UnmanagedMemoryStream(p, data.Length)) { var reader = new ResourceReader(stream); foreach (var entry in reader) { /* reading entries */ } } } }
Nikolai Tillmann RSDE Microsoft Research Pex
Research in Software Engineering
Please fill out your evaluation for this session at: This session will be available as a recording at:
© 2008 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries. The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.