prosody/spec/util_throttle_spec.lua

151 lines
4.1 KiB
Lua

-- luacheck: ignore 411/a
-- 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.throttle", function()
describe("#create()", function()
it("should be created with correct values", function()
now = 5;
local a = throttle.create(3, 10);
assert.same(a, { balance = 3, max = 3, rate = 0.3, t = 5 });
local a = throttle.create(3, 5);
assert.same(a, { balance = 3, max = 3, rate = 0.6, t = 5 });
local a = throttle.create(1, 1);
assert.same(a, { balance = 1, max = 1, rate = 1, t = 5 });
local a = throttle.create(10, 10);
assert.same(a, { balance = 10, max = 10, rate = 1, t = 5 });
local a = throttle.create(10, 1);
assert.same(a, { balance = 10, max = 10, rate = 10, t = 5 });
end);
end);
describe("#update()", function()
it("does nothing when no time has passed, even if balance is not full", function()
now = 5;
local a = throttle.create(10, 10);
for i=1,5 do
a:update();
assert.same(a, { balance = 10, max = 10, rate = 1, t = 5 });
end
a.balance = 0;
for i=1,5 do
a:update();
assert.same(a, { balance = 0, max = 10, rate = 1, t = 5 });
end
end);
it("updates only time when time passes but balance is full", function()
now = 5;
local a = throttle.create(10, 10);
for i=1,5 do
later(5);
a:update();
assert.same(a, { balance = 10, max = 10, rate = 1, t = 5 + i*5 });
end
end);
it("updates balance when balance has room to grow as time passes", function()
now = 5;
local a = throttle.create(10, 10);
a.balance = 0;
assert.same(a, { balance = 0, max = 10, rate = 1, t = 5 });
later(1);
a:update();
assert.same(a, { balance = 1, max = 10, rate = 1, t = 6 });
later(3);
a:update();
assert.same(a, { balance = 4, max = 10, rate = 1, t = 9 });
later(10);
a:update();
assert.same(a, { balance = 10, max = 10, rate = 1, t = 19 });
end);
it("handles 10 x 0.1s updates the same as 1 x 1s update ", function()
now = 5;
local a = throttle.create(1, 1);
a.balance = 0;
later(1);
a:update();
assert.same(a, { balance = 1, max = 1, rate = 1, t = now });
a.balance = 0;
for i=1,10 do
later(0.1);
a:update();
end
assert(math.abs(a.balance - 1) < 0.0001); -- incremental updates cause rounding errors
end);
end);
-- describe("po")
describe("#poll()", function()
it("should only allow successful polls until cost is hit", function()
now = 5;
local a = throttle.create(3, 10);
assert.same(a, { balance = 3, max = 3, rate = 0.3, t = 5 });
assert.is_true(a:poll(1)); -- 3 -> 2
assert.same(a, { balance = 2, max = 3, rate = 0.3, t = 5 });
assert.is_true(a:poll(2)); -- 2 -> 1
assert.same(a, { balance = 0, max = 3, rate = 0.3, t = 5 });
assert.is_false(a:poll(1)); -- MEEP, out of credits!
assert.is_false(a:poll(1)); -- MEEP, out of credits!
assert.same(a, { balance = 0, max = 3, rate = 0.3, t = 5 });
end);
it("should not allow polls more than the cost", function()
now = 0;
local a = throttle.create(10, 10);
assert.same(a, { balance = 10, max = 10, rate = 1, t = 0 });
assert.is_false(a:poll(11));
assert.same(a, { balance = 10, max = 10, rate = 1, t = 0 });
assert.is_true(a:poll(6));
assert.same(a, { balance = 4, max = 10, rate = 1, t = 0 });
assert.is_false(a:poll(5));
assert.same(a, { balance = 4, max = 10, rate = 1, t = 0 });
-- fractional
assert.is_true(a:poll(3.5));
assert.same(a, { balance = 0.5, max = 10, rate = 1, t = 0 });
assert.is_true(a:poll(0.25));
assert.same(a, { balance = 0.25, max = 10, rate = 1, t = 0 });
assert.is_false(a:poll(0.3));
assert.same(a, { balance = 0.25, max = 10, rate = 1, t = 0 });
assert.is_true(a:poll(0.25));
assert.same(a, { balance = 0, max = 10, rate = 1, t = 0 });
assert.is_false(a:poll(0.1));
assert.same(a, { balance = 0, max = 10, rate = 1, t = 0 });
assert.is_true(a:poll(0));
assert.same(a, { balance = 0, max = 10, rate = 1, t = 0 });
end);
end);
end);