fix unit test of readerlink and readerpaging

and have more confidence with the unit testing framework.

Now `make testfront` won't retry on failure and testing files are
ordered in each run so that it's possible to reproduce testing failure.

And this patch also fix flush settings not working before suspend issue:
at some point the `FlushSettings` event is sent to `UIManager` instead
of `ReaderUI`, but `UIManager` only delegated events to active widgets
and `ReaderUI` is actually not an active widgets thus will miss the event.

This patch also add a verbose debug mode with "-v" as a switch to turn
on this mode. With verbose mode on, event handling will be logged.
pull/2218/head
chrox 8 years ago
parent 2fa8ebb7c4
commit 9ab005a1d3

@ -17,9 +17,7 @@ echo "wrap_bin_scripts = false" >> $HOME/.luarocks/config.lua
travis_retry luarocks --local install luafilesystem travis_retry luarocks --local install luafilesystem
# for verbose_print module # for verbose_print module
travis_retry luarocks --local install ansicolors travis_retry luarocks --local install ansicolors
travis_retry luarocks --local install busted 2.0.rc11-0 travis_retry luarocks --local install busted 2.0.rc12-1
travis_retry luarocks --local remove lua_cliargs --force
travis_retry luarocks --local install lua_cliargs 2.5-5 --force
#- mv -f $HOME/.luarocks/bin/busted_bootstrap $HOME/.luarocks/bin/busted #- mv -f $HOME/.luarocks/bin/busted_bootstrap $HOME/.luarocks/bin/busted
travis_retry luarocks --local install luacov travis_retry luarocks --local install luacov
# luasec doesn't automatically detect 64-bit libs # luasec doesn't automatically detect 64-bit libs

@ -5,7 +5,7 @@ source "${CI_DIR}/common.sh"
travis_retry make fetchthirdparty travis_retry make fetchthirdparty
make all make all
retry_cmd 2 make testfront make testfront
set +o pipefail set +o pipefail
luajit $(which luacheck) --no-color -q frontend | tee ./luacheck.out luajit $(which luacheck) --no-color -q frontend | tee ./luacheck.out
test $(grep Total ./luacheck.out | awk '{print $2}') -le 19 test $(grep Total ./luacheck.out | awk '{print $2}') -le 19

