public void EmptyThrowExceptionNodeCreatedProperly()
        {
            var graphId = new FlowGraphId(1);
            var builder = new FlowGraphBuilder(graphId);

            var location = new TestRoutineLocation("ExceptionConstructor");

            var node = builder.AddThrowExceptionNode(location);

            FlowGraphTestHelper.CheckThrowExceptionNode(node, builder.Graph, 0, 0, location, 0);
        }
        public void EmptyCallNodeCreatedProperly()
        {
            var graphId = new FlowGraphId(1);
            var builder = new FlowGraphBuilder(graphId);

            var location = new TestRoutineLocation("CalledRoutine");

            var node = builder.AddCallNode(location);

            FlowGraphTestHelper.CheckCallNode(node, builder.Graph, 0, 0, location, 0, 0);
        }
        public static FlowGraph ComplexExampleGraph(FlowGraphId id)
        {
            var builder = new FlowGraphBuilder(id);

            var aVar      = builder.AddLocalVariable(Sort.Int, "a");
            var a         = (IntHandle)aVar;
            var bVar      = builder.AddLocalVariable(Sort.Int, "b");
            var b         = (IntHandle)bVar;
            var cVar      = builder.AddLocalVariable(Sort.Bool, "c");
            var c         = (BoolHandle)cVar;
            var enterNode = builder.AddEnterNode(new[] { aVar, bVar, cVar });

            var if1Var  = builder.AddLocalVariable(Sort.Bool, "if!1");
            var if1     = (BoolHandle)if1Var;
            var if1Node = builder.AddInnerNode(new Assignment(if1Var, a == 0));

            var ret1Node = builder.AddReturnNode(new[] { ExpressionFactory.IntInterpretation(-1) });

            var isNiceNumberLocation = new TestRoutineLocation("IsNiceNumber");
            var if21Var  = builder.AddLocalVariable(Sort.Bool, "if!2!1");
            var if21     = (BoolHandle)if21Var;
            var if21Node = builder.AddCallNode(isNiceNumberLocation, new[] { aVar }, new[] { if21Var });

            var if22CheckVar  = builder.AddLocalVariable(Sort.Bool, "if!2!2!check");
            var if22Check     = (BoolHandle)if22CheckVar;
            var if22CheckNode = builder.AddInnerNode(new Assignment(if22CheckVar, b != 0));

            var exceptionLocation = new TestRoutineLocation("DivisionByZeroException");
            var if22ThrowNode     = builder.AddThrowExceptionNode(exceptionLocation);

            var if22Var  = builder.AddLocalVariable(Sort.Bool, "if!2!2");
            var if22     = (BoolHandle)if22Var;
            var if22Node = builder.AddInnerNode(new Assignment(if22Var, a / b > 2 && b != -1));

            var dVar         = builder.AddLocalVariable(Sort.Int, "d");
            var d            = (IntHandle)dVar;
            var dEqualsBNode = builder.AddInnerNode(new Assignment(dVar, bVar));

            var while1Var  = builder.AddLocalVariable(Sort.Bool, "while!1");
            var while1     = (BoolHandle)while1Var;
            var while1Node = builder.AddInnerNode(new[] { new Assignment(while1Var, a < b) }, FlowNodeFlags.LoopCondition);

            var assert1Var    = builder.AddLocalVariable(Sort.Bool, "assert!1");
            var assert1       = (BoolHandle)assert1Var;
            var whileBodyNode = builder.AddInnerNode(
                new[]
            {
                new Assignment(aVar, a + a),
                new Assignment(assert1Var, a != 0)
            },
                FlowNodeFlags.LoopBody);

            var elseBodyNode = builder.AddInnerNode(new Assignment(aVar, a + b));

            var ret2Node = builder.AddReturnNode(new[] { aVar });

            builder.AddEdge(enterNode, if1Node);
            builder.AddEdge(if1Node, ret1Node, if1);
            builder.AddEdge(if1Node, if21Node, !if1);
            builder.AddEdge(if21Node, if22CheckNode, if21);
            builder.AddEdge(if22CheckNode, if22ThrowNode, !if22Check);
            builder.AddEdge(if22CheckNode, if22Node, if22Check);
            builder.AddEdge(if22Node, dEqualsBNode, if22);
            builder.AddEdge(dEqualsBNode, while1Node);
            builder.AddEdge(while1Node, whileBodyNode, while1);
            builder.AddEdge(whileBodyNode, while1Node);
            builder.AddEdge(while1Node, ret2Node, !while1);
            builder.AddEdge(if21Node, elseBodyNode, !if21);
            builder.AddEdge(if22Node, elseBodyNode, !if22);
            builder.AddEdge(elseBodyNode, ret2Node);

            return(builder.FreezeAndReleaseGraph());
        }
Beispiel #4
0
        public TestFlowGraphProvider(Type generatorClass)
        {
            Contract.Requires(generatorClass != null);

            var generators = generatorClass
                             .GetMethods(BindingFlags.Public | BindingFlags.Static)
                             .Where(
                methodInfo => methodInfo.ReturnType == typeof(FlowGraph) &&
                !methodInfo.ContainsGenericParameters &&
                methodInfo.GetParameters()
                .Select(p => p.ParameterType)
                .SequenceEqual(new[] { typeof(FlowGraphId) }));

            var generatorToGraphMap = new Dictionary <MethodInfo, FlowGraph>();
            var locations           = new List <TestRoutineLocation>();
            var graphs = new List <FlowGraph>();

            // We have to generate all the graphs beforehand due to immutability
            int id = 0;

            foreach (var generator in generators)
            {
                var props = generator.GetCustomAttribute <GeneratedMethodPropertiesAttribute>()
                            ?? new GeneratedMethodPropertiesAttribute();

                var graph    = (FlowGraph)generator.Invoke(null, new object[] { new FlowGraphId(id) });
                var location = new TestRoutineLocation(generator, props.IsConstructor);

                generatorToGraphMap.Add(generator, graph);
                graphs.Add(graph);
                locations.Add(location);

                id++;
            }

            // Gather a list of call nodes for each graph being called
            var graphCallSites = new List <CallFlowNode> [graphs.Count];

            foreach (var callNode in graphs.SelectMany(g => g.Nodes).OfType <CallFlowNode>())
            {
                if (callNode.Location.CanBeExplored)
                {
                    var calledGen = ((TestRoutineLocation)callNode.Location).Generator;
                    var calledId  = generatorToGraphMap[calledGen].Id;

                    if (graphCallSites[calledId.Value] == null)
                    {
                        graphCallSites[calledId.Value] = new List <CallFlowNode>()
                        {
                            callNode
                        };
                    }
                    else
                    {
                        graphCallSites[calledId.Value].Add(callNode);
                    }
                }
            }

            this.generatorToGraphMap = new ReadOnlyDictionary <MethodInfo, FlowGraph>(generatorToGraphMap);
            this.graphs         = graphs.ToImmutableArray();
            this.graphCallSites = graphCallSites
                                  .Select(c => c?.ToImmutableArray() ?? ImmutableArray <CallFlowNode> .Empty)
                                  .ToImmutableArray();
            this.locations = locations.ToImmutableArray();
            this.GeneratedMethodLocations = locations.ToImmutableArray();
        }