mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-01 17:24:42 -05:00
Adds new graph comparison request handler to the Execution Plan Service. (#1438)
* Adds new graph comparison request handler to the Execution Plan Service. * Code review changes * Renames execution plan compare params, result, and request classes.
This commit is contained in:
@@ -9,7 +9,9 @@ using System.IO;
|
||||
using System.Reflection;
|
||||
using NUnit.Framework;
|
||||
using Microsoft.SqlTools.ServiceLayer.ExecutionPlan;
|
||||
|
||||
using Microsoft.SqlTools.ServiceLayer.ExecutionPlan.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan;
|
||||
using Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan.Comparison;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ShowPlan
|
||||
{
|
||||
@@ -21,18 +23,265 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ShowPlan
|
||||
public void ParseXMLFileReturnsValidShowPlanGraph()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var showPlanGraphs = ShowPlanGraphUtils.CreateShowPlanGraph(queryPlanFileText, "testFile.sql");
|
||||
var showPlanGraphs = ExecutionPlanGraphUtils.CreateShowPlanGraph(queryPlanFileText, "testFile.sql");
|
||||
Assert.AreEqual(1, showPlanGraphs.Count, "exactly one show plan graph should be returned");
|
||||
Assert.NotNull(showPlanGraphs[0], "graph should not be null");
|
||||
Assert.NotNull(showPlanGraphs[0].Root, "graph should have a root");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_CreateSkeleton()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var graphs = ShowPlanGraph.ParseShowPlanXML(this.queryPlanFileText, ShowPlanType.Unknown);
|
||||
var rootNode = graphs[0].Root;
|
||||
|
||||
Assert.NotNull(rootNode, "graph should have a root");
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var skeletonNode = skeletonManager.CreateSkeleton(rootNode);
|
||||
|
||||
Assert.NotNull(skeletonNode, "skeletonNode should not be null");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_CreateSkeletonUsingDefaultConfiguredNode()
|
||||
{
|
||||
var graph = new ShowPlanGraph()
|
||||
{
|
||||
Root = null,
|
||||
Description = new Description()
|
||||
};
|
||||
var context = new NodeBuilderContext(graph, ShowPlanType.Unknown, null);
|
||||
var node = new Node(default, context);
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var skeletonNode = skeletonManager.CreateSkeleton(node);
|
||||
|
||||
Assert.NotNull(skeletonNode, "skeletonNode should not be null");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_DuplicateSkeletons()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var graphs = ShowPlanGraph.ParseShowPlanXML(this.queryPlanFileText, ShowPlanType.Unknown);
|
||||
var rootNode = graphs[0].Root;
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var skeletonNode = skeletonManager.CreateSkeleton(rootNode);
|
||||
var skeletonNode2 = skeletonManager.CreateSkeleton(rootNode);
|
||||
|
||||
var skeletonCompareResult = skeletonManager.AreSkeletonsEquivalent(skeletonNode, skeletonNode2, ignoreDatabaseName: true);
|
||||
|
||||
Assert.IsTrue(skeletonCompareResult);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_TwoDefaultConfiguredSkeletons()
|
||||
{
|
||||
var graph = new ShowPlanGraph()
|
||||
{
|
||||
Root = null,
|
||||
Description = new Description()
|
||||
};
|
||||
var context = new NodeBuilderContext(graph, ShowPlanType.Unknown, null);
|
||||
var firstRoot = new Node(default, context);
|
||||
var secondRoot = new Node(default, context);
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var firstSkeletonNode = skeletonManager.CreateSkeleton(firstRoot);
|
||||
var secondSkeletonNode = skeletonManager.CreateSkeleton(secondRoot);
|
||||
|
||||
var skeletonCompareResult = skeletonManager.AreSkeletonsEquivalent(firstSkeletonNode, secondSkeletonNode, ignoreDatabaseName: true);
|
||||
|
||||
Assert.IsTrue(skeletonCompareResult, "The two compared skeleton nodes should be equivalent");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_ComparingSkeletonAgainstNull()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var graphs = ShowPlanGraph.ParseShowPlanXML(this.queryPlanFileText, ShowPlanType.Unknown);
|
||||
var rootNode = graphs[0].Root;
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var skeletonNode = skeletonManager.CreateSkeleton(rootNode);
|
||||
SkeletonNode skeletonNode2 = null;
|
||||
|
||||
var skeletonCompareResult = skeletonManager.AreSkeletonsEquivalent(skeletonNode, skeletonNode2, ignoreDatabaseName: true);
|
||||
|
||||
Assert.IsFalse(skeletonCompareResult);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_DifferentSkeletonChildCount()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var graphs = ShowPlanGraph.ParseShowPlanXML(this.queryPlanFileText, ShowPlanType.Unknown);
|
||||
var rootNode = graphs[0].Root;
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var skeletonNode = skeletonManager.CreateSkeleton(rootNode);
|
||||
var skeletonNode2 = skeletonManager.CreateSkeleton(rootNode);
|
||||
skeletonNode2.Children.RemoveAt(skeletonNode2.Children.Count - 1);
|
||||
|
||||
var skeletonCompareResult = skeletonManager.AreSkeletonsEquivalent(skeletonNode, skeletonNode2, ignoreDatabaseName: true);
|
||||
|
||||
Assert.IsFalse(skeletonCompareResult);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_ColorMatchingSectionsWithEquivalentSkeletons()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var graphs = ShowPlanGraph.ParseShowPlanXML(this.queryPlanFileText, ShowPlanType.Unknown);
|
||||
var rootNode = graphs[0].Root;
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var skeletonNode = skeletonManager.CreateSkeleton(rootNode);
|
||||
var skeletonNode2 = skeletonManager.CreateSkeleton(rootNode);
|
||||
|
||||
Assert.IsFalse(skeletonNode.HasMatch);
|
||||
Assert.IsFalse(skeletonNode2.HasMatch);
|
||||
|
||||
Assert.Zero(skeletonNode.MatchingNodes.Count);
|
||||
Assert.Zero(skeletonNode2.MatchingNodes.Count);
|
||||
|
||||
skeletonManager.ColorMatchingSections(skeletonNode, skeletonNode2, ignoreDatabaseName: true);
|
||||
|
||||
Assert.IsTrue(skeletonNode.HasMatch);
|
||||
Assert.IsTrue(skeletonNode2.HasMatch);
|
||||
|
||||
Assert.AreEqual(1, skeletonNode.MatchingNodes.Count);
|
||||
Assert.AreEqual(1, skeletonNode2.MatchingNodes.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_ColorMatchingSectionsWithNullAndNonNullSkeleton()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var graphs = ShowPlanGraph.ParseShowPlanXML(this.queryPlanFileText, ShowPlanType.Unknown);
|
||||
var rootNode = graphs[0].Root;
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
SkeletonNode nullSkeletonNode = null;
|
||||
var skeletonNode2 = skeletonManager.CreateSkeleton(rootNode);
|
||||
|
||||
skeletonManager.ColorMatchingSections(nullSkeletonNode, skeletonNode2, ignoreDatabaseName: true);
|
||||
|
||||
Assert.IsNull(nullSkeletonNode);
|
||||
Assert.IsFalse(skeletonNode2.HasMatch);
|
||||
Assert.Zero(skeletonNode2.MatchingNodes.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_ColorMatchingSectionsWithTwoNullSKeletons()
|
||||
{
|
||||
var skeletonManager = new SkeletonManager();
|
||||
SkeletonNode skeletonNode = null;
|
||||
SkeletonNode skeletonNode2 = null;
|
||||
|
||||
skeletonManager.ColorMatchingSections(skeletonNode, skeletonNode2, ignoreDatabaseName: true);
|
||||
|
||||
Assert.IsNull(skeletonNode);
|
||||
Assert.IsNull(skeletonNode2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_ColorMatchingSectionsWithNonNullAndNullSkeleton()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var graphs = ShowPlanGraph.ParseShowPlanXML(this.queryPlanFileText, ShowPlanType.Unknown);
|
||||
var rootNode = graphs[0].Root;
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var skeletonNode = skeletonManager.CreateSkeleton(rootNode);
|
||||
SkeletonNode nullSkeletonNode = null;
|
||||
|
||||
skeletonManager.ColorMatchingSections(skeletonNode, nullSkeletonNode, ignoreDatabaseName: true);
|
||||
|
||||
Assert.IsFalse(skeletonNode.HasMatch);
|
||||
Assert.Zero(skeletonNode.MatchingNodes.Count);
|
||||
Assert.IsNull(nullSkeletonNode);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_ColorMatchingSectionsWithDifferentChildCount()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var graphs = ShowPlanGraph.ParseShowPlanXML(this.queryPlanFileText, ShowPlanType.Unknown);
|
||||
var rootNode = graphs[0].Root;
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var skeletonNode = skeletonManager.CreateSkeleton(rootNode);
|
||||
var skeletonNode2 = skeletonManager.CreateSkeleton(rootNode);
|
||||
skeletonNode2.Children.RemoveAt(skeletonNode2.Children.Count - 1);
|
||||
|
||||
Assert.IsFalse(skeletonNode.Children[0].HasMatch);
|
||||
Assert.IsFalse(skeletonNode2.Children[0].HasMatch);
|
||||
|
||||
Assert.Zero(skeletonNode.Children[0].MatchingNodes.Count);
|
||||
Assert.Zero(skeletonNode2.Children[0].MatchingNodes.Count);
|
||||
|
||||
skeletonManager.ColorMatchingSections(skeletonNode, skeletonNode2, ignoreDatabaseName: true);
|
||||
|
||||
Assert.IsTrue(skeletonNode.Children[0].HasMatch);
|
||||
Assert.IsTrue(skeletonNode2.Children[0].HasMatch);
|
||||
|
||||
Assert.AreEqual(1, skeletonNode.Children[0].MatchingNodes.Count);
|
||||
Assert.AreEqual(1, skeletonNode2.Children[0].MatchingNodes.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_FindNextNonIgnoreNode()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var graphs = ShowPlanGraph.ParseShowPlanXML(this.queryPlanFileText, ShowPlanType.Unknown);
|
||||
var rootNode = graphs[0].Root;
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var result = skeletonManager.FindNextNonIgnoreNode(rootNode);
|
||||
|
||||
Assert.NotNull(result);
|
||||
Assert.AreEqual("InnerJoin", result.LogicalOpUnlocName);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_FindNextNonIgnoreNodeWithChildlessRoot()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
var graphs = ShowPlanGraph.ParseShowPlanXML(this.queryPlanFileText, ShowPlanType.Unknown);
|
||||
var rootNode = graphs[0].Root;
|
||||
|
||||
for (int childIndex = 0; childIndex < rootNode.Children.Count; ++childIndex)
|
||||
{
|
||||
rootNode.Children.RemoveAt(0);
|
||||
}
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var result = skeletonManager.FindNextNonIgnoreNode(rootNode);
|
||||
|
||||
Assert.IsNull(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CompareShowPlan_FindNextNonIgnoreNodeWithNullNode()
|
||||
{
|
||||
Node rootNode = null;
|
||||
|
||||
var skeletonManager = new SkeletonManager();
|
||||
var result = skeletonManager.FindNextNonIgnoreNode(rootNode);
|
||||
|
||||
Assert.IsNull(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParsingNestedProperties()
|
||||
{
|
||||
ReadFile(".ShowPlan.TestShowPlan.xml");
|
||||
string[] commonNestedPropertiesNames = { "MemoryGrantInfo", "OptimizerHardwareDependentProperties" };
|
||||
var showPlanGraphs = ShowPlanGraphUtils.CreateShowPlanGraph(queryPlanFileText, "testFile.sql");
|
||||
var showPlanGraphs = ExecutionPlanGraphUtils.CreateShowPlanGraph(queryPlanFileText, "testFile.sql");
|
||||
ExecutionPlanNode rootNode = showPlanGraphs[0].Root;
|
||||
rootNode.Properties.ForEach(p =>
|
||||
{
|
||||
@@ -49,7 +298,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ShowPlan
|
||||
//The first graph in this execution plan has 3 recommendations
|
||||
ReadFile(".ShowPlan.TestShowPlanRecommendations.xml");
|
||||
string[] commonNestedPropertiesNames = { "MemoryGrantInfo", "OptimizerHardwareDependentProperties" };
|
||||
var showPlanGraphs = ShowPlanGraphUtils.CreateShowPlanGraph(queryPlanFileText, "testFile.sql");
|
||||
var showPlanGraphs = ExecutionPlanGraphUtils.CreateShowPlanGraph(queryPlanFileText, "testFile.sql");
|
||||
List<ExecutionPlanRecommendation> rootNode = showPlanGraphs[0].Recommendations;
|
||||
Assert.AreEqual(3, rootNode.Count, "3 recommendations should be returned by the showplan parser");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user