Пример #1
0
        public ExplorationState(Path path, CallSiteStack callSiteStack, SmtSolverHandler solverHandler)
        {
            Contract.Requires(path != null);
            Contract.Requires(solverHandler != null);

            this.Path          = path;
            this.CallSiteStack = callSiteStack;
            this.SolverHandler = solverHandler;
        }
Пример #2
0
        // TODO: Divide into submethods to make more readable
        internal async Task <bool> ExploreAsync(CancellationToken cancelToken)
        {
            for (
                var currentState = this.ExplorationHeuristic.PickNextState();
                currentState != null;
                currentState = this.ExplorationHeuristic.PickNextState())
            {
                // TODO: Consider reusing the state instead of discarding
                this.RemoveState(currentState);

                IReadOnlyList <FlowEdge> edges;
                var currentNode   = currentState.Path.Node;
                var graphProvider = this.context.FlowGraphProvider;
                if (currentNode is EnterFlowNode)
                {
                    if (currentState.CallSiteStack == CallSiteStack.Empty)
                    {
                        edges = await graphProvider.GetCallEdgesToAsync((EnterFlowNode)currentNode);
                    }
                    else
                    {
                        // The execution is constrained by the call site on the stack
                        var edge = graphProvider.GetCallEdge(
                            currentState.CallSiteStack.CallSite,
                            (EnterFlowNode)currentNode);
                        edges = edge.ToSingular();
                    }
                }
                else if ((currentNode as CallFlowNode)?.Location.CanBeExplored == true &&
                         !(currentState.Path.Preceeding.FirstOrDefault()?.Node is EnterFlowNode))
                {
                    // If we can model the call and we haven't returned from that method yet
                    edges = await graphProvider.GetReturnEdgesToAsync((CallFlowNode)currentNode);
                }
                else
                {
                    edges = currentNode.IngoingEdges;
                }

                var toSolve = new List <ExplorationState>();

                int i = 0;
                foreach (bool doBranch in this.ExplorationHeuristic.DoBranch(currentState, edges))
                {
                    var edge = edges[i];
                    if (doBranch && this.IsEdgeAllowed(edge))
                    {
                        var branchedPath = new Path(
                            ImmutableArray.Create(currentState.Path),
                            currentState.Path.Depth + 1,
                            edge.From,
                            ImmutableArray.Create(edge));
                        CallSiteStack callSiteStack = GetNewCallSiteStack(currentState, edge);

                        var branchedState = new ExplorationState(
                            branchedPath,
                            callSiteStack,
                            currentState.SolverHandler);

                        bool wasMerged = false;
                        foreach (var mergeCandidate in this.statesOnLocations[branchedState.Path.Node].ToArray())
                        {
                            if (this.MergingHeuristic.DoMerge(branchedState, mergeCandidate))
                            {
                                SmtSolverHandler solverHandler;
                                if (branchedState.SolverHandler != mergeCandidate.SolverHandler)
                                {
                                    solverHandler = this.SmtHeuristic.SelectMergedSolverHandler(
                                        branchedState,
                                        mergeCandidate);
                                }
                                else
                                {
                                    solverHandler = branchedState.SolverHandler;
                                }

                                mergeCandidate.Merge(branchedState, solverHandler);
                                wasMerged = true;

                                break;
                            }
                        }

                        if (!wasMerged)
                        {
                            this.AddState(branchedState);
                        }

                        if (this.IsFinalState(branchedState) || this.SmtHeuristic.DoSolve(branchedState))
                        {
                            toSolve.Add(branchedState);
                        }
                    }
                    else
                    {
                        this.IsUnderapproximated = true;
                    }

                    i++;
                }

                if (toSolve.Count > 0)
                {
                    int j = 0;
                    foreach (bool doReuse in this.SmtHeuristic.DoReuse(currentState.SolverHandler, toSolve))
                    {
                        if (!doReuse)
                        {
                            toSolve[j].SolverHandler = currentState.SolverHandler.Clone();
                        }

                        j++;
                    }

                    foreach (var branchedState in toSolve)
                    {
                        var resultKind = branchedState.SolverHandler.Solve(branchedState.Path);
                        SolverCallCount++;

                        if (resultKind != ExplorationResultKind.Reachable || this.IsFinalState(branchedState))
                        {
                            this.RemoveState(branchedState);
                            var result = branchedState.SolverHandler.LastResult;
                            this.resultCallback(result);
                        }
                    }
                }

                // Check the cancellation before picking next node
                if (cancelToken.IsCancellationRequested)
                {
                    // It is an expected behaviour with well defined result, there is no need to throw an exception
                    break;
                }
            }

            // If there are any exploration states left, the results are not exhaustive
            return(this.States.Count == 0);
        }