예제 #1
0
        public async Task ExplorationResultIsCorrect(
            CSharpFlowGraphProvider graphProvider,
            IMethodSymbol methodSymbol,
            InvocationExpressionSyntax targetSyntax)
        {
            string assertionName  = ((MemberAccessExpressionSyntax)targetSyntax.Expression).Name.Identifier.Text;
            bool   isAssertion    = assertionName.EndsWith("Assert");
            bool   shouldFindPath = assertionName.Contains("Invalid");

            var methodLocation = new MethodLocation(methodSymbol);
            var flowGraph      = await graphProvider.GetFlowGraphAsync(methodLocation);

            var displayGraph = graphProvider.GetDisplayGraph(flowGraph.Id);

            var displayNode   = displayGraph.Nodes.First(n => n.Span.Contains(targetSyntax.Span));
            var displayRecord = displayNode.Records.Last();
            var startInfo     = new StartingNodeInfo(displayRecord.FlowNode, displayRecord.OperationIndex, isAssertion);
            var options       = new ExplorationOptions()
            {
                FinalNodeRecognizer = new PublicMethodEntryRecognizer(),
                TimeoutSeconds      = 60
            };
            var exploration = new ExplorationContext(graphProvider, new ContextFactory(), startInfo, options);

            // Cancel after the first found path to save time
            bool success      = !shouldFindPath;
            var  cancelSource = new CancellationTokenSource();

            exploration.ExecutionModelsObservable
            .Subscribe(m => { success = shouldFindPath; cancelSource.Cancel(); }, cancelSource.Token);
            bool wasExhaustive = await exploration.ExploreAsync(cancelSource);

            string message = shouldFindPath ? "No path was found" : "A path was found, although it shouldn't have been";

            if (success && !shouldFindPath && !wasExhaustive)
            {
                success = false;
                message = $"No path was found during the {options.TimeoutSeconds} second timeout";
            }

            Assert.IsTrue(success, message);
        }
예제 #2
0
        private static ResultRow[] EvaluateProgram(
            CSharpFlowGraphProvider graphProvider,
            string programName,
            IMethodSymbol methodSymbol,
            InvocationExpressionSyntax invocation)
        {
            string assertionName  = ((MemberAccessExpressionSyntax)invocation.Expression).Name.Identifier.Text;
            bool   isAssertion    = assertionName.EndsWith("Assert");
            bool   shouldFindPath = assertionName.Contains("Invalid");

            var methodLocation = new MethodLocation(methodSymbol);
            var flowGraph      = graphProvider.GetFlowGraphAsync(methodLocation).Result;
            var displayGraph   = graphProvider.GetDisplayGraph(flowGraph.Id);

            var displayNode   = displayGraph.Nodes.First(n => n.Span.Contains(invocation.Span));
            var displayRecord = displayNode.Records.Last();
            var startInfo     = new StartingNodeInfo(displayRecord.FlowNode, displayRecord.OperationIndex, isAssertion);
            var options       = new ExplorationOptions()
            {
                FinalNodeRecognizer = new PublicMethodEntryRecognizer(),
                TimeoutSeconds      = 40
            };

            var heuristics = GetHeuristicFactories().ToArray();

            var results = new ResultRow[heuristics.Length * RepeatCount];

            int j = 0;

            foreach ((string heuristicName, var heuristicFactory) in heuristics)
            {
                options.SmtHeuristicFactory = heuristicFactory;

                for (int i = 0; i < RepeatCount; i++)
                {
                    var  stopwatch  = new Stopwatch();
                    long?ticksFirst = null;
                    int? callsFirst = null;

                    var exploration = new ExplorationContext(graphProvider, new ContextFactory(), startInfo, options);
                    exploration.ExecutionModelsObservable
                    .Subscribe(m => { ticksFirst = stopwatch.ElapsedTicks; callsFirst = Explorer.SolverCallCount; });

                    stopwatch.Start();
                    exploration.ExploreAsync().ContinueWith(t => stopwatch.Stop()).Wait();
                    long ticksTotal = stopwatch.ElapsedTicks;

                    results[j * RepeatCount + i] = new ResultRow
                    {
                        Heuristic = heuristicName,
                        Program   = programName,
                        FirstCounterexampleTime  = ticksFirst / (double)Stopwatch.Frequency,
                        FirstCounterexampleCalls = callsFirst,
                        TotalTime  = ticksTotal / (double)Stopwatch.Frequency,
                        TotalCalls = Explorer.SolverCallCount
                    };
                }

                j++;
            }

            return(results);
        }
예제 #3
0
        private async void Explore(bool isAssertCheck)
        {
            if (this.IsExploring)
            {
                return;
            }

            this.SelectedPath = null;
            this.Paths.Clear();
            this.foundModels.Clear();
            this.Messages.Clear();
            this.Messages.Add("Analyzing the code on the caret position...");

            this.UpdateCurrentSolution();
            var info = await this.GatherInformationForCurrentCaretPosition();

            if (!info.IsComplete)
            {
                this.Messages.Add("Unable to start the exploration from the selected statement. Ensure the caret is on a valid position and the method contains only supported constructs.");
                this.Messages.Add("Note: The tool is currently unable to recognize the statement when its trailing semicolon is selected, please place the cursor in the middle of it.");
                return;
            }
            else if (isAssertCheck && !info.IsAssertion)
            {
                this.Messages.Add("Only the correctness of assertions can be verified.");
                return;
            }

            Contract.Assert(info.SelectedDisplayNode.Records.Any());
            var flowNodeRecord = info.SelectedDisplayNode.Records.Last();

            var startNode = new StartingNodeInfo(
                flowNodeRecord.FlowNode,
                flowNodeRecord.OperationIndex,
                isAssertCheck);
            var z3ContextFactory = new ContextFactory();
            var options          = new ExplorationOptions
            {
                FinalNodeRecognizer = new PublicMethodEntryRecognizer(),
                TimeoutSeconds      = (this.Timeout > 0) ? this.Timeout : (int?)null,
                IgnoredMethods      = string.IsNullOrEmpty(this.IgnoredMethods)
                    ? ImmutableArray <string> .Empty
                    : this.IgnoredMethods.Split(new[] { Environment.NewLine }, StringSplitOptions.None).ToImmutableArray()
            };

            this.ExplorationContext = new ExplorationContext(this.GraphProvider, z3ContextFactory, startNode, options);

            try
            {
                await this.ExploreImpl(isAssertCheck);
            }
            catch (Exception e)
            {
                this.Messages.Add($"Error during the exploration: {e.Message}");
                Trace.WriteLine(e.ToString());

                if (this.explorationCancelSource != null)
                {
                    this.explorationCancelSource.Cancel();
                }

                this.IsExploring = false;
                this.CallGraph.Redraw();
            }
        }