util.startup: Check root after detecting platform and reading config (thanks SigmaTel71)
Ensures that startup.detect_platform() runs so know whether to use the
POSIX method of checking the current user or something else. Also after
reading the config so we know whether the root override setting is set.
local st
local xml
local map
setup(function()
st = require "util.stanza";
xml = require "util.xml";
map = require "util.datamapper";
end);
describe("util.datamapper", function()
local s, x, d
local disco, disco_info, disco_schema
setup(function()
-- a convenience function for simple attributes, there's a few of them
local attr = {["$ref"]="#/$defs/attr"};
s = {
["$defs"] = { attr = { type = "string"; xml = { attribute = true } } };
type = "object";
xml = {name = "message"; namespace = "jabber:client"};
properties = {
to = attr;
from = attr;
type = attr;
id = attr;
body = true; -- should be assumed to be a string
lang = {type = "string"; xml = {attribute = true; prefix = "xml"}};
delay = {
type = "object";
xml = {namespace = "urn:xmpp:delay"; name = "delay"};
properties = {stamp = attr; from = attr; reason = {type = "string"; xml = {text = true}}};
};
state = {
type = "string";
enum = {
"active",
"inactive",
"gone",
"composing",
"paused",
};
xml = {x_name_is_value = true; namespace = "http://jabber.org/protocol/chatstates"};
};
fallback = {
type = "boolean";
xml = {x_name_is_value = true; name = "fallback"; namespace = "urn:xmpp:fallback:0"};
};
origin_id = {
type = "string";
xml = {name = "origin-id"; namespace = "urn:xmpp:sid:0"; x_single_attribute = "id"};
};
react = {
type = "object";
xml = {namespace = "urn:xmpp:reactions:0"; name = "reactions"};
properties = {
to = {type = "string"; xml = {attribute = true; name = "id"}};
-- should be assumed to be array since it has 'items'
reactions = { items = { xml = { name = "reaction" } } };
};
};
stanza_ids = {
type = "array";
items = {
xml = {name = "stanza-id"; namespace = "urn:xmpp:sid:0"};
type = "object";
properties = {
id = attr;
by = attr;
};
};
};
};
};
x = xml.parse [[
<message xmlns="jabber:client" xml:lang="en" to="a@test" from="b@test" type="chat" id="1">
<body>Hello</body>
<delay xmlns='urn:xmpp:delay' from='test' stamp='2021-03-07T15:59:08+00:00'>Because</delay>
<UNRELATED xmlns='http://jabber.org/protocol/chatstates'/>
<active xmlns='http://jabber.org/protocol/chatstates'/>
<fallback xmlns='urn:xmpp:fallback:0'/>
<origin-id xmlns='urn:xmpp:sid:0' id='qgkmMdPB'/>
<stanza-id xmlns='urn:xmpp:sid:0' id='abc1' by='muc'/>
<stanza-id xmlns='urn:xmpp:sid:0' id='xyz2' by='host'/>
<reactions id='744f6e18-a57a-11e9-a656-4889e7820c76' xmlns='urn:xmpp:reactions:0'>
<reaction>👋</reaction>
<reaction>🐢</reaction>
</reactions>
</message>
]];
d = {
to = "a@test";
from = "b@test";
type = "chat";
id = "1";
lang = "en";
body = "Hello";
delay = {from = "test"; stamp = "2021-03-07T15:59:08+00:00"; reason = "Because"};
state = "active";
fallback = true;
origin_id = "qgkmMdPB";
stanza_ids = {{id = "abc1"; by = "muc"}; {id = "xyz2"; by = "host"}};
react = {
to = "744f6e18-a57a-11e9-a656-4889e7820c76";
reactions = {
"👋",
"🐢",
};
};
};
disco_schema = {
["$defs"] = { attr = { type = "string"; xml = { attribute = true } } };
type = "object";
xml = {
name = "iq";
namespace = "jabber:client"
};
properties = {
to = attr;
from = attr;
type = attr;
id = attr;
disco = {
type = "object";
xml = {
name = "query";
namespace = "http://jabber.org/protocol/disco#info"
};
properties = {
features = {
type = "array";
items = {
type = "string";
xml = {
name = "feature";
x_single_attribute = "var";
};
};
};
};
};
};
};
disco_info = xml.parse[[
<iq type="result" id="disco1" from="example.com">
<query xmlns="http://jabber.org/protocol/disco#info">
<feature var="urn:example:feature:1">wrong</feature>
<feature var="urn:example:feature:2"/>
<feature var="urn:example:feature:3"/>
<unrelated var="urn:example:feature:not"/>
</query>
</iq>
]];
disco = {
type="result";
id="disco1";
from="example.com";
disco = {
features = {
"urn:example:feature:1";
"urn:example:feature:2";
"urn:example:feature:3";
};
};
};
end);
describe("parse", function()
it("works", function()
assert.same(d, map.parse(s, x));
end);
it("handles arrays", function ()
assert.same(disco, map.parse(disco_schema, disco_info));
end);
it("deals with locally built stanzas", function()
-- FIXME this could also be argued to be a util.stanza problem
local ver_schema = {
type = "object";
xml = {name = "iq"};
properties = {
type = {type = "string"; xml = {attribute = true}};
id = {type = "string"; xml = {attribute = true}};
version = {
type = "object";
xml = {name = "query"; namespace = "jabber:iq:version"};
-- properties should be assumed to be strings
properties = {name = true; version = {}; os = {}};
};
};
};
local ver_st = st.iq({type = "result"; id = "v1"})
:query("jabber:iq:version")
:text_tag("name", "Prosody")
:text_tag("version", "trunk")
:text_tag("os", "Lua 5.3")
:reset();
local data = {type = "result"; id = "v1"; version = {name = "Prosody"; version = "trunk"; os = "Lua 5.3"}}
assert.same(data, map.parse(ver_schema, ver_st));
end);
end);
describe("unparse", function()
it("works", function()
local u = map.unparse(s, d);
assert.equal("message", u.name);
assert.same(x.attr, u.attr);
assert.equal(x:get_child_text("body"), u:get_child_text("body"));
assert.equal(x:get_child_text("delay", "urn:xmpp:delay"), u:get_child_text("delay", "urn:xmpp:delay"));
assert.same(x:get_child("delay", "urn:xmpp:delay").attr, u:get_child("delay", "urn:xmpp:delay").attr);
assert.same(x:get_child("origin-id", "urn:xmpp:sid:0").attr, u:get_child("origin-id", "urn:xmpp:sid:0").attr);
assert.same(x:get_child("reactions", "urn:xmpp:reactions:0").attr, u:get_child("reactions", "urn:xmpp:reactions:0").attr);
assert.same(2, #u:get_child("reactions", "urn:xmpp:reactions:0").tags);
for _, tag in ipairs(x.tags) do
if tag.name ~= "UNRELATED" then
assert.truthy(u:get_child(tag.name, tag.attr.xmlns) or u:get_child(tag.name), tag:top_tag())
end
end
assert.equal(#x.tags-1, #u.tags)
end);
it("handles arrays", function ()
local u = map.unparse(disco_schema, disco);
assert.equal("urn:example:feature:1", u:find("{http://jabber.org/protocol/disco#info}query/feature/@var"))
local n = 0;
for child in u:get_child("query", "http://jabber.org/protocol/disco#info"):childtags("feature") do
n = n + 1;
assert.equal(string.format("urn:example:feature:%d", n), child.attr.var);
end
end);
end);
end)