diff --git a/README.md b/README.md index 82c97db..92f1fe9 100644 --- a/README.md +++ b/README.md @@ -116,5 +116,5 @@ QoS provides `priority_override` as last argument for HTTP API functions, this c Return current QoS active requests utilization percentage value. * **`/qos:utilization [priority]`** Return current QoS queue utilization percentage value. -* **`/qos:clear [priority]`** - Return current QoS queue utilization percentage value. +* **`/qos:clear |all`** + Clears selected or all queues. All queued requests are gone for good. diff --git a/commands.lua b/commands.lua index 225bccf..433c943 100644 --- a/commands.lua +++ b/commands.lua @@ -1,10 +1,37 @@ +local function get_priority(priority) + if priority then + priority = tonumber(priority) + if priority and QoS.data.queues[priority] then + return priority + end + return false + end +end + +local function align(s, w) + s = tostring(s) + return s .. string.rep(' ', w - #s) +end + minetest.register_chatcommand("qos:queue_length", { - params = "[priority]", + params = "[]", description = "Return current QoS queue length", privs = { [QoS.config("info_priv")] = true }, func = function(name, priority) - minetest.chat_send_player(name, ("QoS current queue length: %d"):format(QoS.queue_length(tonumber(priority)))) + priority = get_priority(priority) + if priority then + minetest.chat_send_player(name, ("QoS current queue length: %d"):format(QoS.queue_length(priority))) + elseif priority == false then + minetest.chat_send_player(name, "Invalid priority parameter, use empty or 1-"..#QoS.data.queues) + else + local rows = {} + for i,_ in ipairs(QoS.data.queues) do + table.insert(rows, (" %s %d%%"):format(align(i, 8), QoS.utilization(i))) + end + local total = QoS.queue_length() + minetest.chat_send_player(name, ("QoS queue length %d in:\n%s"):format(total, table.concat(rows, "\n"))) + end end }) @@ -25,34 +52,46 @@ minetest.register_chatcommand("qos:active_utilization", { }) minetest.register_chatcommand("qos:utilization", { - params = "[priority]", + params = "[]", description = "Return current QoS queue utilization percentage value", privs = { [QoS.config("info_priv")] = true }, func = function(name, priority) - minetest.chat_send_player(name, ("QoS queue utilization: %d%%"):format(QoS.utilization(tonumber(priority)))) + priority = get_priority(priority) + if priority then + minetest.chat_send_player(name, ("QoS queue utilization: %d%%"):format(QoS.utilization(priority))) + elseif priority == false then + minetest.chat_send_player(name, "Invalid priority parameter, use empty or 1-"..#QoS.data.queues) + else + local rows = {} + for i,_ in ipairs(QoS.data.queues) do + table.insert(rows, (" %s %d%%"):format(align(i, 8), QoS.utilization(i))) + end + local total = QoS.utilization() + minetest.chat_send_player(name, ("QoS queue utilization %d%% in:\n%s") + :format(total, table.concat(rows, "\n")) + ) + end end }) minetest.register_chatcommand("qos:clear", { - params = "[priority]", - description = "Clear QoS queues by priority, clear all queues if piority not given", + params = "|all", + description = "Clear QoS queues by priority, clear all queues if piority is 'all'", privs = { [QoS.config("admin_priv")] = true }, func = function(name, priority) - if priority and priority:find("%S") then - local i = tonumber(priority) - if i and QoS.data.queues[i] then - local length = QoS.data.queues[i].count - QoS.data.queues[i]:clear() - minetest.chat_send_player(name, ("QoS cleared %d priority %d entries"):format(length, i)) - else - minetest.chat_send_player(name, "QoS clear: invalid priority, double check your input") - end - else + if priority == "all" then for i, queue in ipairs(QoS.data.queues) do local length = queue.count queue:clear() - minetest.chat_send_player(name, ("QoS cleared %d priority %d entries"):format(length, i)) + minetest.chat_send_player(name, ("QoS cleared %d entries from priority %d"):format(length, i)) end + elseif get_priority(priority) then + priority = get_priority(priority) + local length = QoS.data.queues[priority].count + QoS.data.queues[priority]:clear() + minetest.chat_send_player(name, ("QoS cleared %d entries from priority %d"):format(length, priority)) + else + minetest.chat_send_player(name, "Invalid priority parameter, use 1-"..#QoS.data.queues.." or 'all'") end end }) diff --git a/spec/command_spec.lua b/spec/command_spec.lua index 117cd21..3dde8c4 100644 --- a/spec/command_spec.lua +++ b/spec/command_spec.lua @@ -6,6 +6,16 @@ mineunit("common/chatcommands") sourcefile("init") +-- Patch spy.on method, see https://github.com/Olivine-Labs/luassert/pull/174 +function spy.on(target_table, target_key) + local s = spy.new(target_table[target_key]) + rawset(target_table, target_key, s) + -- store original data + s.target_table = target_table + s.target_key = target_key + return s +end + describe("Queue initialization", function() it("executes qos:queue_length", function() @@ -19,6 +29,10 @@ describe("Queue initialization", function() func("SX", "1") assert.spy(minetest.chat_send_player).was.called(1) + spy.on(minetest, "chat_send_player") + func("SX", "5") + assert.spy(minetest.chat_send_player).was.called(1) + spy.on(minetest, "chat_send_player") func("SX", "not valid number") assert.spy(minetest.chat_send_player).was.called(1) @@ -51,25 +65,74 @@ describe("Queue initialization", function() func("SX", "1") assert.spy(minetest.chat_send_player).was.called(1) + spy.on(minetest, "chat_send_player") + func("SX", "5") + assert.spy(minetest.chat_send_player).was.called(1) + spy.on(minetest, "chat_send_player") func("SX", "not valid number") assert.spy(minetest.chat_send_player).was.called(1) end) - it("executes qos:clear", function() - local func = minetest.registered_chatcommands["qos:clear"].func - - spy.on(minetest, "chat_send_player") - func("SX") - assert.spy(minetest.chat_send_player).was.called(3) + describe("qos:clear", function() - spy.on(minetest, "chat_send_player") - func("SX", "1") - assert.spy(minetest.chat_send_player).was.called(1) + local func = minetest.registered_chatcommands["qos:clear"].func + local function spy_on_queues_clear() + spy.on(QoS.data.queues[1], "clear") + spy.on(QoS.data.queues[2], "clear") + spy.on(QoS.data.queues[3], "clear") + end + + it("clears all queues", function() + spy.on(minetest, "chat_send_player") + spy_on_queues_clear() + func("SX", "all") + assert.spy(minetest.chat_send_player).was.called(3) + assert.spy(QoS.data.queues[1].clear).was.called(1) + assert.spy(QoS.data.queues[2].clear).was.called(1) + assert.spy(QoS.data.queues[3].clear).was.called(1) + end) + + it("clears selected queue", function() + spy.on(minetest, "chat_send_player") + spy_on_queues_clear() + func("SX", "1") + assert.spy(minetest.chat_send_player).was.called(1) + assert.spy(QoS.data.queues[1].clear).was.called(1) + assert.spy(QoS.data.queues[2].clear).was.called(0) + assert.spy(QoS.data.queues[3].clear).was.called(0) + end) + + it("does not attempt clearing nonexistent queue", function() + spy.on(minetest, "chat_send_player") + spy_on_queues_clear() + func("SX", "5") + assert.spy(minetest.chat_send_player).was.called(1) + assert.spy(QoS.data.queues[1].clear).was.called(0) + assert.spy(QoS.data.queues[2].clear).was.called(0) + assert.spy(QoS.data.queues[3].clear).was.called(0) + end) + + it("does not clear with invalid arguments", function() + spy.on(minetest, "chat_send_player") + spy_on_queues_clear() + func("SX", "not valid number") + assert.spy(minetest.chat_send_player).was.called(1) + assert.spy(QoS.data.queues[1].clear).was.called(0) + assert.spy(QoS.data.queues[2].clear).was.called(0) + assert.spy(QoS.data.queues[3].clear).was.called(0) + end) + + it("does not clear with empty arguments", function() + spy.on(minetest, "chat_send_player") + spy_on_queues_clear() + func("SX") + assert.spy(minetest.chat_send_player).was.called(1) + assert.spy(QoS.data.queues[1].clear).was.called(0) + assert.spy(QoS.data.queues[2].clear).was.called(0) + assert.spy(QoS.data.queues[3].clear).was.called(0) + end) - spy.on(minetest, "chat_send_player") - func("SX", "not valid number") - assert.spy(minetest.chat_send_player).was.called(1) end) end) diff --git a/spec/init_spec.lua b/spec/init_spec.lua index cfde6dd..af83a5c 100644 --- a/spec/init_spec.lua +++ b/spec/init_spec.lua @@ -8,4 +8,13 @@ describe("Mod initialization", function() sourcefile("init") end) + it("Wont crash if initialized with nil", function() + QoS(nil) + QoS() + end) + + it("Wont crash if initialized with nil and priority", function() + QoS(nil, 2) + end) + end)