stanzacmp: Allow scansion:strict at the top level of the stanza

Fri, 14 Sep 2018 12:56:19 +0100

author
Matthew Wild <mwild1@gmail.com>
date
Fri, 14 Sep 2018 12:56:19 +0100
changeset 153
f83ea6e5c3d8
parent 152
ba8219ac7484
child 154
855a32aa56ab

stanzacmp: Allow scansion:strict at the top level of the stanza

scansion/stanzacmp.lua file | annotate | diff | comparison | revisions
spec/stanzacmp_spec.lua file | annotate | diff | comparison | revisions
--- a/scansion/stanzacmp.lua	Thu Sep 13 16:05:45 2018 +0100
+++ b/scansion/stanzacmp.lua	Fri Sep 14 12:56:19 2018 +0100
@@ -11,8 +11,8 @@
 	return (s:gsub("^%s+", ""):gsub("%s+$", ""));
 end
 
-local function wants_strict(tag)
-	local opt = tag.attr["scansion:strict"] or "yes";
+local function wants_strict(tag, default)
+	local opt = tag.attr["scansion:strict"] or default or "yes";
 	if opt == "no" or opt == "false" or opt == "0" then
 		return false;
 	elseif opt == "yes" or opt == "true" or opt == "1" then
@@ -72,6 +72,9 @@
 -- Everything in stanza1 should be present in stanza2
 
 local function stanzas_match(stanza1, stanza2)
+	if wants_strict(stanza1, stanza1.attr.xmlns == nil and "no" or "yes") then
+		return stanzas_strict_match(stanza1, stanza2);
+	end
 	if stanza1.name ~= stanza2.name or stanza1.attr.xmlns ~= stanza2.attr.xmlns then
 		return false;
 	end
@@ -95,12 +98,7 @@
 
 					if type(child2) == type(child) then
 						if type(child) == "table" and child2.name == child.name and child2.attr.xmlns == child.attr.xmlns then
-							if wants_strict(child) then
-								-- Strict deep match
-								match = stanzas_strict_match(child, child2);
-							else
-								match = stanzas_match(child, child2);
-							end
+							match = stanzas_match(child, child2);
 						elseif type(child) == "string" then -- Text nodes, must be equal, ignoring leading/trailing whitespace
 							match = trim(child) == trim(child2);
 						end
--- a/spec/stanzacmp_spec.lua	Thu Sep 13 16:05:45 2018 +0100
+++ b/spec/stanzacmp_spec.lua	Fri Sep 14 12:56:19 2018 +0100
@@ -45,13 +45,24 @@
 		yes(s1, s2);
 		yes(s2, s1);
 
-		s1.attr.to = nil;
+	end);
+
+	it("should allow additional top-level attributes by default", function ()
+		local s1 = [[<message to="foo" />]];
+		local s2 = [[<message to="foo" from="bar" />]];
 
 		yes(s1, s2);
 		no(s2, s1);
+		
+	end);
 
-		s1.attr.to = "foo";
+	it("should work", function ()
+		-- Legacy tests, need to be broken up (pain to debug when it goes wrong)
+		local s1 = st.message({ to = "foo", from = "bar"});
+		local s2 = st.message({ to = "foo", from = "bar"});
+
 		yes(s1, s2);
+		yes(s2, s1);
 
 		s2:tag("blah", { xmlns = "foobar" });
 
@@ -115,14 +126,32 @@
 		yes("<foo><one/><two/></foo>", "<foo><two/><one/></foo>");
 	end);
 
-	it("should not match unordered children", function ()
-		no("<foo><one><a/><b/></one></foo>", "<foo><one><b/><a/></one></foo>");
+	describe("unordered children", function ()
+		it("in the default namespace should match by default", function ()
+			yes("<foo><one><a/><b/></one></foo>", "<foo><one><b/><a/></one></foo>");
+		end)
+
+		it("in the default namespace should not match in strict mode", function ()
+			no("<foo><one scansion:strict='true'><a/><b/></one></foo>", "<foo><one><b/><a/></one></foo>");
+		end)
+
+		it("in a different namespace should not match", function ()
+			no("<foo><one xmlns='foo'><a/><b/></one></foo>", "<foo><one xmlns='foo'><b/><a/></one></foo>");
+		end)
+	end);
+
+	it("should match unordered children within the same namespace by default", function ()
+		yes("<foo><one><a/><b/></one></foo>", "<foo><one><b/><a/></one></foo>");
 	end);
 
 	it("should be possible to disable ordered matching", function ()
 		yes("<foo><one scansion:strict='no'><a/><b/></one></foo>", "<foo><one><b/><a/></one></foo>");
 	end);
 
+	it("should be possible to disable ordered matching at the top level", function ()
+		no("<foo scansion:strict='yes'><one/></foo>", "<foo><one/><two/></foo>");
+	end);
+
 	it("should match when there are many children", function ()
 		yes([[<s>
 			<x>
@@ -151,4 +180,21 @@
 			</query>
 		</iq>]]);
 	end);
+
+	it("should match", function ()
+		yes([[<presence from='room@conference.localhost/Romeo'>
+			<x xmlns='http://jabber.org/protocol/muc#user'>
+				<status code='201' xmlns='http://jabber.org/protocol/muc#user'/>
+				<item jid='user@localhost/KeoGLEr3' role='moderator' xmlns='http://jabber.org/protocol/muc#user' affiliation='owner'/>
+				<status code='110' xmlns='http://jabber.org/protocol/muc#user'/>
+			</x>
+		</presence>]],
+		[[<presence to='user@localhost/KeoGLEr3' from='room@conference.localhost/Romeo'>
+			<x xmlns='http://jabber.org/protocol/muc#user'>
+				<status code='201' xmlns='http://jabber.org/protocol/muc#user'/>
+				<item jid='user@localhost/KeoGLEr3' role='moderator' xmlns='http://jabber.org/protocol/muc#user' affiliation='owner'/>
+				<status code='110' xmlns='http://jabber.org/protocol/muc#user'/>
+			</x>
+		</presence>]]);
+	end);
 end);

mercurial