File

spec/util_throttle_spec.lua @ 10799:763bb2ce3f60

util.pposix,signal: Pass around various OS numbers as integers [Lua 5.3] Passing around PIDs, UIDs etc as integers makes it more sane in Lua 5.3. Getting 1234.0 as PID is silly. Shouldn't change any behavior as these are all integers on the C side and the integral floats are accepted as integers when passed back from Lua into C.
author Kim Alvefur <zash@zash.se>
date Mon, 04 May 2020 21:51:30 +0200
parent 9993:02a41315d275
child 13399:f4415f76727b
line wrap: on
line source



-- 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);