mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
remove autofrontlight + backgroundrunner (#12809)
* remove autofrontlight * remove background-runner thirparty plugins that rely on the backgroundrunner no longer work.
This commit is contained in:
@@ -28,9 +28,6 @@ files["spec/unit/*"].std = "+busted"
|
|||||||
files["spec/unit/*"].globals = {
|
files["spec/unit/*"].globals = {
|
||||||
"match", -- can be removed once luacheck 0.24.0 or higher is used
|
"match", -- can be removed once luacheck 0.24.0 or higher is used
|
||||||
"package",
|
"package",
|
||||||
"requireBackgroundRunner",
|
|
||||||
"stopBackgroundRunner",
|
|
||||||
"notifyBackgroundJobsUpdated",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- TODO: clean up and enforce max line width (631)
|
-- TODO: clean up and enforce max line width (631)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ local DEFAULT_PLUGIN_PATH = "plugins"
|
|||||||
|
|
||||||
-- plugin names that were removed and are no longer available.
|
-- plugin names that were removed and are no longer available.
|
||||||
local OBSOLETE_PLUGINS = {
|
local OBSOLETE_PLUGINS = {
|
||||||
|
autofrontlight = true,
|
||||||
|
backgroundrunner = true,
|
||||||
calibrecompanion = true,
|
calibrecompanion = true,
|
||||||
evernote = true,
|
evernote = true,
|
||||||
goodreads = true,
|
goodreads = true,
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
-- PluginShare is a table for plugins to exchange data between each other.
|
-- PluginShare is a table for plugins to exchange data between each other.
|
||||||
-- It is a singleton, which will persist across views (and, as such, across plugins lifecycle).
|
-- It is a singleton, which will persist across views (and, as such, across plugins lifecycle).
|
||||||
-- Plugins should maintain their own protocols.
|
-- Plugins should maintain their own protocols.
|
||||||
return {
|
return {}
|
||||||
backgroundJobs = {},
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
local _ = require("gettext")
|
|
||||||
return {
|
|
||||||
name = "autofrontlight",
|
|
||||||
fullname = _("Auto frontlight"),
|
|
||||||
description = _([[Automatically turns the frontlight on and off once brightness in the environment reaches a certain level.]]),
|
|
||||||
deprecated = { "remove" },
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
local Device = require("device")
|
|
||||||
|
|
||||||
if not (Device:isKindle() and Device:hasLightSensor()) then
|
|
||||||
return { disabled = true, }
|
|
||||||
end
|
|
||||||
|
|
||||||
local ConfirmBox = require("ui/widget/confirmbox")
|
|
||||||
local DataStorage = require("datastorage")
|
|
||||||
local LuaSettings = require("luasettings")
|
|
||||||
local PluginShare = require("pluginshare")
|
|
||||||
local UIManager = require("ui/uimanager")
|
|
||||||
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
|
||||||
local logger = require("logger")
|
|
||||||
local _ = require("gettext")
|
|
||||||
local T = require("ffi/util").template
|
|
||||||
|
|
||||||
local AutoFrontlight = {
|
|
||||||
settings = LuaSettings:open(DataStorage:getSettingsDir() .. "/autofrontlight.lua"),
|
|
||||||
settings_id = 0,
|
|
||||||
enabled = false,
|
|
||||||
last_brightness = -1,
|
|
||||||
}
|
|
||||||
|
|
||||||
function AutoFrontlight:_schedule(settings_id)
|
|
||||||
local enabled = function()
|
|
||||||
if not self.enabled then
|
|
||||||
logger.dbg("AutoFrontlight:_schedule() is disabled")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
if settings_id ~= self.settings_id then
|
|
||||||
logger.dbg("AutoFrontlight:_schedule(): registered settings_id ",
|
|
||||||
settings_id,
|
|
||||||
" does not equal to current one ",
|
|
||||||
self.settings_id)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(PluginShare.backgroundJobs, {
|
|
||||||
when = 2,
|
|
||||||
repeated = enabled,
|
|
||||||
executable = function()
|
|
||||||
if enabled() then
|
|
||||||
self:_action()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
local Event = require("ui/event")
|
|
||||||
UIManager:broadcastEvent(Event:new("BackgroundJobsUpdated"))
|
|
||||||
end
|
|
||||||
|
|
||||||
function AutoFrontlight:_action()
|
|
||||||
logger.dbg("AutoFrontlight:_action() @ ", os.time())
|
|
||||||
local current_level = Device:ambientBrightnessLevel()
|
|
||||||
logger.dbg("AutoFrontlight:_action(): Retrieved ambient brightness level: ", current_level)
|
|
||||||
if self.last_brightness == current_level then
|
|
||||||
logger.dbg("AutoFrontlight:_action(): recorded brightness is same as current level ",
|
|
||||||
self.last_brightness)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if current_level <= 1 then
|
|
||||||
logger.dbg("AutoFrontlight: going to turn on frontlight")
|
|
||||||
Device:getPowerDevice():turnOnFrontlight()
|
|
||||||
elseif current_level >= 3 then
|
|
||||||
logger.dbg("AutoFrontlight: going to turn off frontlight")
|
|
||||||
Device:getPowerDevice():turnOffFrontlight()
|
|
||||||
end
|
|
||||||
self.last_brightness = current_level
|
|
||||||
end
|
|
||||||
|
|
||||||
function AutoFrontlight:init()
|
|
||||||
self.enabled = self.settings:nilOrTrue("enable")
|
|
||||||
self.settings_id = self.settings_id + 1
|
|
||||||
logger.dbg("AutoFrontlight:init() self.enabled: ", self.enabled, " with id ", self.settings_id)
|
|
||||||
self:_schedule(self.settings_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
function AutoFrontlight:flipSetting()
|
|
||||||
self.settings:flipNilOrTrue("enable")
|
|
||||||
self:init()
|
|
||||||
end
|
|
||||||
|
|
||||||
function AutoFrontlight:onFlushSettings()
|
|
||||||
self.settings:flush()
|
|
||||||
end
|
|
||||||
|
|
||||||
AutoFrontlight:init()
|
|
||||||
|
|
||||||
local AutoFrontlightWidget = WidgetContainer:extend{
|
|
||||||
name = "autofrontlight",
|
|
||||||
}
|
|
||||||
|
|
||||||
function AutoFrontlightWidget:init()
|
|
||||||
-- self.ui and self.ui.menu are nil in unittests.
|
|
||||||
if self.ui ~= nil and self.ui.menu ~= nil then
|
|
||||||
self.ui.menu:registerToMainMenu(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function AutoFrontlightWidget:flipSetting()
|
|
||||||
AutoFrontlight:flipSetting()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- For test only.
|
|
||||||
function AutoFrontlightWidget:deprecateLastTask()
|
|
||||||
logger.dbg("AutoFrontlightWidget:deprecateLastTask() @ ", AutoFrontlight.settings_id)
|
|
||||||
AutoFrontlight.settings_id = AutoFrontlight.settings_id + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
function AutoFrontlightWidget:addToMainMenu(menu_items)
|
|
||||||
menu_items.auto_frontlight = {
|
|
||||||
text = _("Auto frontlight"),
|
|
||||||
callback = function(touchmenu_instance)
|
|
||||||
UIManager:show(ConfirmBox:new{
|
|
||||||
text = T(_("Auto frontlight detects the brightness of the environment and automatically turn on and off the frontlight.\nFrontlight will be turned off to save battery in bright environment, and turned on in dark environment.\nDo you want to %1 it?"),
|
|
||||||
AutoFrontlight.enabled and _("disable") or _("enable")),
|
|
||||||
ok_text = AutoFrontlight.enabled and _("Disable") or _("Enable"),
|
|
||||||
ok_callback = function()
|
|
||||||
self:flipSetting()
|
|
||||||
touchmenu_instance:updateItems()
|
|
||||||
end
|
|
||||||
})
|
|
||||||
end,
|
|
||||||
checked_func = function() return AutoFrontlight.enabled end,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function AutoFrontlightWidget:onFlushSettings()
|
|
||||||
AutoFrontlight:onFlushSettings()
|
|
||||||
end
|
|
||||||
|
|
||||||
return AutoFrontlightWidget
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
local _ = require("gettext")
|
|
||||||
return {
|
|
||||||
name = "backgroundrunner",
|
|
||||||
fullname = _("Background runner"),
|
|
||||||
description = _([[Service to other plugins: allows tasks to run regularly in the background.]]),
|
|
||||||
}
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
local logger = require("logger")
|
|
||||||
local UIManager = require("ui/uimanager")
|
|
||||||
local time = require("ui/time")
|
|
||||||
|
|
||||||
local CommandRunner = {
|
|
||||||
pio = nil,
|
|
||||||
job = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
function CommandRunner:createEnvironmentFromTable(t)
|
|
||||||
if t == nil then return "" end
|
|
||||||
|
|
||||||
local r = ""
|
|
||||||
for k, v in pairs(t) do
|
|
||||||
r = r .. k .. "=" .. v .. " "
|
|
||||||
end
|
|
||||||
|
|
||||||
if string.len(r) > 0 then r = "export " .. r .. ";" end
|
|
||||||
return r
|
|
||||||
end
|
|
||||||
|
|
||||||
function CommandRunner:createEnvironment()
|
|
||||||
if type(self.job.environment) == "table" then
|
|
||||||
return self:createEnvironmentFromTable(self.job.environment)
|
|
||||||
end
|
|
||||||
if type(self.job.environment) == "function" then
|
|
||||||
local status, result = pcall(self.job.environment)
|
|
||||||
if status then
|
|
||||||
return self:createEnvironmentFromTable(result)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return ""
|
|
||||||
end
|
|
||||||
|
|
||||||
function CommandRunner:start(job)
|
|
||||||
assert(self.pio == nil)
|
|
||||||
assert(self.job == nil)
|
|
||||||
self.job = job
|
|
||||||
self.job.start_time = UIManager:getTime()
|
|
||||||
assert(type(self.job.executable) == "string")
|
|
||||||
local command = self:createEnvironment() .. " " ..
|
|
||||||
"sh plugins/backgroundrunner.koplugin/luawrapper.sh " ..
|
|
||||||
"\"" .. self.job.executable .. "\""
|
|
||||||
logger.dbg("CommandRunner: Will execute command " .. command)
|
|
||||||
UIManager:preventStandby()
|
|
||||||
self.pio = io.popen(command)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Polls the status of self.pio.
|
|
||||||
-- @return a table contains the result from luawrapper.sh. Returns nil if the
|
|
||||||
-- command has not been finished.
|
|
||||||
function CommandRunner:poll()
|
|
||||||
assert(self.pio ~= nil)
|
|
||||||
assert(self.job ~= nil)
|
|
||||||
local line = self.pio:read()
|
|
||||||
if line == "" then
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
if line == nil then
|
|
||||||
-- The binary crashes without output. This should not happen.
|
|
||||||
self.job.result = 223
|
|
||||||
else
|
|
||||||
line = line .. self.pio:read("*a")
|
|
||||||
logger.dbg("CommandRunner: Receive output " .. line)
|
|
||||||
local status, result = pcall(loadstring(line))
|
|
||||||
if status and result ~= nil then
|
|
||||||
for k, v in pairs(result) do
|
|
||||||
self.job[k] = v
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- The output from binary is invalid.
|
|
||||||
self.job.result = 222
|
|
||||||
end
|
|
||||||
end
|
|
||||||
UIManager:allowStandby()
|
|
||||||
self.pio:close()
|
|
||||||
self.pio = nil
|
|
||||||
self.job.end_time = time.now()
|
|
||||||
local job = self.job
|
|
||||||
self.job = nil
|
|
||||||
return job
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Whether this is a running job.
|
|
||||||
-- @treturn boolean
|
|
||||||
function CommandRunner:pending()
|
|
||||||
return self.pio ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
return CommandRunner
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Converts the return of "sh wrapper.sh $@" into Lua format.
|
|
||||||
|
|
||||||
CURRENT_DIR=$(dirname "$0")
|
|
||||||
sh "${CURRENT_DIR}/wrapper.sh" "$@" >/dev/null 2>&1 &
|
|
||||||
JOB_ID=$!
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
if ps -p ${JOB_ID} >/dev/null 2>&1; then
|
|
||||||
# Unblock f:read().
|
|
||||||
echo
|
|
||||||
else
|
|
||||||
wait ${JOB_ID}
|
|
||||||
EXIT_CODE=$?
|
|
||||||
if [ "${EXIT_CODE}" -eq "255" ]; then
|
|
||||||
TIMEOUT="true"
|
|
||||||
else
|
|
||||||
TIMEOUT="false"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${EXIT_CODE}" -eq "127" ]; then
|
|
||||||
BADCOMMAND="true"
|
|
||||||
else
|
|
||||||
BADCOMMAND="false"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "return { \
|
|
||||||
result = ${EXIT_CODE}, \
|
|
||||||
timeout = ${TIMEOUT}, \
|
|
||||||
bad_command = ${BADCOMMAND}, \
|
|
||||||
}"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
@@ -1,279 +0,0 @@
|
|||||||
local Device = require("device")
|
|
||||||
|
|
||||||
-- disable on android, since it breaks expect behaviour of an activity.
|
|
||||||
-- it is also unused by other plugins.
|
|
||||||
-- See https://github.com/koreader/koreader/issues/6297
|
|
||||||
if Device:isAndroid() then
|
|
||||||
return { disabled = true, }
|
|
||||||
end
|
|
||||||
|
|
||||||
local CommandRunner = require("commandrunner")
|
|
||||||
local PluginShare = require("pluginshare")
|
|
||||||
local UIManager = require("ui/uimanager")
|
|
||||||
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
|
||||||
local logger = require("logger")
|
|
||||||
local time = require("ui/time")
|
|
||||||
local _ = require("gettext")
|
|
||||||
|
|
||||||
-- BackgroundRunner is an experimental feature to execute non-critical jobs in
|
|
||||||
-- the background.
|
|
||||||
-- A job is defined as a table in PluginShare.backgroundJobs table.
|
|
||||||
-- It contains at least following items:
|
|
||||||
-- when: number, string or function
|
|
||||||
-- number: the delay in seconds
|
|
||||||
-- string: "best-effort" - the job will be started when there is no other jobs
|
|
||||||
-- to be executed.
|
|
||||||
-- "idle" - the job will be started when the device is idle.
|
|
||||||
-- function: if the return value of the function is true, the job will be
|
|
||||||
-- executed immediately.
|
|
||||||
--
|
|
||||||
-- repeated: boolean or function or nil or number
|
|
||||||
-- boolean: true to repeat the job once it finished.
|
|
||||||
-- function: if the return value of the function is true, repeat the job
|
|
||||||
-- once it finishes. If the function throws an error, it equals to
|
|
||||||
-- return false.
|
|
||||||
-- nil: same as false.
|
|
||||||
-- number: times to repeat.
|
|
||||||
--
|
|
||||||
-- executable: string or function
|
|
||||||
-- string: the command line to be executed. The command or binary will be
|
|
||||||
-- executed in the lowest priority. Command or binary will be killed
|
|
||||||
-- if it executes for over 1 hour.
|
|
||||||
-- function: the action to be executed. The execution cannot be killed, but it
|
|
||||||
-- will be considered as timeout if it executes for more than 1
|
|
||||||
-- second.
|
|
||||||
-- If the executable times out, the job will be blocked, i.e. the repeated
|
|
||||||
-- field will be ignored.
|
|
||||||
--
|
|
||||||
-- environment: table or function or nil
|
|
||||||
-- table: the key-value pairs of all environments set for string executable.
|
|
||||||
-- function: the function to return a table of environments.
|
|
||||||
-- nil: ignore.
|
|
||||||
--
|
|
||||||
-- callback: function or nil
|
|
||||||
-- function: the action to be executed when executable has been finished.
|
|
||||||
-- Errors thrown from this function will be ignored.
|
|
||||||
-- nil: ignore.
|
|
||||||
--
|
|
||||||
-- If a job does not contain enough information, it will be ignored.
|
|
||||||
--
|
|
||||||
-- Once the job is finished, several items will be added to the table:
|
|
||||||
-- result: number, the return value of the command. In general, 0 means
|
|
||||||
-- succeeded.
|
|
||||||
-- For function executable, 1 if the function throws an error.
|
|
||||||
-- For string executable, several predefined values indicate the
|
|
||||||
-- internal errors. E.g. 223: the binary crashes. 222: the output is
|
|
||||||
-- invalid. 127: the command is invalid. 255: the command timed out.
|
|
||||||
-- Typically, consumers can use following states instead of hardcodeing
|
|
||||||
-- the error codes.
|
|
||||||
-- exception: error, the error returned from function executable. Not available
|
|
||||||
-- for string executable.
|
|
||||||
-- timeout: boolean, whether the command times out.
|
|
||||||
-- bad_command: boolean, whether the command is not found. Not available for
|
|
||||||
-- function executable.
|
|
||||||
-- blocked: boolean, whether the job is blocked.
|
|
||||||
-- start_time: number, the time (fts) when the job was started.
|
|
||||||
-- end_time: number, the time (fts) when the job was stopped.
|
|
||||||
-- insert_time: number, the time (fts) when the job was inserted into queue.
|
|
||||||
-- (All of them in the monotonic time scale, like the main event loop & task queue).
|
|
||||||
|
|
||||||
local BackgroundRunner = {
|
|
||||||
jobs = PluginShare.backgroundJobs,
|
|
||||||
running = false,
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Copies required fields from |job|.
|
|
||||||
-- @return a new table with required fields of a valid job.
|
|
||||||
function BackgroundRunner:_clone(job)
|
|
||||||
assert(job ~= nil)
|
|
||||||
local result = {}
|
|
||||||
result.when = job.when
|
|
||||||
result.repeated = job.repeated
|
|
||||||
result.executable = job.executable
|
|
||||||
result.callback = job.callback
|
|
||||||
result.environment = job.environment
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
function BackgroundRunner:_shouldRepeat(job)
|
|
||||||
if type(job.repeated) == "nil" then return false end
|
|
||||||
if type(job.repeated) == "boolean" then return job.repeated end
|
|
||||||
if type(job.repeated) == "function" then
|
|
||||||
local status, result = pcall(job.repeated)
|
|
||||||
if status then
|
|
||||||
return result
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if type(job.repeated) == "number" then
|
|
||||||
job.repeated = job.repeated - 1
|
|
||||||
return job.repeated > 0
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function BackgroundRunner:_finishJob(job)
|
|
||||||
if type(job.executable) == "function" then
|
|
||||||
local time_diff = job.end_time - job.start_time
|
|
||||||
local threshold = time.s(1)
|
|
||||||
job.timeout = (time_diff > threshold)
|
|
||||||
end
|
|
||||||
job.blocked = job.timeout
|
|
||||||
if not job.blocked and self:_shouldRepeat(job) then
|
|
||||||
self:_insert(self:_clone(job))
|
|
||||||
end
|
|
||||||
if type(job.callback) == "function" then
|
|
||||||
pcall(job.callback)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Executes |job|.
|
|
||||||
-- @treturn boolean true if job is valid.
|
|
||||||
function BackgroundRunner:_executeJob(job)
|
|
||||||
assert(not CommandRunner:pending())
|
|
||||||
if job == nil then return false end
|
|
||||||
if job.executable == nil then return false end
|
|
||||||
|
|
||||||
if type(job.executable) == "string" then
|
|
||||||
CommandRunner:start(job)
|
|
||||||
return true
|
|
||||||
elseif type(job.executable) == "function" then
|
|
||||||
job.start_time = UIManager:getTime()
|
|
||||||
local status, err = pcall(job.executable)
|
|
||||||
if status then
|
|
||||||
job.result = 0
|
|
||||||
else
|
|
||||||
job.result = 1
|
|
||||||
job.exception = err
|
|
||||||
end
|
|
||||||
job.end_time = time.now()
|
|
||||||
self:_finishJob(job)
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Polls the status of the pending CommandRunner.
|
|
||||||
function BackgroundRunner:_poll()
|
|
||||||
assert(CommandRunner:pending())
|
|
||||||
local result = CommandRunner:poll()
|
|
||||||
if result == nil then return end
|
|
||||||
|
|
||||||
self:_finishJob(result)
|
|
||||||
end
|
|
||||||
|
|
||||||
function BackgroundRunner:_execute()
|
|
||||||
logger.dbg("BackgroundRunner: _execute() @ ", os.time())
|
|
||||||
if CommandRunner:pending() then
|
|
||||||
self:_poll()
|
|
||||||
else
|
|
||||||
local round = 0
|
|
||||||
while #self.jobs > 0 do
|
|
||||||
local job = table.remove(self.jobs, 1)
|
|
||||||
if job.insert_time == nil then
|
|
||||||
-- Jobs are first inserted to jobs table from external users.
|
|
||||||
-- So they may not have an insert field.
|
|
||||||
job.insert_time = UIManager:getTime()
|
|
||||||
end
|
|
||||||
local should_execute = false
|
|
||||||
local should_ignore = false
|
|
||||||
if type(job.when) == "function" then
|
|
||||||
local status, result = pcall(job.when)
|
|
||||||
if status then
|
|
||||||
should_execute = result
|
|
||||||
else
|
|
||||||
should_ignore = true
|
|
||||||
end
|
|
||||||
elseif type(job.when) == "number" then
|
|
||||||
if job.when >= 0 then
|
|
||||||
should_execute = (UIManager:getTime() - job.insert_time >= time.s(job.when))
|
|
||||||
else
|
|
||||||
should_ignore = true
|
|
||||||
end
|
|
||||||
elseif type(job.when) == "string" then
|
|
||||||
--- @todo (Hzj_jie): Implement "idle" mode
|
|
||||||
if job.when == "best-effort" then
|
|
||||||
should_execute = (round > 0)
|
|
||||||
elseif job.when == "idle" then
|
|
||||||
should_execute = (round > 1)
|
|
||||||
else
|
|
||||||
should_ignore = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
should_ignore = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if should_execute then
|
|
||||||
logger.dbg("BackgroundRunner: run job ", job, " @ ", os.time())
|
|
||||||
assert(not should_ignore)
|
|
||||||
self:_executeJob(job)
|
|
||||||
break
|
|
||||||
elseif not should_ignore then
|
|
||||||
table.insert(self.jobs, job)
|
|
||||||
end
|
|
||||||
|
|
||||||
round = round + 1
|
|
||||||
if round > 2 then break end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self.running = false
|
|
||||||
if PluginShare.stopBackgroundRunner == nil then
|
|
||||||
if #self.jobs == 0 and not CommandRunner:pending() then
|
|
||||||
logger.dbg("BackgroundRunnerWidget: no job, stop running @ ", os.time())
|
|
||||||
else
|
|
||||||
self:_schedule()
|
|
||||||
end
|
|
||||||
else
|
|
||||||
logger.dbg("BackgroundRunnerWidget: stop running @ ", os.time())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function BackgroundRunner:_schedule()
|
|
||||||
if self.running == false then
|
|
||||||
if #self.jobs == 0 and not CommandRunner:pending() then
|
|
||||||
logger.dbg("BackgroundRunnerWidget: no job, not running @ ", os.time())
|
|
||||||
else
|
|
||||||
logger.dbg("BackgroundRunnerWidget: start running @ ", os.time())
|
|
||||||
self.running = true
|
|
||||||
UIManager:scheduleIn(2, function() self:_execute() end)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
logger.dbg("BackgroundRunnerWidget: a schedule is pending @ ",
|
|
||||||
os.time())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function BackgroundRunner:_insert(job)
|
|
||||||
job.insert_time = UIManager:getTime()
|
|
||||||
table.insert(self.jobs, job)
|
|
||||||
end
|
|
||||||
|
|
||||||
BackgroundRunner:_schedule()
|
|
||||||
|
|
||||||
local BackgroundRunnerWidget = WidgetContainer:extend{
|
|
||||||
name = "backgroundrunner",
|
|
||||||
runner = BackgroundRunner,
|
|
||||||
}
|
|
||||||
|
|
||||||
function BackgroundRunnerWidget:onSuspend()
|
|
||||||
logger.dbg("BackgroundRunnerWidget:onSuspend() @ ", os.time())
|
|
||||||
PluginShare.stopBackgroundRunner = true
|
|
||||||
end
|
|
||||||
|
|
||||||
function BackgroundRunnerWidget:onResume()
|
|
||||||
logger.dbg("BackgroundRunnerWidget:onResume() @ ", os.time())
|
|
||||||
PluginShare.stopBackgroundRunner = nil
|
|
||||||
BackgroundRunner:_schedule()
|
|
||||||
end
|
|
||||||
|
|
||||||
function BackgroundRunnerWidget:onBackgroundJobsUpdated()
|
|
||||||
logger.dbg("BackgroundRunnerWidget:onBackgroundJobsUpdated() @ ", os.time())
|
|
||||||
PluginShare.stopBackgroundRunner = nil
|
|
||||||
BackgroundRunner:_schedule()
|
|
||||||
end
|
|
||||||
|
|
||||||
return BackgroundRunnerWidget
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Starts the arguments as a bash command in background with low priority. The
|
|
||||||
# command will be killed if it executes for over 1 hour. If the command failed
|
|
||||||
# to start, this script returns 127. If the command is timed out, this script
|
|
||||||
# returns 255. Otherwise the return value of the command will be returned.
|
|
||||||
|
|
||||||
echo "TIMEOUT in environment: ${TIMEOUT}"
|
|
||||||
|
|
||||||
if [ -z "${TIMEOUT}" ]; then
|
|
||||||
TIMEOUT=3600
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Timeout has been set to ${TIMEOUT} seconds"
|
|
||||||
|
|
||||||
echo "Will start command $*"
|
|
||||||
|
|
||||||
echo "$@" | nice -n 19 sh &
|
|
||||||
JOB_ID=$!
|
|
||||||
echo "Job id: ${JOB_ID}"
|
|
||||||
|
|
||||||
for i in $(seq 1 1 "${TIMEOUT}"); do
|
|
||||||
if ps -p "${JOB_ID}" >/dev/null 2>&1; then
|
|
||||||
# Job is still running.
|
|
||||||
sleep 1
|
|
||||||
ROUND=$(printf "%s" "${i}" | tail -c 1)
|
|
||||||
if [ "${ROUND}" -eq "0" ]; then
|
|
||||||
echo "Job ${JOB_ID} is still running ... waited for ${i} seconds."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
wait ${JOB_ID}
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Command $* has timed out"
|
|
||||||
|
|
||||||
kill -9 ${JOB_ID}
|
|
||||||
exit 255
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
describe("AutoFrontlight widget tests", function()
|
|
||||||
local Device, PowerD, MockTime, class, AutoFrontlight, UIManager
|
|
||||||
|
|
||||||
setup(function()
|
|
||||||
require("commonrequire")
|
|
||||||
package.unloadAll()
|
|
||||||
require("document/canvascontext"):init(require("device"))
|
|
||||||
|
|
||||||
MockTime = require("mock_time")
|
|
||||||
MockTime:install()
|
|
||||||
|
|
||||||
PowerD = require("device/generic/powerd"):new{
|
|
||||||
frontlight = 0,
|
|
||||||
}
|
|
||||||
PowerD.frontlightIntensityHW = function()
|
|
||||||
return 2
|
|
||||||
end
|
|
||||||
PowerD.setIntensityHW = function(self, intensity)
|
|
||||||
self.frontlight = intensity
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
teardown(function()
|
|
||||||
MockTime:uninstall()
|
|
||||||
package.unloadAll()
|
|
||||||
require("document/canvascontext"):init(require("device"))
|
|
||||||
end)
|
|
||||||
|
|
||||||
before_each(function()
|
|
||||||
Device = require("device")
|
|
||||||
Device.isKindle = function() return true end
|
|
||||||
Device.model = "KindleVoyage"
|
|
||||||
Device.brightness = 0
|
|
||||||
Device.hasFrontlight = function() return true end
|
|
||||||
Device.hasLightSensor = function() return true end
|
|
||||||
Device.powerd = PowerD:new{
|
|
||||||
device = Device,
|
|
||||||
}
|
|
||||||
Device.ambientBrightnessLevel = function(self)
|
|
||||||
return self.brightness
|
|
||||||
end
|
|
||||||
Device.input.waitEvent = function() end
|
|
||||||
require("luasettings"):
|
|
||||||
open(require("datastorage"):getSettingsDir() .. "/autofrontlight.lua"):
|
|
||||||
saveSetting("enable", true):
|
|
||||||
close()
|
|
||||||
|
|
||||||
UIManager = require("ui/uimanager")
|
|
||||||
UIManager:setRunForeverMode()
|
|
||||||
|
|
||||||
requireBackgroundRunner()
|
|
||||||
class = dofile("plugins/autofrontlight.koplugin/main.lua")
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
-- Ensure the background runner has succeeded set the job.insert_sec.
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
end)
|
|
||||||
|
|
||||||
after_each(function()
|
|
||||||
AutoFrontlight:deprecateLastTask()
|
|
||||||
-- Ensure the scheduled task from this test case won't impact others.
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
AutoFrontlight = nil
|
|
||||||
stopBackgroundRunner()
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should automatically turn on or off frontlight", function()
|
|
||||||
AutoFrontlight = class:new()
|
|
||||||
Device.brightness = 3
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(0, Device:getPowerDevice().frontlight)
|
|
||||||
Device.brightness = 0
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, Device:getPowerDevice().frontlight)
|
|
||||||
Device.brightness = 1
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, Device:getPowerDevice().frontlight)
|
|
||||||
Device.brightness = 2
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, Device:getPowerDevice().frontlight)
|
|
||||||
Device.brightness = 3
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(0, Device:getPowerDevice().frontlight)
|
|
||||||
Device.brightness = 4
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(0, Device:getPowerDevice().frontlight)
|
|
||||||
Device.brightness = 3
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(0, Device:getPowerDevice().frontlight)
|
|
||||||
Device.brightness = 2
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(0, Device:getPowerDevice().frontlight)
|
|
||||||
Device.brightness = 1
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, Device:getPowerDevice().frontlight)
|
|
||||||
Device.brightness = 0
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, Device:getPowerDevice().frontlight)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should turn on frontlight at the beginning", function()
|
|
||||||
Device:getPowerDevice():turnOffFrontlight()
|
|
||||||
Device.brightness = 0
|
|
||||||
AutoFrontlight = class:new()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, Device:getPowerDevice().frontlight)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should turn off frontlight at the beginning", function()
|
|
||||||
Device:getPowerDevice():turnOnFrontlight()
|
|
||||||
Device.brightness = 3
|
|
||||||
AutoFrontlight = class:new()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(0, Device:getPowerDevice().frontlight)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should handle configuration update", function()
|
|
||||||
Device:getPowerDevice():turnOffFrontlight()
|
|
||||||
Device.brightness = 0
|
|
||||||
AutoFrontlight = class:new()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, Device:getPowerDevice().frontlight)
|
|
||||||
AutoFrontlight:flipSetting()
|
|
||||||
Device.brightness = 3
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, Device:getPowerDevice().frontlight)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
@@ -1,374 +0,0 @@
|
|||||||
describe("BackgroundRunner widget tests", function()
|
|
||||||
local Device, PluginShare, MockTime, UIManager
|
|
||||||
|
|
||||||
setup(function()
|
|
||||||
require("commonrequire")
|
|
||||||
package.unloadAll()
|
|
||||||
require("document/canvascontext"):init(require("device"))
|
|
||||||
-- Device needs to be loaded before UIManager.
|
|
||||||
Device = require("device")
|
|
||||||
Device.input.waitEvent = function() end
|
|
||||||
PluginShare = require("pluginshare")
|
|
||||||
MockTime = require("mock_time")
|
|
||||||
MockTime:install()
|
|
||||||
UIManager = require("ui/uimanager")
|
|
||||||
UIManager:setRunForeverMode()
|
|
||||||
requireBackgroundRunner()
|
|
||||||
end)
|
|
||||||
|
|
||||||
teardown(function()
|
|
||||||
MockTime:uninstall()
|
|
||||||
package.unloadAll()
|
|
||||||
require("document/canvascontext"):init(require("device"))
|
|
||||||
stopBackgroundRunner()
|
|
||||||
end)
|
|
||||||
|
|
||||||
before_each(function()
|
|
||||||
require("util").clearTable(PluginShare.backgroundJobs)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should start job", function()
|
|
||||||
local executed = false
|
|
||||||
table.insert(PluginShare.backgroundJobs, {
|
|
||||||
when = 10,
|
|
||||||
executable = function()
|
|
||||||
executed = true
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.is_false(executed)
|
|
||||||
MockTime:increase(9)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.is_false(executed)
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.is_true(executed)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should repeat job", function()
|
|
||||||
local executed = 0
|
|
||||||
table.insert(PluginShare.backgroundJobs, {
|
|
||||||
when = 1,
|
|
||||||
repeated = function() return executed < 10 end,
|
|
||||||
executable = function()
|
|
||||||
executed = executed + 1
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
|
|
||||||
for i = 1, 10 do
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(i, executed)
|
|
||||||
end
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(10, executed)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should repeat job for predefined times", function()
|
|
||||||
local executed = 0
|
|
||||||
table.insert(PluginShare.backgroundJobs, {
|
|
||||||
when = 1,
|
|
||||||
repeated = 10,
|
|
||||||
executable = function()
|
|
||||||
executed = executed + 1
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
|
|
||||||
for i = 1, 10 do
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(i, executed)
|
|
||||||
end
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(10, executed)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should block long job", function()
|
|
||||||
local executed = 0
|
|
||||||
local job = {
|
|
||||||
when = 1,
|
|
||||||
repeated = true,
|
|
||||||
executable = function()
|
|
||||||
executed = executed + 1
|
|
||||||
MockTime:increase(2)
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
table.insert(PluginShare.backgroundJobs, job)
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(1, executed)
|
|
||||||
assert.is_true(job.timeout)
|
|
||||||
assert.is_true(job.blocked)
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(1, executed)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should execute binary", function()
|
|
||||||
local executed = false
|
|
||||||
local job = {
|
|
||||||
when = 1,
|
|
||||||
executable = "ls | grep this-should-not-be-a-file",
|
|
||||||
callback = function()
|
|
||||||
executed = true
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
table.insert(PluginShare.backgroundJobs, job)
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
while job.end_time == nil do
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- grep should return 1 when there is no match.
|
|
||||||
assert.are.equal(1, job.result)
|
|
||||||
assert.is_false(job.timeout)
|
|
||||||
assert.is_false(job.bad_command)
|
|
||||||
assert.is_true(executed)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should forward string environment to the executable", function()
|
|
||||||
local job = {
|
|
||||||
when = 1,
|
|
||||||
repeated = false,
|
|
||||||
executable = "echo $ENV1 | grep $ENV2",
|
|
||||||
environment = {
|
|
||||||
ENV1 = "yes",
|
|
||||||
ENV2 = "yes",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
table.insert(PluginShare.backgroundJobs, job)
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
while job.end_time == nil do
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- grep should return 0 when there is a match.
|
|
||||||
assert.are.equal(0, job.result)
|
|
||||||
assert.is_false(job.timeout)
|
|
||||||
assert.is_false(job.bad_command)
|
|
||||||
|
|
||||||
job.environment = {
|
|
||||||
ENV1 = "yes",
|
|
||||||
ENV2 = "no",
|
|
||||||
}
|
|
||||||
job.end_time = nil
|
|
||||||
table.insert(PluginShare.backgroundJobs, job)
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
while job.end_time == nil do
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- grep should return 1 when there is no match.
|
|
||||||
assert.are.equal(1, job.result)
|
|
||||||
assert.is_false(job.timeout)
|
|
||||||
assert.is_false(job.bad_command)
|
|
||||||
|
|
||||||
assert.are.not_equal(os.getenv("ENV1"), "yes")
|
|
||||||
assert.are.not_equal(os.getenv("ENV2"), "yes")
|
|
||||||
assert.are.not_equal(os.getenv("ENV2"), "no")
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should forward function environment to the executable", function()
|
|
||||||
local env2 = "yes"
|
|
||||||
local job = {
|
|
||||||
when = 1,
|
|
||||||
repeated = false,
|
|
||||||
executable = "echo $ENV1 | grep $ENV2",
|
|
||||||
environment = function()
|
|
||||||
return {
|
|
||||||
ENV1 = "yes",
|
|
||||||
ENV2 = env2,
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
table.insert(PluginShare.backgroundJobs, job)
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
while job.end_time == nil do
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- grep should return 0 when there is a match.
|
|
||||||
assert.are.equal(0, job.result)
|
|
||||||
assert.is_false(job.timeout)
|
|
||||||
assert.is_false(job.bad_command)
|
|
||||||
|
|
||||||
job.end_time = nil
|
|
||||||
env2 = "no"
|
|
||||||
table.insert(PluginShare.backgroundJobs, job)
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
while job.end_time == nil do
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- grep should return 1 when there is no match.
|
|
||||||
assert.are.equal(1, job.result)
|
|
||||||
assert.is_false(job.timeout)
|
|
||||||
assert.is_false(job.bad_command)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should block long binary job", function()
|
|
||||||
local job = {
|
|
||||||
when = 1,
|
|
||||||
repeated = true,
|
|
||||||
executable = "sleep 1h",
|
|
||||||
environment = {
|
|
||||||
TIMEOUT = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
table.insert(PluginShare.backgroundJobs, job)
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
while job.end_time == nil do
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
end
|
|
||||||
|
|
||||||
assert.are.equal(255, job.result)
|
|
||||||
assert.is_true(job.timeout)
|
|
||||||
assert.is_true(job.blocked)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should execute callback", function()
|
|
||||||
local executed = 0
|
|
||||||
table.insert(PluginShare.backgroundJobs, {
|
|
||||||
when = 1,
|
|
||||||
repeated = 10,
|
|
||||||
executable = function() end,
|
|
||||||
callback = function()
|
|
||||||
executed = executed + 1
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
|
|
||||||
for i = 1, 10 do
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(i, executed)
|
|
||||||
end
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(10, executed)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should not execute two jobs sequentially", function()
|
|
||||||
local executed = 0
|
|
||||||
table.insert(PluginShare.backgroundJobs, {
|
|
||||||
when = 1,
|
|
||||||
executable = function()
|
|
||||||
executed = executed + 1
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
table.insert(PluginShare.backgroundJobs, {
|
|
||||||
when = 1,
|
|
||||||
executable = function()
|
|
||||||
executed = executed + 1
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(1, executed)
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, executed)
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, executed)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should stop executing when suspending", function()
|
|
||||||
local executed = 0
|
|
||||||
local job = {
|
|
||||||
when = 1,
|
|
||||||
repeated = true,
|
|
||||||
executable = function()
|
|
||||||
executed = executed + 1
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
table.insert(PluginShare.backgroundJobs, job)
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(1, executed)
|
|
||||||
-- Simulate a suspend event.
|
|
||||||
requireBackgroundRunner():onSuspend()
|
|
||||||
for i = 1, 10 do
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, executed)
|
|
||||||
end
|
|
||||||
-- Simulate a resume event.
|
|
||||||
requireBackgroundRunner():onResume()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(3, executed)
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(4, executed)
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should not start multiple times after multiple onResume", function()
|
|
||||||
local executed = 0
|
|
||||||
local job = {
|
|
||||||
when = 1,
|
|
||||||
repeated = true,
|
|
||||||
executable = function()
|
|
||||||
executed = executed + 1
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
table.insert(PluginShare.backgroundJobs, job)
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
|
|
||||||
for i = 1, 10 do
|
|
||||||
requireBackgroundRunner():onResume()
|
|
||||||
end
|
|
||||||
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(1, executed)
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, executed)
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(3, executed)
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
describe("BackgroundTaskPlugin", function()
|
|
||||||
require("commonrequire")
|
|
||||||
local BackgroundTaskPlugin = require("ui/plugin/background_task_plugin")
|
|
||||||
local MockTime = require("mock_time")
|
|
||||||
local UIManager = require("ui/uimanager")
|
|
||||||
|
|
||||||
local BackgroundTaskPlugin_schedule_orig = BackgroundTaskPlugin._schedule
|
|
||||||
setup(function()
|
|
||||||
MockTime:install()
|
|
||||||
local Device = require("device")
|
|
||||||
Device.input.waitEvent = function() end
|
|
||||||
UIManager:setRunForeverMode()
|
|
||||||
requireBackgroundRunner()
|
|
||||||
-- Monkey patch this method to notify BackgroundRunner
|
|
||||||
-- as it is not accessible to UIManager in these tests
|
|
||||||
BackgroundTaskPlugin._schedule = function(...)
|
|
||||||
BackgroundTaskPlugin_schedule_orig(...)
|
|
||||||
notifyBackgroundJobsUpdated()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
teardown(function()
|
|
||||||
MockTime:uninstall()
|
|
||||||
package.unloadAll()
|
|
||||||
require("document/canvascontext"):init(require("device"))
|
|
||||||
stopBackgroundRunner()
|
|
||||||
BackgroundTaskPlugin._schedule = BackgroundTaskPlugin_schedule_orig
|
|
||||||
end)
|
|
||||||
|
|
||||||
local createTestPlugin = function(executable)
|
|
||||||
return BackgroundTaskPlugin:new({
|
|
||||||
name = "test_plugin",
|
|
||||||
default_enable = true,
|
|
||||||
when = 2,
|
|
||||||
executable = executable,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
local TestPlugin2 = BackgroundTaskPlugin:extend()
|
|
||||||
|
|
||||||
function TestPlugin2:new(o)
|
|
||||||
o = o or {}
|
|
||||||
o.name = "test_plugin2"
|
|
||||||
o.default_enable = true
|
|
||||||
o.when = 2
|
|
||||||
o.executed = 0
|
|
||||||
o.executable = function()
|
|
||||||
o.executed = o.executed + 1
|
|
||||||
end
|
|
||||||
o = BackgroundTaskPlugin.new(self, o)
|
|
||||||
return o
|
|
||||||
end
|
|
||||||
|
|
||||||
it("should be able to create a plugin", function()
|
|
||||||
local executed = 0
|
|
||||||
local test_plugin = createTestPlugin(function()
|
|
||||||
executed = executed + 1
|
|
||||||
end)
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(1, executed)
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, executed)
|
|
||||||
|
|
||||||
test_plugin:flipSetting()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(3, executed) -- The last job is still pending.
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(3, executed)
|
|
||||||
|
|
||||||
test_plugin:flipSetting()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(3, executed) -- The new job has just been inserted.
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(4, executed)
|
|
||||||
|
|
||||||
-- Fake a settings_id increment.
|
|
||||||
test_plugin:_init()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(5, executed) -- The job is from last settings_id.
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(5, executed) -- The new job has just been inserted.
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(6, executed) -- The job is from current settings_id.
|
|
||||||
|
|
||||||
-- Ensure test_plugin is stopped.
|
|
||||||
test_plugin:flipSetting()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
end)
|
|
||||||
|
|
||||||
it("should be able to create a derived plugin", function()
|
|
||||||
local test_plugin = TestPlugin2:new()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(1, test_plugin.executed)
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(2, test_plugin.executed)
|
|
||||||
|
|
||||||
test_plugin:flipSetting()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(3, test_plugin.executed) -- The last job is still pending.
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(3, test_plugin.executed)
|
|
||||||
|
|
||||||
test_plugin:flipSetting()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(3, test_plugin.executed) -- The new job has just been inserted.
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(4, test_plugin.executed)
|
|
||||||
|
|
||||||
-- Fake a settings_id increment.
|
|
||||||
test_plugin:_init()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(5, test_plugin.executed) -- The job is from last settings_id.
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(5, test_plugin.executed) -- The new job has just been inserted.
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
assert.are.equal(6, test_plugin.executed) -- The job is from current settings_id.
|
|
||||||
|
|
||||||
-- Ensure test_plugin is stopped.
|
|
||||||
test_plugin:flipSetting()
|
|
||||||
MockTime:increase(2)
|
|
||||||
UIManager:handleInput()
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
@@ -119,26 +119,3 @@ package.unloadAll = function()
|
|||||||
end
|
end
|
||||||
return #pending
|
return #pending
|
||||||
end
|
end
|
||||||
|
|
||||||
local background_runner
|
|
||||||
requireBackgroundRunner = function()
|
|
||||||
require("pluginshare").stopBackgroundRunner = nil
|
|
||||||
if background_runner == nil then
|
|
||||||
local package_path = package.path
|
|
||||||
package.path = "plugins/backgroundrunner.koplugin/?.lua;" .. package.path
|
|
||||||
background_runner = dofile("plugins/backgroundrunner.koplugin/main.lua")
|
|
||||||
package.path = package_path
|
|
||||||
end
|
|
||||||
return background_runner
|
|
||||||
end
|
|
||||||
|
|
||||||
stopBackgroundRunner = function()
|
|
||||||
background_runner = nil
|
|
||||||
require("pluginshare").stopBackgroundRunner = true
|
|
||||||
end
|
|
||||||
|
|
||||||
notifyBackgroundJobsUpdated = function()
|
|
||||||
if background_runner then
|
|
||||||
background_runner:onBackgroundJobsUpdated()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|||||||
Reference in New Issue
Block a user