aboutsummaryrefslogtreecommitdiffstats
path: root/spec/core_storagemanager_spec.lua
diff options
context:
space:
mode:
Diffstat (limited to 'spec/core_storagemanager_spec.lua')
-rw-r--r--spec/core_storagemanager_spec.lua332
1 files changed, 332 insertions, 0 deletions
diff --git a/spec/core_storagemanager_spec.lua b/spec/core_storagemanager_spec.lua
new file mode 100644
index 00000000..a0a8b5ef
--- /dev/null
+++ b/spec/core_storagemanager_spec.lua
@@ -0,0 +1,332 @@
+local unpack = table.unpack or unpack;
+local server = require "net.server_select";
+package.loaded["net.server"] = server;
+
+local st = require "util.stanza";
+
+local function mock_prosody()
+ _G.prosody = {
+ core_post_stanza = function () end;
+ events = require "util.events".new();
+ hosts = {};
+ paths = {
+ data = "./data";
+ };
+ };
+end
+
+local configs = {
+ memory = {
+ storage = "memory";
+ };
+ internal = {
+ storage = "internal";
+ };
+ sqlite = {
+ storage = "sql";
+ sql = { driver = "SQLite3", database = "prosody-tests.sqlite" };
+ };
+ mysql = {
+ storage = "sql";
+ sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" };
+ };
+ postgres = {
+ storage = "sql";
+ sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" };
+ };
+};
+
+local test_host = "storage-unit-tests.invalid";
+
+describe("storagemanager", function ()
+ for backend, backend_config in pairs(configs) do
+ local tagged_name = "#"..backend;
+ if backend ~= backend_config.storage then
+ tagged_name = tagged_name.." #"..backend_config.storage;
+ end
+ insulate(tagged_name.." #storage backend", function ()
+ mock_prosody();
+
+ local config = require "core.configmanager";
+ local sm = require "core.storagemanager";
+ local hm = require "core.hostmanager";
+ local mm = require "core.modulemanager";
+
+ -- Simple check to ensure insulation is working correctly
+ assert.is_nil(config.get(test_host, "storage"));
+
+ for k, v in pairs(backend_config) do
+ config.set(test_host, k, v);
+ end
+ assert(hm.activate(test_host, {}));
+ sm.initialize_host(test_host);
+ assert(mm.load(test_host, "storage_"..backend_config.storage));
+
+ describe("key-value stores", function ()
+ -- These tests rely on being executed in order, disable any order
+ -- randomization for this block
+ randomize(false);
+
+ local store;
+ it("may be opened", function ()
+ store = assert(sm.open(test_host, "test"));
+ end);
+
+ local simple_data = { foo = "bar" };
+
+ it("may set data for a user", function ()
+ assert(store:set("user9999", simple_data));
+ end);
+
+ it("may get data for a user", function ()
+ assert.same(simple_data, assert(store:get("user9999")));
+ end);
+
+ it("may remove data for a user", function ()
+ assert(store:set("user9999", nil));
+ local ret, err = store:get("user9999");
+ assert.is_nil(ret);
+ assert.is_nil(err);
+ end);
+ end);
+
+ describe("archive stores", function ()
+ randomize(false);
+
+ local archive;
+ it("can be opened", function ()
+ archive = assert(sm.open(test_host, "test-archive", "archive"));
+ end);
+
+ local test_stanza = st.stanza("test", { xmlns = "urn:example:foo" })
+ :tag("foo"):up()
+ :tag("foo"):up();
+ local test_time = 1539204123;
+
+ local test_data = {
+ { nil, test_stanza, test_time, "contact@example.com" };
+ { nil, test_stanza, test_time+1, "contact2@example.com" };
+ { nil, test_stanza, test_time+2, "contact2@example.com" };
+ { nil, test_stanza, test_time-1, "contact2@example.com" };
+ };
+
+ it("can be added to", function ()
+ for _, data_item in ipairs(test_data) do
+ local ok = archive:append("user", unpack(data_item, 1, 4));
+ assert.truthy(ok);
+ end
+ end);
+
+ describe("can be queried", function ()
+ it("for all items", function ()
+ local data, err = archive:find("user", {});
+ assert.truthy(data);
+ local count = 0;
+ for id, item, when in data do
+ count = count + 1;
+ assert.truthy(id);
+ assert(st.is_stanza(item));
+ assert.equal("test", item.name);
+ assert.equal("urn:example:foo", item.attr.xmlns);
+ assert.equal(2, #item.tags);
+ assert.equal(test_data[count][3], when);
+ end
+ assert.equal(#test_data, count);
+ end);
+
+ it("by JID", function ()
+ local data, err = archive:find("user", {
+ with = "contact@example.com";
+ });
+ assert.truthy(data);
+ local count = 0;
+ for id, item, when in data do
+ count = count + 1;
+ assert.truthy(id);
+ assert(st.is_stanza(item));
+ assert.equal("test", item.name);
+ assert.equal("urn:example:foo", item.attr.xmlns);
+ assert.equal(2, #item.tags);
+ assert.equal(test_time, when);
+ end
+ assert.equal(1, count);
+ end);
+
+ it("by time (end)", function ()
+ local data, err = archive:find("user", {
+ ["end"] = test_time;
+ });
+ assert.truthy(data);
+ local count = 0;
+ for id, item, when in data do
+ count = count + 1;
+ assert.truthy(id);
+ assert(st.is_stanza(item));
+ assert.equal("test", item.name);
+ assert.equal("urn:example:foo", item.attr.xmlns);
+ assert.equal(2, #item.tags);
+ assert(test_time >= when);
+ end
+ assert.equal(2, count);
+ end);
+
+ it("by time (start)", function ()
+ local data, err = archive:find("user", {
+ ["start"] = test_time;
+ });
+ assert.truthy(data);
+ local count = 0;
+ for id, item, when in data do
+ count = count + 1;
+ assert.truthy(id);
+ assert(st.is_stanza(item));
+ assert.equal("test", item.name);
+ assert.equal("urn:example:foo", item.attr.xmlns);
+ assert.equal(2, #item.tags);
+ assert(test_time <= when);
+ end
+ assert.equal(#test_data -1, count);
+ end);
+
+ it("by time (start+end)", function ()
+ local data, err = archive:find("user", {
+ ["start"] = test_time;
+ ["end"] = test_time+1;
+ });
+ assert.truthy(data);
+ local count = 0;
+ for id, item, when in data do
+ count = count + 1;
+ assert.truthy(id);
+ assert(st.is_stanza(item));
+ assert.equal("test", item.name);
+ assert.equal("urn:example:foo", item.attr.xmlns);
+ assert.equal(2, #item.tags);
+ assert(when >= test_time, ("%d >= %d"):format(when, test_time));
+ assert(when <= test_time+1, ("%d <= %d"):format(when, test_time+1));
+ end
+ assert.equal(2, count);
+ end);
+ end);
+
+ it("can selectively delete items", function ()
+ local delete_id;
+ do
+ local data = assert(archive:find("user", {}));
+ local count = 0;
+ for id, item, when in data do --luacheck: ignore 213/item 213/when
+ count = count + 1;
+ if count == 2 then
+ delete_id = id;
+ end
+ assert.truthy(id);
+ end
+ assert.equal(#test_data, count);
+ end
+
+ assert(archive:delete("user", { key = delete_id }));
+
+ do
+ local data = assert(archive:find("user", {}));
+ local count = 0;
+ for id, item, when in data do --luacheck: ignore 213/item 213/when
+ count = count + 1;
+ assert.truthy(id);
+ assert.not_equal(delete_id, id);
+ end
+ assert.equal(#test_data-1, count);
+ end
+ end);
+
+ it("can be purged", function ()
+ local ok, err = archive:delete("user");
+ assert.truthy(ok);
+ local data, err = archive:find("user", {
+ with = "contact@example.com";
+ });
+ assert.truthy(data);
+ local count = 0;
+ for id, item, when in data do -- luacheck: ignore id item when
+ count = count + 1;
+ end
+ assert.equal(0, count);
+ end);
+
+ it("can truncate the oldest items", function ()
+ local username = "user-truncate";
+ for i = 1, 10 do
+ assert(archive:append(username, nil, test_stanza, i, "contact@example.com"));
+ end
+ assert(archive:delete(username, { truncate = 3 }));
+
+ do
+ local data = assert(archive:find(username, {}));
+ local count = 0;
+ for id, item, when in data do --luacheck: ignore 213/when
+ count = count + 1;
+ assert.truthy(id);
+ assert(st.is_stanza(item));
+ assert(when > 7, ("%d > 7"):format(when));
+ end
+ assert.equal(3, count);
+ end
+ end);
+
+ it("overwrites existing keys with new data", function ()
+ local prefix = ("a"):rep(50);
+ local username = "user-overwrite";
+ assert(archive:append(username, prefix.."-1", test_stanza, test_time, "contact@example.com"));
+ assert(archive:append(username, prefix.."-2", test_stanza, test_time, "contact@example.com"));
+
+ do
+ local data = assert(archive:find(username, {}));
+ local count = 0;
+ for id, item, when in data do --luacheck: ignore 213/when
+ count = count + 1;
+ assert.truthy(id);
+ assert.equals(("%s-%d"):format(prefix, count), id);
+ assert(st.is_stanza(item));
+ end
+ assert.equal(2, count);
+ end
+
+ local new_stanza = st.clone(test_stanza);
+ new_stanza.attr.foo = "bar";
+ assert(archive:append(username, prefix.."-2", new_stanza, test_time+1, "contact2@example.com"));
+
+ do
+ local data = assert(archive:find(username, {}));
+ local count = 0;
+ for id, item, when in data do
+ count = count + 1;
+ assert.truthy(id);
+ assert.equals(("%s-%d"):format(prefix, count), id);
+ assert(st.is_stanza(item));
+ if count == 2 then
+ assert.equals(test_time+1, when);
+ assert.equals("bar", item.attr.foo);
+ end
+ end
+ assert.equal(2, count);
+ end
+ end);
+
+ it("can contain multiple long unique keys #issue1073", function ()
+ local prefix = ("a"):rep(50);
+ assert(archive:append("user-issue1073", prefix.."-1", test_stanza, test_time, "contact@example.com"));
+ assert(archive:append("user-issue1073", prefix.."-2", test_stanza, test_time, "contact@example.com"));
+
+ local data = assert(archive:find("user-issue1073", {}));
+ local count = 0;
+ for id, item, when in data do --luacheck: ignore 213/when
+ count = count + 1;
+ assert.truthy(id);
+ assert(st.is_stanza(item));
+ end
+ assert.equal(2, count);
+ assert(archive:delete("user-issue1073"));
+ end);
+ end);
+ end);
+ end
+end);