Skip to content

Commit

Permalink
Bug fix for issue #4
Browse files Browse the repository at this point in the history
Web.config files (and generally XML) are case-sensitive. But when building the XTree the element and attributes' names were being converted to lower case.
These names were then being used to construct the XPath expression in transform attributes (InsertBefore, InsertAfter etc).
I've removed the conversion to lower case and added tests for case sensitive comparison.
  • Loading branch information
CameronWills committed Jan 7, 2017
1 parent be83d03 commit 4e3a236
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 67 deletions.
53 changes: 53 additions & 0 deletions FatAntelope.Tests/XTreeEqualityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,59 @@ public void IsomorphicXmlAreEqual()
Assert.IsTrue(Enumerable.SequenceEqual(tree1.Root.Hash, tree2.Root.Hash));
}


[TestMethod]
public void ElementsAreCaseSensitive()
{
var doc1 = new XmlDocument();
doc1.LoadXml(@"
<root>
<child1 name1='child1' type1='elem1'>child1</child1>
<child2 name2='child2' type2='elem2'>child2</child2>
</root>"
);

// reordered xml but same values
var doc2 = new XmlDocument();
doc2.LoadXml(@"
<root>
<child1 type1='elem1' name1='child1'>child1</child1>
<CHILD2 type2='elem2' name2='child2'>child2</CHILD2>
</root>"
);

var tree1 = new XTree(doc1);
var tree2 = new XTree(doc2);

Assert.IsFalse(Enumerable.SequenceEqual(tree1.Root.Hash, tree2.Root.Hash));
}

[TestMethod]
public void AttributesAreCaseSensitive()
{
var doc1 = new XmlDocument();
doc1.LoadXml(@"
<root>
<child1 name1='child1' type1='elem1'>child1</child1>
<child2 name2='child2' type2='elem2'>child2</child2>
</root>"
);

// reordered xml but same values
var doc2 = new XmlDocument();
doc2.LoadXml(@"
<root>
<child1 type1='elem1' name1='child1'>child1</child1>
<child2 TYPE2='elem2' name2='child2'>child2</child2>
</root>"
);

var tree1 = new XTree(doc1);
var tree2 = new XTree(doc2);

Assert.IsFalse(Enumerable.SequenceEqual(tree1.Root.Hash, tree2.Root.Hash));
}

