prosody/spec/util_dbuffer_spec.lua
Matthew Wild 44d68caf9a util.dbuffer: Add a bunch of missing test cases
Found via mutation testing.
2022-10-11 11:38:32 +01:00

222 lines
6.1 KiB
Lua

local dbuffer = require "util.dbuffer";
describe("util.dbuffer", function ()
describe("#new", function ()
it("has a constructor", function ()
assert.Function(dbuffer.new);
end);
it("can be created", function ()
assert.truthy(dbuffer.new());
assert.truthy(dbuffer.new(1));
assert.truthy(dbuffer.new(1024));
end);
it("won't create an empty buffer", function ()
assert.falsy(dbuffer.new(0));
end);
it("won't create a negatively sized buffer", function ()
assert.falsy(dbuffer.new(-1));
end);
end);
describe(":write", function ()
local b = dbuffer.new(10, 3);
it("works", function ()
assert.truthy(b:write("hi"));
end);
it("fails when the buffer is full", function ()
local ret = b:write(" there world, this is a long piece of data");
assert.is_falsy(ret);
end);
it("works when max_chunks is reached", function ()
-- Chunks are an optimization, dbuffer should collapse chunks when needed
for _ = 1, 8 do
assert.truthy(b:write("!"));
end
assert.falsy(b:write("!")); -- Length reached
end);
end);
describe(":read", function ()
it("supports optional bytes parameter", function ()
-- should return the frontmost chunk
local b = dbuffer.new();
assert.truthy(b:write("hello"));
assert.truthy(b:write(" "));
assert.truthy(b:write("world"));
assert.equal("h", b:read(1));
assert.equal("ello", b:read());
assert.equal(" ", b:read());
assert.equal("world", b:read());
end);
it("fails when there is not enough data in the buffer", function ()
local b = dbuffer.new(12);
b:write("hello");
b:write(" ");
b:write("world");
assert.is_falsy(b:read(12));
assert.is_falsy(b:read(13));
end);
end);
describe(":read_until", function ()
it("works", function ()
local b = dbuffer.new();
b:write("hello\n");
b:write("world");
b:write("\n");
b:write("\n\n");
b:write("stuff");
b:write("more\nand more");
assert.equal(nil, b:read_until("."));
assert.equal(nil, b:read_until("%"));
assert.equal("hello\n", b:read_until("\n"));
assert.equal("world\n", b:read_until("\n"));
assert.equal("\n", b:read_until("\n"));
assert.equal("\n", b:read_until("\n"));
assert.equal("stu", b:read(3));
assert.equal("ffmore\n", b:read_until("\n"));
assert.equal(nil, b:read_until("\n"));
assert.equal("and more", b:read_chunk());
end);
end);
describe(":discard", function ()
local b = dbuffer.new();
it("works", function ()
assert.truthy(b:write("hello world"));
assert.truthy(b:discard(6));
assert.equal(5, b:length());
assert.equal(5, b:len());
assert.equal("world", b:read(5));
end);
it("works across chunks", function ()
assert.truthy(b:write("hello"));
assert.truthy(b:write(" "));
assert.truthy(b:write("world"));
assert.truthy(b:discard(3));
assert.equal(8, b:length());
assert.truthy(b:discard(3));
assert.equal(5, b:length());
assert.equal("world", b:read(5));
end);
it("can discard the entire buffer", function ()
assert.equal(b:len(), 0);
assert.truthy(b:write("hello world"));
assert.truthy(b:discard(11));
assert.equal(0, b:len());
assert.truthy(b:write("hello world"));
assert.truthy(b:discard(12));
assert.equal(0, b:len());
assert.truthy(b:write("hello world"));
assert.truthy(b:discard(128));
assert.equal(0, b:len());
end);
it("works on an empty buffer", function ()
assert.truthy(dbuffer.new():discard());
assert.truthy(dbuffer.new():discard(0));
assert.truthy(dbuffer.new():discard(1));
end);
end);
describe(":collapse()", function ()
it("works", function ()
local b = dbuffer.new();
b:write("hello");
b:write(" ");
b:write("world");
b:collapse(6);
local ret, bytes = b:read_chunk();
assert.equal("hello ", ret);
assert.equal(6, bytes);
end);
it("works on an empty buffer", function ()
local b = dbuffer.new();
b:collapse();
end);
end);
describe(":sub", function ()
-- Helper function to compare buffer:sub() with string:sub()
local s = "hello world";
local function test_sub(b, x, y)
local string_result, buffer_result = s:sub(x, y), b:sub(x, y);
assert.equals(string_result, buffer_result, ("buffer:sub(%d, %s) does not match string:sub()"):format(x, y and ("%d"):format(y) or "nil"));
end
it("works", function ()
local b = dbuffer.new();
assert.truthy(b:write("hello world"));
assert.equals("hello", b:sub(1, 5));
end);
it("works after discard", function ()
local b = dbuffer.new(256);
assert.truthy(b:write("foobar"));
assert.equals("foobar", b:sub(1, 6));
assert.truthy(b:discard(3)); -- consume "foo"
assert.equals("bar", b:sub(1, 3));
end);
it("supports optional end parameter", function ()
local b = dbuffer.new();
assert.truthy(b:write("hello world"));
assert.equals("hello world", b:sub(1));
assert.equals("world", b:sub(-5));
end);
it("is equivalent to string:sub", function ()
local b = dbuffer.new(11);
assert.truthy(b:write(s));
for i = -13, 13 do
for j = -13, 13 do
test_sub(b, i, j);
end
end
end);
it("works on an empty buffer", function ()
local b = dbuffer.new();
assert.equal("", b:sub(1, 12));
end);
end);
describe(":byte", function ()
-- Helper function to compare buffer:byte() with string:byte()
local s = "hello world"
local function test_byte(b, x, y)
local string_result, buffer_result = {s:byte(x, y)}, {b:byte(x, y)};
assert.same(
string_result,
buffer_result,
("buffer:byte(%s, %s) does not match string:byte()"):format(x and ("%d"):format(x) or "nil", y and ("%d"):format(y) or "nil")
);
end
it("is equivalent to string:byte", function ()
local b = dbuffer.new(11);
assert.truthy(b:write(s));
test_byte(b, 1);
test_byte(b, 3);
test_byte(b, -1);
test_byte(b, -3);
test_byte(b, nil, 5);
for i = -13, 13 do
for j = -13, 13 do
test_byte(b, i, j);
end
end
end);
it("works with characters > 127", function ()
local b = dbuffer.new();
b:write(string.char(0, 140));
local r = { b:byte(1, 2) };
assert.same({ 0, 140 }, r);
end);
it("works on an empty buffer", function ()
local b = dbuffer.new();
assert.equal("", b:sub(1,1));
end);
end);
end);