Port tests to the busted test runner

This commit is contained in:
Waqas Hussain 2017-09-15 17:07:57 -04:00
parent 4c6c255113
commit 67293fc09f
84 changed files with 1468 additions and 2303 deletions

View file

@ -0,0 +1,31 @@
local configmanager = require "core.configmanager";
describe("core.configmanager", function()
describe("#get()", function()
it("should work", function()
configmanager.set("example.com", "testkey", 123);
assert.are.equal(configmanager.get("example.com", "testkey"), 123, "Retrieving a set key");
configmanager.set("*", "testkey1", 321);
assert.are.equal(configmanager.get("*", "testkey1"), 321, "Retrieving a set global key");
assert.are.equal(configmanager.get("example.com", "testkey1"), 321, "Retrieving a set key of undefined host, of which only a globally set one exists");
configmanager.set("example.com", ""); -- Creates example.com host in config
assert.are.equal(configmanager.get("example.com", "testkey1"), 321, "Retrieving a set key, of which only a globally set one exists");
assert.are.equal(configmanager.get(), nil, "No parameters to get()");
assert.are.equal(configmanager.get("undefined host"), nil, "Getting for undefined host");
assert.are.equal(configmanager.get("undefined host", "undefined key"), nil, "Getting for undefined host & key");
end);
end);
describe("#set()", function()
it("should work", function()
assert.are.equal(configmanager.set("*"), false, "Set with no key");
assert.are.equal(configmanager.set("*", "set_test", "testkey"), true, "Setting a nil global value");
assert.are.equal(configmanager.set("*", "set_test", "testkey", 123), true, "Setting a global value");
end);
end);
end);

View file

