summaryrefslogtreecommitdiff
path: root/Source/UnitTests/CoreTests/Duplicator.cs
diff options
context:
space:
mode:
authorGravatar Dan Liew <daniel.liew@imperial.ac.uk>2014-11-17 20:58:26 +0000
committerGravatar Dan Liew <daniel.liew@imperial.ac.uk>2014-11-17 20:58:26 +0000
commit8e5671a4763542c767a8bdba4b6ea41a2ad7691f (patch)
tree2bf38d77e7b39dbfe009239e6c13baab54b80238 /Source/UnitTests/CoreTests/Duplicator.cs
parentc7a2a70a879e2506f6470e0abab2e03b1b60408a (diff)
Introduce unit tests which use NUnit. NUnit is now a dependency
so developers need to install it via NuGet. There aren't many tests yet. Just a few for Core and Basetypes but hopefully more will be added in the future. More information can be found in Source/UnitTests/README.md
Diffstat (limited to 'Source/UnitTests/CoreTests/Duplicator.cs')
-rw-r--r--Source/UnitTests/CoreTests/Duplicator.cs258
1 files changed, 258 insertions, 0 deletions
diff --git a/Source/UnitTests/CoreTests/Duplicator.cs b/Source/UnitTests/CoreTests/Duplicator.cs
new file mode 100644
index 00000000..978a041b
--- /dev/null
+++ b/Source/UnitTests/CoreTests/Duplicator.cs
@@ -0,0 +1,258 @@
+using Microsoft.Boogie.TestUtil;
+using Microsoft.Boogie;
+using Microsoft.Basetypes;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+
+namespace CoreTests
+{
+ [TestFixture ()]
+ public class DuplicatorTests : BoogieTestBase, IErrorSink {
+ Duplicator d;
+
+ public void Error(IToken tok, string msg) {
+ Assert.Fail(msg);
+ }
+
+ [SetUp]
+ public void Init() {
+ d = new Duplicator();
+ }
+
+ [Test()]
+ public void BVConcatExpr() {
+ var bv1_8 = new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 8);
+ var bv2_8 = new LiteralExpr(Token.NoToken, BigNum.FromInt(2), 8);
+ var A = new BvConcatExpr(Token.NoToken, bv1_8, bv2_8);
+ var B = d.Visit(A);
+
+ // The duplicator should ensure we get new BVConcatExprs
+ Assert.AreNotSame(A, B);
+ }
+
+ [Test()]
+ public void BvExtractExpr() {
+ var bv2_8 = new LiteralExpr(Token.NoToken, BigNum.FromInt(2), 8);
+ var A = new BvExtractExpr(Token.NoToken, bv2_8, 6,0);
+ var B = d.Visit(A);
+
+ // The duplicator should ensure we get new BVExtractExprs
+ Assert.AreNotSame(A, B);
+ }
+
+ [Test()]
+ public void NaryExpr() {
+ var bv1_8 = new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 8);
+ var bv2_8 = new LiteralExpr(Token.NoToken, BigNum.FromInt(2), 8);
+ var A = NAryExpr.Eq (bv1_8, bv2_8);
+ var B = d.Visit(A);
+
+ Assert.AreNotSame(A, B);
+ }
+
+ [Test()]
+ public void WholeProgram() {
+ var p = new Program();
+ var t = new TypedIdent(Token.NoToken, "foo", Microsoft.Boogie.Type.Bool);
+ var gv = new GlobalVariable(Token.NoToken, t);
+ p.AddTopLevelDeclaration(gv);
+ string metaDataString = "This is a test";
+ p.SetMetadata(0, metaDataString);
+
+ // Now try to clone
+ var p2 = (Program) d.Visit(p);
+
+ // Check global is a copy
+ int counter = 0;
+ GlobalVariable gv2 = null;
+ foreach (var g in p2.TopLevelDeclarations)
+ {
+ ++counter;
+ Assert.IsInstanceOf<GlobalVariable>(g);
+ gv2 = g as GlobalVariable;
+ }
+ Assert.AreEqual(1, counter);
+ Assert.AreNotSame(gv, gv2);
+ Assert.AreEqual(metaDataString, p2.GetMetadata<string>(0));
+
+
+ // Check Top level declarations list is duplicated properly
+ var t2 = new TypedIdent(Token.NoToken, "bar", Microsoft.Boogie.Type.Bool);
+ var gv3 = new GlobalVariable(Token.NoToken, t2);
+ p2.AddTopLevelDeclaration(gv3);
+
+ counter = 0;
+ foreach (var g in p2.TopLevelDeclarations) {
+ ++counter;
+ Assert.IsInstanceOf<GlobalVariable>(g);
+ }
+ Assert.AreEqual(2, counter);
+
+ // The original program should still only have one global variable
+ counter = 0;
+ foreach (var g in p.TopLevelDeclarations) {
+ ++counter;
+ Assert.IsInstanceOf<GlobalVariable>(g);
+ Assert.AreSame(g, gv);
+ }
+
+ Assert.AreEqual(1, counter);
+
+ // Change Metadata in p2, this shouldn't affect p
+ string newMetaDataString = "Another test";
+ p2.SetMetadata(0, newMetaDataString);
+
+ Assert.AreNotEqual(p2.GetMetadata<string>(0), p.GetMetadata<string>(0));
+ }
+
+ [Test()]
+ public void GotoTargets() {
+ Program p = TestUtil.ProgramLoader.LoadProgramFrom(@"
+ procedure main()
+ {
+ entry:
+ assume true;
+ goto thing1, thing2;
+
+ thing1:
+ assume true;
+ assume true;
+ goto entry, thing1;
+
+ thing2:
+ assume true;
+ assume true;
+ return;
+ }
+ ");
+
+ var main = p.TopLevelDeclarations.OfType<Implementation>().Where(x => x.Name == "main").First();
+
+ // Access blocks via their labels of gotocmds
+ var oldEntryBlock = ( main.Blocks[1].TransferCmd as GotoCmd ).labelTargets[0];
+ Assert.AreEqual("entry", oldEntryBlock.Label);
+
+ var oldThing1Block = ( main.Blocks[1].TransferCmd as GotoCmd ).labelTargets[1];
+ Assert.AreEqual("thing1", oldThing1Block.Label);
+
+ var oldThing2Block = ( main.Blocks[0].TransferCmd as GotoCmd ).labelTargets[1];
+ Assert.AreEqual("thing2", oldThing2Block.Label);
+
+ // Now duplicate
+ var newProgram = (Program) d.Visit(p);
+
+ // First lets check blocks have been duplicated
+ var newMain= newProgram.TopLevelDeclarations.OfType<Implementation>().Where(x => x.Name == "main").First();
+ var newEntryBlock = newMain.Blocks[0];
+ Assert.AreEqual("entry", newEntryBlock.Label);
+ Assert.AreNotSame(newEntryBlock, oldEntryBlock);
+
+ var newThing1Block = newMain.Blocks[1];
+ Assert.AreEqual("thing1", newThing1Block.Label);
+ Assert.AreNotSame(newThing1Block, oldThing1Block);
+
+ var newThing2Block = newMain.Blocks[2];
+ Assert.AreEqual("thing2", newThing2Block.Label);
+ Assert.AreNotSame(newThing2Block, oldThing2Block);
+
+ // Now let's examine the gotos and make sure they point to the duplicated blocks.
+ var newEntryGotoCmd = newEntryBlock.TransferCmd as GotoCmd;
+ var newthing1GotoCmd = newThing1Block.TransferCmd as GotoCmd;
+
+ Assert.AreNotSame(newEntryGotoCmd.labelTargets[0], oldThing1Block);
+ Assert.AreSame(newEntryGotoCmd.labelTargets[0], newThing1Block);
+ Assert.AreNotSame(newEntryGotoCmd.labelTargets[1], oldThing2Block);
+ Assert.AreSame(newEntryGotoCmd.labelTargets[1], newThing2Block);
+
+ Assert.AreNotSame(newthing1GotoCmd.labelTargets[0], oldEntryBlock);
+ Assert.AreSame(newthing1GotoCmd.labelTargets[0], newEntryBlock);
+ Assert.AreNotSame(newthing1GotoCmd.labelTargets[1], oldThing1Block);
+ Assert.AreSame(newthing1GotoCmd.labelTargets[1], newThing1Block);
+
+ }
+
+ [Test()]
+ public void ImplementationProcedureResolving() {
+ Program p = TestUtil.ProgramLoader.LoadProgramFrom(@"
+ procedure main(a:int) returns (r:int);
+ requires a > 0;
+ ensures r > a;
+
+ implementation main(a:int) returns (r:int)
+ {
+ r:= a + 1;
+ }
+ ");
+
+ // Check resolved
+ var oldMainImpl = p.TopLevelDeclarations.OfType<Implementation>().Where(i => i.Name == "main").First();
+ var oldMainProc = p.TopLevelDeclarations.OfType<Procedure>().Where(i => i.Name == "main").First();
+ Assert.AreSame(oldMainImpl.Proc, oldMainProc);
+
+ // Now duplicate the program
+ var newProgram = (Program) d.Visit(p);
+
+ // Resolving doesn't seem to fix this.
+ var rc = new ResolutionContext(this);
+ newProgram.Resolve(rc);
+
+ // Check resolved
+ var newMainImpl = newProgram.TopLevelDeclarations.OfType<Implementation>().Where(i => i.Name == "main").First();
+ var newMainProc = newProgram.TopLevelDeclarations.OfType<Procedure>().Where(i => i.Name == "main").First();
+ Assert.AreSame(newMainImpl.Proc, newMainProc);
+ }
+
+ [Test()]
+ public void CallCmdResolving() {
+ Program p = TestUtil.ProgramLoader.LoadProgramFrom(@"
+ procedure main()
+ {
+ var x:int;
+ call x := foo();
+ call x := bar();
+ }
+
+ procedure foo() returns(r:int)
+ {
+ r := 0;
+ }
+
+ procedure bar() returns(r:int);
+ ensures r == 0;
+ ");
+
+ // Get hold of the procedures that will be used with the CallCmd
+ var oldFoo = p.TopLevelDeclarations.OfType<Procedure>().Where(i => i.Name == "foo").First();
+ var oldBar = p.TopLevelDeclarations.OfType<Procedure>().Where(i => i.Name == "bar").First();
+
+ // Get the CallCmds to foo and bar
+ var oldCmdsInMain = p.TopLevelDeclarations.OfType<Implementation>().Where(i => i.Name == "main").SelectMany(i => i.Blocks).SelectMany(b => b.Cmds);
+ var oldCallToFoo = oldCmdsInMain.OfType<CallCmd>().Where(c => c.callee == "foo").First();
+ var oldCallToBar = oldCmdsInMain.OfType<CallCmd>().Where(c => c.callee == "bar").First();
+
+ // Check the Calls
+ Assert.AreSame(oldCallToFoo.Proc, oldFoo);
+ Assert.AreSame(oldCallToBar.Proc, oldBar);
+
+ // Now duplicate the program and check that the calls are resolved correctly
+ var newProgram = (Program) d.Visit(p);
+
+ var foo = newProgram.TopLevelDeclarations.OfType<Procedure>().Where(i => i.Name == "foo").First();
+ var bar = newProgram.TopLevelDeclarations.OfType<Procedure>().Where(i => i.Name == "bar").First();
+
+ // Get the call to Foo
+ var cmdsInMain = newProgram.TopLevelDeclarations.OfType<Implementation>().Where(i => i.Name == "main").SelectMany(i => i.Blocks).SelectMany(b => b.Cmds);
+ var callToFoo = cmdsInMain.OfType<CallCmd>().Where(c => c.callee == "foo").First();
+ var callToBar = cmdsInMain.OfType<CallCmd>().Where(c => c.callee == "bar").First();
+
+ // Check the Calls
+ Assert.AreNotSame(callToFoo.Proc, oldFoo);
+ Assert.AreSame(callToFoo.Proc, foo);
+ Assert.AreNotSame(callToBar.Proc, oldBar);
+ Assert.AreSame(callToBar.Proc, bar);
+ }
+ }
+}
+