@ -98,7 +98,10 @@ $(INSTALL_DIR)/koreader/.luacov:
ln -sf ../../.luacov $(INSTALL_DIR)/koreader ln -sf ../../.luacov $(INSTALL_DIR)/koreader
testfront: $(INSTALL_DIR)/koreader/.busted testfront: $(INSTALL_DIR)/koreader/.busted
# sdr files may have unexpected impact on unit testing
rm -rf spec/unit/data/*.sdr
cd $(INSTALL_DIR)/koreader && ./luajit $(shell which busted) \ cd $(INSTALL_DIR)/koreader && ./luajit $(shell which busted) \
--sort-files \
--no-auto-insulate \ --no-auto-insulate \
-o verbose_print --exclude-tags=notest -o verbose_print --exclude-tags=notest

@ -1 +1 @@
Subproject commit d33be25e6ad412bb98a6fa2ac3edf5f26d36c8ca Subproject commit a57567246963a561585b53bafed16584afa1703b

@ -52,6 +52,8 @@ it works using data gathered from a document interface
]]-- ]]--
local ReaderUI = InputContainer:new{ local ReaderUI = InputContainer:new{
name = "ReaderUI",
key_events = { key_events = {
Close = { { "Home" }, Close = { { "Home" },
doc = "close document", event = "Close" }, doc = "close document", event = "Close" },
@ -74,6 +76,7 @@ local ReaderUI = InputContainer:new{
function ReaderUI:registerModule(name, ui_module, always_active) function ReaderUI:registerModule(name, ui_module, always_active)
if name then self[name] = ui_module end if name then self[name] = ui_module end
ui_module.name = "reader" .. name
table.insert(always_active and self.active_widgets or self, ui_module) table.insert(always_active and self.active_widgets or self, ui_module)
end end

@ -3,6 +3,7 @@ local isAndroid, android = pcall(require, "android")
local Dbg = { local Dbg = {
is_on = nil, is_on = nil,
is_verbose = nil,
ev_log = nil, ev_log = nil,
} }
@ -59,6 +60,16 @@ function Dbg:turnOff()
end end
end end
function Dbg:setVerbose(verbose)
self.is_verbose = verbose
end
function Dbg:v(...)
if self.is_verbose then
LvDEBUG(math.huge, ...)
end
end
function Dbg:logEv(ev) function Dbg:logEv(ev)
local log = ev.type.."|"..ev.code.."|" local log = ev.type.."|"..ev.code.."|"
..ev.value.."|"..ev.time.sec.."|"..ev.time.usec.."\n" ..ev.value.."|"..ev.time.sec.."|"..ev.time.usec.."\n"

@ -152,6 +152,12 @@ end
-- modal widget should be always on the top -- modal widget should be always on the top
-- for refreshtype & refreshregion see description of setDirty() -- for refreshtype & refreshregion see description of setDirty()
function UIManager:show(widget, refreshtype, refreshregion, x, y) function UIManager:show(widget, refreshtype, refreshregion, x, y)
if not widget then
dbg("widget not exist to be closed")
return
end
dbg("show widget", widget.id or widget.name or "unknown")
self._running = true self._running = true
local window = {x = x or 0, y = y or 0, widget = widget} local window = {x = x or 0, y = y or 0, widget = widget}
-- put this window on top of the toppest non-modal window -- put this window on top of the toppest non-modal window
@ -182,7 +188,7 @@ function UIManager:close(widget, refreshtype, refreshregion)
dbg("widget not exist to be closed") dbg("widget not exist to be closed")
return return
end end
dbg("close widget", widget.id) dbg("close widget", widget.id or widget.name)
local dirty = false local dirty = false
-- first send close event to widget -- first send close event to widget
widget:handleEvent(Event:new("CloseWidget")) widget:handleEvent(Event:new("CloseWidget"))
@ -328,7 +334,7 @@ dbg:guard(UIManager, 'setDirty',
if self._window_stack[i].widget == widget then found = true end if self._window_stack[i].widget == widget then found = true end
end end
if not found then if not found then
dbg("INFO: invalid widget for setDirty()", debug.traceback()) dbg:v("INFO: invalid widget for setDirty()", debug.traceback())
end end
end) end)
@ -382,6 +388,7 @@ end
-- transmit an event to an active widget -- transmit an event to an active widget
function UIManager:sendEvent(event) function UIManager:sendEvent(event)
--dbg:v("send event", event)
if #self._window_stack == 0 then return end if #self._window_stack == 0 then return end
local top_widget = self._window_stack[#self._window_stack] local top_widget = self._window_stack[#self._window_stack]
@ -395,22 +402,25 @@ function UIManager:sendEvent(event)
end end
end end
-- if the event is not consumed, active widgets (from top to bottom) can -- if the event is not consumed, widgets (from top to bottom) can
-- access it. NOTE: _window_stack can shrink on close event -- access it. NOTE: _window_stack can shrink on close event
local checked_widgets = {top_widget} local checked_widgets = {top_widget}
for i = #self._window_stack, 1, -1 do for i = #self._window_stack, 1, -1 do
local widget = self._window_stack[i] local widget = self._window_stack[i]
if checked_widgets[widget] == nil then if checked_widgets[widget] == nil then
if widget.widget.is_always_active then -- active widgets has precedence to handle this event
checked_widgets[widget] = true -- Note: ReaderUI currently only has one active_widget: readerscreenshot
if widget.widget:handleEvent(event) then return end
end
if widget.widget.active_widgets then if widget.widget.active_widgets then
checked_widgets[widget] = true checked_widgets[widget] = true
for _, active_widget in ipairs(widget.widget.active_widgets) do for _, active_widget in ipairs(widget.widget.active_widgets) do
if active_widget:handleEvent(event) then return end if active_widget:handleEvent(event) then return end
end end
end end
-- ordinary widgets will handle this event
-- Note: is_always_active widgets currently are vitualkeyboard and
-- readerconfig
checked_widgets[widget] = true
if widget.widget:handleEvent(event) then return end
end end
end end
end end

@ -6,6 +6,7 @@ will call a method "onEventName" for an event with name
"EventName" "EventName"
--]] --]]
local EventListener = {} local EventListener = {}
local DEBUG = require("dbg")
function EventListener:new(new_o) function EventListener:new(new_o)
local o = new_o or {} local o = new_o or {}
@ -17,6 +18,9 @@ end
function EventListener:handleEvent(event) function EventListener:handleEvent(event)
if self[event.handler] then if self[event.handler] then
if self.id or self.name then
DEBUG:v(self.id or self.name, "handling event", event)
end
return self[event.handler](self, unpack(event.args)) return self[event.handler](self, unpack(event.args))
end end
end end

@ -48,6 +48,7 @@ local function showusage()
print("Read all the books on your E-Ink reader") print("Read all the books on your E-Ink reader")
print("") print("")
print("-d start in debug mode") print("-d start in debug mode")
print("-v debug in verbose mode")
print("-p enable Lua code profiling") print("-p enable Lua code profiling")
print("-h show this usage help") print("-h show this usage help")
print("") print("")
@ -82,6 +83,8 @@ while argidx <= #ARGV do
return showusage() return showusage()
elseif arg == "-d" then elseif arg == "-d" then
DEBUG:turnOn() DEBUG:turnOn()
elseif arg == "-v" then
DEBUG:setVerbose(true)
elseif arg == "-p" then elseif arg == "-p" then
Profiler = require("jit.p") Profiler = require("jit.p")
Profiler.start("la") Profiler.start("la")

@ -1,17 +1,26 @@
describe("Dbg module", function() describe("Dbg module", function()
local dbg local dbg, dbg_on
setup(function() setup(function()
package.path = "?.lua;common/?.lua;rocks/share/lua/5.1/?.lua;frontend/?.lua;" .. package.path package.path = "?.lua;common/?.lua;rocks/share/lua/5.1/?.lua;frontend/?.lua;" .. package.path
dbg = require("dbg") dbg = require("dbg")
dbg_on = dbg.is_on
end)
after_each(function()
if dbg_on then
dbg:turnOn()
else
dbg:turnOff()
end
end) end)
it("setup mt.__call and guard after tunrnOn is called", function() it("setup mt.__call and guard after tunrnOn is called", function()
dbg:turnOff()
local old_call = getmetatable(dbg).__call local old_call = getmetatable(dbg).__call
local old_guard = dbg.guard local old_guard = dbg.guard
dbg:turnOn() dbg:turnOn()
assert.is_not.same(old_call, getmetatable(dbg).__call) assert.is_not.same(old_call, getmetatable(dbg).__call)
assert.is_not.same(old_guard, dbg.guard) assert.is_not.same(old_guard, dbg.guard)
dbg:turnOff()
end) end)
it("should call pre_gard callback", function() it("should call pre_gard callback", function()
@ -27,7 +36,6 @@ describe("Dbg module", function()
dbg:guard(foo, 'bar', function() called = true end) dbg:guard(foo, 'bar', function() called = true end)
foo:bar() foo:bar()
assert.is.truthy(called) assert.is.truthy(called)
dbg:turnOff()
end) end)
it("should call post_gard callback", function() it("should call post_gard callback", function()
@ -43,7 +51,6 @@ describe("Dbg module", function()
dbg:guard(foo, 'bar', nil, function() called = true end) dbg:guard(foo, 'bar', nil, function() called = true end)
foo:bar() foo:bar()
assert.is.truthy(called) assert.is.truthy(called)
dbg:turnOff()
end) end)
it("should return all values returned by the guarded function", function() it("should return all values returned by the guarded function", function()
@ -64,6 +71,5 @@ describe("Dbg module", function()
assert.is.falsy(called) assert.is.falsy(called)
re = {foo:bar()} re = {foo:bar()}
assert.is.same(re, {1, 2, 3}) assert.is.same(re, {1, 2, 3})
dbg:turnOff()
end) end)
end) end)

@ -187,6 +187,7 @@ describe("device module", function()
Device.isKobo:revert() Device.isKobo:revert()
NickelConf.frontLightLevel.get:revert() NickelConf.frontLightLevel.get:revert()
NickelConf.frontLightState.get:revert() NickelConf.frontLightState.get:revert()
readerui.onFlushSettings:revert()
UIManager._startAutoSuspend = nil UIManager._startAutoSuspend = nil
UIManager._stopAutoSuspend = nil UIManager._stopAutoSuspend = nil
UIManager._resetAutoSuspendTimer = saved_noop UIManager._resetAutoSuspendTimer = saved_noop

@ -41,7 +41,10 @@ describe("ReaderLink module", function()
readerui.paging:onGotoPage(1) readerui.paging:onGotoPage(1)
readerui.link:onTap(nil, {pos = {x = 250, y = 534}}) readerui.link:onTap(nil, {pos = {x = 250, y = 534}})
UIManager:run() UIManager:run()
assert.is.same(21, readerui.paging.current_page) -- its really hard to get the exact page number in scroll mode
-- page positions may have unexpected impact on page number
assert.truthy(readerui.paging.current_page == 21
or readerui.paging.current_page == 20)
end) end)
it("should be able to go back after link jump in epub", function() it("should be able to go back after link jump in epub", function()
@ -78,7 +81,8 @@ describe("ReaderLink module", function()
readerui.paging:onGotoPage(1) readerui.paging:onGotoPage(1)
readerui.link:onTap(nil, {pos = {x = 250, y = 534}}) readerui.link:onTap(nil, {pos = {x = 250, y = 534}})
UIManager:run() UIManager:run()
assert.is.same(21, readerui.paging.current_page) assert.truthy(readerui.paging.current_page == 21
or readerui.paging.current_page == 20)
readerui.link:onGoBackLink() readerui.link:onGoBackLink()
assert.is.same(1, readerui.paging.current_page) assert.is.same(1, readerui.paging.current_page)
end) end)

@ -1,22 +1,27 @@
describe("Readerpaging module", function() describe("Readerpaging module", function()
local sample_pdf = "spec/front/unit/data/sample.pdf" local sample_pdf = "spec/front/unit/data/sample.pdf"
local readerui local readerui, UIManager, Event
local paging local paging
setup(function() require("commonrequire") end) setup(function()
require("commonrequire")
UIManager = require("ui/uimanager")
Event = require("ui/event")
end)
describe("Page mode", function() describe("Page mode", function()
local Event
setup(function() setup(function()
Event = require("ui/event")
readerui = require("apps/reader/readerui"):new{ readerui = require("apps/reader/readerui"):new{
document = require("document/documentregistry"):openDocument(sample_pdf), document = require("document/documentregistry"):openDocument(sample_pdf),
} }
paging = readerui.paging paging = readerui.paging
end) end)
it("should emit EndOfBook event at the end in page mode", function() it("should emit EndOfBook event at the end", function()
UIManager:quit()
UIManager:show(readerui)
UIManager:scheduleIn(1, function() UIManager:close(readerui) end)
UIManager:run()
readerui:handleEvent(Event:new("SetScrollMode", false)) readerui:handleEvent(Event:new("SetScrollMode", false))
readerui.zooming:setZoomMode("pageheight") readerui.zooming:setZoomMode("pageheight")
paging:onGotoPage(readerui.document:getPageCount()) paging:onGotoPage(readerui.document:getPageCount())
@ -27,19 +32,7 @@ describe("Readerpaging module", function()
paging:onPagingRel(1) paging:onPagingRel(1)
assert.is.truthy(called) assert.is.truthy(called)
readerui.onEndOfBook = nil readerui.onEndOfBook = nil
end) UIManager:quit()
it("should emit EndOfBook event at the end in scroll mode", function()
readerui:handleEvent(Event:new("SetScrollMode", true))
paging:onGotoPage(readerui.document:getPageCount())
readerui.zooming:setZoomMode("pageheight")
local called = false
readerui.onEndOfBook = function()
called = true
end
paging:onPagingRel(1)
assert.is.truthy(called)
readerui.onEndOfBook = nil
end) end)
end) end)
@ -57,16 +50,23 @@ describe("Readerpaging module", function()
end) end)
it("should emit EndOfBook event at the end", function() it("should emit EndOfBook event at the end", function()
UIManager:quit()
UIManager:show(readerui)
UIManager:scheduleIn(1, function() UIManager:close(readerui) end)
UIManager:run()
paging.page_positions = {}
readerui:handleEvent(Event:new("SetScrollMode", true))
paging:onGotoPage(readerui.document:getPageCount()) paging:onGotoPage(readerui.document:getPageCount())
readerui.zooming:setZoomMode("pageheight") readerui.zooming:setZoomMode("pageheight")
readerui.view:onSetScrollMode(true)
local called = false local called = false
readerui.onEndOfBook = function() readerui.onEndOfBook = function()
called = true called = true
end end
paging:onPagingRel(1) paging:onPagingRel(1)
paging:onPagingRel(1)
assert.is.truthy(called) assert.is.truthy(called)
readerui.onEndOfBook = nil readerui.onEndOfBook = nil
UIManager:quit()
end) end)
end) end)
end) end)

@ -51,6 +51,7 @@ describe("Readerview module", function()
document = DocumentRegistry:openDocument(sample_pdf), document = DocumentRegistry:openDocument(sample_pdf),
} }
readerui:handleEvent(Event:new("SetScrollMode", false)) readerui:handleEvent(Event:new("SetScrollMode", false))
readerui.zooming:setZoomMode("page")
local view = readerui.view local view = readerui.view
local ctx = view:getViewContext() local ctx = view:getViewContext()
local zoom = ctx[1].zoom local zoom = ctx[1].zoom
@ -98,6 +99,7 @@ describe("Readerview module", function()
document = DocumentRegistry:openDocument(sample_pdf), document = DocumentRegistry:openDocument(sample_pdf),
} }
readerui:handleEvent(Event:new("SetScrollMode", true)) readerui:handleEvent(Event:new("SetScrollMode", true))
readerui.zooming:setZoomMode("page")
local view = readerui.view local view = readerui.view
local ctx = view:getViewContext() local ctx = view:getViewContext()
local zoom = ctx[1].zoom local zoom = ctx[1].zoom

Loading…
Cancel
Save