@ -0,0 +1,76 @@
package.loaded["core.configmanager"] = {};
package.loaded["core.statsmanager"] = {};
package.loaded["net.server"] = {};
local set = require "util.set";
_G.prosody = { hosts = {}, core_post_stanza = true };
local api = require "core.moduleapi";
local module = setmetatable({}, {__index = api});
local opt = nil;
function module:log() end
function module:get_option(name)
if name == "opt" then
return opt;
else
return nil;
end
end
function test_option_value(value, returns)
opt = value;
assert(module:get_option_number("opt") == returns.number, "number doesn't match");
assert(module:get_option_string("opt") == returns.string, "string doesn't match");
assert(module:get_option_boolean("opt") == returns.boolean, "boolean doesn't match");
if type(returns.array) == "table" then
local target_array, returned_array = returns.array, module:get_option_array("opt");
assert(#target_array == #returned_array, "array length doesn't match");
for i=1,#target_array do
assert(target_array[i] == returned_array[i], "array item doesn't match");
end
else
assert(module:get_option_array("opt") == returns.array, "array is returned (not nil)");
end
if type(returns.set) == "table" then
local target_items, returned_items = set.new(returns.set), module:get_option_set("opt");
assert(target_items == returned_items, "set doesn't match");
else
assert(module:get_option_set("opt") == returns.set, "set is returned (not nil)");
end
end
describe("core.moduleapi", function()
describe("#get_option_*()", function()
it("should handle missing options", function()
test_option_value(nil, {});
end);
it("should return correctly handle boolean options", function()
test_option_value(true, { boolean = true, string = "true", array = {true}, set = {true} });
test_option_value(false, { boolean = false, string = "false", array = {false}, set = {false} });
test_option_value("true", { boolean = true, string = "true", array = {"true"}, set = {"true"} });
test_option_value("false", { boolean = false, string = "false", array = {"false"}, set = {"false"} });
test_option_value(1, { boolean = true, string = "1", array = {1}, set = {1}, number = 1 });
test_option_value(0, { boolean = false, string = "0", array = {0}, set = {0}, number = 0 });
end);
it("should return handle strings", function()
test_option_value("hello world", { string = "hello world", array = {"hello world"}, set = {"hello world"} });
end);
it("should return handle numbers", function()
test_option_value(1234, { string = "1234", number = 1234, array = {1234}, set = {1234} });
end);
it("should return handle arrays", function()
test_option_value({1, 2, 3}, { boolean = true, string = "1", number = 1, array = {1, 2, 3}, set = {1, 2, 3} });
test_option_value({1, 2, 3, 3, 4}, {boolean = true, string = "1", number = 1, array = {1, 2, 3, 3, 4}, set = {1, 2, 3, 4} });
test_option_value({0, 1, 2, 3}, { boolean = false, string = "0", number = 0, array = {0, 1, 2, 3}, set = {0, 1, 2, 3} });
end);
end)
end)

View file

@ -0,0 +1,52 @@
local httpstreams = { [[
GET / HTTP/1.1
Host: example.com
]], [[
HTTP/1.1 200 OK
Content-Length: 0
]], [[
HTTP/1.1 200 OK
Content-Length: 7
Hello
HTTP/1.1 200 OK
Transfer-Encoding: chunked
1
H
1
e
2
ll
1
o
0
]]
}
local http_parser = require "net.http.parser";
describe("net.http.parser", function()
describe("#new()", function()
it("should work", function()
for _, stream in ipairs(httpstreams) do
local success;
local function success_cb(packet)
success = true;
end
stream = stream:gsub("\n", "\r\n");
local parser = http_parser.new(success_cb, error, stream:sub(1,4) == "HTTP" and "client" or "server")
for chunk in stream:gmatch("..?.?") do
parser:feed(chunk);
end
assert.is_true(success);
end
end);
end);
end);

316
spec/util_cache_spec.lua Normal file
View file

@ -0,0 +1,316 @@
local cache = require "util.cache";
describe("util.cache", function()
describe("#new()", function()
it("should work", function()
local c = cache.new(5);
local function expect_kv(key, value, actual_key, actual_value)
assert.are.equal(key, actual_key, "key incorrect");
assert.are.equal(value, actual_value, "value incorrect");
end
expect_kv(nil, nil, c:head());
expect_kv(nil, nil, c:tail());
assert.are.equal(c:count(), 0);
c:set("one", 1)
assert.are.equal(c:count(), 1);
expect_kv("one", 1, c:head());
expect_kv("one", 1, c:tail());
c:set("two", 2)
expect_kv("two", 2, c:head());
expect_kv("one", 1, c:tail());
c:set("three", 3)
expect_kv("three", 3, c:head());
expect_kv("one", 1, c:tail());
c:set("four", 4)
c:set("five", 5);
assert.are.equal(c:count(), 5);
expect_kv("five", 5, c:head());
expect_kv("one", 1, c:tail());
c:set("foo", nil);
assert.are.equal(c:count(), 5);
expect_kv("five", 5, c:head());
expect_kv("one", 1, c:tail());
assert.are.equal(c:get("one"), 1);
expect_kv("five", 5, c:head());
expect_kv("one", 1, c:tail());
assert.are.equal(c:get("two"), 2);
assert.are.equal(c:get("three"), 3);
assert.are.equal(c:get("four"), 4);
assert.are.equal(c:get("five"), 5);
assert.are.equal(c:get("foo"), nil);
assert.are.equal(c:get("bar"), nil);
c:set("six", 6);
assert.are.equal(c:count(), 5);
expect_kv("six", 6, c:head());
expect_kv("two", 2, c:tail());
assert.are.equal(c:get("one"), nil);
assert.are.equal(c:get("two"), 2);
assert.are.equal(c:get("three"), 3);
assert.are.equal(c:get("four"), 4);
assert.are.equal(c:get("five"), 5);
assert.are.equal(c:get("six"), 6);
c:set("three", nil);
assert.are.equal(c:count(), 4);
assert.are.equal(c:get("one"), nil);
assert.are.equal(c:get("two"), 2);
assert.are.equal(c:get("three"), nil);
assert.are.equal(c:get("four"), 4);
assert.are.equal(c:get("five"), 5);
assert.are.equal(c:get("six"), 6);
c:set("seven", 7);
assert.are.equal(c:count(), 5);
assert.are.equal(c:get("one"), nil);
assert.are.equal(c:get("two"), 2);
assert.are.equal(c:get("three"), nil);
assert.are.equal(c:get("four"), 4);
assert.are.equal(c:get("five"), 5);
assert.are.equal(c:get("six"), 6);
assert.are.equal(c:get("seven"), 7);
c:set("eight", 8);
assert.are.equal(c:count(), 5);
assert.are.equal(c:get("one"), nil);
assert.are.equal(c:get("two"), nil);
assert.are.equal(c:get("three"), nil);
assert.are.equal(c:get("four"), 4);
assert.are.equal(c:get("five"), 5);
assert.are.equal(c:get("six"), 6);
assert.are.equal(c:get("seven"), 7);
assert.are.equal(c:get("eight"), 8);
c:set("four", 4);
assert.are.equal(c:count(), 5);
assert.are.equal(c:get("one"), nil);
assert.are.equal(c:get("two"), nil);
assert.are.equal(c:get("three"), nil);
assert.are.equal(c:get("four"), 4);
assert.are.equal(c:get("five"), 5);
assert.are.equal(c:get("six"), 6);
assert.are.equal(c:get("seven"), 7);
assert.are.equal(c:get("eight"), 8);
c:set("nine", 9);
assert.are.equal(c:count(), 5);
assert.are.equal(c:get("one"), nil);
assert.are.equal(c:get("two"), nil);
assert.are.equal(c:get("three"), nil);
assert.are.equal(c:get("four"), 4);
assert.are.equal(c:get("five"), nil);
assert.are.equal(c:get("six"), 6);
assert.are.equal(c:get("seven"), 7);
assert.are.equal(c:get("eight"), 8);
assert.are.equal(c:get("nine"), 9);
do
local keys = { "nine", "four", "eight", "seven", "six" };
local values = { 9, 4, 8, 7, 6 };
local i = 0;
for k, v in c:items() do
i = i + 1;
assert.are.equal(k, keys[i]);
assert.are.equal(v, values[i]);
end
assert.are.equal(i, 5);
c:set("four", "2+2");
assert.are.equal(c:count(), 5);
assert.are.equal(c:get("one"), nil);
assert.are.equal(c:get("two"), nil);
assert.are.equal(c:get("three"), nil);
assert.are.equal(c:get("four"), "2+2");
assert.are.equal(c:get("five"), nil);
assert.are.equal(c:get("six"), 6);
assert.are.equal(c:get("seven"), 7);
assert.are.equal(c:get("eight"), 8);
assert.are.equal(c:get("nine"), 9);
end
do
local keys = { "four", "nine", "eight", "seven", "six" };
local values = { "2+2", 9, 8, 7, 6 };
local i = 0;
for k, v in c:items() do
i = i + 1;
assert.are.equal(k, keys[i]);
assert.are.equal(v, values[i]);
end
assert.are.equal(i, 5);
c:set("foo", nil);
assert.are.equal(c:count(), 5);
assert.are.equal(c:get("one"), nil);
assert.are.equal(c:get("two"), nil);
assert.are.equal(c:get("three"), nil);
assert.are.equal(c:get("four"), "2+2");
assert.are.equal(c:get("five"), nil);
assert.are.equal(c:get("six"), 6);
assert.are.equal(c:get("seven"), 7);
assert.are.equal(c:get("eight"), 8);
assert.are.equal(c:get("nine"), 9);
end
do
local keys = { "four", "nine", "eight", "seven", "six" };
local values = { "2+2", 9, 8, 7, 6 };
local i = 0;
for k, v in c:items() do
i = i + 1;
assert.are.equal(k, keys[i]);
assert.are.equal(v, values[i]);
end
assert.are.equal(i, 5);
c:set("four", nil);
assert.are.equal(c:get("one"), nil);
assert.are.equal(c:get("two"), nil);
assert.are.equal(c:get("three"), nil);
assert.are.equal(c:get("four"), nil);
assert.are.equal(c:get("five"), nil);
assert.are.equal(c:get("six"), 6);
assert.are.equal(c:get("seven"), 7);
assert.are.equal(c:get("eight"), 8);
assert.are.equal(c:get("nine"), 9);
end
do
local keys = { "nine", "eight", "seven", "six" };
local values = { 9, 8, 7, 6 };
local i = 0;
for k, v in c:items() do
i = i + 1;
assert.are.equal(k, keys[i]);
assert.are.equal(v, values[i]);
end
assert.are.equal(i, 4);
end
do
local evicted_key, evicted_value;
local c2 = cache.new(3, function (_key, _value)
evicted_key, evicted_value = _key, _value;
end);
local function set(k, v, should_evict_key, should_evict_value)
evicted_key, evicted_value = nil, nil;
c2:set(k, v);
assert.are.equal(evicted_key, should_evict_key);
assert.are.equal(evicted_value, should_evict_value);
end
set("a", 1)
set("a", 1)
set("a", 1)
set("a", 1)
set("a", 1)
set("b", 2)
set("c", 3)
set("b", 2)
set("d", 4, "a", 1)
set("e", 5, "c", 3)
end
do
local evicted_key, evicted_value;
local c3 = cache.new(1, function (_key, _value)
evicted_key, evicted_value = _key, _value;
if _key == "a" then
-- Sanity check for what we're evicting
assert.are.equal(_key, "a");
assert.are.equal(_value, 1);
-- We're going to block eviction of this key/value, so set to nil...
evicted_key, evicted_value = nil, nil;
-- Returning false to block eviction
return false
end
end);
local function set(k, v, should_evict_key, should_evict_value)
evicted_key, evicted_value = nil, nil;
local ret = c3:set(k, v);
assert.are.equal(evicted_key, should_evict_key);
assert.are.equal(evicted_value, should_evict_value);
return ret;
end
set("a", 1)
set("a", 1)
set("a", 1)
set("a", 1)
set("a", 1)
-- Our on_evict prevents "a" from being evicted, causing this to fail...
assert.are.equal(set("b", 2), false, "Failed to prevent eviction, or signal result");
expect_kv("a", 1, c3:head());
expect_kv("a", 1, c3:tail());
-- Check the final state is what we expect
assert.are.equal(c3:get("a"), 1);
assert.are.equal(c3:get("b"), nil);
assert.are.equal(c3:count(), 1);
end
local c4 = cache.new(3, false);
assert.are.equal(c4:set("a", 1), true);
assert.are.equal(c4:set("a", 1), true);
assert.are.equal(c4:set("a", 1), true);
assert.are.equal(c4:set("a", 1), true);
assert.are.equal(c4:set("b", 2), true);
assert.are.equal(c4:set("c", 3), true);
assert.are.equal(c4:set("d", 4), false);
assert.are.equal(c4:set("d", 4), false);
assert.are.equal(c4:set("d", 4), false);
expect_kv("c", 3, c4:head());
expect_kv("a", 1, c4:tail());
local c5 = cache.new(3, function (k, v)
if k == "a" then
return nil;
elseif k == "b" then
return true;
end
return false;
end);
assert.are.equal(c5:set("a", 1), true);
assert.are.equal(c5:set("a", 1), true);
assert.are.equal(c5:set("a", 1), true);
assert.are.equal(c5:set("a", 1), true);
assert.are.equal(c5:set("b", 2), true);
assert.are.equal(c5:set("c", 3), true);
assert.are.equal(c5:set("d", 4), true); -- "a" evicted (cb returned nil)
assert.are.equal(c5:set("d", 4), true); -- nop
assert.are.equal(c5:set("d", 4), true); -- nop
assert.are.equal(c5:set("e", 5), true); -- "b" evicted (cb returned true)
assert.are.equal(c5:set("f", 6), false); -- "c" won't evict (cb returned false)
expect_kv("e", 5, c5:head());
expect_kv("c", 3, c5:tail());
end);
end);
end);

View file

@ -0,0 +1,22 @@
local encodings = require "util.encodings";
local utf8 = assert(encodings.utf8, "no encodings.utf8 module");
describe("util.encodings.utf8", function()
describe("#valid()", function()
it("should work", function()
for line in io.lines("spec/utf8_sequences.txt") do
local data = line:match(":%s*([^#]+)"):gsub("%s+", ""):gsub("..", function (c) return string.char(tonumber(c, 16)); end)
local expect = line:match("(%S+):");
assert(expect == "pass" or expect == "fail", "unknown expectation: "..line:match("^[^:]+"));
local valid = utf8.valid(data);
assert.is.equal(valid, utf8.valid(data.." "));
assert.is.equal(valid, expect == "pass", line);
end
end);
end);
end);

64
spec/util_http_spec.lua Normal file
View file

@ -0,0 +1,64 @@
local http = require "util.http";
describe("util.http", function()
describe("#urlencode()", function()
it("should not change normal characters", function()
assert.are.equal(http.urlencode("helloworld123"), "helloworld123");
end);
it("should escape spaces", function()
assert.are.equal(http.urlencode("hello world"), "hello%20world");
end);
it("should escape important URL characters", function()
assert.are.equal(http.urlencode("This & that = something"), "This%20%26%20that%20%3d%20something");
end);
end);
describe("#urldecode()", function()
it("should not change normal characters", function()
assert.are.equal("helloworld123", http.urldecode("helloworld123"), "Normal characters not escaped");
end);
it("should decode spaces", function()
assert.are.equal("hello world", http.urldecode("hello%20world"), "Spaces escaped");
end);
it("should decode important URL characters", function()
assert.are.equal("This & that = something", http.urldecode("This%20%26%20that%20%3d%20something"), "Important URL chars escaped");
end);
end);
describe("#formencode()", function()
it("should encode basic data", function()
assert.are.equal(http.formencode({ { name = "one", value = "1"}, { name = "two", value = "2" } }), "one=1&two=2", "Form encoded");
end);
it("should encode special characters with escaping", function()
assert.are.equal(http.formencode({ { name = "one two", value = "1"}, { name = "two one&", value = "2" } }), "one+two=1&two+one%26=2", "Form encoded");
end);
end);
describe("#formdecode()", function()
it("should decode basic data", function()
local t = http.formdecode("one=1&two=2");
assert.are.same(t, {
{ name = "one", value = "1" };
{ name = "two", value = "2" };
one = "1";
two = "2";
});
end);
it("should decode special characters", function()
local t = http.formdecode("one+two=1&two+one%26=2");
assert.are.same(t, {
{ name = "one two", value = "1" };
{ name = "two one&", value = "2" };
["one two"] = "1";
["two one&"] = "2";
});
end);
end);
end);

103
spec/util_ip_spec.lua Normal file
View file

@ -0,0 +1,103 @@
local ip = require "util.ip";
local new_ip = ip.new_ip;
local match = ip.match;
local parse_cidr = ip.parse_cidr;
local commonPrefixLength = ip.commonPrefixLength;
describe("util.ip", function()
describe("#match()", function()
it("should work", function()
local _ = new_ip;
local ip = _"10.20.30.40";
assert.are.equal(match(ip, _"10.0.0.0", 8), true);
assert.are.equal(match(ip, _"10.0.0.0", 16), false);
assert.are.equal(match(ip, _"10.0.0.0", 24), false);
assert.are.equal(match(ip, _"10.0.0.0", 32), false);
assert.are.equal(match(ip, _"10.20.0.0", 8), true);
assert.are.equal(match(ip, _"10.20.0.0", 16), true);
assert.are.equal(match(ip, _"10.20.0.0", 24), false);
assert.are.equal(match(ip, _"10.20.0.0", 32), false);
assert.are.equal(match(ip, _"0.0.0.0", 32), false);
assert.are.equal(match(ip, _"0.0.0.0", 0), true);
assert.are.equal(match(ip, _"0.0.0.0"), false);
assert.are.equal(match(ip, _"10.0.0.0", 255), false, "excessive number of bits");
assert.are.equal(match(ip, _"10.0.0.0", -8), true, "negative number of bits");
assert.are.equal(match(ip, _"10.0.0.0", -32), true, "negative number of bits");
assert.are.equal(match(ip, _"10.0.0.0", 0), true, "zero bits");
assert.are.equal(match(ip, _"10.0.0.0"), false, "no specified number of bits (differing ip)");
assert.are.equal(match(ip, _"10.20.30.40"), true, "no specified number of bits (same ip)");
assert.are.equal(match(_"127.0.0.1", _"127.0.0.1"), true, "simple ip");
assert.are.equal(match(_"8.8.8.8", _"8.8.0.0", 16), true);
assert.are.equal(match(_"8.8.4.4", _"8.8.0.0", 16), true);
end);
end);
describe("#parse_cidr()", function()
it("should work", function()
assert.are.equal(new_ip"0.0.0.0", new_ip"0.0.0.0")
local function assert_cidr(cidr, ip, bits)
local parsed_ip, parsed_bits = parse_cidr(cidr);
assert.are.equal(new_ip(ip), parsed_ip, cidr.." parsed ip is "..ip);
assert.are.equal(bits, parsed_bits, cidr.." parsed bits is "..tostring(bits));
end
assert_cidr("0.0.0.0", "0.0.0.0", nil);
assert_cidr("127.0.0.1", "127.0.0.1", nil);
assert_cidr("127.0.0.1/0", "127.0.0.1", 0);
assert_cidr("127.0.0.1/8", "127.0.0.1", 8);
assert_cidr("127.0.0.1/32", "127.0.0.1", 32);
assert_cidr("127.0.0.1/256", "127.0.0.1", 256);
assert_cidr("::/48", "::", 48);
end);
end);
describe("#new_ip()", function()
it("should work", function()
local v4, v6 = "IPv4", "IPv6";
local function assert_proto(s, proto)
local ip = new_ip(s);
if proto then
assert.are.equal(ip and ip.proto, proto, "protocol is correct for "..("%q"):format(s));
else
assert.are.equal(ip, nil, "address is invalid");
end
end
assert_proto("127.0.0.1", v4);
assert_proto("::1", v6);
assert_proto("", nil);
assert_proto("abc", nil);
assert_proto(" ", nil);
end);
end);
describe("#commonPrefixLength()", function()
it("should work", function()
local function assert_cpl6(a, b, len, v4)
local ipa, ipb = new_ip(a), new_ip(b);
if v4 then len = len+96; end
assert.are.equal(commonPrefixLength(ipa, ipb), len, "common prefix length of "..a.." and "..b.." is "..len);
assert.are.equal(commonPrefixLength(ipb, ipa), len, "common prefix length of "..b.." and "..a.." is "..len);
end
local function assert_cpl4(a, b, len)
return assert_cpl6(a, b, len, "IPv4");
end
assert_cpl4("0.0.0.0", "0.0.0.0", 32);
assert_cpl4("255.255.255.255", "0.0.0.0", 0);
assert_cpl4("255.255.255.255", "255.255.0.0", 16);
assert_cpl4("255.255.255.255", "255.255.255.255", 32);
assert_cpl4("255.255.255.255", "255.255.255.255", 32);
assert_cpl6("::1", "::1", 128);
assert_cpl6("abcd::1", "abcd::1", 128);
assert_cpl6("abcd::abcd", "abcd::", 112);
assert_cpl6("abcd::abcd", "abcd::abcd:abcd", 96);
end);
end);
end);

146
spec/util_jid_spec.lua Normal file
View file

@ -0,0 +1,146 @@
local jid = require "util.jid";
describe("util.jid", function()
describe("#join()", function()
it("should work", function()
assert.are.equal(jid.join("a", "b", "c"), "a@b/c", "builds full JID");
assert.are.equal(jid.join("a", "b", nil), "a@b", "builds bare JID");
assert.are.equal(jid.join(nil, "b", "c"), "b/c", "builds full host JID");
assert.are.equal(jid.join(nil, "b", nil), "b", "builds bare host JID");
assert.are.equal(jid.join(nil, nil, nil), nil, "invalid JID is nil");
assert.are.equal(jid.join("a", nil, nil), nil, "invalid JID is nil");
assert.are.equal(jid.join(nil, nil, "c"), nil, "invalid JID is nil");
assert.are.equal(jid.join("a", nil, "c"), nil, "invalid JID is nil");
end);
end);
describe("#split()", function()
it("should work", function()
local function test(input_jid, expected_node, expected_server, expected_resource)
local rnode, rserver, rresource = jid.split(input_jid);
assert.are.equal(expected_node, rnode, "split("..tostring(input_jid)..") failed");
assert.are.equal(expected_server, rserver, "split("..tostring(input_jid)..") failed");
assert.are.equal(expected_resource, rresource, "split("..tostring(input_jid)..") failed");
end
-- Valid JIDs
test("node@server", "node", "server", nil );
test("node@server/resource", "node", "server", "resource" );
test("server", nil, "server", nil );
test("server/resource", nil, "server", "resource" );
test("server/resource@foo", nil, "server", "resource@foo" );
test("server/resource@foo/bar", nil, "server", "resource@foo/bar");
-- Always invalid JIDs
test(nil, nil, nil, nil);
test("node@/server", nil, nil, nil);
test("@server", nil, nil, nil);
test("@server/resource", nil, nil, nil);
test("@/resource", nil, nil, nil);
end);
end);
describe("#bare()", function()
it("should work", function()
assert.are.equal(jid.bare("user@host"), "user@host", "bare JID remains bare");
assert.are.equal(jid.bare("host"), "host", "Host JID remains host");
assert.are.equal(jid.bare("host/resource"), "host", "Host JID with resource becomes host");
assert.are.equal(jid.bare("user@host/resource"), "user@host", "user@host JID with resource becomes user@host");
assert.are.equal(jid.bare("user@/resource"), nil, "invalid JID is nil");
assert.are.equal(jid.bare("@/resource"), nil, "invalid JID is nil");
assert.are.equal(jid.bare("@/"), nil, "invalid JID is nil");
assert.are.equal(jid.bare("/"), nil, "invalid JID is nil");
assert.are.equal(jid.bare(""), nil, "invalid JID is nil");
assert.are.equal(jid.bare("@"), nil, "invalid JID is nil");
assert.are.equal(jid.bare("user@"), nil, "invalid JID is nil");
assert.are.equal(jid.bare("user@@"), nil, "invalid JID is nil");
assert.are.equal(jid.bare("user@@host"), nil, "invalid JID is nil");
assert.are.equal(jid.bare("user@@host/resource"), nil, "invalid JID is nil");
assert.are.equal(jid.bare("user@host/"), nil, "invalid JID is nil");
end);
end);
describe("#compare()", function()
it("should work", function()
assert.are.equal(jid.compare("host", "host"), true, "host should match");
assert.are.equal(jid.compare("host", "other-host"), false, "host should not match");
assert.are.equal(jid.compare("other-user@host/resource", "host"), true, "host should match");
assert.are.equal(jid.compare("other-user@host", "user@host"), false, "user should not match");
assert.are.equal(jid.compare("user@host", "host"), true, "host should match");
assert.are.equal(jid.compare("user@host/resource", "host"), true, "host should match");
assert.are.equal(jid.compare("user@host/resource", "user@host"), true, "user and host should match");
assert.are.equal(jid.compare("user@other-host", "host"), false, "host should not match");
assert.are.equal(jid.compare("user@other-host", "user@host"), false, "host should not match");
end);
end);
it("should work with nodes", function()
local function test(_jid, expected_node)
assert.are.equal(jid.node(_jid), expected_node, "Unexpected node for "..tostring(_jid));
end
test("example.com", nil);
test("foo.example.com", nil);
test("foo.example.com/resource", nil);
test("foo.example.com/some resource", nil);
test("foo.example.com/some@resource", nil);
test("foo@foo.example.com/some@resource", "foo");
test("foo@example/some@resource", "foo");
test("foo@example/@resource", "foo");
test("foo@example@resource", nil);
test("foo@example", "foo");
test("foo", nil);
test(nil, nil);
end);
it("should work with hosts", function()
local function test(_jid, expected_host)
assert.are.equal(jid.host(_jid), expected_host, "Unexpected host for "..tostring(_jid));
end
test("example.com", "example.com");
test("foo.example.com", "foo.example.com");
test("foo.example.com/resource", "foo.example.com");
test("foo.example.com/some resource", "foo.example.com");
test("foo.example.com/some@resource", "foo.example.com");
test("foo@foo.example.com/some@resource", "foo.example.com");
test("foo@example/some@resource", "example");
test("foo@example/@resource", "example");
test("foo@example@resource", nil);
test("foo@example", "example");
test("foo", "foo");
test(nil, nil);
end);
it("should work with resources", function()
local function test(_jid, expected_resource)
assert.are.equal(jid.resource(_jid), expected_resource, "Unexpected resource for "..tostring(_jid));
end
test("example.com", nil);
test("foo.example.com", nil);
test("foo.example.com/resource", "resource");
test("foo.example.com/some resource", "some resource");
test("foo.example.com/some@resource", "some@resource");
test("foo@foo.example.com/some@resource", "some@resource");
test("foo@example/some@resource", "some@resource");
test("foo@example/@resource", "@resource");
test("foo@example@resource", nil);
test("foo@example", nil);
test("foo", nil);
test("/foo", nil);
test("@x/foo", nil);
test("@/foo", nil);
test(nil, nil);
end);
end);

70
spec/util_json_spec.lua Normal file
View file

@ -0,0 +1,70 @@
local json = require "util.json";
describe("util.json", function()
describe("#encode()", function()
it("should work", function()
local function test(f, j, e)
if e then
assert.are.equal(f(j), e);
end
assert.are.equal(f(j), f(json.decode(f(j))));
end
test(json.encode, json.null, "null")
test(json.encode, {}, "{}")
test(json.encode, {a=1});
test(json.encode, {a={1,2,3}});
test(json.encode, {1}, "[1]");
end);
end);
describe("#decode()", function()
it("should work", function()
local empty_array = json.decode("[]");
assert.are.equal(type(empty_array), "table");
assert.are.equal(#empty_array, 0);
assert.are.equal(next(empty_array), nil);
end);
end);
describe("testcases", function()
local valid_data = {};
local invalid_data = {};
local skip = "fail1.json fail9.json fail18.json fail15.json fail13.json fail25.json fail26.json fail27.json fail28.json fail17.json pass1.json";
setup(function()
local lfs = require "lfs";
local path = "spec/json";
for name in lfs.dir(path) do
if name:match("%.json$") then
local f = assert(io.open(path.."/"..name));
local content = assert(f:read("*a"));
assert(f:close());
if skip:find(name) then
-- Skip
elseif name:match("^pass") then
valid_data[name] = content;
elseif name:match("^fail") then
invalid_data[name] = content;
end
end
end
end)
it("should pass valid testcases", function()
for name, content in pairs(valid_data) do
local parsed, err = json.decode(content);
assert(parsed, name..": "..tostring(err));
end
end);
it("should fail invalid testcases", function()
for name, content in pairs(invalid_data) do
local parsed, err = json.decode(content);
assert(not parsed, name..": "..tostring(err));
end
end);
end)
end);

View file

@ -0,0 +1,60 @@
local multitable = require "util.multitable";
describe("util.multitable", function()
describe("#new()", function()
it("should create a multitable", function()
local mt = multitable.new();
assert.is_table(mt, "Multitable is a table");
assert.is_function(mt.add, "Multitable has method add");
assert.is_function(mt.get, "Multitable has method get");
assert.is_function(mt.remove, "Multitable has method remove");
end);
end);
describe("#get()", function()
it("should allow getting correctly", function()
local function has_items(list, ...)
local should_have = {};
if select('#', ...) > 0 then
assert.is_table(list, "has_items: list is table", 3);
else
assert.is.falsy(list and #list > 0, "No items, and no list");
return true, "has-all";
end
for n=1,select('#', ...) do should_have[select(n, ...)] = true; end
for _, item in ipairs(list) do
if not should_have[item] then return false, "too-many"; end
should_have[item] = nil;
end
if next(should_have) then
return false, "not-enough";
end
return true, "has-all";
end
local function assert_has_all(message, list, ...)
return assert.are.equal(select(2, has_items(list, ...)), "has-all", message or "List has all expected items, and no more", 2);
end
local mt = multitable.new();
local trigger1, trigger2, trigger3 = {}, {}, {};
local item1, item2, item3 = {}, {}, {};
assert_has_all("Has no items with trigger1", mt:get(trigger1));
mt:add(1, 2, 3, item1);
assert_has_all("Has item1 for 1, 2, 3", mt:get(1, 2, 3), item1);
end);
end);
-- Doesn't support nil
--[[ mt:add(nil, item1);
mt:add(nil, item2);
mt:add(nil, item3);
assert_has_all("Has all items with (nil)", mt:get(nil), item1, item2, item3);
]]
end);

82
spec/util_queue_spec.lua Normal file
View file

@ -0,0 +1,82 @@
local queue = require "util.queue";
describe("util.queue", function()
describe("#new()", function()
it("should work", function()
do
local q = queue.new(10);
assert.are.equal(q.size, 10);
assert.are.equal(q:count(), 0);
assert.is_true(q:push("one"));
assert.is_true(q:push("two"));
assert.is_true(q:push("three"));
for i = 4, 10 do
assert.is_true(q:push("hello"));
assert.are.equal(q:count(), i, "count is not "..i.."("..q:count()..")");
end
assert.are.equal(q:push("hello"), nil, "queue overfull!");
assert.are.equal(q:push("hello"), nil, "queue overfull!");
assert.are.equal(q:pop(), "one", "queue item incorrect");
assert.are.equal(q:pop(), "two", "queue item incorrect");
assert.is_true(q:push("hello"));
assert.is_true(q:push("hello"));
assert.are.equal(q:pop(), "three", "queue item incorrect");
assert.is_true(q:push("hello"));
assert.are.equal(q:push("hello"), nil, "queue overfull!");
assert.are.equal(q:push("hello"), nil, "queue overfull!");
assert.are.equal(q:count(), 10, "queue count incorrect");
for _ = 1, 10 do
assert.are.equal(q:pop(), "hello", "queue item incorrect");
end
assert.are.equal(q:count(), 0, "queue count incorrect");
assert.is_true(q:push(1));
for i = 1, 1001 do
assert.are.equal(q:pop(), i);
assert.are.equal(q:count(), 0);
assert.is_true(q:push(i+1));
assert.are.equal(q:count(), 1);
end
assert.are.equal(q:pop(), 1002);
assert.is_true(q:push(1));
for i = 1, 1000 do
assert.are.equal(q:pop(), i);
assert.is_true(q:push(i+1));
end
assert.are.equal(q:pop(), 1001);
assert.are.equal(q:count(), 0);
end
do
-- Test queues that purge old items when pushing to a full queue
local q = queue.new(10, true);
for i = 1, 10 do
q:push(i);
end
assert.are.equal(q:count(), 10);
assert.is_true(q:push(11));
assert.are.equal(q:count(), 10);
assert.are.equal(q:pop(), 2); -- First item should have been purged
for i = 12, 32 do
assert.is_true(q:push(i));
end
assert.are.equal(q:count(), 10);
assert.are.equal(q:pop(), 23);
end
end);
end);
end);

19
spec/util_random_spec.lua Normal file
View file

@ -0,0 +1,19 @@
local random = require "util.random";
describe("util.random", function()
describe("#bytes()", function()
it("should return a string", function()
assert.is_string(random.bytes(16));
end);
it("should return the requested number of bytes", function()
-- Makes no attempt at testing how random the bytes are,
-- just that it returns the number of bytes requested
for i = 1, 255 do
assert.are.equal(i, #random.bytes(i));
end
end);
end);
end);

View file

@ -0,0 +1,97 @@
local rfc6724 = require "util.rfc6724";
local new_ip = require"util.ip".new_ip;
describe("util.rfc6724", function()
describe("#source()", function()
it("should work", function()
assert.are.equal(rfc6724.source(new_ip("2001:db8:1::1", "IPv6"),
{new_ip("2001:db8:3::1", "IPv6"), new_ip("fe80::1", "IPv6")}).addr,
"2001:db8:3::1",
"prefer appropriate scope");
assert.are.equal(rfc6724.source(new_ip("ff05::1", "IPv6"),
{new_ip("2001:db8:3::1", "IPv6"), new_ip("fe80::1", "IPv6")}).addr,
"2001:db8:3::1",
"prefer appropriate scope");
assert.are.equal(rfc6724.source(new_ip("2001:db8:1::1", "IPv6"),
{new_ip("2001:db8:1::1", "IPv6"), new_ip("2001:db8:2::1", "IPv6")}).addr,
"2001:db8:1::1",
"prefer same address"); -- "2001:db8:1::1" should be marked "deprecated" here, we don't handle that right now
assert.are.equal(rfc6724.source(new_ip("fe80::1", "IPv6"),
{new_ip("fe80::2", "IPv6"), new_ip("2001:db8:1::1", "IPv6")}).addr,
"fe80::2",
"prefer appropriate scope"); -- "fe80::2" should be marked "deprecated" here, we don't handle that right now
assert.are.equal(rfc6724.source(new_ip("2001:db8:1::1", "IPv6"),
{new_ip("2001:db8:1::2", "IPv6"), new_ip("2001:db8:3::2", "IPv6")}).addr,
"2001:db8:1::2",
"longest matching prefix");
--[[ "2001:db8:1::2" should be a care-of address and "2001:db8:3::2" a home address, we can't handle this and would fail
assert.are.equal(rfc6724.source(new_ip("2001:db8:1::1", "IPv6"),
{new_ip("2001:db8:1::2", "IPv6"), new_ip("2001:db8:3::2", "IPv6")}).addr,
"2001:db8:3::2",
"prefer home address");
]]
assert.are.equal(rfc6724.source(new_ip("2002:c633:6401::1", "IPv6"),
{new_ip("2002:c633:6401::d5e3:7953:13eb:22e8", "IPv6"), new_ip("2001:db8:1::2", "IPv6")}).addr,
"2002:c633:6401::d5e3:7953:13eb:22e8",
"prefer matching label"); -- "2002:c633:6401::d5e3:7953:13eb:22e8" should be marked "temporary" here, we don't handle that right now
assert.are.equal(rfc6724.source(new_ip("2001:db8:1::d5e3:0:0:1", "IPv6"),
{new_ip("2001:db8:1::2", "IPv6"), new_ip("2001:db8:1::d5e3:7953:13eb:22e8", "IPv6")}).addr,
"2001:db8:1::d5e3:7953:13eb:22e8",
"prefer temporary address") -- "2001:db8:1::2" should be marked "public" and "2001:db8:1::d5e3:7953:13eb:22e8" should be marked "temporary" here, we don't handle that right now
end);
end);
describe("#destination()", function()
it("should work", function()
local order;
order = rfc6724.destination({new_ip("2001:db8:1::1", "IPv6"), new_ip("198.51.100.121", "IPv4")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("fe80::1", "IPv6"), new_ip("169.254.13.78", "IPv4")})
assert.are.equal(order[1].addr, "2001:db8:1::1", "prefer matching scope");
assert.are.equal(order[2].addr, "198.51.100.121", "prefer matching scope");
order = rfc6724.destination({new_ip("2001:db8:1::1", "IPv6"), new_ip("198.51.100.121", "IPv4")},
{new_ip("fe80::1", "IPv6"), new_ip("198.51.100.117", "IPv4")})
assert.are.equal(order[1].addr, "198.51.100.121", "prefer matching scope");
assert.are.equal(order[2].addr, "2001:db8:1::1", "prefer matching scope");
order = rfc6724.destination({new_ip("2001:db8:1::1", "IPv6"), new_ip("10.1.2.3", "IPv4")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("fe80::1", "IPv6"), new_ip("10.1.2.4", "IPv4")})
assert.are.equal(order[1].addr, "2001:db8:1::1", "prefer higher precedence");
assert.are.equal(order[2].addr, "10.1.2.3", "prefer higher precedence");
order = rfc6724.destination({new_ip("2001:db8:1::1", "IPv6"), new_ip("fe80::1", "IPv6")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("fe80::2", "IPv6")})
assert.are.equal(order[1].addr, "fe80::1", "prefer smaller scope");
assert.are.equal(order[2].addr, "2001:db8:1::1", "prefer smaller scope");
--[[ "2001:db8:1::2" and "fe80::2" should be marked "care-of address", while "2001:db8:3::1" should be marked "home address", we can't currently handle this and would fail the test
order = rfc6724.destination({new_ip("2001:db8:1::1", "IPv6"), new_ip("fe80::1", "IPv6")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("2001:db8:3::1", "IPv6"), new_ip("fe80::2", "IPv6")})
assert.are.equal(order[1].addr, "2001:db8:1::1", "prefer home address");
assert.are.equal(order[2].addr, "fe80::1", "prefer home address");
]]
--[[ "fe80::2" should be marked "deprecated", we can't currently handle this and would fail the test
order = rfc6724.destination({new_ip("2001:db8:1::1", "IPv6"), new_ip("fe80::1", "IPv6")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("fe80::2", "IPv6")})
assert.are.equal(order[1].addr, "2001:db8:1::1", "avoid deprecated addresses");
assert.are.equal(order[2].addr, "fe80::1", "avoid deprecated addresses");
]]
order = rfc6724.destination({new_ip("2001:db8:1::1", "IPv6"), new_ip("2001:db8:3ffe::1", "IPv6")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("2001:db8:3f44::2", "IPv6"), new_ip("fe80::2", "IPv6")})
assert.are.equal(order[1].addr, "2001:db8:1::1", "longest matching prefix");
assert.are.equal(order[2].addr, "2001:db8:3ffe::1", "longest matching prefix");
order = rfc6724.destination({new_ip("2002:c633:6401::1", "IPv6"), new_ip("2001:db8:1::1", "IPv6")},
{new_ip("2002:c633:6401::2", "IPv6"), new_ip("fe80::2", "IPv6")})
assert.are.equal(order[1].addr, "2002:c633:6401::1", "prefer matching label");
assert.are.equal(order[2].addr, "2001:db8:1::1", "prefer matching label");
order = rfc6724.destination({new_ip("2002:c633:6401::1", "IPv6"), new_ip("2001:db8:1::1", "IPv6")},
{new_ip("2002:c633:6401::2", "IPv6"), new_ip("2001:db8:1::2", "IPv6"), new_ip("fe80::2", "IPv6")})
assert.are.equal(order[1].addr, "2001:db8:1::1", "prefer higher precedence");
assert.are.equal(order[2].addr, "2002:c633:6401::1", "prefer higher precedence");
end);
end);
end);

159
spec/util_stanza_spec.lua Normal file
View file

@ -0,0 +1,159 @@
local st = require "util.stanza";
describe("util.stanza", function()
describe("#preserialize()", function()
it("should work", function()
local stanza = st.stanza("message", { a = "a" });
local stanza2 = st.preserialize(stanza);
assert.is_string(stanza2 and stanza.name, "preserialize returns a stanza");
assert.is_nil(stanza2.tags, "Preserialized stanza has no tag list");
assert.is_nil(stanza2.last_add, "Preserialized stanza has no last_add marker");
assert.is_nil(getmetatable(stanza2), "Preserialized stanza has no metatable");
end);
end);
describe("#preserialize()", function()
it("should work", function()
local stanza = st.stanza("message", { a = "a" });
local stanza2 = st.deserialize(st.preserialize(stanza));
assert.is_string(stanza2 and stanza.name, "deserialize returns a stanza");
assert.is_table(stanza2.attr, "Deserialized stanza has attributes");
assert.are.equal(stanza2.attr.a, "a", "Deserialized stanza retains attributes");
assert.is_table(getmetatable(stanza2), "Deserialized stanza has metatable");
end);
end);
describe("#stanza()", function()
it("should work", function()
local s = st.stanza("foo", { xmlns = "myxmlns", a = "attr-a" });
assert.are.equal(s.name, "foo");
assert.are.equal(s.attr.xmlns, "myxmlns");
assert.are.equal(s.attr.a, "attr-a");
local s1 = st.stanza("s1");
assert.are.equal(s1.name, "s1");
assert.are.equal(s1.attr.xmlns, nil);
assert.are.equal(#s1, 0);
assert.are.equal(#s1.tags, 0);
s1:tag("child1");
assert.are.equal(#s1.tags, 1);
assert.are.equal(s1.tags[1].name, "child1");
s1:tag("grandchild1"):up();
assert.are.equal(#s1.tags, 1);
assert.are.equal(s1.tags[1].name, "child1");
assert.are.equal(#s1.tags[1], 1);
assert.are.equal(s1.tags[1][1].name, "grandchild1");
s1:up():tag("child2");
assert.are.equal(#s1.tags, 2, tostring(s1));
assert.are.equal(s1.tags[1].name, "child1");
assert.are.equal(s1.tags[2].name, "child2");
assert.are.equal(#s1.tags[1], 1);
assert.are.equal(s1.tags[1][1].name, "grandchild1");
s1:up():text("Hello world");
assert.are.equal(#s1.tags, 2);
assert.are.equal(#s1, 3);
assert.are.equal(s1.tags[1].name, "child1");
assert.are.equal(s1.tags[2].name, "child2");
assert.are.equal(#s1.tags[1], 1);
assert.are.equal(s1.tags[1][1].name, "grandchild1");
end);
end);
describe("#message()", function()
it("should work", function()
local m = st.message();
assert.are.equal(m.name, "message");
end);
end);
describe("#iq()", function()
it("should work", function()
local i = st.iq();
assert.are.equal(i.name, "iq");
end);
end);
describe("#iq()", function()
it("should work", function()
local p = st.presence();
assert.are.equal(p.name, "presence");
end);
end);
describe("#reply()", function()
it("should work for <s>", function()
-- Test stanza
local s = st.stanza("s", { to = "touser", from = "fromuser", id = "123" })
:tag("child1");
-- Make reply stanza
local r = st.reply(s);
assert.are.equal(r.name, s.name);
assert.are.equal(r.id, s.id);
assert.are.equal(r.attr.to, s.attr.from);
assert.are.equal(r.attr.from, s.attr.to);
assert.are.equal(#r.tags, 0, "A reply should not include children of the original stanza");
end);
it("should work for <iq get>", function()
-- Test stanza
local s = st.stanza("iq", { to = "touser", from = "fromuser", id = "123", type = "get" })
:tag("child1");
-- Make reply stanza
local r = st.reply(s);
assert.are.equal(r.name, s.name);
assert.are.equal(r.id, s.id);
assert.are.equal(r.attr.to, s.attr.from);
assert.are.equal(r.attr.from, s.attr.to);
assert.are.equal(r.attr.type, "result");
assert.are.equal(#r.tags, 0, "A reply should not include children of the original stanza");
end);
it("should work for <iq set>", function()
-- Test stanza
local s = st.stanza("iq", { to = "touser", from = "fromuser", id = "123", type = "set" })
:tag("child1");
-- Make reply stanza
local r = st.reply(s);
assert.are.equal(r.name, s.name);
assert.are.equal(r.id, s.id);
assert.are.equal(r.attr.to, s.attr.from);
assert.are.equal(r.attr.from, s.attr.to);
assert.are.equal(r.attr.type, "result");
assert.are.equal(#r.tags, 0, "A reply should not include children of the original stanza");
end);
end);
describe("#error_reply()", function()
it("should work for <s>", function()
-- Test stanza
local s = st.stanza("s", { to = "touser", from = "fromuser", id = "123" })
:tag("child1");
-- Make reply stanza
local r = st.error_reply(s);
assert.are.equal(r.name, s.name);
assert.are.equal(r.id, s.id);
assert.are.equal(r.attr.to, s.attr.from);
assert.are.equal(r.attr.from, s.attr.to);
assert.are.equal(#r.tags, 1);
end);
it("should work for <iq get>", function()
-- Test stanza
local s = st.stanza("iq", { to = "touser", from = "fromuser", id = "123", type = "get" })
:tag("child1");
-- Make reply stanza
local r = st.error_reply(s);
assert.are.equal(r.name, s.name);
assert.are.equal(r.id, s.id);
assert.are.equal(r.attr.to, s.attr.from);
assert.are.equal(r.attr.from, s.attr.to);
assert.are.equal(r.attr.type, "error");
assert.are.equal(#r.tags, 1);
end);
end);
end);

View file

@ -0,0 +1,30 @@
-- Mock util.time
local now = 0; -- wibbly-wobbly... timey-wimey... stuff
local function later(n)
now = now + n; -- time passes at a different rate
end
package.loaded["util.time"] = {
now = function() return now; end
}
local throttle = require "util.throttle";
describe("util.sasl.scram", function()
describe("#Hi()", function()
it("should work", function()
local a = throttle.create(3, 10);
assert.are.equal(a:poll(1), true); -- 3 -> 2
assert.are.equal(a:poll(1), true); -- 2 -> 1
assert.are.equal(a:poll(1), true); -- 1 -> 0
assert.are.equal(a:poll(1), false); -- MEEP, out of credits!
later(1); -- ... what about
assert.are.equal(a:poll(1), false); -- now? - Still no!
later(9); -- Later that day
assert.are.equal(a:poll(1), true); -- Should be back at 3 credits ... 2
end);
end);
end);

31
spec/util_uuid_spec.lua Normal file
View file

@ -0,0 +1,31 @@
-- This tests the format, not the randomness
local uuid = require "util.uuid";
describe("util.uuid", function()
describe("#generate()", function()
it("should work follow the UUID pattern", function()
-- https://tools.ietf.org/html/rfc4122#section-4.4
local pattern = "^" .. table.concat({
string.rep("%x", 8),
string.rep("%x", 4),
"4" .. -- version
string.rep("%x", 3),
"[89ab]" .. -- reserved bits of 1 and 0
string.rep("%x", 3),
string.rep("%x", 12),
}, "%-") .. "$";
for _ = 1, 100 do
assert.is_string(uuid.generate():match(pattern));
end
end);
end);
describe("#seed()", function()
it("should return nothing", function()
assert.is_nil(uuid.seed("random string here"), "seed doesn't return anything");
end);
end);
end);

20
spec/util_xml_spec.lua Normal file
View file

@ -0,0 +1,20 @@
local xml = require "util.xml";
describe("util.xml", function()
describe("#parse()", function()
it("should work", function()
local x =
[[<x xmlns:a="b">
<y xmlns:a="c"> <!-- this overwrites 'a' -->
<a:z/>
</y>
<a:z/> <!-- prefix 'a' is nil here, but should be 'b' -->
</x>
]]
local stanza = xml.parse(x);
assert.are.equal(stanza.tags[2].attr.xmlns, "b");
assert.are.equal(stanza.tags[2].namespaces["a"], "b");
end);
end);
end);

View file

@ -0,0 +1,90 @@
local xmppstream = require "util.xmppstream";
describe("util.xmppstream", function()
describe("#new()", function()
it("should work", function()
local function test(xml, expect_success, ex)
local stanzas = {};
local session = { notopen = true };
local callbacks = {
stream_ns = "streamns";
stream_tag = "stream";
default_ns = "stanzans";
streamopened = function (_session)
assert.are.equal(session, _session);
assert.are.equal(session.notopen, true);
_session.notopen = nil;
return true;
end;
handlestanza = function (_session, stanza)
assert.are.equal(session, _session);
assert.are.equal(_session.notopen, nil);
table.insert(stanzas, stanza);
end;
streamclosed = function (_session)
assert.are.equal(session, _session);
assert.are.equal(_session.notopen, nil);
_session.notopen = nil;
end;
}
if type(ex) == "table" then
for k, v in pairs(ex) do
if k ~= "_size_limit" then
callbacks[k] = v;
end
end
end
local stream = xmppstream.new(session, callbacks, size_limit);
local ok, err = pcall(function ()
assert(stream:feed(xml));
end);
if ok and type(expect_success) == "function" then
expect_success(stanzas);
end
assert.are.equal(not not ok, not not expect_success, "Expected "..(expect_success and ("success ("..tostring(err)..")") or "failure"));
end
local function test_stanza(stanza, expect_success, ex)
return test([[<stream:stream xmlns:stream="streamns" xmlns="stanzans">]]..stanza, expect_success, ex);
end
test([[<stream:stream xmlns:stream="streamns"/>]], true);
test([[<stream xmlns="streamns"/>]], true);
test([[<stream1 xmlns="streamns"/>]], false);
test([[<stream xmlns="streamns1"/>]], false);
test("<>", false);
test_stanza("<message/>", function (stanzas)
assert.are.equal(#stanzas, 1);
assert.are.equal(stanzas[1].name, "message");
end);
test_stanza("< message>>>>/>\n", false);
test_stanza([[<x xmlns:a="b">
<y xmlns:a="c">
<a:z/>
</y>
<a:z/>
</x>]], function (stanzas)
assert.are.equal(#stanzas, 1);
local s = stanzas[1];
assert.are.equal(s.name, "x");
assert.are.equal(#s.tags, 2);
assert.are.equal(s.tags[1].name, "y");
assert.are.equal(s.tags[1].attr.xmlns, nil);
assert.are.equal(s.tags[1].tags[1].name, "z");
assert.are.equal(s.tags[1].tags[1].attr.xmlns, "c");
assert.are.equal(s.tags[2].name, "z");
assert.are.equal(s.tags[2].attr.xmlns, "b");
assert.are.equal(s.namespaces, nil);
end);
end);
end);
end);

View file

@ -1,55 +0,0 @@
package.path = "../?.lua;"..package.path;
local api = require "core.modulemanager".api;
local module = setmetatable({}, {__index = api});
local opt = nil;
function module:log() end
function module:get_option(name)
if name == "opt" then
return opt;
else
return nil;
end
end
function test_value(value, returns)
opt = value;
assert(module:get_option_number("opt") == returns.number, "number doesn't match");
assert(module:get_option_string("opt") == returns.string, "string doesn't match");
assert(module:get_option_boolean("opt") == returns.boolean, "boolean doesn't match");
if type(returns.array) == "table" then
local target_array, returned_array = returns.array, module:get_option_array("opt");
assert(#target_array == #returned_array, "array length doesn't match");
for i=1,#target_array do
assert(target_array[i] == returned_array[i], "array item doesn't match");
end
else
assert(module:get_option_array("opt") == returns.array, "array is returned (not nil)");
end
if type(returns.set) == "table" then
local target_items, returned_items = set.new(returns.set), module:get_option_set("opt");
assert(target_items == returned_items, "set doesn't match");
else
assert(module:get_option_set("opt") == returns.set, "set is returned (not nil)");
end
end
test_value(nil, {});
test_value(true, { boolean = true, string = "true", array = {true}, set = {true} });
test_value(false, { boolean = false, string = "false", array = {false}, set = {false} });
test_value("true", { boolean = true, string = "true", array = {"true"}, set = {"true"} });
test_value("false", { boolean = false, string = "false", array = {"false"}, set = {"false"} });
test_value(1, { boolean = true, string = "1", array = {1}, set = {1}, number = 1 });
test_value(0, { boolean = false, string = "0", array = {0}, set = {0}, number = 0 });
test_value("hello world", { string = "hello world", array = {"hello world"}, set = {"hello world"} });
test_value(1234, { string = "1234", number = 1234, array = {1234}, set = {1234} });
test_value({1, 2, 3}, { boolean = true, string = "1", number = 1, array = {1, 2, 3}, set = {1, 2, 3} });
test_value({1, 2, 3, 3, 4}, {boolean = true, string = "1", number = 1, array = {1, 2, 3, 3, 4}, set = {1, 2, 3, 4} });
test_value({0, 1, 2, 3}, { boolean = false, string = "0", number = 0, array = {0, 1, 2, 3}, set = {0, 1, 2, 3} });

View file

@ -1 +0,0 @@
This file was intentionally left blank.

View file

@ -1,10 +0,0 @@
@echo off
set oldpath=%path%
set path=%path%;..;..\lualibs
del reports\*.report
lua test.lua %*
set path=%oldpath%
set oldpath=

View file

@ -1,3 +0,0 @@
#!/bin/sh
rm reports/*.report
exec lua test.lua "$@"

View file

@ -1,256 +0,0 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local tests_passed = true;
function run_all_tests()
package.loaded["net.connlisteners"] = { get = function () return {} end };
dotest "util.jid"
dotest "util.multitable"
dotest "util.rfc6724"
dotest "util.http"
dotest "core.stanza_router"
dotest "core.s2smanager"
dotest "core.configmanager"
dotest "util.ip"
dotest "util.json"
dotest "util.stanza"
dotest "util.sasl.scram"
dotest "util.async"
dotest "util.cache"
dotest "util.throttle"
dotest "util.uuid"
dotest "util.random"
dotest "util.xml"
dotest "util.xmppstream"
dotest "util.queue"
dotest "net.http.parser"
dosingletest("test_sasl.lua", "latin1toutf8");
dosingletest("test_utf8.lua", "valid");
end
local verbosity = tonumber(arg[1]) or 2;
if os.getenv("WINDIR") then
package.path = package.path..";..\\?.lua";
package.cpath = package.cpath..";..\\?.dll";
else
package.path = package.path..";../?.lua";
package.cpath = package.cpath..";../?.so";
end
local _realG = _G;
require "util.import"
local envloadfile = require "util.envload".envloadfile;
local env_mt = { __index = function (t,k) return rawget(_realG, k) or print("WARNING: Attempt to access nil global '"..tostring(k).."'"); end };
function testlib_new_env(t)
return setmetatable(t or {}, env_mt);
end
function assert_equal(a, b, message, level)
if not (a == b) then
error("\n assert_equal failed: "..tostring(a).." ~= "..tostring(b)..(message and ("\n Message: "..message) or ""), (level or 1) + 1);
elseif verbosity >= 4 then
print("assert_equal succeeded: "..tostring(a).." == "..tostring(b));
end
end
function assert_table(a, message, level)
assert_equal(type(a), "table", message, (level or 1) + 1);
end
function assert_function(a, message, level)
assert_equal(type(a), "function", message, (level or 1) + 1);
end
function assert_string(a, message, level)
assert_equal(type(a), "string", message, (level or 1) + 1);
end
function assert_boolean(a, message)
assert_equal(type(a), "boolean", message);
end
function assert_is(a, message)
assert_equal(not not a, true, message);
end
function assert_is_not(a, message)
assert_equal(not not a, false, message);
end
function dosingletest(testname, fname)
local tests = setmetatable({}, { __index = _realG });
tests.__unit = testname;
tests.__test = fname;
local chunk, err = envloadfile(testname, tests);
if not chunk then
print("WARNING: ", "Failed to load tests for "..testname, err);
return;
end
local success, err = pcall(chunk);
if not success then
print("WARNING: ", "Failed to initialise tests for "..testname, err);
return;
end
if type(tests[fname]) ~= "function" then
error(testname.." has no test '"..fname.."'", 0);
end
local line_hook, line_info = new_line_coverage_monitor(testname);
debug.sethook(line_hook, "l")
local success, ret = pcall(tests[fname]);
debug.sethook();
if not success then
tests_passed = false;
print("TEST FAILED! Unit: ["..testname.."] Function: ["..fname.."]");
print(" Location: "..ret:gsub(":%s*\n", "\n"));
line_info(fname, false, report_file);
elseif verbosity >= 2 then
print("TEST SUCCEEDED: ", testname, fname);
print(string.format("TEST COVERED %d/%d lines", line_info(fname, true, report_file)));
else
line_info(name, success, report_file);
end
end
function dotest(unitname)
local _fakeG = setmetatable({}, {__index = _realG});
_fakeG._G = _fakeG;
local tests = setmetatable({}, { __index = _fakeG });
tests.__unit = unitname;
local chunk, err = envloadfile("test_"..unitname:gsub("%.", "_")..".lua", tests);
if not chunk then
print("WARNING: ", "Failed to load tests for "..unitname, err);
return;
end
local success, err = pcall(chunk);
if not success then
print("WARNING: ", "Failed to initialise tests for "..unitname, err);
return;
end
if tests.env then setmetatable(tests.env, { __index = _realG }); end
local unit = setmetatable({}, { __index = setmetatable({ _G = tests.env or _fakeG }, { __index = tests.env or _fakeG }) });
local fn = "../"..unitname:gsub("%.", "/")..".lua";
local chunk, err = envloadfile(fn, unit);
if not chunk then
print("WARNING: ", "Failed to load module: "..unitname, err);
return;
end
local oldmodule, old_M = _fakeG.module, _fakeG._M;
_fakeG.module = function ()
setmetatable(unit, nil);
unit._M = unit;
end
local success, ret = pcall(chunk);
_fakeG.module, _fakeG._M = oldmodule, old_M;
if not success then
print("WARNING: ", "Failed to initialise module: "..unitname, ret);
return;
end
if type(ret) == "table" then
for k,v in pairs(ret) do
unit[k] = v;
end
end
for name, f in pairs(unit) do
local test = rawget(tests, name);
if type(f) ~= "function" then
if verbosity >= 3 then
print("INFO: ", "Skipping "..unitname.."."..name.." because it is not a function");
end
elseif type(test) ~= "function" then
if verbosity >= 1 then
print("WARNING: ", unitname.."."..name.." has no test!");
end
else
if verbosity >= 4 then
print("INFO: ", "Testing "..unitname.."."..name);
end
local line_hook, line_info = new_line_coverage_monitor(fn);
debug.sethook(line_hook, "l")
local success, ret = pcall(test, f, unit);
debug.sethook();
if not success then
tests_passed = false;
print("TEST FAILED! Unit: ["..unitname.."] Function: ["..name.."]");
print(" Location: "..ret:gsub(":%s*\n", "\n"));
line_info(name, false, report_file);
elseif verbosity >= 2 then
print("TEST SUCCEEDED: ", unitname, name);
print(string.format("TEST COVERED %d/%d lines", line_info(name, true, report_file)));
else
line_info(name, success, report_file);
end
end
end
end
function runtest(f, msg)
if not f then print("SUBTEST NOT FOUND: "..(msg or "(no description)")); return; end
local success, ret = pcall(f);
if success and verbosity >= 2 then
print("SUBTEST PASSED: "..(msg or "(no description)"));
elseif (not success) and verbosity >= 0 then
tests_passed = false;
print("SUBTEST FAILED: "..(msg or "(no description)"));
error(ret, 0);
end
end
function new_line_coverage_monitor(file)
local lines_hit, funcs_hit = {}, {};
local total_lines, covered_lines = 0, 0;
for line in io.lines(file) do
total_lines = total_lines + 1;
end
return function (event, line) -- Line hook
if not lines_hit[line] then
local info = debug.getinfo(2, "fSL")
if not info.source:find(file) then return; end
if not funcs_hit[info.func] and info.activelines then
funcs_hit[info.func] = true;
for line in pairs(info.activelines) do
lines_hit[line] = false; -- Marks it as hittable, but not hit yet
end
end
if lines_hit[line] == false then
--print("New line hit: "..line.." in "..debug.getinfo(2, "S").source);
lines_hit[line] = true;
covered_lines = covered_lines + 1;
end
end
end,
function (test_name, success) -- Get info
local fn = file:gsub("^%W*", "");
local total_active_lines = 0;
local coverage_file = io.open("reports/coverage_"..fn:gsub("%W+", "_")..".report", "a+");
for line, active in pairs(lines_hit) do
if active ~= nil then total_active_lines = total_active_lines + 1; end
if coverage_file then
if active == false then coverage_file:write(fn, "|", line, "|", name or "", "|miss\n");
else coverage_file:write(fn, "|", line, "|", name or "", "|", tostring(success), "\n"); end
end
end
if coverage_file then coverage_file:close(); end
return covered_lines, total_active_lines, lines_hit;
end
end
run_all_tests()
os.exit(tests_passed and 0 or 1);

View file

@ -1,33 +0,0 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
function get(get, config)
config.set("example.com", "testkey", 123);
assert_equal(get("example.com", "testkey"), 123, "Retrieving a set key");
config.set("*", "testkey1", 321);
assert_equal(get("*", "testkey1"), 321, "Retrieving a set global key");
assert_equal(get("example.com", "testkey1"), 321, "Retrieving a set key of undefined host, of which only a globally set one exists");
config.set("example.com", ""); -- Creates example.com host in config
assert_equal(get("example.com", "testkey1"), 321, "Retrieving a set key, of which only a globally set one exists");
assert_equal(get(), nil, "No parameters to get()");
assert_equal(get("undefined host"), nil, "Getting for undefined host");
assert_equal(get("undefined host", "undefined key"), nil, "Getting for undefined host & key");
end
function set(set, u)
assert_equal(set("*"), false, "Set with no key");
assert_equal(set("*", "set_test", "testkey"), true, "Setting a nil global value");
assert_equal(set("*", "set_test", "testkey", 123), true, "Setting a global value");
end

View file

@ -1,50 +0,0 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
env = {
prosody = { events = require "util.events".new() };
};
function compare_srv_priorities(csp)
local r1 = { priority = 10, weight = 0 }
local r2 = { priority = 100, weight = 0 }
local r3 = { priority = 1000, weight = 2 }
local r4 = { priority = 1000, weight = 2 }
local r5 = { priority = 1000, weight = 5 }
assert_equal(csp(r1, r1), false);
assert_equal(csp(r1, r2), true);
assert_equal(csp(r1, r3), true);
assert_equal(csp(r1, r4), true);
assert_equal(csp(r1, r5), true);
assert_equal(csp(r2, r1), false);
assert_equal(csp(r2, r2), false);
assert_equal(csp(r2, r3), true);
assert_equal(csp(r2, r4), true);
assert_equal(csp(r2, r5), true);
assert_equal(csp(r3, r1), false);
assert_equal(csp(r3, r2), false);
assert_equal(csp(r3, r3), false);
assert_equal(csp(r3, r4), false);
assert_equal(csp(r3, r5), false);
assert_equal(csp(r4, r1), false);
assert_equal(csp(r4, r2), false);
assert_equal(csp(r4, r3), false);
assert_equal(csp(r4, r4), false);
assert_equal(csp(r4, r5), false);
assert_equal(csp(r5, r1), false);
assert_equal(csp(r5, r2), false);
assert_equal(csp(r5, r3), true);
assert_equal(csp(r5, r4), true);
assert_equal(csp(r5, r5), false);
end

View file

@ -1,232 +0,0 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
_G.prosody = { full_sessions = {}; bare_sessions = {}; hosts = {}; };
function core_process_stanza(core_process_stanza, u)
local stanza = require "util.stanza";
local s2sout_session = { to_host = "remotehost", from_host = "localhost", type = "s2sout" }
local s2sin_session = { from_host = "remotehost", to_host = "localhost", type = "s2sin", hosts = { ["remotehost"] = { authed = true } } }
local local_host_session = { host = "localhost", type = "local", s2sout = { ["remotehost"] = s2sout_session } }
local local_user_session = { username = "user", host = "localhost", resource = "resource", full_jid = "user@localhost/resource", type = "c2s" }
_G.prosody.hosts["localhost"] = local_host_session;
_G.prosody.full_sessions["user@localhost/resource"] = local_user_session;
_G.prosody.bare_sessions["user@localhost"] = { sessions = { resource = local_user_session } };
-- Test message routing
local function test_message_full_jid()
local env = testlib_new_env();
local msg = stanza.stanza("message", { to = "user@localhost/resource", type = "chat" }):tag("body"):text("Hello world");
local target_routed;
function env.core_post_stanza(p_origin, p_stanza)
assert_equal(p_origin, local_user_session, "origin of routed stanza is not correct");
assert_equal(p_stanza, msg, "routed stanza is not correct one: "..p_stanza:pretty_print());
target_routed = true;
end
env.hosts = hosts;
env.prosody = { hosts = hosts };
setfenv(core_process_stanza, env);
assert_equal(core_process_stanza(local_user_session, msg), nil, "core_process_stanza returned incorrect value");
assert_equal(target_routed, true, "stanza was not routed successfully");
end
local function test_message_bare_jid()
local env = testlib_new_env();
local msg = stanza.stanza("message", { to = "user@localhost", type = "chat" }):tag("body"):text("Hello world");
local target_routed;
function env.core_post_stanza(p_origin, p_stanza)
assert_equal(p_origin, local_user_session, "origin of routed stanza is not correct");
assert_equal(p_stanza, msg, "routed stanza is not correct one: "..p_stanza:pretty_print());
target_routed = true;
end
env.hosts = hosts;
setfenv(core_process_stanza, env);
assert_equal(core_process_stanza(local_user_session, msg), nil, "core_process_stanza returned incorrect value");
assert_equal(target_routed, true, "stanza was not routed successfully");
end
local function test_message_no_to()
local env = testlib_new_env();
local msg = stanza.stanza("message", { type = "chat" }):tag("body"):text("Hello world");
local target_handled;
function env.core_post_stanza(p_origin, p_stanza)
assert_equal(p_origin, local_user_session, "origin of handled stanza is not correct");
assert_equal(p_stanza, msg, "handled stanza is not correct one: "..p_stanza:pretty_print());
target_handled = true;
end
env.hosts = hosts;
setfenv(core_process_stanza, env);
assert_equal(core_process_stanza(local_user_session, msg), nil, "core_process_stanza returned incorrect value");
assert_equal(target_handled, true, "stanza was not handled successfully");
end
local function test_message_to_remote_bare()
local env = testlib_new_env();
local msg = stanza.stanza("message", { to = "user@remotehost", type = "chat" }):tag("body"):text("Hello world");
local target_routed;
function env.core_route_stanza(p_origin, p_stanza)
assert_equal(p_origin, local_user_session, "origin of handled stanza is not correct");
assert_equal(p_stanza, msg, "handled stanza is not correct one: "..p_stanza:pretty_print());
target_routed = true;
end
function env.core_post_stanza(...) env.core_route_stanza(...); end
env.hosts = hosts;
setfenv(core_process_stanza, env);
assert_equal(core_process_stanza(local_user_session, msg), nil, "core_process_stanza returned incorrect value");
assert_equal(target_routed, true, "stanza was not routed successfully");
end
local function test_message_to_remote_server()
local env = testlib_new_env();
local msg = stanza.stanza("message", { to = "remotehost", type = "chat" }):tag("body"):text("Hello world");
local target_routed;
function env.core_route_stanza(p_origin, p_stanza)
assert_equal(p_origin, local_user_session, "origin of handled stanza is not correct");
assert_equal(p_stanza, msg, "handled stanza is not correct one: "..p_stanza:pretty_print());
target_routed = true;
end
function env.core_post_stanza(...)
env.core_route_stanza(...);
end
env.hosts = hosts;
setfenv(core_process_stanza, env);
assert_equal(core_process_stanza(local_user_session, msg), nil, "core_process_stanza returned incorrect value");
assert_equal(target_routed, true, "stanza was not routed successfully");
end
--IQ tests
local function test_iq_to_remote_server()
local env = testlib_new_env();
local msg = stanza.stanza("iq", { to = "remotehost", type = "get", id = "id" }):tag("body"):text("Hello world");
local target_routed;
function env.core_route_stanza(p_origin, p_stanza)
assert_equal(p_origin, local_user_session, "origin of handled stanza is not correct");
assert_equal(p_stanza, msg, "handled stanza is not correct one: "..p_stanza:pretty_print());
target_routed = true;
end
function env.core_post_stanza(...)
env.core_route_stanza(...);
end
env.hosts = hosts;
setfenv(core_process_stanza, env);
assert_equal(core_process_stanza(local_user_session, msg), nil, "core_process_stanza returned incorrect value");
assert_equal(target_routed, true, "stanza was not routed successfully");
end
local function test_iq_error_to_local_user()
local env = testlib_new_env();
local msg = stanza.stanza("iq", { to = "user@localhost/resource", from = "user@remotehost", type = "error", id = "id" }):tag("error", { type = 'cancel' }):tag("item-not-found", { xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' });
local target_routed;
function env.core_route_stanza(p_origin, p_stanza)
assert_equal(p_origin, s2sin_session, "origin of handled stanza is not correct");
assert_equal(p_stanza, msg, "handled stanza is not correct one: "..p_stanza:pretty_print());
target_routed = true;
end
function env.core_post_stanza(...)
env.core_route_stanza(...);
end
env.hosts = hosts;
setfenv(core_process_stanza, env);
assert_equal(core_process_stanza(s2sin_session, msg), nil, "core_process_stanza returned incorrect value");
assert_equal(target_routed, true, "stanza was not routed successfully");
end
local function test_iq_to_local_bare()
local env = testlib_new_env();
local msg = stanza.stanza("iq", { to = "user@localhost", from = "user@localhost", type = "get", id = "id" }):tag("ping", { xmlns = "urn:xmpp:ping:0" });
local target_handled;
function env.core_post_stanza(p_origin, p_stanza)
assert_equal(p_origin, local_user_session, "origin of handled stanza is not correct");
assert_equal(p_stanza, msg, "handled stanza is not correct one: "..p_stanza:pretty_print());
target_handled = true;
end
env.hosts = hosts;
setfenv(core_process_stanza, env);
assert_equal(core_process_stanza(local_user_session, msg), nil, "core_process_stanza returned incorrect value");
assert_equal(target_handled, true, "stanza was not handled successfully");
end
runtest(test_message_full_jid, "Messages with full JID destinations get routed");
runtest(test_message_bare_jid, "Messages with bare JID destinations get routed");
runtest(test_message_no_to, "Messages with no destination are handled by the server");
runtest(test_message_to_remote_bare, "Messages to a remote user are routed by the server");
runtest(test_message_to_remote_server, "Messages to a remote server's JID are routed");
runtest(test_iq_to_remote_server, "iq to a remote server's JID are routed");
runtest(test_iq_to_local_bare, "iq from a local user to a local user's bare JID are handled");
runtest(test_iq_error_to_local_user, "iq type=error to a local user's JID are routed");
end
function core_route_stanza(core_route_stanza)
local stanza = require "util.stanza";
local s2sout_session = { to_host = "remotehost", from_host = "localhost", type = "s2sout" }
local s2sin_session = { from_host = "remotehost", to_host = "localhost", type = "s2sin", hosts = { ["remotehost"] = { authed = true } } }
local local_host_session = { host = "localhost", type = "local", s2sout = { ["remotehost"] = s2sout_session }, sessions = {} }
local local_user_session = { username = "user", host = "localhost", resource = "resource", full_jid = "user@localhost/resource", type = "c2s" }
local hosts = {
["localhost"] = local_host_session;
}
local function test_iq_result_to_offline_user()
local env = testlib_new_env();
local msg = stanza.stanza("iq", { to = "user@localhost/foo", from = "user@localhost", type = "result" }):tag("ping", { xmlns = "urn:xmpp:ping:0" });
local msg2 = stanza.stanza("iq", { to = "user@localhost/foo", from = "user@localhost", type = "error" }):tag("ping", { xmlns = "urn:xmpp:ping:0" });
--package.loaded["core.usermanager"] = { user_exists = function (user, host) print("RAR!") return true or user == "user" and host == "localhost" and true; end };
local target_handled, target_replied;
function env.core_post_stanza(p_origin, p_stanza)
target_handled = true;
end
function local_user_session.send(data)
--print("Replying with: ", tostring(data));
--print(debug.traceback())
target_replied = true;
end
env.hosts = hosts;
setfenv(core_route_stanza, env);
assert_equal(core_route_stanza(local_user_session, msg), nil, "core_route_stanza returned incorrect value");
assert_equal(target_handled, nil, "stanza was handled and not dropped");
assert_equal(target_replied, nil, "stanza was replied to and not dropped");
package.loaded["core.usermanager"] = nil;
end
--runtest(test_iq_result_to_offline_user, "iq type=result|error to an offline user are not replied to");
end

View file

@ -1,47 +0,0 @@
local httpstreams = { [[
GET / HTTP/1.1
Host: example.com
]], [[
HTTP/1.1 200 OK
Content-Length: 0
]], [[
HTTP/1.1 200 OK
Content-Length: 7
Hello
HTTP/1.1 200 OK
Transfer-Encoding: chunked
1
H
1
e
2
ll
1
o
0
]]
}
function new(new)
for _, stream in ipairs(httpstreams) do
local success;
local function success_cb(packet)
success = true;
end
stream = stream:gsub("\n", "\r\n");
local parser = new(success_cb, error, stream:sub(1,4) == "HTTP" and "client" or "server")
for chunk in stream:gmatch("..?.?") do
parser:feed(chunk);
end
assert_is(success);
end
end

View file

@ -1,38 +0,0 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local gmatch = string.gmatch;
local t_concat, t_insert = table.concat, table.insert;
local to_byte, to_char = string.byte, string.char;
local function _latin1toutf8(str)
if not str then return str; end
local p = {};
for ch in gmatch(str, ".") do
ch = to_byte(ch);
if (ch < 0x80) then
t_insert(p, to_char(ch));
elseif (ch < 0xC0) then
t_insert(p, to_char(0xC2, ch));
else
t_insert(p, to_char(0xC3, ch - 64));
end
end
return t_concat(p);
end
function latin1toutf8()
local function assert_utf8(latin, utf8)
assert_equal(_latin1toutf8(latin), utf8, "Incorrect UTF8 from Latin1: "..tostring(latin));
end
assert_utf8("", "")
assert_utf8("test", "test")
assert_utf8(nil, nil)
assert_utf8("foobar.r\229kat.se", "foobar.r\195\165kat.se")
end

View file

@ -1,18 +0,0 @@
package.cpath = "../?.so"
package.path = "../?.lua";
function valid()
local encodings = require "util.encodings";
local utf8 = assert(encodings.utf8, "no encodings.utf8 module");
for line in io.lines("utf8_sequences.txt") do
local data = line:match(":%s*([^#]+)"):gsub("%s+", ""):gsub("..", function (c) return string.char(tonumber(c, 16)); end)
local expect = line:match("(%S+):");
if expect ~= "pass" and expect ~= "fail" then
error("unknown expectation: "..line:match("^[^:]+"));
end
local valid = utf8.valid(data);
assert_equal(valid, utf8.valid(data.." "));
assert_equal(valid, expect == "pass", line);
end
end

View file

@ -1,301 +0,0 @@
-- Test passing nil to runner
-- Test runners work correctly after errors (coroutine gets recreated)
-- What happens if an error is thrown, but more items are in the queue? (I think runner might stall)
-- Test errors thrown halfway through a queue
-- Multiple runners
function runner(new_runner, async)
local function new(func, name)
local log = {};
return new_runner(func, setmetatable({}, {
__index = function (_, event)
return function (runner, err)
print(name, "event", event, err)
table.insert(log, { event = event, err = err });
end;
end;
})), log;
end
--------------------
local r, l = new(function (item) assert(type(item) == "number") end);
r:run(1);
r:run(2);
--for k, v in ipairs(l) do print(k,v) end
--------------------
local wait, done;
local r, l = new(function (item)
assert(type(item) == "number")
if item == 3 then
wait, done = async.waiter();
wait();
end
end);
r:run(1);
assert(r.state == "ready");
r:run(2);
assert(r.state == "ready");
r:run(3);
assert(r.state == "waiting");
done();
assert(r.state == "ready");
--for k, v in ipairs(l) do print(k,v) end
--------------------
local wait, done;
local last_item = 0;
local r, l = new(function (item)
assert(type(item) == "number")
assert(item == last_item + 1);
last_item = item;
if item == 3 then
wait, done = async.waiter();
wait();
end
end);
r:run(1);
assert(r.state == "ready");
r:run(2);
assert(r.state == "ready");
r:run(3);
assert(r.state == "waiting");
r:run(4);
assert(r.state == "waiting");
done();
assert(r.state == "ready");
--for k, v in ipairs(l) do print(k,v) end
--------------------
local wait, done;
local last_item = 0;
local r, l = new(function (item)
assert(type(item) == "number")
assert((item == last_item + 1) or item == 3);
last_item = item;
if item == 3 then
wait, done = async.waiter();
wait();
end
end);
r:run(1);
assert(r.state == "ready");
r:run(2);
assert(r.state == "ready");
local dones = {};
r:run(3);
assert(r.state == "waiting");
r:run(3);
assert(r.state == "waiting");
r:run(3);
assert(r.state == "waiting");
r:run(4);
assert(r.state == "waiting");
for i = 1, 3 do
done();
if i < 3 then
assert(r.state == "waiting");
end
end
assert(r.state == "ready");
--for k, v in ipairs(l) do print(k,v) end
--------------------
local wait, done;
local last_item = 0;
local r, l = new(function (item)
assert(type(item) == "number")
assert((item == last_item + 1) or item == 3);
last_item = item;
if item == 3 then
wait, done = async.waiter();
wait();
end
end);
r:run(1);
assert(r.state == "ready");
r:run(2);
assert(r.state == "ready");
local dones = {};
r:run(3);
assert(r.state == "waiting");
r:run(3);
assert(r.state == "waiting");
for i = 1, 2 do
done();
if i < 2 then
assert(r.state == "waiting");
end
end
assert(r.state == "ready");
r:run(4);
assert(r.state == "ready");
assert(r.state == "ready");
--for k, v in ipairs(l) do print(k,v) end
-- Now with multiple runners
--------------------
local wait1, done1;
local last_item1 = 0;
local r1, l1 = new(function (item)
assert(type(item) == "number")
assert((item == last_item1 + 1) or item == 3);
last_item1 = item;
if item == 3 then
wait1, done1 = async.waiter();
wait1();
end
end, "r1");
local wait2, done2;
local last_item2 = 0;
local r2, l2 = new(function (item)
assert(type(item) == "number")
assert((item == last_item2 + 1) or item == 3);
last_item2 = item;
if item == 3 then
wait2, done2 = async.waiter();
wait2();
end
end, "r2");
r1:run(1);
assert(r1.state == "ready");
r1:run(2);
assert(r1.state == "ready");
local dones = {};
r1:run(3);
assert(r1.state == "waiting");
r1:run(3);
assert(r1.state == "waiting");
r2:run(1);
assert(r1.state == "waiting");
assert(r2.state == "ready");
r2:run(2);
assert(r1.state == "waiting");
assert(r2.state == "ready");
r2:run(3);
assert(r1.state == "waiting");
assert(r2.state == "waiting");
done2();
r2:run(3);
assert(r1.state == "waiting");
assert(r2.state == "waiting");
done2();
r2:run(2);
assert(r1.state == "waiting");
assert(r2.state == "ready");
for i = 1, 2 do
done1();
if i < 2 then
assert(r1.state == "waiting");
end
end
assert(r1.state == "ready");
r1:run(4);
assert(r1.state == "ready");
assert(r1.state == "ready");
--for k, v in ipairs(l1) do print(k,v) end
--------------------
local wait1, done1;
local last_item1 = 0;
local r1, l1 = new(function (item)
assert(type(item) == "number")
assert((item == last_item1 + 1) or item == 3);
last_item1 = item;
if item == 3 then
wait1, done1 = async.waiter();
wait1();
end
end, "r1");
local wait2, done2;
local last_item2 = 0;
local r2, l2 = new(function (item)
assert(type(item) == "number")
assert((item == last_item2 + 1) or item == 3);
last_item2 = item;
if item == 3 then
wait2, done2 = async.waiter();
wait2();
end
end, "r2");
r1:run(1);
assert(r1.state == "ready");
r1:run(2);
assert(r1.state == "ready");
r1:run(5);
assert(r1.state == "ready");
local dones = {};
r1:run(3);
assert(r1.state == "waiting");
r1:run(5); -- Will error, when we get to it
assert(r1.state == "waiting");
r1:run(3);
assert(r1.state == "waiting");
r2:run(1);
assert(r1.state == "waiting");
assert(r2.state == "ready");
r2:run(2);
assert(r1.state == "waiting");
assert(r2.state == "ready");
r2:run(3);
assert(r1.state == "waiting");
assert(r2.state == "waiting");
done2();
r2:run(3);
assert(r1.state == "waiting");
assert(r2.state == "waiting");
done2();
r2:run(2);
assert(r1.state == "waiting");
assert(r2.state == "ready");
for i = 1, 2 do
done1();
if i < 2 then
assert_equal(r1.state, "waiting");
end
end
assert(r1.state == "ready");
r1:run(4);
assert(r1.state == "ready");
assert(r1.state == "ready");
--for k, v in ipairs(l1) do print(k,v) end
end

View file

@ -1,309 +0,0 @@
function new(new)
local c = new(5);
local function expect_kv(key, value, actual_key, actual_value)
assert_equal(key, actual_key, "key incorrect");
assert_equal(value, actual_value, "value incorrect");
end
expect_kv(nil, nil, c:head());
expect_kv(nil, nil, c:tail());
assert_equal(c:count(), 0);
c:set("one", 1)
assert_equal(c:count(), 1);
expect_kv("one", 1, c:head());
expect_kv("one", 1, c:tail());
c:set("two", 2)
expect_kv("two", 2, c:head());
expect_kv("one", 1, c:tail());
c:set("three", 3)
expect_kv("three", 3, c:head());
expect_kv("one", 1, c:tail());
c:set("four", 4)
c:set("five", 5);
assert_equal(c:count(), 5);
expect_kv("five", 5, c:head());
expect_kv("one", 1, c:tail());
c:set("foo", nil);
assert_equal(c:count(), 5);
expect_kv("five", 5, c:head());
expect_kv("one", 1, c:tail());
assert_equal(c:get("one"), 1);
expect_kv("five", 5, c:head());
expect_kv("one", 1, c:tail());
assert_equal(c:get("two"), 2);
assert_equal(c:get("three"), 3);
assert_equal(c:get("four"), 4);
assert_equal(c:get("five"), 5);
assert_equal(c:get("foo"), nil);
assert_equal(c:get("bar"), nil);
c:set("six", 6);
assert_equal(c:count(), 5);
expect_kv("six", 6, c:head());
expect_kv("two", 2, c:tail());
assert_equal(c:get("one"), nil);
assert_equal(c:get("two"), 2);
assert_equal(c:get("three"), 3);
assert_equal(c:get("four"), 4);
assert_equal(c:get("five"), 5);
assert_equal(c:get("six"), 6);
c:set("three", nil);
assert_equal(c:count(), 4);
assert_equal(c:get("one"), nil);
assert_equal(c:get("two"), 2);
assert_equal(c:get("three"), nil);
assert_equal(c:get("four"), 4);
assert_equal(c:get("five"), 5);
assert_equal(c:get("six"), 6);
c:set("seven", 7);
assert_equal(c:count(), 5);
assert_equal(c:get("one"), nil);
assert_equal(c:get("two"), 2);
assert_equal(c:get("three"), nil);
assert_equal(c:get("four"), 4);
assert_equal(c:get("five"), 5);
assert_equal(c:get("six"), 6);
assert_equal(c:get("seven"), 7);
c:set("eight", 8);
assert_equal(c:count(), 5);
assert_equal(c:get("one"), nil);
assert_equal(c:get("two"), nil);
assert_equal(c:get("three"), nil);
assert_equal(c:get("four"), 4);
assert_equal(c:get("five"), 5);
assert_equal(c:get("six"), 6);
assert_equal(c:get("seven"), 7);
assert_equal(c:get("eight"), 8);
c:set("four", 4);
assert_equal(c:count(), 5);
assert_equal(c:get("one"), nil);
assert_equal(c:get("two"), nil);
assert_equal(c:get("three"), nil);
assert_equal(c:get("four"), 4);
assert_equal(c:get("five"), 5);
assert_equal(c:get("six"), 6);
assert_equal(c:get("seven"), 7);
assert_equal(c:get("eight"), 8);
c:set("nine", 9);
assert_equal(c:count(), 5);
assert_equal(c:get("one"), nil);
assert_equal(c:get("two"), nil);
assert_equal(c:get("three"), nil);
assert_equal(c:get("four"), 4);
assert_equal(c:get("five"), nil);
assert_equal(c:get("six"), 6);
assert_equal(c:get("seven"), 7);
assert_equal(c:get("eight"), 8);
assert_equal(c:get("nine"), 9);
do
local keys = { "nine", "four", "eight", "seven", "six" };
local values = { 9, 4, 8, 7, 6 };
local i = 0;
for k, v in c:items() do
i = i + 1;
assert_equal(k, keys[i]);
assert_equal(v, values[i]);
end
assert_equal(i, 5);
c:set("four", "2+2");
assert_equal(c:count(), 5);
assert_equal(c:get("one"), nil);
assert_equal(c:get("two"), nil);
assert_equal(c:get("three"), nil);
assert_equal(c:get("four"), "2+2");
assert_equal(c:get("five"), nil);
assert_equal(c:get("six"), 6);
assert_equal(c:get("seven"), 7);
assert_equal(c:get("eight"), 8);
assert_equal(c:get("nine"), 9);
end
do
local keys = { "four", "nine", "eight", "seven", "six" };
local values = { "2+2", 9, 8, 7, 6 };
local i = 0;
for k, v in c:items() do
i = i + 1;
assert_equal(k, keys[i]);
assert_equal(v, values[i]);
end
assert_equal(i, 5);
c:set("foo", nil);
assert_equal(c:count(), 5);
assert_equal(c:get("one"), nil);
assert_equal(c:get("two"), nil);
assert_equal(c:get("three"), nil);
assert_equal(c:get("four"), "2+2");
assert_equal(c:get("five"), nil);
assert_equal(c:get("six"), 6);
assert_equal(c:get("seven"), 7);
assert_equal(c:get("eight"), 8);
assert_equal(c:get("nine"), 9);
end
do
local keys = { "four", "nine", "eight", "seven", "six" };
local values = { "2+2", 9, 8, 7, 6 };
local i = 0;
for k, v in c:items() do
i = i + 1;
assert_equal(k, keys[i]);
assert_equal(v, values[i]);
end
assert_equal(i, 5);
c:set("four", nil);
assert_equal(c:get("one"), nil);
assert_equal(c:get("two"), nil);
assert_equal(c:get("three"), nil);
assert_equal(c:get("four"), nil);
assert_equal(c:get("five"), nil);
assert_equal(c:get("six"), 6);
assert_equal(c:get("seven"), 7);
assert_equal(c:get("eight"), 8);
assert_equal(c:get("nine"), 9);
end
do
local keys = { "nine", "eight", "seven", "six" };
local values = { 9, 8, 7, 6 };
local i = 0;
for k, v in c:items() do
i = i + 1;
assert_equal(k, keys[i]);
assert_equal(v, values[i]);
end
assert_equal(i, 4);
end
do
local evicted_key, evicted_value;
local c2 = new(3, function (_key, _value)
evicted_key, evicted_value = _key, _value;
end);
local function set(k, v, should_evict_key, should_evict_value)
evicted_key, evicted_value = nil, nil;
c2:set(k, v);
assert_equal(evicted_key, should_evict_key);
assert_equal(evicted_value, should_evict_value);
end
set("a", 1)
set("a", 1)
set("a", 1)
set("a", 1)
set("a", 1)
set("b", 2)
set("c", 3)
set("b", 2)
set("d", 4, "a", 1)
set("e", 5, "c", 3)
end
do
local evicted_key, evicted_value;
local c3 = new(1, function (_key, _value)
evicted_key, evicted_value = _key, _value;
if _key == "a" then
-- Sanity check for what we're evicting
assert_equal(_key, "a");
assert_equal(_value, 1);
-- We're going to block eviction of this key/value, so set to nil...
evicted_key, evicted_value = nil, nil;
-- Returning false to block eviction
return false
end
end);
local function set(k, v, should_evict_key, should_evict_value)
evicted_key, evicted_value = nil, nil;
local ret = c3:set(k, v);
assert_equal(evicted_key, should_evict_key);
assert_equal(evicted_value, should_evict_value);
return ret;
end
set("a", 1)
set("a", 1)
set("a", 1)
set("a", 1)
set("a", 1)
-- Our on_evict prevents "a" from being evicted, causing this to fail...
assert_equal(set("b", 2), false, "Failed to prevent eviction, or signal result");
expect_kv("a", 1, c3:head());
expect_kv("a", 1, c3:tail());
-- Check the final state is what we expect
assert_equal(c3:get("a"), 1);
assert_equal(c3:get("b"), nil);
assert_equal(c3:count(), 1);
end
local c4 = new(3, false);
assert_equal(c4:set("a", 1), true);
assert_equal(c4:set("a", 1), true);
assert_equal(c4:set("a", 1), true);
assert_equal(c4:set("a", 1), true);
assert_equal(c4:set("b", 2), true);
assert_equal(c4:set("c", 3), true);
assert_equal(c4:set("d", 4), false);
assert_equal(c4:set("d", 4), false);
assert_equal(c4:set("d", 4), false);
expect_kv("c", 3, c4:head());
expect_kv("a", 1, c4:tail());
local c5 = new(3, function (k, v)
if k == "a" then
return nil;
elseif k == "b" then
return true;
end
return false;
end);
assert_equal(c5:set("a", 1), true);
assert_equal(c5:set("a", 1), true);
assert_equal(c5:set("a", 1), true);
assert_equal(c5:set("a", 1), true);
assert_equal(c5:set("b", 2), true);
assert_equal(c5:set("c", 3), true);
assert_equal(c5:set("d", 4), true); -- "a" evicted (cb returned nil)
assert_equal(c5:set("d", 4), true); -- nop
assert_equal(c5:set("d", 4), true); -- nop
assert_equal(c5:set("e", 5), true); -- "b" evicted (cb returned true)
assert_equal(c5:set("f", 6), false); -- "c" won't evict (cb returned false)
expect_kv("e", 5, c5:head());
expect_kv("c", 3, c5:tail());
end

View file

@ -1,41 +0,0 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
function urlencode(urlencode)
assert_equal(urlencode("helloworld123"), "helloworld123", "Normal characters not escaped");
assert_equal(urlencode("hello world"), "hello%20world", "Spaces escaped");
assert_equal(urlencode("This & that = something"), "This%20%26%20that%20%3d%20something", "Important URL chars escaped");
end
function urldecode(urldecode)
assert_equal("helloworld123", urldecode("helloworld123"), "Normal characters not escaped");
assert_equal("hello world", urldecode("hello%20world"), "Spaces escaped");
assert_equal("This & that = something", urldecode("This%20%26%20that%20%3d%20something"), "Important URL chars escaped");
assert_equal("This & that = something", urldecode("This%20%26%20that%20%3D%20something"), "Important URL chars escaped");
end
function formencode(formencode)
assert_equal(formencode({ { name = "one", value = "1"}, { name = "two", value = "2" } }), "one=1&two=2", "Form encoded");
assert_equal(formencode({ { name = "one two", value = "1"}, { name = "two one&", value = "2" } }), "one+two=1&two+one%26=2", "Form encoded");
end
function formdecode(formdecode)
do
local t = formdecode("one=1&two=2");
assert_table(t[1]);
assert_equal(t[1].name, "one"); assert_equal(t[1].value, "1");
assert_table(t[2]);
assert_equal(t[2].name, "two"); assert_equal(t[2].value, "2");
end
do
local t = formdecode("one+two=1&two+one%26=2");
assert_equal(t[1].name, "one two"); assert_equal(t[1].value, "1");
assert_equal(t[2].name, "two one&"); assert_equal(t[2].value, "2");
end
end

View file

@ -1,89 +0,0 @@
function match(match, _M)
local _ = _M.new_ip;
local ip = _"10.20.30.40";
assert_equal(match(ip, _"10.0.0.0", 8), true);
assert_equal(match(ip, _"10.0.0.0", 16), false);
assert_equal(match(ip, _"10.0.0.0", 24), false);
assert_equal(match(ip, _"10.0.0.0", 32), false);
assert_equal(match(ip, _"10.20.0.0", 8), true);
assert_equal(match(ip, _"10.20.0.0", 16), true);
assert_equal(match(ip, _"10.20.0.0", 24), false);
assert_equal(match(ip, _"10.20.0.0", 32), false);
assert_equal(match(ip, _"0.0.0.0", 32), false);
assert_equal(match(ip, _"0.0.0.0", 0), true);
assert_equal(match(ip, _"0.0.0.0"), false);
assert_equal(match(ip, _"10.0.0.0", 255), false, "excessive number of bits");
assert_equal(match(ip, _"10.0.0.0", -8), true, "negative number of bits");
assert_equal(match(ip, _"10.0.0.0", -32), true, "negative number of bits");
assert_equal(match(ip, _"10.0.0.0", 0), true, "zero bits");
assert_equal(match(ip, _"10.0.0.0"), false, "no specified number of bits (differing ip)");
assert_equal(match(ip, _"10.20.30.40"), true, "no specified number of bits (same ip)");
assert_equal(match(_"127.0.0.1", _"127.0.0.1"), true, "simple ip");
assert_equal(match(_"8.8.8.8", _"8.8.0.0", 16), true);
assert_equal(match(_"8.8.4.4", _"8.8.0.0", 16), true);
end
function parse_cidr(parse_cidr, _M)
local new_ip = _M.new_ip;
assert_equal(new_ip"0.0.0.0", new_ip"0.0.0.0")
local function assert_cidr(cidr, ip, bits)
local parsed_ip, parsed_bits = parse_cidr(cidr);
assert_equal(new_ip(ip), parsed_ip, cidr.." parsed ip is "..ip);
assert_equal(bits, parsed_bits, cidr.." parsed bits is "..tostring(bits));
end
assert_cidr("0.0.0.0", "0.0.0.0", nil);
assert_cidr("127.0.0.1", "127.0.0.1", nil);
assert_cidr("127.0.0.1/0", "127.0.0.1", 0);
assert_cidr("127.0.0.1/8", "127.0.0.1", 8);
assert_cidr("127.0.0.1/32", "127.0.0.1", 32);
assert_cidr("127.0.0.1/256", "127.0.0.1", 256);
assert_cidr("::/48", "::", 48);
end
function new_ip(new_ip)
local v4, v6 = "IPv4", "IPv6";
local function assert_proto(s, proto)
local ip = new_ip(s);
if proto then
assert_equal(ip and ip.proto, proto, "protocol is correct for "..("%q"):format(s));
else
assert_equal(ip, nil, "address is invalid");
end
end
assert_proto("127.0.0.1", v4);
assert_proto("::1", v6);
assert_proto("", nil);
assert_proto("abc", nil);
assert_proto(" ", nil);
end
function commonPrefixLength(cpl, _M)
local new_ip = _M.new_ip;
local function assert_cpl6(a, b, len, v4)
local ipa, ipb = new_ip(a), new_ip(b);
if v4 then len = len+96; end
assert_equal(cpl(ipa, ipb), len, "common prefix length of "..a.." and "..b.." is "..len);
assert_equal(cpl(ipb, ipa), len, "common prefix length of "..b.." and "..a.." is "..len);
end
local function assert_cpl4(a, b, len)
return assert_cpl6(a, b, len, "IPv4");
end
assert_cpl4("0.0.0.0", "0.0.0.0", 32);
assert_cpl4("255.255.255.255", "0.0.0.0", 0);
assert_cpl4("255.255.255.255", "255.255.0.0", 16);
assert_cpl4("255.255.255.255", "255.255.255.255", 32);
assert_cpl4("255.255.255.255", "255.255.255.255", 32);
assert_cpl6("::1", "::1", 128);
assert_cpl6("abcd::1", "abcd::1", 128);
assert_cpl6("abcd::abcd", "abcd::", 112);
assert_cpl6("abcd::abcd", "abcd::abcd:abcd", 96);
end

View file

@ -1,143 +0,0 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
function join(join)
assert_equal(join("a", "b", "c"), "a@b/c", "builds full JID");
assert_equal(join("a", "b", nil), "a@b", "builds bare JID");
assert_equal(join(nil, "b", "c"), "b/c", "builds full host JID");
assert_equal(join(nil, "b", nil), "b", "builds bare host JID");
assert_equal(join(nil, nil, nil), nil, "invalid JID is nil");
assert_equal(join("a", nil, nil), nil, "invalid JID is nil");
assert_equal(join(nil, nil, "c"), nil, "invalid JID is nil");
assert_equal(join("a", nil, "c"), nil, "invalid JID is nil");
end
function split(split)
local function test(input_jid, expected_node, expected_server, expected_resource)
local rnode, rserver, rresource = split(input_jid);
assert_equal(expected_node, rnode, "split("..tostring(input_jid)..") failed");
assert_equal(expected_server, rserver, "split("..tostring(input_jid)..") failed");
assert_equal(expected_resource, rresource, "split("..tostring(input_jid)..") failed");
end
-- Valid JIDs
test("node@server", "node", "server", nil );
test("node@server/resource", "node", "server", "resource" );
test("server", nil, "server", nil );
test("server/resource", nil, "server", "resource" );
test("server/resource@foo", nil, "server", "resource@foo" );
test("server/resource@foo/bar", nil, "server", "resource@foo/bar");
-- Always invalid JIDs
test(nil, nil, nil, nil);
test("node@/server", nil, nil, nil);
test("@server", nil, nil, nil);
test("@server/resource", nil, nil, nil);
test("@/resource", nil, nil, nil);
end
function bare(bare)
assert_equal(bare("user@host"), "user@host", "bare JID remains bare");
assert_equal(bare("host"), "host", "Host JID remains host");
assert_equal(bare("host/resource"), "host", "Host JID with resource becomes host");
assert_equal(bare("user@host/resource"), "user@host", "user@host JID with resource becomes user@host");
assert_equal(bare("user@/resource"), nil, "invalid JID is nil");
assert_equal(bare("@/resource"), nil, "invalid JID is nil");
assert_equal(bare("@/"), nil, "invalid JID is nil");
assert_equal(bare("/"), nil, "invalid JID is nil");
assert_equal(bare(""), nil, "invalid JID is nil");
assert_equal(bare("@"), nil, "invalid JID is nil");
assert_equal(bare("user@"), nil, "invalid JID is nil");
assert_equal(bare("user@@"), nil, "invalid JID is nil");
assert_equal(bare("user@@host"), nil, "invalid JID is nil");
assert_equal(bare("user@@host/resource"), nil, "invalid JID is nil");
assert_equal(bare("user@host/"), nil, "invalid JID is nil");
end
function compare(compare)
assert_equal(compare("host", "host"), true, "host should match");
assert_equal(compare("host", "other-host"), false, "host should not match");
assert_equal(compare("other-user@host/resource", "host"), true, "host should match");
assert_equal(compare("other-user@host", "user@host"), false, "user should not match");
assert_equal(compare("user@host", "host"), true, "host should match");
assert_equal(compare("user@host/resource", "host"), true, "host should match");
assert_equal(compare("user@host/resource", "user@host"), true, "user and host should match");
assert_equal(compare("user@other-host", "host"), false, "host should not match");
assert_equal(compare("user@other-host", "user@host"), false, "host should not match");
end
function node(node)
local function test(jid, expected_node)
assert_equal(node(jid), expected_node, "Unexpected node for "..tostring(jid));
end
test("example.com", nil);
test("foo.example.com", nil);
test("foo.example.com/resource", nil);
test("foo.example.com/some resource", nil);
test("foo.example.com/some@resource", nil);
test("foo@foo.example.com/some@resource", "foo");
test("foo@example/some@resource", "foo");
test("foo@example/@resource", "foo");
test("foo@example@resource", nil);
test("foo@example", "foo");
test("foo", nil);
test(nil, nil);
end
function host(host)
local function test(jid, expected_host)
assert_equal(host(jid), expected_host, "Unexpected host for "..tostring(jid));
end
test("example.com", "example.com");
test("foo.example.com", "foo.example.com");
test("foo.example.com/resource", "foo.example.com");
test("foo.example.com/some resource", "foo.example.com");
test("foo.example.com/some@resource", "foo.example.com");
test("foo@foo.example.com/some@resource", "foo.example.com");
test("foo@example/some@resource", "example");
test("foo@example/@resource", "example");
test("foo@example@resource", nil);
test("foo@example", "example");
test("foo", "foo");
test(nil, nil);
end
function resource(resource)
local function test(jid, expected_resource)
assert_equal(resource(jid), expected_resource, "Unexpected resource for "..tostring(jid));
end
test("example.com", nil);
test("foo.example.com", nil);
test("foo.example.com/resource", "resource");
test("foo.example.com/some resource", "some resource");
test("foo.example.com/some@resource", "some@resource");
test("foo@foo.example.com/some@resource", "some@resource");
test("foo@example/some@resource", "some@resource");
test("foo@example/@resource", "@resource");
test("foo@example@resource", nil);
test("foo@example", nil);
test("foo", nil);
test("/foo", nil);
test("@x/foo", nil);
test("@/foo", nil);
test(nil, nil);
end

View file

@ -1,21 +0,0 @@
function encode(encode, json)
local function test(f, j, e)
if e then
assert_equal(f(j), e);
end
assert_equal(f(j), f(json.decode(f(j))));
end
test(encode, json.null, "null")
test(encode, {}, "{}")
test(encode, {a=1});
test(encode, {a={1,2,3}});
test(encode, {1}, "[1]");
end
function decode(decode)
local empty_array = decode("[]");
assert_equal(type(empty_array), "table");
assert_equal(#empty_array, 0);
assert_equal(next(empty_array), nil);
end

View file

@ -1,39 +0,0 @@
#!/bin/bash
export LUA_PATH="../?.lua;;"
export LUA_CPATH="../?.so;;"
#set -x
if ! which "$RUNWITH"; then
echo "Unable to find interpreter $RUNWITH";
exit 1;
fi
if ! $RUNWITH -e 'assert(require"util.json")' 2>/dev/null; then
echo "Unable to find util.json";
exit 1;
fi
FAIL=0
for f in json/pass*.json; do
if ! $RUNWITH -e 'local j=require"util.json" assert(j.decode(io.read("*a"))~=nil)' <"$f" 2>/dev/null; then
echo "Failed to decode valid JSON: $f";
FAIL=1
fi
done
for f in json/fail*.json; do
if ! $RUNWITH -e 'local j=require"util.json" assert(j.decode(io.read("*a"))==nil)' <"$f" 2>/dev/null; then
echo "Invalid JSON decoded without error: $f";
FAIL=1
fi
done
if [ "$FAIL" == "1" ]; then
echo "JSON tests failed"
exit 1;
fi
exit 0;

View file

@ -1,62 +0,0 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
function new(new, multitable)
local mt = new();
assert_table(mt, "Multitable is a table");
assert_function(mt.add, "Multitable has method add");
assert_function(mt.get, "Multitable has method get");
assert_function(mt.remove, "Multitable has method remove");
get(mt.get, multitable);
end
function get(get, multitable)
local function has_items(list, ...)
local should_have = {};
if select('#', ...) > 0 then
assert_table(list, "has_items: list is table", 3);
else
assert_is_not(list and #list > 0, "No items, and no list");
return true, "has-all";
end
for n=1,select('#', ...) do should_have[select(n, ...)] = true; end
for _, item in ipairs(list) do
if not should_have[item] then return false, "too-many"; end
should_have[item] = nil;
end
if next(should_have) then
return false, "not-enough";
end
return true, "has-all";
end
local function assert_has_all(message, list, ...)
return assert_equal(select(2, has_items(list, ...)), "has-all", message or "List has all expected items, and no more", 2);
end
local mt = multitable.new();
local trigger1, trigger2, trigger3 = {}, {}, {};
local item1, item2, item3 = {}, {}, {};
assert_has_all("Has no items with trigger1", mt:get(trigger1));
mt:add(1, 2, 3, item1);
assert_has_all("Has item1 for 1, 2, 3", mt:get(1, 2, 3), item1);
-- Doesn't support nil
--[[ mt:add(nil, item1);
mt:add(nil, item2);
mt:add(nil, item3);
assert_has_all("Has all items with (nil)", mt:get(nil), item1, item2, item3);
]]
end

View file

@ -1,74 +0,0 @@
function new(new)
do
local q = new(10);
assert_equal(q.size, 10);
assert_equal(q:count(), 0);
assert_is(q:push("one"));
assert_is(q:push("two"));
assert_is(q:push("three"));
for i = 4, 10 do
assert_is(q:push("hello"));
assert_equal(q:count(), i, "count is not "..i.."("..q:count()..")");
end
assert_equal(q:push("hello"), nil, "queue overfull!");
assert_equal(q:push("hello"), nil, "queue overfull!");
assert_equal(q:pop(), "one", "queue item incorrect");
assert_equal(q:pop(), "two", "queue item incorrect");
assert_is(q:push("hello"));
assert_is(q:push("hello"));
assert_equal(q:pop(), "three", "queue item incorrect");
assert_is(q:push("hello"));
assert_equal(q:push("hello"), nil, "queue overfull!");
assert_equal(q:push("hello"), nil, "queue overfull!");
assert_equal(q:count(), 10, "queue count incorrect");
for _ = 1, 10 do
assert_equal(q:pop(), "hello", "queue item incorrect");
end
assert_equal(q:count(), 0, "queue count incorrect");
assert_is(q:push(1));
for i = 1, 1001 do
assert_equal(q:pop(), i);
assert_equal(q:count(), 0);
assert_is(q:push(i+1));
assert_equal(q:count(), 1);
end
assert_equal(q:pop(), 1002);
assert_is(q:push(1));
for i = 1, 1000 do
assert_equal(q:pop(), i);
assert_is(q:push(i+1));
end
assert_equal(q:pop(), 1001);
assert_equal(q:count(), 0);
end
do
-- Test queues that purge old items when pushing to a full queue
local q = new(10, true);
for i = 1, 10 do
q:push(i);
end
assert_equal(q:count(), 10);
assert_is(q:push(11));
assert_equal(q:count(), 10);
assert_equal(q:pop(), 2); -- First item should have been purged
for i = 12, 32 do
assert_is(q:push(i));
end
assert_equal(q:count(), 10);
assert_equal(q:pop(), 23);
end
end

View file

@ -1,10 +0,0 @@
-- Makes no attempt at testing how random the bytes are,
-- just that it returns the number of bytes requested
function bytes(bytes)
assert_is(bytes(16));
for i = 1, 255 do
assert_equal(i, #bytes(i));
end
end

View file

@ -1,97 +0,0 @@
-- Prosody IM
-- Copyright (C) 2011-2013 Florian Zeitz
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
function source(source)
local new_ip = require"util.ip".new_ip;
assert_equal(source(new_ip("2001:db8:1::1", "IPv6"),
{new_ip("2001:db8:3::1", "IPv6"), new_ip("fe80::1", "IPv6")}).addr,
"2001:db8:3::1",
"prefer appropriate scope");
assert_equal(source(new_ip("ff05::1", "IPv6"),
{new_ip("2001:db8:3::1", "IPv6"), new_ip("fe80::1", "IPv6")}).addr,
"2001:db8:3::1",
"prefer appropriate scope");
assert_equal(source(new_ip("2001:db8:1::1", "IPv6"),
{new_ip("2001:db8:1::1", "IPv6"), new_ip("2001:db8:2::1", "IPv6")}).addr,
"2001:db8:1::1",
"prefer same address"); -- "2001:db8:1::1" should be marked "deprecated" here, we don't handle that right now
assert_equal(source(new_ip("fe80::1", "IPv6"),
{new_ip("fe80::2", "IPv6"), new_ip("2001:db8:1::1", "IPv6")}).addr,
"fe80::2",
"prefer appropriate scope"); -- "fe80::2" should be marked "deprecated" here, we don't handle that right now
assert_equal(source(new_ip("2001:db8:1::1", "IPv6"),
{new_ip("2001:db8:1::2", "IPv6"), new_ip("2001:db8:3::2", "IPv6")}).addr,
"2001:db8:1::2",
"longest matching prefix");
--[[ "2001:db8:1::2" should be a care-of address and "2001:db8:3::2" a home address, we can't handle this and would fail
assert_equal(source(new_ip("2001:db8:1::1", "IPv6"),
{new_ip("2001:db8:1::2", "IPv6"), new_ip("2001:db8:3::2", "IPv6")}).addr,
"2001:db8:3::2",
"prefer home address");
]]
assert_equal(source(new_ip("2002:c633:6401::1", "IPv6"),
{new_ip("2002:c633:6401::d5e3:7953:13eb:22e8", "IPv6"), new_ip("2001:db8:1::2", "IPv6")}).addr,
"2002:c633:6401::d5e3:7953:13eb:22e8",
"prefer matching label"); -- "2002:c633:6401::d5e3:7953:13eb:22e8" should be marked "temporary" here, we don't handle that right now
assert_equal(source(new_ip("2001:db8:1::d5e3:0:0:1", "IPv6"),
{new_ip("2001:db8:1::2", "IPv6"), new_ip("2001:db8:1::d5e3:7953:13eb:22e8", "IPv6")}).addr,
"2001:db8:1::d5e3:7953:13eb:22e8",
"prefer temporary address") -- "2001:db8:1::2" should be marked "public" and "2001:db8:1::d5e3:7953:13eb:22e8" should be marked "temporary" here, we don't handle that right now
end
function destination(dest)
local order;
local new_ip = require"util.ip".new_ip;
order = dest({new_ip("2001:db8:1::1", "IPv6"), new_ip("198.51.100.121", "IPv4")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("fe80::1", "IPv6"), new_ip("169.254.13.78", "IPv4")})
assert_equal(order[1].addr, "2001:db8:1::1", "prefer matching scope");
assert_equal(order[2].addr, "198.51.100.121", "prefer matching scope");
order = dest({new_ip("2001:db8:1::1", "IPv6"), new_ip("198.51.100.121", "IPv4")},
{new_ip("fe80::1", "IPv6"), new_ip("198.51.100.117", "IPv4")})
assert_equal(order[1].addr, "198.51.100.121", "prefer matching scope");
assert_equal(order[2].addr, "2001:db8:1::1", "prefer matching scope");
order = dest({new_ip("2001:db8:1::1", "IPv6"), new_ip("10.1.2.3", "IPv4")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("fe80::1", "IPv6"), new_ip("10.1.2.4", "IPv4")})
assert_equal(order[1].addr, "2001:db8:1::1", "prefer higher precedence");
assert_equal(order[2].addr, "10.1.2.3", "prefer higher precedence");
order = dest({new_ip("2001:db8:1::1", "IPv6"), new_ip("fe80::1", "IPv6")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("fe80::2", "IPv6")})
assert_equal(order[1].addr, "fe80::1", "prefer smaller scope");
assert_equal(order[2].addr, "2001:db8:1::1", "prefer smaller scope");
--[[ "2001:db8:1::2" and "fe80::2" should be marked "care-of address", while "2001:db8:3::1" should be marked "home address", we can't currently handle this and would fail the test
order = dest({new_ip("2001:db8:1::1", "IPv6"), new_ip("fe80::1", "IPv6")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("2001:db8:3::1", "IPv6"), new_ip("fe80::2", "IPv6")})
assert_equal(order[1].addr, "2001:db8:1::1", "prefer home address");
assert_equal(order[2].addr, "fe80::1", "prefer home address");
]]
--[[ "fe80::2" should be marked "deprecated", we can't currently handle this and would fail the test
order = dest({new_ip("2001:db8:1::1", "IPv6"), new_ip("fe80::1", "IPv6")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("fe80::2", "IPv6")})
assert_equal(order[1].addr, "2001:db8:1::1", "avoid deprecated addresses");
assert_equal(order[2].addr, "fe80::1", "avoid deprecated addresses");
]]
order = dest({new_ip("2001:db8:1::1", "IPv6"), new_ip("2001:db8:3ffe::1", "IPv6")},
{new_ip("2001:db8:1::2", "IPv6"), new_ip("2001:db8:3f44::2", "IPv6"), new_ip("fe80::2", "IPv6")})
assert_equal(order[1].addr, "2001:db8:1::1", "longest matching prefix");
assert_equal(order[2].addr, "2001:db8:3ffe::1", "longest matching prefix");
order = dest({new_ip("2002:c633:6401::1", "IPv6"), new_ip("2001:db8:1::1", "IPv6")},
{new_ip("2002:c633:6401::2", "IPv6"), new_ip("fe80::2", "IPv6")})
assert_equal(order[1].addr, "2002:c633:6401::1", "prefer matching label");
assert_equal(order[2].addr, "2001:db8:1::1", "prefer matching label");
order = dest({new_ip("2002:c633:6401::1", "IPv6"), new_ip("2001:db8:1::1", "IPv6")},
{new_ip("2002:c633:6401::2", "IPv6"), new_ip("2001:db8:1::2", "IPv6"), new_ip("fe80::2", "IPv6")})
assert_equal(order[1].addr, "2001:db8:1::1", "prefer higher precedence");
assert_equal(order[2].addr, "2002:c633:6401::1", "prefer higher precedence");
end

View file

@ -1,23 +0,0 @@
local hmac_sha1 = require "util.hashes".hmac_sha1;
local function toHex(s)
return s and (s:gsub(".", function (c) return ("%02x"):format(c:byte()); end));
end
function Hi(Hi)
assert( toHex(Hi(hmac_sha1, "password", "salt", 1)) == "0c60c80f961f0e71f3a9b524af6012062fe037a6",
[[FAIL: toHex(Hi(hmac_sha1, "password", "salt", 1)) == "0c60c80f961f0e71f3a9b524af6012062fe037a6"]])
assert( toHex(Hi(hmac_sha1, "password", "salt", 2)) == "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957",
[[FAIL: toHex(Hi(hmac_sha1, "password", "salt", 2)) == "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957"]])
assert( toHex(Hi(hmac_sha1, "password", "salt", 64)) == "a7bc9b6efea2cbd717da72d83bfcc4e17d0b6280",
[[FAIL: toHex(Hi(hmac_sha1, "password", "salt", 64)) == "a7bc9b6efea2cbd717da72d83bfcc4e17d0b6280"]])
assert( toHex(Hi(hmac_sha1, "password", "salt", 4096)) == "4b007901b765489abead49d926f721d065a429c1",
[[FAIL: toHex(Hi(hmac_sha1, "password", "salt", 4096)) == "4b007901b765489abead49d926f721d065a429c1"]])
-- assert( toHex(Hi(hmac_sha1, "password", "salt", 16777216)) == "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984",
-- [[FAIL: toHex(Hi(hmac_sha1, "password", "salt", 16777216)) == "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984"]])
end
function init(init)
-- no tests
end

View file

@ -1,152 +0,0 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
function preserialize(preserialize, st)
local stanza = st.stanza("message", { a = "a" });
local stanza2 = preserialize(stanza);
assert_is(stanza2 and stanza.name, "preserialize returns a stanza");
assert_is_not(stanza2.tags, "Preserialized stanza has no tag list");
assert_is_not(stanza2.last_add, "Preserialized stanza has no last_add marker");
assert_is_not(getmetatable(stanza2), "Preserialized stanza has no metatable");
end
function deserialize(deserialize, st)
local stanza = st.stanza("message", { a = "a" });
local stanza2 = deserialize(st.preserialize(stanza));
assert_is(stanza2 and stanza.name, "deserialize returns a stanza");
assert_table(stanza2.attr, "Deserialized stanza has attributes");
assert_equal(stanza2.attr.a, "a", "Deserialized stanza retains attributes");
assert_table(getmetatable(stanza2), "Deserialized stanza has metatable");
end
function stanza(stanza)
local s = stanza("foo", { xmlns = "myxmlns", a = "attr-a" });
assert_equal(s.name, "foo");
assert_equal(s.attr.xmlns, "myxmlns");
assert_equal(s.attr.a, "attr-a");
local s1 = stanza("s1");
assert_equal(s1.name, "s1");
assert_equal(s1.attr.xmlns, nil);
assert_equal(#s1, 0);
assert_equal(#s1.tags, 0);
s1:tag("child1");
assert_equal(#s1.tags, 1);
assert_equal(s1.tags[1].name, "child1");
s1:tag("grandchild1"):up();
assert_equal(#s1.tags, 1);
assert_equal(s1.tags[1].name, "child1");
assert_equal(#s1.tags[1], 1);
assert_equal(s1.tags[1][1].name, "grandchild1");
s1:up():tag("child2");
assert_equal(#s1.tags, 2, tostring(s1));
assert_equal(s1.tags[1].name, "child1");
assert_equal(s1.tags[2].name, "child2");
assert_equal(#s1.tags[1], 1);
assert_equal(s1.tags[1][1].name, "grandchild1");
s1:up():text("Hello world");
assert_equal(#s1.tags, 2);
assert_equal(#s1, 3);
assert_equal(s1.tags[1].name, "child1");
assert_equal(s1.tags[2].name, "child2");
assert_equal(#s1.tags[1], 1);
assert_equal(s1.tags[1][1].name, "grandchild1");
end
function message(message)
local m = message();
assert_equal(m.name, "message");
end
function iq(iq)
local i = iq();
assert_equal(i.name, "iq");
end
function presence(presence)
local p = presence();
assert_equal(p.name, "presence");
end
function reply(reply, _M)
do
-- Test stanza
local s = _M.stanza("s", { to = "touser", from = "fromuser", id = "123" })
:tag("child1");
-- Make reply stanza
local r = reply(s);
assert_equal(r.name, s.name);
assert_equal(r.id, s.id);
assert_equal(r.attr.to, s.attr.from);
assert_equal(r.attr.from, s.attr.to);
assert_equal(#r.tags, 0, "A reply should not include children of the original stanza");
end
do
-- Test stanza
local s = _M.stanza("iq", { to = "touser", from = "fromuser", id = "123", type = "get" })
:tag("child1");
-- Make reply stanza
local r = reply(s);
assert_equal(r.name, s.name);
assert_equal(r.id, s.id);
assert_equal(r.attr.to, s.attr.from);
assert_equal(r.attr.from, s.attr.to);
assert_equal(r.attr.type, "result");
assert_equal(#r.tags, 0, "A reply should not include children of the original stanza");
end
do
-- Test stanza
local s = _M.stanza("iq", { to = "touser", from = "fromuser", id = "123", type = "set" })
:tag("child1");
-- Make reply stanza
local r = reply(s);
assert_equal(r.name, s.name);
assert_equal(r.id, s.id);
assert_equal(r.attr.to, s.attr.from);
assert_equal(r.attr.from, s.attr.to);
assert_equal(r.attr.type, "result");
assert_equal(#r.tags, 0, "A reply should not include children of the original stanza");
end
end
function error_reply(error_reply, _M)
do
-- Test stanza
local s = _M.stanza("s", { to = "touser", from = "fromuser", id = "123" })
:tag("child1");
-- Make reply stanza
local r = error_reply(s);
assert_equal(r.name, s.name);
assert_equal(r.id, s.id);
assert_equal(r.attr.to, s.attr.from);
assert_equal(r.attr.from, s.attr.to);
assert_equal(#r.tags, 1);
end
do
-- Test stanza
local s = _M.stanza("iq", { to = "touser", from = "fromuser", id = "123", type = "get" })
:tag("child1");
-- Make reply stanza
local r = error_reply(s);
assert_equal(r.name, s.name);
assert_equal(r.id, s.id);
assert_equal(r.attr.to, s.attr.from);
assert_equal(r.attr.from, s.attr.to);
assert_equal(r.attr.type, "error");
assert_equal(#r.tags, 1);
end
end

View file

@ -1,34 +0,0 @@
local now = 0; -- wibbly-wobbly... timey-wimey... stuff
local function predictable_gettime()
return now;
end
local function later(n)
now = now + n; -- time passes at a different rate
end
local function override_gettime(throttle)
local i = 0;
repeat
i = i + 1;
local name = debug.getupvalue(throttle.update, i);
if name then
debug.setupvalue(throttle.update, i, predictable_gettime);
return throttle;
end
until not name;
end
function create(create)
local a = override_gettime( create(3, 10) );
assert_equal(a:poll(1), true); -- 3 -> 2
assert_equal(a:poll(1), true); -- 2 -> 1
assert_equal(a:poll(1), true); -- 1 -> 0
assert_equal(a:poll(1), false); -- MEEP, out of credits!
later(1); -- ... what about
assert_equal(a:poll(1), false); -- now? - Still no!
later(9); -- Later that day
assert_equal(a:poll(1), true); -- Should be back at 3 credits ... 2
end

View file

@ -1,24 +0,0 @@
-- This tests the format, not the randomness
-- https://tools.ietf.org/html/rfc4122#section-4.4
local pattern = "^" .. table.concat({
string.rep("%x", 8),
string.rep("%x", 4),
"4" .. -- version
string.rep("%x", 3),
"[89ab]" .. -- reserved bits of 1 and 0
string.rep("%x", 3),
string.rep("%x", 12),
}, "%-") .. "$";
function generate(generate)
for _ = 1, 100 do
assert_is(generate():match(pattern));
end
end
function seed(seed)
assert_equal(seed("random string here"), nil, "seed doesn't return anything");
end

View file

@ -1,13 +0,0 @@
function parse(parse)
local x =
[[<x xmlns:a="b">
<y xmlns:a="c"> <!-- this overwrites 'a' -->
<a:z/>
</y>
<a:z/> <!-- prefix 'a' is nil here, but should be 'b' -->
</x>
]]
local stanza = parse(x);
assert_equal(stanza.tags[2].attr.xmlns, "b");
assert_equal(stanza.tags[2].namespaces["a"], "b");
end

View file

@ -1,83 +0,0 @@
function new(new_stream, _M)
local function test(xml, expect_success, ex)
local stanzas = {};
local session = { notopen = true };
local callbacks = {
stream_ns = "streamns";
stream_tag = "stream";
default_ns = "stanzans";
streamopened = function (_session)
assert_equal(session, _session);
assert_equal(session.notopen, true);
_session.notopen = nil;
return true;
end;
handlestanza = function (_session, stanza)
assert_equal(session, _session);
assert_equal(_session.notopen, nil);
table.insert(stanzas, stanza);
end;
streamclosed = function (_session)
assert_equal(session, _session);
assert_equal(_session.notopen, nil);
_session.notopen = nil;
end;
}
if type(ex) == "table" then
for k, v in pairs(ex) do
if k ~= "_size_limit" then
callbacks[k] = v;
end
end
end
local stream = new_stream(session, callbacks, size_limit);
local ok, err = pcall(function ()
assert(stream:feed(xml));
end);
if ok and type(expect_success) == "function" then
expect_success(stanzas);
end
assert_equal(not not ok, not not expect_success, "Expected "..(expect_success and ("success ("..tostring(err)..")") or "failure"));
end
local function test_stanza(stanza, expect_success, ex)
return test([[<stream:stream xmlns:stream="streamns" xmlns="stanzans">]]..stanza, expect_success, ex);
end
test([[<stream:stream xmlns:stream="streamns"/>]], true);
test([[<stream xmlns="streamns"/>]], true);
test([[<stream1 xmlns="streamns"/>]], false);
test([[<stream xmlns="streamns1"/>]], false);
test("<>", false);
test_stanza("<message/>", function (stanzas)
assert_equal(#stanzas, 1);
assert_equal(stanzas[1].name, "message");
end);
test_stanza("< message>>>>/>\n", false);
test_stanza([[<x xmlns:a="b">
<y xmlns:a="c">
<a:z/>
</y>
<a:z/>
</x>]], function (stanzas)
assert_equal(#stanzas, 1);
local s = stanzas[1];
assert_equal(s.name, "x");
assert_equal(#s.tags, 2);
assert_equal(s.tags[1].name, "y");
assert_equal(s.tags[1].attr.xmlns, nil);
assert_equal(s.tags[1].tags[1].name, "z");
assert_equal(s.tags[1].tags[1].attr.xmlns, "c");
assert_equal(s.tags[2].name, "z");
assert_equal(s.tags[2].attr.xmlns, "b");
assert_equal(s.namespaces, nil);
end);
end

View file

@ -1,45 +0,0 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local format = string.format;
local print = print;
local debug = debug;
local tostring = tostring;
local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring;
local do_pretty_printing = not os.getenv("WINDIR");
local _ENV = nil
local _M = {}
local logstyles = {};
--TODO: This should be done in config, but we don't have proper config yet
if do_pretty_printing then
logstyles["info"] = getstyle("bold");
logstyles["warn"] = getstyle("bold", "yellow");
logstyles["error"] = getstyle("bold", "red");
end
function _M.init(name)
--name = nil; -- While this line is not commented, will automatically fill in file/line number info
return function (level, message, ...)
if level == "debug" or level == "info" then return; end
if not name then
local inf = debug.getinfo(3, 'Snl');
level = level .. ","..tostring(inf.short_src):match("[^/]*$")..":"..inf.currentline;
end
if ... then
print(name, getstring(logstyles[level], level), format(message, ...));
else
print(name, getstring(logstyles[level], level), message);
end
end
end
return _M;