Thu, 23 Mar 2023 18:28:20 +0000
Add support for component connections
--luacheck: std +busted local stanzacmp = require "scansion.stanzacmp"; require "verse"; local st = require "util.stanza"; local xml = require "scansion.xml"; local function parse(...) local n = select("#", ...); local out = {}; for i = 1, n do local v = (select(i, ...)); if type(v) == "string" then out[i] = xml.parse(v); else out[i] = v; end end return table.unpack(out, 1, n); end local function yes(s1, s2, captures) s1, s2 = parse(s1, s2); if not stanzacmp.stanzas_match(s1, s2, captures) then print("s1", s1) print("s2", s2) print("literal", tostring(s1) == tostring(s2)); assert(false, "No match, but they should."); end end local function no(s1, s2, captures) s1, s2 = parse(s1, s2); if stanzacmp.stanzas_match(s1, s2, captures) then print("s1", s1) print("s2", s2) assert(false, "Match, but they should not."); end end describe("stanzacmp", function () it("should work", function () local s1 = st.message({ to = "foo", from = "bar"}); local s2 = st.message({ to = "foo", from = "bar"}); yes(s1, s2); yes(s2, s1); 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); 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" }); yes(s1, s2); no(s2, s1); s1:tag("blah", { xmlns = "foobar" }); yes(s1, s2); yes(s2, s1); s1:tag("a"); no(s1, s2); s2:tag("a"); yes(s1, s2); s2:up():up(); s2:tag("extension", { xmlns = "blah" }); yes(s1, s2); s2:tag("b"); yes(s1, s2); s1:up():up(); s1:tag("extension", { xmlns = "blah" }); no(s1, s2); s1:tag("b"); yes(s1, s2); s1:tag("c", { n = "1" }); no(s1, s2); end); it("should allow matching any attribute value with {scansion:any}", function () --[[ <message from="user@localhost/71652fc8-93cb-40c7-8220-47ce80cc417b" type="chat"> <body>Hello Juliet, are you there?</body> <delay xmlns="urn:xmpp:delay" from="localhost"/> </message> ]] local s01 = st.message({ from = "user@localhost/71652fc8-93cb-40c7-8220-47ce80cc417b", type = "chat" }) :tag("body"):text("Hello Juliet, are you there?"):up() :tag("delay", { xmlns = "urn:xmpp:delay", from = "localhost", stamp = "{scansion:any}" }):up(); --[[ <message to="juliet@localhost" type="chat" from="user@localhost/71652fc8-93cb-40c7-8220-47ce80cc417b"> <body>Hello Juliet, are you there?</body> <stanza-id xmlns="urn:xmpp:sid:0" by="user@localhost" id="eb9eaf13-384e-47d1-a6c0-303ef4f1ac70"/> <stanza-id xmlns="urn:xmpp:sid:0" by="juliet@localhost" id="f6c6f61d-0b15-46d6-9f69-bca1640401d1"/> <delay xmlns="urn:xmpp:delay" stamp="2017-05-07T09:46:21Z" from="localhost"/> </message> ]] local s02 = st.message({ to = "juliet@localhost", from = "user@localhost/71652fc8-93cb-40c7-8220-47ce80cc417b", type = "chat" }) :tag("body"):text("Hello Juliet, are you there?"):up() :tag("stanza-id", { xmlns = "urn:xmpp:sid:0", by = "user@localhost", id = "eb9eaf13-384e-47d1-a6c0-303ef4f1ac70" }):up() :tag("stanza-id", { xmlns = "urn:xmpp:sid:0", by = "juliet@localhost", id = "f6c6f61d-0b15-46d6-9f69-bca1640401d1" }):up() :tag("delay", { xmlns = "urn:xmpp:delay", stamp = "2017-05-07T09:46:21Z", from = "localhost" }):up(); yes(s01, s02); end); it("should match unordered children at the top level", function () yes("<foo><one/><two/></foo>", "<foo><two/><one/></foo>"); end); 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> <a/> <b/> <c/> </x> </s>]] , [[<s> <x> <a/> <b/> <c/> </x> </s>]]); end); it("should match", function () yes([[<iq type='set' id='{scansion:any}'> <query ver='{scansion:any}' xmlns='jabber:iq:roster'> <item xmlns='jabber:iq:roster' jid='nurse@localhost' subscription='none'/> </query> </iq>]], [[<iq type='set' id='ncvDjS1d'> <query ver='1' xmlns='jabber:iq:roster'> <item xmlns='jabber:iq:roster' jid='nurse@localhost' subscription='none'/> </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); it("supports captures", function () local captures = {}; yes([[<presence from='room@conference.localhost/Romeo'> <x xmlns='http://jabber.org/protocol/muc#user'> <status code='{scansion:capture:code1}' xmlns='http://jabber.org/protocol/muc#user'/> <item jid='{scansion:any}' role='moderator' xmlns='http://jabber.org/protocol/muc#user' affiliation='{scansion:any}'/> <status code='{scansion:capture:code2}' 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>]], captures); assert.same({ ["attr:jid"] = 'user@localhost/KeoGLEr3'; ["attr:affiliation"] = "owner"; ["code1"] = "201"; ["code2"] = "110"; }, captures); end); end);