Example #1
0
        /// <summary>
        /// Given:
        ///   - a file-to-file map (<paramref name="file2file"/>), and
        ///   - indexes of changed nodes (<paramref name="changed"/>)
        /// computes
        ///   - downstream nodes (and asserts they match <paramref name="expectedDownstream"/>
        ///   - upsteram nodes (and asserts they match <paramref name="expectedUpstream"/>
        ///   - indirect upstream nodes (and asserts they match <paramref name="expectedIndirectUpstream"/>
        ///   - all affected nodes (and asserts they match <paramref name="expectedAffected"/>
        ///
        /// Definitions:
        ///   - 'downstream' nodes: all nodes reachable from <paramref name="changed"/> (excluding the
        ///     changed nodes themselves) by following the reverse edges in <paramref name="file2file"/>
        ///   - 'upstream' nodes: all nodes reachable from <paramref name="changed"/> (excluding the
        ///     changed nodes themselves) by following the edges in <paramref name="file2file"/>
        ///   - 'affected' nodes: upstream of 'changed' + 'downstream' nodes, including the changed and
        ///     downstream nodes themselves
        ///   - 'indirect upstream' nodes: 'affected' nodes that are neither 'changed' or 'upstream' or 'downstream'
        /// </summary>
        /// <remarks>
        /// Some remarks about the notation in the comments below:
        ///   - the '^' means transitive closure
        ///   - the '*' means reflexive transitive closure
        ///   - the '.' means relational join
        /// For example
        ///   - changed.^Edges means all reachable nodes from 'changed' by following 'Edges', excluding the nodes in 'changed'
        ///   - changed.*Edges means all reachable nodes from 'changed' by following 'Edges', including the nodes in 'changed'.
        /// </remarks>
        private void ComputeAndCheckSpecStates(SimpleGraph file2file, int[] changed, int[] expectedDownstream,
                                               int[] expectedUpstream, int[] expectedIndirectUpstream, int[] expectedAffected)
        {
            // downstream = changed.^reverseEdges
            var downstream = file2file.ComputeDownstream(changed);

            XAssert.AreSetsEqual(expectedDownstream, downstream, expectedResult: true, format: "Downstream nodes don't match");

            // upstream = changed.^edges
            var upstream = file2file.ComputeUpstream(changed);

            XAssert.AreSetsEqual(expectedUpstream, upstream, expectedResult: true, format: "Upstream nodes don't match");

            // allAffected = (changed.*reverseEdges).*edges
            var allAffected = file2file.ComputeReflexiveUpstream(file2file.ComputeReflexiveDownstream(changed));

            XAssert.AreSetsEqual(expectedAffected, allAffected, expectedResult: true, format: "Affected nodes don't match");

            // indirectUpstream = allAffected - changed - upstream - downstream
            var indirectUpstream = allAffected.Except(changed).Except(upstream).Except(downstream);

            XAssert.AreSetsEqual(expectedIndirectUpstream, indirectUpstream, expectedResult: true, format: "Indirect upstream nodes don't match");
        }