public void TestWildcardEventAction() { var test = @" namespace Foo { machine M { start state S { on *,e1.e2 goto S2; on * push S2; } } }"; var configuration = Configuration.Create(); configuration.Verbose = 2; var context = CompilationContext.Create(configuration).LoadSolution(test); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); var syntaxTree = context.GetProjects()[0].PSharpPrograms[0].GetSyntaxTree(); var expected = @" using Microsoft.PSharp; namespace Foo { class M : Machine { [Microsoft.PSharp.Start] [OnEventGotoState(typeof(Microsoft.PSharp.WildCardEvent), typeof(S2))] [OnEventGotoState(typeof(e1.e2), typeof(S2))] [OnEventPushState(typeof(Microsoft.PSharp.WildCardEvent), typeof(S2))] class S : MachineState { } } }"; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), syntaxTree.ToString().Replace("\n", string.Empty)); }
public void TestMonitorStateGroupDeclaration() { var test = @" namespace Foo { monitor M { start state S1 { } group G { state S2 { } } } }"; var configuration = Configuration.Create(); configuration.Verbose = 2; var context = CompilationContext.Create(configuration).LoadSolution(test); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); var syntaxTree = context.GetProjects()[0].PSharpPrograms[0].GetSyntaxTree(); var expected = @" using Microsoft.PSharp; namespace Foo { class M : Monitor { [Microsoft.PSharp.Start] class S1 : MonitorState { } class G : StateGroup { public class S2 : MonitorState { } } } }"; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), syntaxTree.ToString().Replace("\n", string.Empty)); }
public void TestEntryDeclaration() { var test = @" namespace Foo { machine M { start state S { entry{} } } }"; var configuration = Configuration.Create(); configuration.Verbose = 2; var context = CompilationContext.Create(configuration).LoadSolution(test); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); var syntaxTree = context.GetProjects()[0].PSharpPrograms[0].GetSyntaxTree(); var expected = @" using Microsoft.PSharp; namespace Foo { class M : Machine { [Microsoft.PSharp.Start] [OnEntry(nameof(psharp_S_on_entry_action))] class S : MachineState { } protected void psharp_S_on_entry_action() { } } }"; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), syntaxTree.ToString().Replace("\n", string.Empty)); }
public void TestOnComplexGenericEventGotoStateDeclarationWithBody() { var test = @" namespace Foo { machine M { start state S1 { on e<List<Tuple<bool, object>>, Dictionary<string, float>> goto S2 with {} } } }"; var configuration = Configuration.Create(); configuration.Verbose = 2; var context = CompilationContext.Create(configuration).LoadSolution(test); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); var syntaxTree = context.GetProjects()[0].PSharpPrograms[0].GetSyntaxTree(); var expected = @" using Microsoft.PSharp; namespace Foo { class M : Machine { [Microsoft.PSharp.Start] [OnEventGotoState(typeof(e<List<Tuple<bool,object>>,Dictionary<string,float>>), typeof(S2), nameof(psharp_S1_e_type_0_action))] class S1 : MachineState { } protected void psharp_S1_e_type_0_action() { } } }"; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), syntaxTree.ToString().Replace("\n", string.Empty)); }
public void TestOnEventDoActionDeclaration2() { var test = @" namespace Foo { machine M { start state S1 { on e1 do Bar; on e2 do Baz; } } }"; var configuration = Configuration.Create(); configuration.Verbose = 2; var context = CompilationContext.Create(configuration).LoadSolution(test); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); var syntaxTree = context.GetProjects()[0].PSharpPrograms[0].GetSyntaxTree(); var expected = @" using Microsoft.PSharp; namespace Foo { class M : Machine { [Microsoft.PSharp.Start] [OnEventDoAction(typeof(e1), nameof(Bar))] [OnEventDoAction(typeof(e2), nameof(Baz))] class S1 : MachineState { } } }"; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), syntaxTree.ToString().Replace("\n", string.Empty)); }
public void TestBasicLoop() { var test = @" using Microsoft.PSharp; namespace Foo { class M : Machine { [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { int k = 10; for (int i = 0; i < k; i++) { k = 2; } k = 3; } } }"; var configuration = base.GetConfiguration(); IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "No static analysis errors detected."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
public void TestDeferEventDeclarationQualifiedComplex() { var test = @" namespace Foo { machine M { start state S { defer e1<int>, halt, default, Foo.e2<Bar.e3>; } } }"; var configuration = Configuration.Create(); configuration.Verbose = 2; var context = CompilationContext.Create(configuration).LoadSolution(test); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); var syntaxTree = context.GetProjects()[0].PSharpPrograms[0].GetSyntaxTree(); var expected = @" using Microsoft.PSharp; namespace Foo { class M : Machine { [Microsoft.PSharp.Start] [DeferEvents(typeof(e1<int>), typeof(Microsoft.PSharp.Halt), typeof(Microsoft.PSharp.Default), typeof(Foo.e2<Bar.e3>))] class S : MachineState { } } }"; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), syntaxTree.ToString().Replace("\n", string.Empty)); }
public void TestUsingDeclaration() { var test = "using System.Text;"; var configuration = Configuration.Create(); configuration.Verbose = 2; var context = CompilationContext.Create(configuration).LoadSolution(test); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); var syntaxTree = context.GetProjects()[0].PSharpPrograms[0].GetSyntaxTree(); var expected = @" using Microsoft.PSharp; using System.Text;"; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), syntaxTree.ToString().Replace("\n", string.Empty)); }
public void TestMemberVisibility() { var test = @" namespace Foo { class M : Machine { int Num; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { this.Num = 1; } } }"; var configuration = base.GetConfiguration(); IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "No static analysis errors detected."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
/// <summary> /// Rewrites the assemblies specified in the configuration. /// </summary> private static void RewriteAssemblies(Configuration configuration, RewritingOptions options) { try { string assemblyDir = null; var fileList = new HashSet <string>(); if (!string.IsNullOrEmpty(configuration.AssemblyToBeAnalyzed)) { var fullPath = Path.GetFullPath(configuration.AssemblyToBeAnalyzed); Console.WriteLine($". Rewriting {fullPath}"); assemblyDir = Path.GetDirectoryName(fullPath); fileList.Add(fullPath); } else if (Directory.Exists(configuration.RewritingOptionsPath)) { assemblyDir = Path.GetFullPath(configuration.RewritingOptionsPath); Console.WriteLine($". Rewriting the assemblies specified in {assemblyDir}"); } RewritingOptions config = options; if (!string.IsNullOrEmpty(assemblyDir)) { // Create a new RewritingOptions object from command line args only. config.AssembliesDirectory = assemblyDir; config.OutputDirectory = assemblyDir; config.AssemblyPaths = fileList; } else { // Load options from JSON file. config = RewritingOptions.ParseFromJSON(configuration.RewritingOptionsPath); Console.WriteLine($". Rewriting the assemblies specified in {configuration.RewritingOptionsPath}"); config.PlatformVersion = configuration.PlatformVersion; // allow command line options to override the json file. if (!string.IsNullOrEmpty(options.StrongNameKeyFile)) { config.StrongNameKeyFile = options.StrongNameKeyFile; } if (options.IsRewritingDependencies) { config.IsRewritingDependencies = options.IsRewritingDependencies; } if (options.IsRewritingThreads) { config.IsRewritingThreads = options.IsRewritingThreads; } if (options.IsRewritingUnitTests) { config.IsRewritingUnitTests = options.IsRewritingUnitTests; } } RewritingEngine.Run(configuration, config); } catch (Exception ex) { Debug.WriteLine(ex.StackTrace); Error.ReportAndExit(ex.Message); } }
public void TestFieldSendAlias() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public int Num; public Letter(string text, int num) { this.Text = text; this.Num = num; } } class M : Machine { MachineId Target; Letter Letter; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { var letter = new Letter(""test"", 0); this.Target = this.CreateMachine(typeof(M)); var otherLetter = letter; letter = this.Foo(letter); this.Send(this.Target, new eUnit(otherLetter)); } Letter Foo(Letter letter) { return this.Bar(letter); } Letter Bar(Letter letter) { Letter otherLetter = new Letter(""test"", 0); otherLetter = this.Letter; return otherLetter; } } }"; var configuration = base.GetConfiguration(); IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "No static analysis errors detected."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
/// <summary> /// Checks if the test executed by the testing engine has been rewritten. /// </summary> /// <returns>True if the test has been rewritten, else false.</returns> public bool IsTestRewritten() => RewritingEngine.IsAssemblyRewritten(this.TestMethodInfo.Assembly);
public void TestFieldAccessAfterGivenUpOwnership2Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public MachineId Target; public Letter Letter; public eUnit(MachineId target, Letter letter) : base() { this.Target = target; this.Letter = letter; } } struct Letter { public string Text; public int Num; public Letter(string text, int num) { this.Text = text; this.Num = num; } } class M : Machine { MachineId Target; Letter Letter; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { this.Target = this.CreateMachine(typeof(M)); this.Send(this.Target, new eUnit(this.Id, this.Letter)); int num = this.Letter.Num; this.Letter.Text = ""London""; } } }"; var configuration = base.GetConfiguration(); configuration.DoStateTransitionAnalysis = false; IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '3' errors."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
public void TestWriteAccessAfterSendInCallee3Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public int Num; public Letter(string text, int num) { this.Text = text; this.Num = num; } } class M : Machine { MachineId Target; Letter Letter; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { var letter = new Letter(""test"", 0); this.Target = this.CreateMachine(typeof(M)); this.Send(this.Target, new eUnit(letter)); this.Foo(letter); } void Foo(Letter letter) { this.Letter = letter; // ERROR letter = new Letter(""test2"", 2); this.Letter.Num = 1; // ERROR int num = this.Letter.Num; // ERROR letter.Text = ""Bangalore""; this.Letter.Text = ""Taipei""; // ERROR } } }"; var configuration = base.GetConfiguration(); configuration.DoStateTransitionAnalysis = false; IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '7' errors."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
public void TestAccessInVirtualMethod() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public Letter(string text) { this.Text = text; } } internal class Envelope { internal Letter Letter; internal virtual void Foo(Letter letter) { } } internal class SuperEnvelope : Envelope { internal override void Foo(Letter letter) { letter.Text = ""Bangalore""; } } class M : Machine { MachineId Target; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { var letter = new Letter(""London""); this.Target = this.CreateMachine(typeof(M)); Envelope envelope = new Envelope(); this.Send(this.Target, new eUnit(letter)); envelope.Foo(letter); } } }"; var configuration = base.GetConfiguration(); IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "No static analysis errors detected."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
public void TestComplexAccessesInCall11Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public Letter(string text) { this.Text = text; } } class OtherClass { AnotherClass AC; public void Foo(Letter letter) { var ac = new AnotherClass(letter); this.AC = ac; this.AC.Bar(); } } class AnotherClass { internal Letter Letter; public AnotherClass(Letter letter) { this.Letter = letter; } public void Bar() { this.Letter.Text = ""Test""; // ERROR } } class M : Machine { MachineId Target; Letter Letter; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { this.Target = this.CreateMachine(typeof(M)); Letter letter = new Letter(""London""); var oc = new OtherClass(); this.Send(this.Target, new eUnit(letter)); oc.Foo(letter); } } }"; var configuration = base.GetConfiguration(); configuration.DoStateTransitionAnalysis = false; IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '2' errors."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
public void TestEventRaiseStatementWithPSharpAPI() { var test = @" using Microsoft.PSharp; namespace Foo { class e1 : Event { public e1() : base() { } } class M : Machine { [Microsoft.PSharp.Start] [OnEntry(nameof(psharp_S1_on_entry_action))] [OnEventGotoState(typeof(e1), typeof(S2))] class S1 : MachineState { } class S2 : MachineState { } protected void psharp_S1_on_entry_action() { this.Raise(new e1()); } } }"; var configuration = Configuration.Create(); configuration.Verbose = 2; var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); var syntaxTree = context.GetProjects()[0].CSharpPrograms[0].GetSyntaxTree(); var expected = @" using Microsoft.PSharp; namespace Foo { class e1 : Event { public e1() : base() { } } class M : Machine { [Microsoft.PSharp.Start] [OnEntry(nameof(psharp_S1_on_entry_action))] [OnEventGotoState(typeof(e1), typeof(S2))] class S1 : MachineState { } class S2 : MachineState { } protected void psharp_S1_on_entry_action() { { this.Raise(new e1());return; } } } }"; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), syntaxTree.ToString().Replace(Environment.NewLine, string.Empty)); }
public void TestIfStatement8Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } class eReq : Event { public int Value; public eReq(int value) : base() { this.Value = value; } } struct Letter { public string Text; public Letter(string text) { this.Text = text; } } class M : Machine { MachineId Target; Letter Letter; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { int num = (this.ReceivedEvent as eReq).Value; this.Target = this.CreateMachine(typeof(M)); Letter letter = new Letter(""London""); Letter otherLetter = new Letter(""Bangalore""); this.Letter = letter; if (num == 0) { otherLetter = new Letter(""Redmond""); } else { otherLetter = letter; } this.Send(this.Target, new eUnit(otherLetter)); this.Letter.Text = ""text""; } } }"; var configuration = base.GetConfiguration(); IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '2' errors."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
public void TestWriteAccessAfterSendInLoop2() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public Letter(string text) { this.Text = text; } } class M : Machine { MachineId Target; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { var letter = new Letter(""London""); this.Target = this.CreateMachine(typeof(M)); int k = 10; for (int i = 0; i < k; i++) { continue; letter.Text = ""Bangalore""; this.Send(this.Target, new eUnit(letter)); } } } }"; var configuration = base.GetConfiguration(); IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "No static analysis errors detected."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
public void TestFieldGivenUpOwnership1Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public Letter(string text) { this.Text = text; } } class M : Machine { MachineId Target; Letter Letter; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { var letter = new Letter(""test""); this.Target = this.CreateMachine(typeof(M)); this.Send(this.Target, new eUnit(letter)); this.Letter = letter; } } }"; var configuration = base.GetConfiguration(); configuration.DoStateTransitionAnalysis = false; IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '1' error."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); var error = "Error: Method 'FirstOnEntryAction' of machine 'Foo.M' assigns " + "'letter' to field 'Foo.M.Letter' after giving up its ownership."; var actual = IO.GetOutput(); Assert.AreEqual(error.Replace(Environment.NewLine, string.Empty), actual.Substring(0, actual.IndexOf(Environment.NewLine))); IO.StopWritingToMemory(); }
public void TestComplexAccessesInCall1Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Envelope Envelope; public eUnit(Envelope envelope) : base() { this.Envelope = envelope; } } struct Letter { public string Text; public Letter(string text) { this.Text = text; } } struct Envelope { public Letter Letter; public string Address; public int Id; public Envelope(string address, int id) { this.Letter = new Letter(""""); this.Address = address; this.Id = id; } } class M : Machine { MachineId Target; Letter Letter; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { this.Target = this.CreateMachine(typeof(M)); Envelope envelope = new Envelope(""London"", 0); Envelope otherEnvelope = envelope; this.Foo(otherEnvelope); this.Send(this.Target, new eUnit(envelope)); this.Bar(otherEnvelope.Letter); otherEnvelope.Letter.Text = ""text""; // ERROR envelope = new Envelope(); this.FooBar(envelope, otherEnvelope.Letter); } void Foo(Envelope envelope) { this.Letter = envelope.Letter; // ERROR } void Bar(Letter letter) { letter.Text = ""text2""; // ERROR } void FooBar(Envelope envelope, Letter letter) { string str = letter.Text; // ERROR envelope.Id = 5; } } }"; var configuration = base.GetConfiguration(); configuration.DoStateTransitionAnalysis = false; IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '4' errors."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
public void TestAccessInVirtualMethod7Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public Letter(string text) { this.Text = text; } } internal class Envelope { internal Letter Letter; internal virtual void Foo(Letter letter) { } internal virtual void Bar(Letter letter) { } } internal class SuperEnvelope : Envelope { internal override void Foo(Letter letter) { letter.Text = ""Bangalore""; } internal override void Bar(Letter letter) { base.Letter.Text = ""Bangalore""; } } class M : Machine { MachineId Target; bool Check; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { var letter = new Letter(""London""); this.Target = this.CreateMachine(typeof(M)); Envelope envelope = this.Foo(); this.Send(this.Target, new eUnit(letter)); envelope.Foo(letter); // ERROR } Envelope Foo() { Envelope envelope = new SuperEnvelope(); Envelope anotherEnvelope = new Envelope(); anotherEnvelope = envelope; if (this.Check) { return new Envelope(); } else { return anotherEnvelope; } } } }"; var configuration = base.GetConfiguration(); IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '1' error."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); var error = "Error: Method 'FirstOnEntryAction' of machine 'Foo.M' accesses " + "'letter' after giving up its ownership."; var actual = IO.GetOutput(); Assert.AreEqual(error.Replace(Environment.NewLine, string.Empty), actual.Substring(0, actual.IndexOf(Environment.NewLine))); IO.StopWritingToMemory(); }
public void TestComplexAccessesInCall10Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public Letter(string text) { this.Text = text; } } class OtherClass { internal Letter Letter; public void Foo(Letter letter) { this.Letter = letter; } } class M : Machine { MachineId Target; Letter Letter; OtherClass OC; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { this.Target = this.CreateMachine(typeof(M)); Letter letter = new Letter(""London""); var oc = new OtherClass(); oc.Foo(letter); this.OC = oc; this.Send(this.Target, new eUnit(letter)); // ERROR } } }"; var configuration = base.GetConfiguration(); configuration.DoStateTransitionAnalysis = false; IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '1' error."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); var error = "Error: Method 'FirstOnEntryAction' of machine 'Foo.M' sends " + "'letter', which contains data from field 'letter'."; var actual = IO.GetOutput(); Assert.AreEqual(error.Replace(Environment.NewLine, string.Empty), actual.Substring(0, actual.IndexOf(Environment.NewLine))); IO.StopWritingToMemory(); }
public void TestCreateNamedMachineStatementWithDoublePayload() { var test = @" namespace Foo { event e1 (k:int, s:string); machine M { machine Target; start state S { entry { string s = ""hello""; create(M, ""NamedMachine"", e1, 10, s); } } } }"; var configuration = Configuration.Create(); configuration.Verbose = 2; var context = CompilationContext.Create(configuration).LoadSolution(test); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); var syntaxTree = context.GetProjects()[0].PSharpPrograms[0].GetSyntaxTree(); var expected = @" using Microsoft.PSharp; namespace Foo { class e1 : Event { public int k; public string s; public e1(int k, string s) : base() { this.k = k; this.s = s; } } class M : Machine { MachineId Target; [Microsoft.PSharp.Start] [OnEntry(nameof(psharp_S_on_entry_action))] class S : MachineState { } protected void psharp_S_on_entry_action() { string s = ""hello""; this.CreateMachine(typeof(M),""NamedMachine"",new e1(10, s)); } } }"; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), syntaxTree.ToString().Replace("\n", string.Empty)); }
public void TestFieldSendAlias6Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public int Num; public Letter(string text, int num) { this.Text = text; this.Num = num; } } class M : Machine { MachineId Target; Object Obj; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { this.Target = this.CreateMachine(typeof(M)); this.Obj = (this.ReceivedEvent as eUnit).Letter; this.Send(this.Target, new eUnit((this.ReceivedEvent as eUnit).Letter)); } } }"; var configuration = base.GetConfiguration(); configuration.DoStateTransitionAnalysis = false; IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '1' error."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); var error = "Error: Method 'FirstOnEntryAction' of machine 'Foo.M' sends " + "'ReceivedEvent', which contains data from field 'Foo.M.Obj'."; var actual = IO.GetOutput(); Assert.AreEqual(error.Replace(Environment.NewLine, string.Empty), actual.Substring(0, actual.IndexOf(Environment.NewLine))); IO.StopWritingToMemory(); }
public void TestAccessInVirtualMethod9Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public Letter(string text) { this.Text = text; } } internal class Envelope { internal Letter Letter; internal virtual void Foo(Letter letter) { } } internal class SuperEnvelope : Envelope { internal override void Foo(Letter letter) { Letter = letter; // ERROR base.Letter.Text = ""Bangalore""; // ERROR } } class M : Machine { MachineId Target; bool Check; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { this.Target = this.CreateMachine(typeof(M)); var letter = new Letter(""London""); Envelope envelope = this.Foo(); this.Send(this.Target, new eUnit(letter)); this.Bar(envelope, letter); } Envelope Foo() { Envelope someEnvelope = new SuperEnvelope(); Envelope anotherEnvelope; anotherEnvelope = new Envelope(); anotherEnvelope = someEnvelope; if (this.Check) { return new Envelope(); } else { return anotherEnvelope; } } void Bar(Envelope envelope, Letter letter) { this.FooBar(envelope, letter); } void FooBar(Envelope envelope, Letter letter) { envelope.Foo(letter); } } }"; var configuration = base.GetConfiguration(); configuration.DoStateTransitionAnalysis = false; IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '3' errors."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
public void TestReturnAliasAccess8Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Envelope Envelope; public eUnit(Envelope envelope) : base() { this.Envelope = envelope; } } struct Envelope { public Letter Letter; public Envelope(Letter letter) { this.Letter = letter; } } struct Letter { public string Text; public int Num; public Letter(string text, int num) { this.Text = text; this.Num = num; } } class M : Machine { MachineId Target; Letter Letter; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { this.Target = this.CreateMachine(typeof(M)); this.Foo(); } void Foo() { var letter = new Letter(""test"", 0); var envelope = new Envelope(letter); envelope.Letter = this.Bar(); this.Send(this.Target, new eUnit(envelope)); } Letter Bar() { return this.Letter; } } }"; var configuration = base.GetConfiguration(); configuration.DoStateTransitionAnalysis = false; IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '1' error."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); var error = "Error: Method 'Foo' of machine 'Foo.M' sends 'envelope', " + "which contains data from field 'Foo.M.Letter'."; var actual = IO.GetOutput(); Assert.AreEqual(error.Replace(Environment.NewLine, string.Empty), actual.Substring(0, actual.IndexOf(Environment.NewLine))); IO.StopWritingToMemory(); }
public void TestSwitchStatement() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public Letter(string text) { this.Text = text; } } class M : Machine { MachineId Target; int Num; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { this.Target = this.CreateMachine(typeof(M)); var letter = new Letter(""London""); this.Send(this.Target, new eUnit(letter)); switch (this.Num) { case 0: case 1: letter = new Letter(""Taipei""); break; case 2: letter = new Letter(""Redmond""); break; default: letter = new Letter(""Bangalore""); break; } letter.Text = ""text""; } } }"; var configuration = base.GetConfiguration(); IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "No static analysis errors detected."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); IO.StopWritingToMemory(); }
public void TestWriteAccessAfterSendInCallee5Fail() { var test = @" using Microsoft.PSharp; namespace Foo { class eUnit : Event { public Letter Letter; public eUnit(Letter letter) : base() { this.Letter = letter; } } struct Letter { public string Text; public int Num; public Letter(string text, int num) { this.Text = text; this.Num = num; } public int Get() { return 0; } } class M : Machine { MachineId Target; Letter Letter; [Start] [OnEntry(nameof(FirstOnEntryAction))] class First : MachineState { } void FirstOnEntryAction() { var letter = new Letter(""test"", 0); this.Target = this.CreateMachine(typeof(M)); this.Send(this.Target, new eUnit(letter)); this.Foo(letter); } void Foo(Letter letter) { var k = letter.Get(); // ERROR } } }"; var configuration = base.GetConfiguration(); IO.StartWritingToMemory(); var context = CompilationContext.Create(configuration).LoadSolution(test, "cs"); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); AnalysisErrorReporter.ResetStats(); StaticAnalysisEngine.Create(context).Run(); var stats = AnalysisErrorReporter.GetStats(); var expected = "Static analysis detected '1' error."; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty), stats); var error = "Error: Method 'FirstOnEntryAction' of machine 'Foo.M' " + "accesses 'letter' after giving up its ownership."; var actual = IO.GetOutput(); Assert.AreEqual(error.Replace(Environment.NewLine, string.Empty), actual.Substring(0, actual.IndexOf(Environment.NewLine))); IO.StopWritingToMemory(); }
public void TestMachineNestedGroups() { var test = @" namespace Foo { machine M { group G1 { start state S1 { entry { jump(G3.S2); } } group G3 { state S2 { entry { jump(S1); } } state S3 { entry { jump(S2); } } } } } }"; var configuration = Configuration.Create(); configuration.Verbose = 2; var context = CompilationContext.Create(configuration).LoadSolution(test); ParsingEngine.Create(context).Run(); RewritingEngine.Create(context).Run(); var syntaxTree = context.GetProjects()[0].PSharpPrograms[0].GetSyntaxTree(); var expected = @" using Microsoft.PSharp; namespace Foo { class M : Machine { class G1 : StateGroup { public class G3 : StateGroup { [OnEntry(nameof(psharp_G1_G3_S2_on_entry_action))] public class S2 : MachineState { } [OnEntry(nameof(psharp_G1_G3_S3_on_entry_action))] public class S3 : MachineState { } } [Microsoft.PSharp.Start] [OnEntry(nameof(psharp_G1_S1_on_entry_action))] public class S1 : MachineState { } } protected void psharp_G1_S1_on_entry_action(){ { this.Goto(typeof(G1.G3.S2));return; } } protected void psharp_G1_G3_S2_on_entry_action(){ { this.Goto(typeof(G1.S1));return; } } protected void psharp_G1_G3_S3_on_entry_action(){ { this.Goto(typeof(G1.G3.S2));return; } } } } "; Assert.AreEqual(expected.Replace(Environment.NewLine, string.Empty).Replace("\n", string.Empty), syntaxTree.ToString().Replace("\n", string.Empty)); }