public void ExplodedGraph_BothBranchesVisited_NonCondition() { string testInput = "var str = this?.ToString();"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var countConditionEvaluated = 0; explodedGraph.ConditionEvaluated += (sender, args) => { countConditionEvaluated++; }; var visitedBlocks = new HashSet <Block>(); explodedGraph.InstructionProcessed += (sender, args) => { visitedBlocks.Add(args.ProgramPoint.Block); }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(cfg.Blocks.Count() - 1 /* Exit block */, visitedBlocks.Count); Assert.AreEqual(0, countConditionEvaluated); }
private static ISymbol GetSymbol() { var testInput = "var a = true; var b = false; b = !b; a = (b);"; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(ControlFlowGraphTest.TestInput, testInput), "Bar", out var semanticModel); return(semanticModel.GetDeclaredSymbol(method)); }
public void ExplodedGraph_SequentialInput_Max() { var inputBuilder = new StringBuilder(); for (int i = 0; i < ExplodedGraph.MaxStepCount / 2 + 1; i++) { inputBuilder.AppendLine($"var x{i} = true;"); } string testInput = inputBuilder.ToString(); SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var maxStepCountReached = false; explodedGraph.MaxStepCountReached += (sender, args) => { maxStepCountReached = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; explodedGraph.Walk(); Assert.IsFalse(explorationEnded); Assert.IsTrue(maxStepCountReached); Assert.AreEqual(0, numberOfExitBlockReached); }
public void ExplodedGraph_LoopExploration() { string testInput = "var i = 0; while (i < 1) { i = i + 1; }"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var exceeded = 0; explodedGraph.ProgramPointVisitCountExceedLimit += (sender, args) => { exceeded++; args.ProgramPoint.Block.Instructions.Where(i => i.ToString() == "i < 1").Should().NotBeEmpty(); }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(1, exceeded); }
public void ExplodedGraph_SequentialInput_Max() { var inputBuilder = new StringBuilder(); for (var i = 0; i < CSharpExplodedGraph.MaxStepCount / 2 + 1; i++) { inputBuilder.AppendLine($"var x{i} = true;"); } var testInput = inputBuilder.ToString(); var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel); var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var maxStepCountReached = false; explodedGraph.MaxStepCountReached += (sender, args) => { maxStepCountReached = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; explodedGraph.Walk(); explorationEnded.Should().BeFalse(); maxStepCountReached.Should().BeTrue(); numberOfExitBlockReached.Should().Be(0); }
public void ExplodedGraph_BothBranchesVisited_NonCondition() { var testInput = "var str = this?.ToString();"; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel); var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var countConditionEvaluated = 0; explodedGraph.ConditionEvaluated += (sender, args) => { countConditionEvaluated++; }; var visitedBlocks = new HashSet <Block>(); explodedGraph.InstructionProcessed += (sender, args) => { visitedBlocks.Add(args.ProgramPoint.Block); }; explodedGraph.Walk(); explorationEnded.Should().BeTrue(); visitedBlocks.Count.Should().Be(cfg.Blocks.Count() - 1 /* Exit block */); countConditionEvaluated.Should().Be(0); }
public void ExplodedGraph_LoopExploration() { var testInput = "var i = 0; while (i < 1) { i = i + 1; }"; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel); var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var exceeded = 0; explodedGraph.ProgramPointVisitCountExceedLimit += (sender, args) => { exceeded++; args.ProgramPoint.Block.Instructions.Should().Contain(i => i.ToString() == "i < 1"); }; explodedGraph.Walk(); explorationEnded.Should().BeTrue(); exceeded.Should().Be(1); }
public void ExplodedGraph_SingleBranchVisited_If() { string testInput = "var a = false; bool b; if (a) { b = true; } else { b = false; } a = b;"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var bSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfLastInstructionVisits = 0; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = false") { Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False); } if (args.Instruction.ToString() == "b = true") { Assert.Fail("We should never get into this branch"); } if (args.Instruction.ToString() == "b = false") { Assert.IsTrue(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False); Assert.IsNull(args.ProgramState.GetSymbolValue(aSymbol), "a is dead, so there should be no associated value to it."); } if (args.Instruction.ToString() == "a = b") { numberOfLastInstructionVisits++; } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(10, numberOfProcessedInstructions); Assert.AreEqual(1, numberOfExitBlockReached); Assert.AreEqual(1, numberOfLastInstructionVisits); }
public void ExplodedGraph_SequentialInput() { string testInput = "var a = true; var b = false; b = !b; a = (b);"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var bSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = true") { Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.True); } if (args.Instruction.ToString() == "b = false") { Assert.IsTrue(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False); } if (args.Instruction.ToString() == "b = !b") { Assert.IsFalse(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.False); Assert.IsFalse(args.ProgramState.GetSymbolValue(bSymbol) == SymbolicValue.True); } if (args.Instruction.ToString() == "a = (b)") { Assert.AreEqual( args.ProgramState.GetSymbolValue(bSymbol), args.ProgramState.GetSymbolValue(aSymbol)); } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(11, numberOfProcessedInstructions); Assert.AreEqual(1, numberOfExitBlockReached); }
public void ExplodedGraph_SequentialInput() { var testInput = "var a = true; var b = false; b = !b; a = (b);"; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var bSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b")); var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel); var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = true") { args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.True); } if (args.Instruction.ToString() == "b = false") { args.ProgramState.GetSymbolValue(bSymbol).Should().Be(SymbolicValue.False); } if (args.Instruction.ToString() == "b = !b") { args.ProgramState.GetSymbolValue(bSymbol).Should().NotBe(SymbolicValue.False); args.ProgramState.GetSymbolValue(bSymbol).Should().NotBe(SymbolicValue.True); } if (args.Instruction.ToString() == "a = (b)") { args.ProgramState.GetSymbolValue(bSymbol) .Should().Be(args.ProgramState.GetSymbolValue(aSymbol)); } }; explodedGraph.Walk(); explorationEnded.Should().BeTrue(); numberOfProcessedInstructions.Should().Be(9); numberOfExitBlockReached.Should().Be(1); }
public void ExplodedGraph_AllBranchesVisited() { string testInput = "int i = 1; switch (i) { case 1: default: cw1(); break; case 2: cw2(); break; }"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfCw1InstructionVisits = 0; var numberOfCw2InstructionVisits = 0; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "cw1()") { numberOfCw1InstructionVisits++; } if (args.Instruction.ToString() == "cw2()") { numberOfCw2InstructionVisits++; } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(1, numberOfExitBlockReached); Assert.AreEqual(1, numberOfCw1InstructionVisits); Assert.AreEqual(1, numberOfCw2InstructionVisits); }
public void ExplodedGraph_BothBranchesVisited_StateMerge() { string testInput = "var a = !true; bool b; if (inParameter) { b = false; } else { b = false; } a = b;"; SemanticModel semanticModel; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfLastInstructionVisits = 0; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = b") { Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False); numberOfLastInstructionVisits++; } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(1, numberOfExitBlockReached); Assert.AreEqual(1, numberOfLastInstructionVisits); }
public void ExplodedGraph_SingleBranchVisited_And() { string testInput = "var a = false; if (a && !a) { a = true; }"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = !true") { Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False); // Roslyn is clever !true has const value. } if (args.Instruction.ToString() == "!a") { Assert.Fail("We should never get into this branch"); } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(1, numberOfExitBlockReached); }
public LiveVariableAnalysisContext(string methodBody, string localFunctionName = null) { var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, methodBody), "Main", out var semanticModel); IMethodSymbol symbol; CSharpSyntaxNode body; if (localFunctionName == null) { symbol = semanticModel.GetDeclaredSymbol(method); body = method.Body; } else { var function = (LocalFunctionStatementSyntaxWrapper)method.DescendantNodes().Single(x => x.Kind() == SyntaxKindEx.LocalFunctionStatement && ((LocalFunctionStatementSyntaxWrapper)x).Identifier.Text == localFunctionName); symbol = semanticModel.GetDeclaredSymbol(function) as IMethodSymbol; body = (CSharpSyntaxNode)function.Body ?? function.ExpressionBody; } this.CFG = CSharpControlFlowGraph.Create(body, semanticModel); this.LVA = CSharpLiveVariableAnalysis.Analyze(this.CFG, symbol, semanticModel); }
public void ExplodedGraph_NonLocalNorFieldSymbolBranching() { string testInput = "if (Property) { cw(); }"; SemanticModel semanticModel; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var propertySymbol = semanticModel.GetSymbolInfo( method.DescendantNodes().OfType <IdentifierNameSyntax>().First(d => d.Identifier.ToString() == "Property")).Symbol; propertySymbol.Should().NotBeNull(); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "Property") { args.ProgramState.GetSymbolValue(propertySymbol).Should().BeNull(); } }; explodedGraph.Walk(); explorationEnded.Should().BeTrue(); numberOfExitBlockReached.Should().Be(1); }
public void ExplodedGraph_NonLocalSymbolBranching() { string testInput = "if (field) { cw(); }"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var fieldSymbol = semanticModel.GetSymbolInfo( method.DescendantNodes().OfType <IdentifierNameSyntax>().First(d => d.Identifier.ToString() == "field")).Symbol; Assert.IsNotNull(fieldSymbol); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "field") { Assert.IsNull(args.ProgramState.GetSymbolValue(fieldSymbol)); } }; explodedGraph.Walk(); Assert.IsTrue(explorationEnded); Assert.AreEqual(1, numberOfExitBlockReached); }
public void ExplodedGraph_SequentialInput_OutParameter() { string testInput = "outParameter = true;"; SemanticModel semanticModel; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var parameters = method.DescendantNodes().OfType <ParameterSyntax>(); var outParameterSymbol = semanticModel.GetDeclaredSymbol(parameters.First(d => d.Identifier.ToString() == "outParameter")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfProcessedInstructions = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "outParameter = true") { args.ProgramState.GetSymbolValue(outParameterSymbol) .Should().Be(SymbolicValue.True); } }; explodedGraph.Walk(); explorationEnded.Should().BeTrue(); numberOfProcessedInstructions.Should().Be(2); numberOfExitBlockReached.Should().Be(1); }
public void ExplodedGraph_NonDecisionMakingAssignments() { string testInput = "var a = true; a |= false; var b = 42; b++; ++b;"; SemanticModel semanticModel; var method = ControlFlowGraphTest.Compile(string.Format(TestInput, testInput), "Bar", out semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var bSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b")); var cfg = ControlFlowGraph.Create(method.Body, semanticModel); var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new ExplodedGraph(cfg, methodSymbol, semanticModel, lva); SymbolicValue sv = null; var numberOfProcessedInstructions = 0; var branchesVisited = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = true") { branchesVisited++; Assert.IsTrue(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.True); } if (args.Instruction.ToString() == "a |= false") { branchesVisited++; Assert.IsNotNull(args.ProgramState.GetSymbolValue(aSymbol)); Assert.IsFalse(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.False); Assert.IsFalse(args.ProgramState.GetSymbolValue(aSymbol) == SymbolicValue.True); } if (args.Instruction.ToString() == "b = 42") { branchesVisited++; sv = args.ProgramState.GetSymbolValue(bSymbol); Assert.IsNotNull(sv); } if (args.Instruction.ToString() == "b++") { branchesVisited++; var svNew = args.ProgramState.GetSymbolValue(bSymbol); Assert.IsNotNull(svNew); Assert.AreNotEqual(sv, svNew); } if (args.Instruction.ToString() == "++b") { branchesVisited++; var svNew = args.ProgramState.GetSymbolValue(bSymbol); Assert.IsNotNull(svNew); Assert.AreNotEqual(sv, svNew); } }; explodedGraph.Walk(); Assert.AreEqual(11, numberOfProcessedInstructions); Assert.AreEqual(5, branchesVisited); }
public void ExplodedGraph_NonDecisionMakingAssignments() { var testInput = "var a = true; a |= false; var b = 42; b++; ++b;"; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var bSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b")); var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel); var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva); SymbolicValue sv = null; var numberOfProcessedInstructions = 0; var branchesVisited = 0; explodedGraph.InstructionProcessed += (sender, args) => { numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = true") { branchesVisited++; args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.True); } if (args.Instruction.ToString() == "a |= false") { branchesVisited++; args.ProgramState.GetSymbolValue(aSymbol).Should().NotBeNull(); args.ProgramState.GetSymbolValue(aSymbol).Should().NotBe(SymbolicValue.False); args.ProgramState.GetSymbolValue(aSymbol).Should().NotBe(SymbolicValue.True); } if (args.Instruction.ToString() == "b = 42") { branchesVisited++; sv = args.ProgramState.GetSymbolValue(bSymbol); sv.Should().NotBeNull(); } if (args.Instruction.ToString() == "b++") { branchesVisited++; var svNew = args.ProgramState.GetSymbolValue(bSymbol); svNew.Should().NotBeNull(); svNew.Should().NotBe(sv); } if (args.Instruction.ToString() == "++b") { branchesVisited++; var svNew = args.ProgramState.GetSymbolValue(bSymbol); svNew.Should().NotBeNull(); svNew.Should().NotBe(sv); } }; explodedGraph.Walk(); numberOfProcessedInstructions.Should().Be(11); branchesVisited.Should().Be(5); }
public void ExplodedGraph_BothBranchesVisited() { var testInput = "var a = false; bool b; if (inParameter) { b = inParameter; } else { b = !inParameter; } a = b;"; var method = ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, testInput), "Bar", out var semanticModel); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var varDeclarators = method.DescendantNodes().OfType <VariableDeclaratorSyntax>(); var aSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "a")); var bSymbol = semanticModel.GetDeclaredSymbol(varDeclarators.First(d => d.Identifier.ToString() == "b")); var parameters = method.DescendantNodes().OfType <ParameterSyntax>(); var inParameterSymbol = semanticModel.GetDeclaredSymbol(parameters.First(d => d.Identifier.ToString() == "inParameter")); var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel); var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var numberOfExitBlockReached = 0; explodedGraph.ExitBlockReached += (sender, args) => { numberOfExitBlockReached++; }; var numberOfLastInstructionVisits = 0; var numberOfProcessedInstructions = 0; var visitedBlocks = new HashSet <Block>(); var branchesVisited = 0; explodedGraph.InstructionProcessed += (sender, args) => { visitedBlocks.Add(args.ProgramPoint.Block); numberOfProcessedInstructions++; if (args.Instruction.ToString() == "a = false") { branchesVisited++; args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.False); // Roslyn is clever !true has const value. } if (args.Instruction.ToString() == "b = inParameter") { branchesVisited++; bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState).Should().BeTrue(); inParameterSymbol.HasConstraint(BoolConstraint.True, args.ProgramState).Should().BeTrue(); } if (args.Instruction.ToString() == "b = !inParameter") { branchesVisited++; // b has value, but not true or false args.ProgramState.GetSymbolValue(bSymbol).Should().NotBeNull(); bSymbol.HasConstraint(BoolConstraint.False, args.ProgramState).Should().BeFalse(); bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState).Should().BeFalse(); inParameterSymbol.HasConstraint(BoolConstraint.False, args.ProgramState).Should().BeTrue(); } if (args.Instruction.ToString() == "a = b") { branchesVisited++; args.ProgramState.GetSymbolValue(inParameterSymbol).Should().BeNull(); // not out/ref parameter and LVA says dead numberOfLastInstructionVisits++; } }; explodedGraph.Walk(); explorationEnded.Should().BeTrue(); branchesVisited.Should().Be(4 + 1); numberOfExitBlockReached.Should().Be(1, "All variables are dead at the ExitBlock, so whenever we get there, the ExplodedGraph nodes should be the same, " + "and thus should be processed only once."); numberOfLastInstructionVisits.Should().Be(2); visitedBlocks.Count.Should().Be(cfg.Blocks.Count() - 1 /* Exit block*/); }
public ExplodedGraphContext(string methodBody) : this(ControlFlowGraphTest.CompileWithMethodBody(string.Format(TestInput, methodBody), "Main", out var semanticModel), semanticModel) { }
public void ExplodedGraph_InternalStateCount_MaxReached() { var testInput = @" using System; namespace TesteAnalyzer { class Program { static bool GetBool() { return bool.Parse(""True""); } static void Main(string[] args) { bool corrupted = false; corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); corrupted |= !GetBool(); if (!corrupted) { Console.Out.WriteLine(); } } } } "; var tree = ControlFlowGraphTest.Compile(testInput, out var semanticModel); var method = tree.GetRoot().DescendantNodes().OfType <MethodDeclarationSyntax>().First(m => m.Identifier.ValueText == "Main"); var methodSymbol = semanticModel.GetDeclaredSymbol(method); var cfg = CSharpControlFlowGraph.Create(method.Body, semanticModel); var lva = CSharpLiveVariableAnalysis.Analyze(cfg, methodSymbol, semanticModel); var explodedGraph = new CSharpExplodedGraph(cfg, methodSymbol, semanticModel, lva); var explorationEnded = false; explodedGraph.ExplorationEnded += (sender, args) => { explorationEnded = true; }; var maxStepCountReached = false; explodedGraph.MaxStepCountReached += (sender, args) => { maxStepCountReached = true; }; var maxInternalStateCountReached = false; explodedGraph.MaxInternalStateCountReached += (sender, args) => { maxInternalStateCountReached = true; }; explodedGraph.Walk(); explorationEnded.Should().BeFalse(); maxStepCountReached.Should().BeFalse(); maxInternalStateCountReached.Should().BeTrue(); }
public string Main() {{ return {ControlFlowGraphTest.ExtremelyNestedExpression()}; }} }}";