You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koreader/spec/unit/device_spec.lua

504 lines
18 KiB
Lua

describe("device module", function()
-- luacheck: push ignore
local mock_fb, mock_input
local iopen = io.open
local ipopen = io.popen
local osgetenv = os.getenv
local ffi, C
setup(function()
local fb = require("ffi/framebuffer")
mock_fb = {
new = function()
return {
device = package.loaded.device,
bb = require("ffi/blitbuffer").new(600, 800, 1),
getRawSize = function() return {w = 600, h = 800} end,
getWidth = function() return 600 end,
getHeight = function() return 800 end,
getDPI = function() return 72 end,
setViewport = function() end,
getRotationMode = function() return 0 end,
getScreenMode = function() return "portrait" end,
setRotationMode = function() end,
scaleByDPI = fb.scaleByDPI,
scaleBySize = fb.scaleBySize,
setWindowTitle = function() end,
refreshFull = function() end,
getHWNightmode = function() return false end,
setupDithering = function() end,
}
end
}
require("commonrequire")
package.unloadAll()
ffi = require("ffi")
C = ffi.C
require("ffi/linux_input_h")
require("document/canvascontext"):init(require("device"))
end)
before_each(function()
package.loaded["ffi/framebuffer_mxcfb"] = mock_fb
mock_input = require("device/input")
stub(mock_input, "open")
stub(os, "getenv")
stub(os, "execute")
end)
after_each(function()
-- Don't let UIManager hang on to a stale Device reference, and vice-versa...
package.unload("device")
package.unload("device/generic/device")
package.unload("device/generic/powerd")
package.unload("ui/uimanager")
package.unload("apps/reader/readerui")
mock_input.open:revert()
os.getenv:revert()
os.execute:revert()
os.getenv = osgetenv
io.open = iopen
io.popen = ipopen
end)
describe("kobo", function()
local time
local NickelConf
setup(function()
time = require("ui/time")
NickelConf = require("device/kobo/nickel_conf")
end)
before_each(function()
stub(NickelConf.frontLightLevel, "get")
NickelConf.frontLightLevel.get.returns(0)
stub(NickelConf.frontLightState, "get")
end)
after_each(function()
NickelConf.frontLightLevel.get:revert()
NickelConf.frontLightState.get:revert()
end)
it("should initialize properly on Kobo dahlia", function()
os.getenv.returns("dahlia")
local kobo_dev = require("device/kobo/device")
kobo_dev:init()
assert.is.same("Kobo_dahlia", kobo_dev.model)
end)
it("should setup eventAdjustHooks properly for input on trilogy C", function()
os.getenv.invokes(function(key)
if key == "PRODUCT" then
return "trilogy"
elseif key == "MODEL_NUMBER" then
return "320"
else
return osgetenv(key)
end
end)
package.loaded["device/kobo/device"] = nil
local kobo_dev = require("device/kobo/device")
kobo_dev:init()
local Screen = kobo_dev.screen
assert.is.same("Kobo_trilogy_C", kobo_dev.model)
local x, y = Screen:getWidth()-5, 10
-- mirror x, then switch_xy
local ev_x = {
type = C.EV_ABS,
code = C.ABS_X,
value = y,
time = time:realtime(),
}
local ev_y = {
type = C.EV_ABS,
code = C.ABS_Y,
value = Screen:getWidth() - 1 - x,
time = time:realtime(),
}
kobo_dev.input:eventAdjustHook(ev_x)
kobo_dev.input:eventAdjustHook(ev_y)
assert.is.same(x, ev_y.value)
assert.is.same(C.ABS_X, ev_y.code)
assert.is.same(y, ev_x.value)
assert.is.same(C.ABS_Y, ev_x.code)
-- reset eventAdjustHook
kobo_dev.input.eventAdjustHook = function() end
end)
it("should setup eventAdjustHooks properly for trilogy with non-epoch ev time", function()
-- This has no more value since #6798 as ev time can now stay
-- non-epoch. Adjustments are made on first event handled, and
-- have only effects when handling long-press (so, the long-press
-- for dict lookup tests with test this).
-- We just check here it still works with non-epoch ev time, as previous test
os.getenv.invokes(function(key)
if key == "PRODUCT" then
return "trilogy"
elseif key == "MODEL_NUMBER" then
return "320"
else
return osgetenv(key)
end
end)
package.loaded["device/kobo/device"] = nil
local kobo_dev = require("device/kobo/device")
kobo_dev:init()
local Screen = kobo_dev.screen
assert.is.same("Kobo_trilogy_C", kobo_dev.model)
local x, y = Screen:getWidth()-5, 10
local ev_x = {
type = C.EV_ABS,
code = C.ABS_X,
value = y,
time = {sec = 1000}
}
local ev_y = {
type = C.EV_ABS,
code = C.ABS_Y,
value = Screen:getWidth() - 1 - x,
time = {sec = 1000}
}
kobo_dev.input:eventAdjustHook(ev_x)
kobo_dev.input:eventAdjustHook(ev_y)
assert.is.same(x, ev_y.value)
assert.is.same(C.ABS_X, ev_y.code)
assert.is.same(y, ev_x.value)
assert.is.same(C.ABS_Y, ev_x.code)
-- reset eventAdjustHook
kobo_dev.input.eventAdjustHook = function() end
end)
end)
describe("kindle", function()
local function make_io_open_kindle_model_override(model_no)
return function(filename, mode)
if filename == "/proc/usid" then
return {
read = function() return model_no end,
close = function() end
}
else
return iopen(filename, mode)
end
end
end
insulate("without framework", function()
local mock_lipc = {
init = function()
return {
set_int_property = mock(function() end),
get_int_property = function() return 0 end,
get_string_property = function() return "string prop" end,
set_string_property = function() end,
register_int_property = function() return {} end,
close = function () end,
}
end
}
package.loaded["liblipclua"] = mock_lipc
before_each(function()
os.getenv.invokes(function(e)
if e == "STOP_FRAMEWORK" then
return "yes"
else
return osgetenv(e)
end
end)
end)
it("sets framework_lipc_handle", function ()
io.open = make_io_open_kindle_model_override("B013XX")
local kindle_dev = require("device/kindle/device")
assert.is.truthy(kindle_dev.framework_lipc_handle)
end)
it("reactivates voyage whispertouch keys", function ()
io.open = make_io_open_kindle_model_override("B013XX")
local kindle_dev = require("device/kindle/device")
local fw_lipc_handle = kindle_dev.framework_lipc_handle
kindle_dev:init()
for _, fsr_prop in pairs{
"fsrkeypadEnable",
"fsrkeypadPrevEnable",
"fsrkeypadNextEnable"
} do
assert.stub(fw_lipc_handle.set_int_property).was.called_with(
fw_lipc_handle, "com.lab126.deviced", fsr_prop, 1
)
end
end)
end)
insulate("with framework", function()
it("does not set framework_lipc_handle", function ()
io.open = make_io_open_kindle_model_override("B013XX")
local kindle_dev = require("device/kindle/device")
assert.is.falsy(kindle_dev.framework_lipc_handle)
end)
end)
it("should initialize voyage without error", function()
io.open = make_io_open_kindle_model_override("B013XX")
local kindle_dev = require("device/kindle/device")
assert.is.same(kindle_dev.model, "KindleVoyage")
kindle_dev:init()
assert.is.same(kindle_dev.input.event_map[104], "LPgBack")
assert.is.same(kindle_dev.input.event_map[109], "LPgFwd")
assert.is.same(kindle_dev.powerd.fl_min, 0)
-- NOTE: fl_max + 1 since #5989
assert.is.same(kindle_dev.powerd.fl_max, 25)
end)
it("should toggle frontlight", function()
io.open = function(filename, mode)
if filename == "/proc/usid" then
return {
read = function() return "B013XX" end,
close = function() end
}
elseif filename == "/sys/class/backlight/max77696-bl/brightness" then
return {
read = function() return 12 end,
close = function() end
}
else
return iopen(filename, mode)
end
end
local kindle_dev = require("device/kindle/device")
kindle_dev:init()
assert.is.same(kindle_dev.powerd.fl_intensity, 12)
kindle_dev.powerd:setIntensity(5)
assert.is.same(kindle_dev.powerd.fl_intensity, 5)
kindle_dev.powerd:toggleFrontlight()
-- Here be shenanigans: we don't override powerd's fl_intensity when we turn the light off,
-- so that we can properly turn it back on at the previous intensity ;)
assert.is.same(kindle_dev.powerd.fl_intensity, 5)
-- But if we were to cat /sys/class/backlight/max77696-bl/brightness, it should now be 0.
kindle_dev.powerd:toggleFrontlight()
assert.is.same(kindle_dev.powerd.fl_intensity, 5)
-- And /sys/class/backlight/max77696-bl/brightness is now !0
-- (exact value is HW-dependent, each model has a different curve, we let lipc do the work for us).
end)
it("oasis should interpret orientation event", function()
package.unload("device/kindle/device")
io.open = make_io_open_kindle_model_override("G0B0GCXXX")
mock_ffi_input = require("ffi/input")
stub(mock_ffi_input, "waitForEvent")
mock_ffi_input.waitForEvent.returns(true, {
{
type = C.EV_ABS,
time = {
usec = 450565,
sec = 1471081881
},
code = 24, -- C.ABS_PRESSURE
value = 16
}
})
local UIManager = require("ui/uimanager")
stub(UIManager, "onRotation")
local kindle_dev = require("device/kindle/device")
assert.is.same("KindleOasis", kindle_dev.model)
kindle_dev:init()
kindle_dev:lockGSensor(true)
kindle_dev.input:waitEvent()
assert.stub(UIManager.onRotation).was_called()
mock_ffi_input.waitForEvent:revert()
UIManager.onRotation:revert()
end)
end)
describe("Flush book Settings for", function()
it("Kobo", function()
os.getenv.invokes(function(key)
if key == "PRODUCT" then
return "trilogy"
elseif key == "MODEL_NUMBER" then
return "320"
else
return osgetenv(key)
end
end)
-- Bypass frontend/device probeDevice, while making sure that it points to the right implementation
local Device = require("device/kobo/device")
-- Apparently common isn't setup properly in the testsuite, so we can't have nice things
stub(Device, "initNetworkManager")
stub(Device, "suspend")
Device:init()
-- Don't poke the RTC
Device.wakeup_mgr = require("device/wakeupmgr"):new{rtc = require("device/kindle/mockrtc")}
-- Don't poke the fl
Device.powerd.fl = nil
package.loaded.device = Device
local UIManager = require("ui/uimanager")
-- Generic's onPowerEvent may request a repaint, but we can't do that
stub(UIManager, "forceRePaint")
UIManager:init()
local sample_pdf = "spec/front/unit/data/tall.pdf"
local ReaderUI = require("apps/reader/readerui")
ReaderUI:doShowReader(sample_pdf)
local readerui = ReaderUI.instance
stub(readerui, "onFlushSettings")
UIManager.event_handlers.PowerPress()
UIManager.event_handlers.PowerRelease()
assert.stub(readerui.onFlushSettings).was_called()
UIManager.forceRePaint:revert()
Device.initNetworkManager:revert()
Device.suspend:revert()
readerui.onFlushSettings:revert()
Device.screen_saver_mode = false
readerui:onClose()
end)
it("Cervantes", function()
io.popen = function(filename, mode)
if filename:find("/usr/bin/ntxinfo") then
return {
read = function()
return 68 -- Cervantes4
end,
close = function() end
}
else
return ipopen(filename, mode)
end
end
local Device = require("device/cervantes/device")
stub(Device, "initNetworkManager")
stub(Device, "suspend")
Device:init()
Device.powerd.fl = nil
package.loaded.device = Device
local UIManager = require("ui/uimanager")
stub(UIManager, "forceRePaint")
UIManager:init()
local sample_pdf = "spec/front/unit/data/tall.pdf"
local ReaderUI = require("apps/reader/readerui")
ReaderUI:doShowReader(sample_pdf)
local readerui = ReaderUI.instance
stub(readerui, "onFlushSettings")
UIManager.event_handlers.PowerPress()
UIManager.event_handlers.PowerRelease()
assert.stub(readerui.onFlushSettings).was_called()
UIManager.forceRePaint:revert()
Device.initNetworkManager:revert()
Device.suspend:revert()
readerui.onFlushSettings:revert()
Device.screen_saver_mode = false
readerui:onClose()
end)
it("Remarkable", function()
io.open = function(filename, mode)
if filename == "/usr/bin/xochitl" then
return {
read = function()
return true
end,
close = function() end
}
elseif filename == "/sys/devices/soc0/machine" then
return {
read = function()
return "reMarkable", "generic"
end,
close = function() end
}
else
return iopen(filename, mode)
end
end
local Device = require("device/remarkable/device")
stub(Device, "initNetworkManager")
stub(Device, "suspend")
Device:init()
Device.powerd.fl = nil
package.loaded.device = Device
local UIManager = require("ui/uimanager")
stub(UIManager, "forceRePaint")
UIManager:init()
local sample_pdf = "spec/front/unit/data/tall.pdf"
local ReaderUI = require("apps/reader/readerui")
ReaderUI:doShowReader(sample_pdf)
local readerui = ReaderUI.instance
stub(readerui, "onFlushSettings")
UIManager.event_handlers.PowerPress()
UIManager.event_handlers.PowerRelease()
assert.stub(readerui.onFlushSettings).was_called()
UIManager.forceRePaint:revert()
Device.initNetworkManager:revert()
Device.suspend:revert()
readerui.onFlushSettings:revert()
Device.screen_saver_mode = false
readerui:onClose()
end)
it("SDL", function()
local Device = require("device/sdl/device")
stub(Device, "initNetworkManager")
stub(Device, "suspend")
Device:init()
package.loaded.device = Device
local UIManager = require("ui/uimanager")
UIManager:init()
local sample_pdf = "spec/front/unit/data/tall.pdf"
local ReaderUI = require("apps/reader/readerui")
ReaderUI:doShowReader(sample_pdf)
local readerui = ReaderUI.instance
stub(readerui, "onFlushSettings")
-- UIManager.event_handlers.PowerPress() -- We only fake a Release event on the Emu
UIManager.event_handlers.PowerRelease()
assert.stub(readerui.onFlushSettings).was_called()
Device.initNetworkManager:revert()
Device.suspend:revert()
readerui.onFlushSettings:revert()
Device.screen_saver_mode = false
readerui:onClose()
end)
end)
-- luacheck: pop
end)