telescope-frecency.nvim/lua/frecency/tests/frecency_spec.lua
JINNOUCHI Yasushi c140e6ff9c
feat: make query() faster and more lazier (#241)
* refactor: simplify logic to load web_devicons

* refactor: make register() asynchronous

* fix: load lazily modules outside this plugin

* refactor: simplify logic to wait initialization

* refactor: use uv.hrtime() instead of os.clock()

* fix: avoid errors in calling plenary.log in async

* test: store elapsed time to check in tests

* test: fix module names

This becomes a problem only in Ubuntu because macOS and Windows does not
care cases in filenames.

* test: fix types and unused modules

* style: fix by stylua

* refactor: make recency / entry_maker loaded lazily
2024-08-25 19:28:52 +09:00

326 lines
13 KiB
Lua

-- HACK: This is needed because plenary.test_harness resets &rtp.
-- https://github.com/nvim-lua/plenary.nvim/blob/663246936325062427597964d81d30eaa42ab1e4/lua/plenary/test_harness.lua#L86-L86
vim.opt.runtimepath:append(vim.env.TELESCOPE_PATH)
local Timer = require "frecency.timer"
local util = require "frecency.tests.util"
local log = require "plenary.log"
local filepath = util.filepath
local make_epoch = util.make_epoch
local make_register = util.make_register
local with_fake_register = util.with_fake_register
local with_files = util.with_files
describe("frecency", function()
describe("register", function()
describe("when opening files", function()
with_files({ "hoge1.txt", "hoge2.txt" }, function(frecency, finder, dir)
local register = make_register(frecency, dir)
local epoch1 = make_epoch "2023-07-29T00:00:00+09:00"
local epoch2 = make_epoch "2023-07-29T01:00:00+09:00"
-- HACK: This suspicious 'swapfile' setting is for avoiding E303.
vim.o.swapfile = false
register("hoge1.txt", epoch1)
vim.o.swapfile = true
register("hoge2.txt", epoch2)
it("has valid records in DB", function()
local results = finder:get_results(nil, make_epoch "2023-07-29T02:00:00+09:00")
assert.are.same({
{ count = 1, path = filepath(dir, "hoge2.txt"), score = 10, timestamps = { epoch2 } },
{ count = 1, path = filepath(dir, "hoge1.txt"), score = 10, timestamps = { epoch1 } },
}, results)
end)
end)
end)
describe("when opening again", function()
with_files({ "hoge1.txt", "hoge2.txt" }, function(frecency, finder, dir)
local register = make_register(frecency, dir)
local epoch11 = make_epoch "2023-07-29T00:00:00+09:00"
local epoch2 = make_epoch "2023-07-29T01:00:00+09:00"
local epoch12 = make_epoch "2023-07-29T02:00:00+09:00"
register("hoge1.txt", epoch11)
register("hoge2.txt", epoch2)
register("hoge1.txt", epoch12, true)
it("increases the score", function()
local results = finder:get_results(nil, make_epoch "2023-07-29T03:00:00+09:00")
assert.are.same({
{ count = 2, path = filepath(dir, "hoge1.txt"), score = 40, timestamps = { epoch11, epoch12 } },
{ count = 1, path = filepath(dir, "hoge2.txt"), score = 10, timestamps = { epoch2 } },
}, results)
end)
end)
end)
describe("when opening again but the same instance", function()
with_files({ "hoge1.txt", "hoge2.txt" }, function(frecency, finder, dir)
local register = make_register(frecency, dir)
local epoch11 = make_epoch "2023-07-29T00:00:00+09:00"
local epoch2 = make_epoch "2023-07-29T01:00:00+09:00"
local epoch12 = make_epoch "2023-07-29T02:00:00+09:00"
register("hoge1.txt", epoch11)
register("hoge2.txt", epoch2)
register("hoge1.txt", epoch12)
it("does not increase the score", function()
local results = finder:get_results(nil, make_epoch "2023-07-29T03:00:00+09:00")
assert.are.same({
{ count = 1, path = filepath(dir, "hoge2.txt"), score = 10, timestamps = { epoch2 } },
{ count = 1, path = filepath(dir, "hoge1.txt"), score = 10, timestamps = { epoch11 } },
}, results)
end)
end)
end)
describe("when opening more than 10 times", function()
with_files({ "hoge1.txt", "hoge2.txt" }, function(frecency, finder, dir)
local register = make_register(frecency, dir)
local epoch11 = make_epoch "2023-07-29T00:00:00+09:00"
local epoch12 = make_epoch "2023-07-29T00:01:00+09:00"
register("hoge1.txt", epoch11)
register("hoge1.txt", epoch12, true)
local epoch201 = make_epoch "2023-07-29T00:00:00+09:00"
local epoch202 = make_epoch "2023-07-29T00:01:00+09:00"
local epoch203 = make_epoch "2023-07-29T00:02:00+09:00"
local epoch204 = make_epoch "2023-07-29T00:03:00+09:00"
local epoch205 = make_epoch "2023-07-29T00:04:00+09:00"
local epoch206 = make_epoch "2023-07-29T00:05:00+09:00"
local epoch207 = make_epoch "2023-07-29T00:06:00+09:00"
local epoch208 = make_epoch "2023-07-29T00:07:00+09:00"
local epoch209 = make_epoch "2023-07-29T00:08:00+09:00"
local epoch210 = make_epoch "2023-07-29T00:09:00+09:00"
local epoch211 = make_epoch "2023-07-29T00:10:00+09:00"
local epoch212 = make_epoch "2023-07-29T00:11:00+09:00"
register("hoge2.txt", epoch201)
register("hoge2.txt", epoch202, true)
register("hoge2.txt", epoch203, true)
register("hoge2.txt", epoch204, true)
register("hoge2.txt", epoch205, true)
register("hoge2.txt", epoch206, true)
register("hoge2.txt", epoch207, true)
register("hoge2.txt", epoch208, true)
register("hoge2.txt", epoch209, true)
register("hoge2.txt", epoch210, true)
register("hoge2.txt", epoch211, true)
register("hoge2.txt", epoch212, true)
it("calculates score from the recent 10 times", function()
local results = finder:get_results(nil, make_epoch "2023-07-29T00:12:00+09:00")
assert.are.same({
{
count = 12,
path = filepath(dir, "hoge2.txt"),
score = 12 * (10 * 100) / 10,
timestamps = {
epoch203,
epoch204,
epoch205,
epoch206,
epoch207,
epoch208,
epoch209,
epoch210,
epoch211,
epoch212,
},
},
{
count = 2,
path = filepath(dir, "hoge1.txt"),
score = 2 * (2 * 100) / 10,
timestamps = { epoch11, epoch12 },
},
}, results)
end)
end)
end)
describe("when ignore_register is set", function()
with_files({ "hoge1.txt", "hoge2.txt" }, {
ignore_register = function(bufnr)
local _, bufname = pcall(vim.api.nvim_buf_get_name, bufnr)
local should_ignore = not not (bufname and bufname:find "hoge2%.txt$")
log.debug { bufnr = bufnr, bufname = bufname, should_ignore = should_ignore }
return should_ignore
end,
}, function(frecency, finder, dir)
local register = make_register(frecency, dir)
local epoch1 = make_epoch "2023-07-29T00:00:00+09:00"
register("hoge1.txt", epoch1)
local epoch2 = make_epoch "2023-07-29T01:00:00+09:00"
register("hoge2.txt", epoch2)
it("ignores the file the func returns true", function()
local results = finder:get_results(nil, make_epoch "2023-07-29T02:00:00+09:00")
assert.are.same({
{ count = 1, path = filepath(dir, "hoge1.txt"), score = 10, timestamps = { epoch1 } },
}, results)
end)
end)
end)
end)
describe("benchmark", function()
describe("after registered over >5000 files", function()
with_files({}, function(frecency, finder, dir)
with_fake_register(frecency, dir, function(register)
-- TODO: 6000 records is too many to use with native?
-- local file_count = 6000
local file_count = 600
if not os.getenv "CI" then
log.info "It works not on CI. Files is decreased into 10 count."
file_count = 10
end
local expected = {}
log.info(("making %d files and register them"):format(file_count))
for i = 1, file_count do
local file = ("hoge%08d.txt"):format(i)
table.insert(expected, { count = 1, path = filepath(dir, file), score = 10 })
-- HACK: disable log because it fails with too many logging
log.new({ level = "info" }, true)
register(file, make_epoch "2023-07-29T00:00:00+09:00")
log.new({}, true)
end
local timer = Timer.new "all results"
local results = vim.tbl_map(function(result)
result.timestamps = nil
return result
end, finder:get_results(nil, make_epoch "2023-07-29T00:01:00+09:00"))
table.sort(results, function(a, b)
return a.path < b.path
end)
timer:finish()
it("returns appropriate latency (<1.0 second)", function()
assert.are.is_true(timer.elapsed < 1.0)
end)
it("returns valid response", function()
assert.are.same(expected, results)
end)
end)
end)
end)
end)
describe("delete", function()
describe("when file exists", function()
with_files({ "hoge1.txt", "hoge2.txt" }, function(frecency, finder, dir)
local register = make_register(frecency, dir)
local epoch1 = make_epoch "2023-07-29T00:00:00+09:00"
local epoch2 = make_epoch "2023-07-29T00:01:00+09:00"
register("hoge1.txt", epoch1)
register("hoge2.txt", epoch2)
it("deletes the file successfully", function()
local path = filepath(dir, "hoge2.txt")
local result
---@diagnostic disable-next-line: duplicate-set-field, invisible
frecency.notify = function(self, fmt, ...)
---@diagnostic disable-next-line: invisible
vim.notify(self:message(fmt, ...))
result = true
end
frecency:delete(path)
assert.are.same(result, true)
end)
it("returns valid results", function()
local results = finder:get_results(nil, make_epoch "2023-07-29T02:00:00+09:00")
assert.are.same({
{ count = 1, path = filepath(dir, "hoge1.txt"), score = 10, timestamps = { epoch1 } },
}, results)
end)
end)
end)
end)
describe("query", function()
with_files({ "hoge1.txt", "hoge2.txt", "hoge3.txt", "hoge4.txt" }, function(frecency, _, dir)
local register = make_register(frecency, dir)
local epoch11 = make_epoch "2023-07-29T00:00:00+09:00"
local epoch2 = make_epoch "2023-07-29T00:01:00+09:00"
local epoch12 = make_epoch "2023-07-29T00:02:00+09:00"
local epoch31 = make_epoch "2023-07-29T00:03:00+09:00"
local epoch13 = make_epoch "2023-07-29T00:04:00+09:00"
local epoch32 = make_epoch "2023-07-29T00:05:00+09:00"
local epoch4 = make_epoch "2023-07-29T00:06:00+09:00"
register("hoge1.txt", epoch11)
register("hoge2.txt", epoch2)
register("hoge1.txt", epoch12, true)
register("hoge3.txt", epoch31)
register("hoge1.txt", epoch13, true)
register("hoge3.txt", epoch32, true)
register("hoge4.txt", epoch4)
for _, c in ipairs {
{
desc = "with no opts",
opts = nil,
results = {
filepath(dir, "hoge1.txt"),
filepath(dir, "hoge3.txt"),
filepath(dir, "hoge2.txt"),
filepath(dir, "hoge4.txt"),
},
},
{
desc = "with an empty opts",
opts = {},
results = {
filepath(dir, "hoge1.txt"),
filepath(dir, "hoge3.txt"),
filepath(dir, "hoge2.txt"),
filepath(dir, "hoge4.txt"),
},
},
{
desc = "with limit",
opts = { limit = 3 },
results = {
filepath(dir, "hoge1.txt"),
filepath(dir, "hoge3.txt"),
filepath(dir, "hoge2.txt"),
},
},
{
desc = "with limit, direction",
opts = { direction = "asc", limit = 3 },
results = {
filepath(dir, "hoge2.txt"),
filepath(dir, "hoge4.txt"),
filepath(dir, "hoge3.txt"),
},
},
{
desc = "with limit, direction, order",
opts = { direction = "asc", limit = 3, order = "path" },
results = {
filepath(dir, "hoge1.txt"),
filepath(dir, "hoge2.txt"),
filepath(dir, "hoge3.txt"),
},
},
{
desc = "with limit, direction, order, record",
opts = { direction = "asc", limit = 3, order = "path", record = true },
results = {
{ count = 3, path = filepath(dir, "hoge1.txt"), score = 90, timestamps = { epoch11, epoch12, epoch13 } },
{ count = 1, path = filepath(dir, "hoge2.txt"), score = 10, timestamps = { epoch2 } },
{ count = 2, path = filepath(dir, "hoge3.txt"), score = 40, timestamps = { epoch31, epoch32 } },
},
},
} do
describe(c.desc, function()
it("returns valid results", function()
assert.are.same(c.results, frecency:query(c.opts, make_epoch "2023-07-29T04:00:00+09:00"))
end)
end)
end
end)
end)
end)