[TestMethod]
public void DifferentXmlAttributesAreDifferent()
{
Expand Down
130 changes: 65 additions & 65 deletions FatAntelope.Tests/XdtDiffWriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,24 @@ public void InsertFollowedByParentChange()
// Insert a child element into a parent element that has a change affecting its unique trait.

var source = @"
<root>
<parent name='elem1' />
<parent name='elem3'>
<child name='child1' />
<child name='child3' />
</parent>
</root>";
<rootNode>
<parentNode nameNode='elem1' />
<parentNode nameNode='elem3'>
<childNode nameNode='child1' />
<childNode nameNode='child3' />
</parentNode>
</rootNode>";

var target = @"
<root>
<parent name='elem1' />
<parent name='elem2' />
<parent name='DIFFERENT'>
<child name='child1' />
<child name='child2' />
<child name='child3' />
</parent>
</root>";
<rootNode>
<parentNode nameNode='elem1' />
<parentNode nameNode='elem2' />
<parentNode nameNode='DIFFERENT'>
<childNode nameNode='child1' />
<childNode nameNode='child2' />
<childNode nameNode='child3' />
</parentNode>
</rootNode>";

var patch = GetPatch(source, target);

Expand All @@ -124,22 +124,22 @@ public void InsertAndRemove()
// Insert a child element into a parent element that has a change affecting its unique trait.

var source = @"
<root>
<type1 />
<type1 />
<type1 />
<type1 />
</root>";
<rootNode>
<type1Node />
<type1Node />
<type1Node />
<type1Node />
</rootNode>";

var target = @"
<root>
<type1 />
<type1 />
<type2 />
<type1 />
<type2 />
<type2 />
</root>";
<rootNode>
<type1Node />
<type1Node />
<type2Node />
<type1Node />
<type2Node />
<type2Node />
</rootNode>";

var patch = GetPatch(source, target);

Expand All @@ -152,35 +152,35 @@ public void InsertChildWithParentChange()
// Insert a child element into a parent element that has a change affecting its unique trait.

var source = @"
<root>
<parent name='parent1'>
<child name='child1' />
<child name='child3' />
</parent>
<parent name='parent2'>
<child name='child1' />
<child name='child2' />
</parent>
</root>";
<rootNode>
<parentNode nameNode='parent1'>
<childNode nameNode='child1' />
<childNode nameNode='child3' />
</parentNode>
<parentNode nameNode='parent2'>
<childNode nameNode='child1' />
<childNode nameNode='child2' />
</parentNode>
</rootNode>";

var target = @"
<root>
<parent name='DIFFERENT'>
<child name='child1' />
<child name='child2' />
<child name='child3' />
</parent>
<parent name='parent2'>
<child name='child1' />
<child name='child2' />
</parent>
</root>";
<rootNode>
<parentNode nameNode='DIFFERENT'>
<childNode nameNode='child1' />
<childNode nameNode='child2' />
<childNode nameNode='child3' />
</parentNode>
<parentNode nameNode='parent2'>
<childNode nameNode='child1' />
<childNode nameNode='child2' />
</parentNode>
</rootNode>";

var patch = GetPatch(source, target);

AssertLocator(patch.SelectSingleNode("/root/parent[1]"), "Condition(1)");
AssertTransform(patch.SelectSingleNode("/root/parent[1]"), "SetAttributes(name)");
AssertTransform(patch.SelectSingleNode("/root/parent[1]/child[1]"), "InsertAfter(/root/parent[(@name='DIFFERENT')]/child[(@name='child1')])");
AssertLocator(patch.SelectSingleNode("/rootNode/parentNode[1]"), "Condition(1)");
AssertTransform(patch.SelectSingleNode("/rootNode/parentNode[1]"), "SetAttributes(nameNode)");
AssertTransform(patch.SelectSingleNode("/rootNode/parentNode[1]/childNode[1]"), "InsertAfter(/rootNode/parentNode[(@nameNode='DIFFERENT')]/childNode[(@nameNode='child1')])");

AssertCanTransform(source, target);
}
Expand Down Expand Up @@ -309,25 +309,25 @@ public void InsertAfterIndex()
public void InsertAfterSimple()
{
var source = @"
<root>
<child1 />
<child3 />
</root>";
<configSettings>
<appSettings />
<webServer />
</configSettings>";

var target = @"
<root>
<child1 />
<clear all='true' />
<child3 />
</root>";
<configSettings>
<appSettings />
<connectionStrings all='true' />
<webServer />
</configSettings>";

var patch = GetPatch(source, target);

// Locator = none
AssertNoLocator(patch.SelectSingleNode("/root/clear"));
AssertNoLocator(patch.SelectSingleNode("/configSettings/connectionStrings"));

// Transform = SetAttribute(type)
AssertTransform(patch.SelectSingleNode("/root/clear"), "InsertAfter(/root/child1)");
AssertTransform(patch.SelectSingleNode("/configSettings/connectionStrings"), "InsertAfter(/configSettings/appSettings)");

AssertCanTransform(source, target);
}
Expand Down
4 changes: 2 additions & 2 deletions FatAntelope/XNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public static XNode Build(XmlNode node, XNode parent)
if (node.NodeType == XmlNodeType.Attribute)
{
var xnode = new XNode(node, parent);
xnode.Name = node.Name.ToLowerInvariant();
xnode.Name = node.Name;
var name = "@" + xnode.Name;
xnode.Hash = Murmur3Hasher.HashString(name + "/" + (node.Value ?? string.Empty));
return xnode;
Expand All @@ -146,7 +146,7 @@ public static XNode Build(XmlNode node, XNode parent)
else if (node.NodeType == XmlNodeType.Element)
{
var xnode = new XNode(node, parent);
var name = node.Name.ToLowerInvariant();
var name = node.Name;
xnode.Name = name;
var hashes = new List<byte[]>();
hashes.Add(Murmur3Hasher.HashString(name + "/"));
Expand Down

0 comments on commit 4e3a236

Please sign in to comment.