summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Forlot <romain.forlot@iot.bzh>2018-07-18 19:50:57 +0200
committerRomain Forlot <romain.forlot@iot.bzh>2018-07-21 10:05:16 +0000
commit3f00d0fea4b8db29ef8268f2189704a3ea8e3360 (patch)
tree03d2d6abb708a8830682250653c43d79d24100cf
parent99043faef2d12b70dc27e2c816738a9ba2fff659 (diff)
Fix: events callback aren't correctly registered
They were stored in the mapis sections instead of the events one. Clean and handle raw events as well. Before that it could only process events coming from monitoring api. Now it could receive the event directly. Make sure that the event handle is valid before sends the request response. This prevent to subcribe or push an event while the event handle hasn't been correctly created. This could happens if the testVerb hasn't not been called from a session. In that case, the response will just be that tests has been launched. Format. Change-Id: I0aa522939162684f91dd426cc14919bb0ec3f69e Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
-rw-r--r--conf.d/controller/lua.d/aft.lua189
-rw-r--r--src/aft.c10
-rw-r--r--src/mapis.c24
3 files changed, 165 insertions, 58 deletions
diff --git a/conf.d/controller/lua.d/aft.lua b/conf.d/controller/lua.d/aft.lua
index 918deb1..b9061fb 100644
--- a/conf.d/controller/lua.d/aft.lua
+++ b/conf.d/controller/lua.d/aft.lua
@@ -22,6 +22,14 @@ local lu = require('luaunit')
lu.LuaUnit:setOutputType('JUNIT')
lu.LuaUnit.fname = "xUnitResults.xml"
+local function table_size(t)
+ local size = 0
+ for _,_ in pairs(t) do
+ size = size + 1
+ end
+ return size
+end
+
_AFT = {
exit = {0, code},
context = _ctx,
@@ -98,71 +106,151 @@ function _AFT.registerData(dict, eventData)
end
end
-function _AFT.requestDaemonEventHandler(eventObj)
- local eventName = eventObj.data.message
- local log = _AFT.monitored_events[eventName]
- local api = nil
-
- if eventObj.daemon then
- api = eventObj.daemon.api
- elseif eventObj.request then
- api = eventObj.request.api
+function _AFT.bindingEventHandler(eventObj, uid)
+ local eventName = nil
+ local eventListeners = nil
+ local data = nil
+
+ if uid then
+ eventName = uid
+ data = eventObj
+ elseif eventObj.event.name then
+ eventName = eventObj.event.name
+ eventListeners = eventObj.data.result
+ -- Remove from event to hold the bare event data and be able to assert it
+ eventObj.data.result = nil
+ data = eventObj.data
end
- if log and log.api == api and log.type == eventObj.data.type then
+ if type(_AFT.monitored_events[eventName]) == 'table' then
+ if eventListeners then
+ _AFT.monitored_events[eventName].eventListeners = eventListeners
+ end
+
_AFT.incrementCount(_AFT.monitored_events[eventName])
- _AFT.registerData(_AFT.monitored_events[eventName], eventObj.data)
+ _AFT.registerData(_AFT.monitored_events[eventName], data)
end
+end
+function _evt_catcher_(source, action, eventObj)
+ local uid = AFB:getuid(source)
+ if uid == "monitor/trace" then
+ if eventObj.type == "event" then
+ _AFT.bindingEventHandler(eventObj)
+ end
+ else
+ _AFT.bindingEventHandler(eventObj, uid)
+ end
end
-function _AFT.bindingEventHandler(eventObj)
- local eventName = eventObj.event.name
- local eventListeners = eventObj.data.result
+function _AFT.lockWait(eventName, timeout)
+ if type(eventName) ~= "string" then
+ print("Error: wrong argument given to wait an event. 1st argument should be a string")
+ return 0
+ end
- -- Remove from event to hold the bare event data and be able to assert it
- eventObj.data.result = nil
+ local count = 0
+ if _AFT.monitored_events[eventName].receivedCount and timeout then
+ count = _AFT.monitored_events[eventName].receivedCount
+ end
- if type(_AFT.monitored_events[eventName]) == 'table' then
- _AFT.monitored_events[eventName].eventListeners = eventListeners
+ while timeout > 0 do
+ timeout = AFB:lockwait(_AFT.context, timeout)
+ AFB:lockwait(_AFT.context, 0) --without it _evt_catcher_ cannot received event
- _AFT.incrementCount(_AFT.monitored_events[eventName])
- _AFT.registerData(_AFT.monitored_events[eventName], eventObj.data)
+ if _AFT.monitored_events[eventName].receivedCount == count + 1 then
+ return 1
+ end
end
+ return 0
end
-function _evt_catcher_ (source, action, eventObj)
- if eventObj.type == "event" then
- _AFT.bindingEventHandler(eventObj)
- elseif eventObj.type == "daemon" or eventObj.type == "request" then
- _AFT.requestDaemonEventHandler(eventObj)
+function _AFT.lockWaitGroup(eventGroup, timeout)
+ if type(eventGroup) ~= "table" then
+ print("Error: wrong argument given to wait a group of events. 1st argument should be a table")
+ return 0
+ end
+ local eventGroupCpy = {table.unpack(eventGroup)}
+
+ while timeout > 0 do
+ timeout = AFB:lockwait(_AFT.context, timeout)
+ AFB:lockwait(_AFT.context, 0) --without it _evt_catcher_ cannot received event
+
+ for key,event in pairs(eventGroupCpy) do
+ if _AFT.monitored_events[event.name].receivedCount == event.receivedCount + 1 then
+ eventGroupCpy[key] = nil
+ end
+ end
+ if table_size(eventGroupCpy) == 0 then return 1 end
end
+ return 0
end
--[[
Assert and test functions about the event part.
]]
-function _AFT.lockwait(eventName, timeout)
- local count = 0
- if _AFT.monitored_events[eventName].receivedCount then
- if timeout then
- count = _AFT.monitored_events[eventName].receivedCount
- end
+function _AFT.assertEvtGrpNotReceived(eventGroup, timeout)
+ local count = 0
+ local eventName = ""
+ for _,event in pairs(eventGroup) do
+ eventGroup[key] = {name = event, receivedCount = _AFT.monitored_events[event].receivedCount}
end
- while timeout > 0 do
- timeout = AFB:lockwait(_AFT.context, timeout)
- AFB:lockwait(_AFT.context, 0) --without it ev catcher cannot received event
- if _AFT.monitored_events[eventName].receivedCount == count + 1 then
- return 1
- end
- end
- return 0
+ if timeout then
+ count = _AFT.lockWaitGroup(eventGroup, timeout)
+ else
+ for _,v in pairs(eventGroup) do
+ count = count + v.count
+ end
+ end
+
+ for _,event in pairs(eventGroup) do
+ eventName = eventName .. " " .. event.name
+ end
+ _AFT.assertIsTrue(count == 0, "One of the following events has been received: '".. eventName .."' but it shouldn't")
+
+ for _,event in pairs(eventGroup) do
+ if _AFT.monitored_events[event.name].cb then
+ local data_n = table_size(_AFT.monitored_events[event.name].data)
+ _AFT.monitored_events[event.name].cb(v.name, _AFT.monitored_events[event.name].data[data_n])
+ end
+ end
+end
+
+function _AFT.assertEvtGrpReceived(eventGroup, timeout)
+ local count = 0
+ local eventName = ""
+ for key,event in pairs(eventGroup) do
+ eventGroup[key] = {name = event, receivedCount = _AFT.monitored_events[event].receivedCount}
+ end
+
+ if timeout then
+ count = _AFT.lockWaitGroup(eventGroup, timeout)
+ else
+ for _,v in pairs(eventGroup) do
+ count = count + v.receivedCount
+ end
+ end
+
+ for _,event in pairs(eventGroup) do
+ eventName = eventName .. " " .. event.name
+ end
+ _AFT.assertIsTrue(count >= table_size(eventGroup), "None or one of the following events: '".. eventName .."' has not been received")
+
+ for _,event in pairs(eventGroup) do
+ if _AFT.monitored_events[event.name].cb then
+ local data_n = table_size(_AFT.monitored_events[event.name].data)
+ _AFT.monitored_events[event.name].cb(v.name, _AFT.monitored_events[event.name].data[data_n])
+ end
+ end
end
function _AFT.assertEvtNotReceived(eventName, timeout)
- local count = _AFT.lockwait(eventName, timeout)
+ local count = _AFT.monitored_events[eventName].receivedCount
+ if timeout then
+ count = _AFT.lockWait(eventName, timeout)
+ end
_AFT.assertIsTrue(count == 0, "Event '".. eventName .."' received but it shouldn't")
@@ -173,7 +261,10 @@ function _AFT.assertEvtNotReceived(eventName, timeout)
end
function _AFT.assertEvtReceived(eventName, timeout)
- local count = _AFT.lockwait(eventName, timeout)
+ local count = _AFT.monitored_events[eventName].receivedCount
+ if timeout then
+ count = _AFT.lockWait(eventName, timeout)
+ end
_AFT.assertIsTrue(count > 0, "No event '".. eventName .."' received")
@@ -460,8 +551,10 @@ local function call_tests()
local failures="Failures : "..tostring(lu.LuaUnit.result.testCount-lu.LuaUnit.result.passedCount)
local evtHandle = AFB:evtmake(_AFT.context, 'results')
- AFB:subscribe(_AFT.context,evtHandle)
- AFB:evtpush(_AFT.context,evtHandle,{info = success.." "..failures})
+ if type(evtHandle) == "userdata" then
+ AFB:subscribe(_AFT.context,evtHandle)
+ AFB:evtpush(_AFT.context,evtHandle,{info = success.." "..failures})
+ end
end
function _launch_test(context, args)
@@ -470,7 +563,15 @@ function _launch_test(context, args)
-- Prepare the tests execution configuring the monitoring and loading
-- lua test files to execute in the Framework.
AFB:servsync(_AFT.context, "monitor", "set", { verbosity = "debug" })
- AFB:servsync(_AFT.context, "monitor", "trace", { add = { api = args.trace, request = "vverbose", event = "push_after" }})
+ if type(args.trace) == "string" then
+ AFB:servsync(_AFT.context, "monitor", "trace", { add = { api = args.trace, request = "vverbose", event = "push_after" }})
+ elseif type(args.trace) == "table" then
+ for _,v in pairs(args.trace) do
+ if type(v) == "string" then
+ AFB:servsync(_AFT.context, "monitor", "trace", { add = { api = v, request = "vverbose", event = "push_after" }})
+ end
+ end
+ end
if args.files and type(args.files) == 'table' then
for _,f in pairs(args.files) do
dofile('var/'..f)
diff --git a/src/aft.c b/src/aft.c
index 36a8b17..1a5edc1 100644
--- a/src/aft.c
+++ b/src/aft.c
@@ -62,7 +62,7 @@ static AFB_ApiVerbs CtrlApiVerbs[] = {
static int CtrlLoadStaticVerbs(afb_dynapi *apiHandle, AFB_ApiVerbs *verbs) {
int errcount = 0;
- for (int idx = 0; verbs[idx].verb; idx++) {
+ for(int idx = 0; verbs[idx].verb; idx++) {
errcount += afb_dynapi_add_verb(
apiHandle, CtrlApiVerbs[idx].verb, NULL, CtrlApiVerbs[idx].callback,
(void *)&CtrlApiVerbs[idx], CtrlApiVerbs[idx].auth, 0);
@@ -91,7 +91,7 @@ static int CtrlLoadOneApi(void *cbdata, AFB_ApiT apiHandle) {
// add static controls verbs
int err = CtrlLoadStaticVerbs(apiHandle, CtrlApiVerbs);
- if (err) {
+ if(err) {
AFB_ApiError(apiHandle, "CtrlLoadSection fail to register static V2 verbs");
return ERROR;
}
@@ -132,21 +132,21 @@ int afbBindingEntry(afb_dynapi *apiHandle) {
}
configPath = CtlConfigSearch(apiHandle, dirList, prefix);
- if (!configPath) {
+ if(!configPath) {
AFB_ApiError(apiHandle, "CtlPreInit: No %s* config found in %s ", GetBinderName(), dirList);
return ERROR;
}
// load config file and create API
ctrlConfig = CtlLoadMetaDataUsingPrefix(apiHandle, configPath, prefix);
- if (!ctrlConfig) {
+ if(!ctrlConfig) {
AFB_ApiError(apiHandle,
"CtrlBindingDyn No valid control config file in:\n-- %s",
configPath);
return ERROR;
}
- if (!ctrlConfig->api) {
+ if(!ctrlConfig->api) {
AFB_ApiError(apiHandle,
"CtrlBindingDyn API Missing from metadata in:\n-- %s",
configPath);
diff --git a/src/mapis.c b/src/mapis.c
index 145c01f..64543e5 100644
--- a/src/mapis.c
+++ b/src/mapis.c
@@ -16,8 +16,9 @@
* limitations under the License.
*/
+#include <string.h>
#include <mapis.h>
-#include <ctl-plugin.h>
+#include <ctl-config.h>
struct mapisHandleT {
AFB_ApiT mainApiHandle;
@@ -27,11 +28,11 @@ struct mapisHandleT {
json_object *eventsJ;
};
-static int LoadOneMapi(void *data, AFB_ApiT apiHandle)
-{
- int savedCount = 0, count = 0;
+static int LoadOneMapi(void *data, AFB_ApiT apiHandle) {
+ int savedCount = 0, count = 0, idx = 0;
CtlActionT *savedActions = NULL, *newActions = NULL;
struct mapisHandleT *mapisHandle = (struct mapisHandleT*)data;
+ CtlConfigT *ctrlConfig = afb_dynapi_get_userdata(mapisHandle->mainApiHandle);
if(PluginConfig(apiHandle, mapisHandle->section, mapisHandle->mapiJ)) {
AFB_ApiError(apiHandle, "Problem loading the plugin as an API for %s, see log message above", json_object_get_string(mapisHandle->mapiJ));
@@ -45,7 +46,12 @@ static int LoadOneMapi(void *data, AFB_ApiT apiHandle)
}
// Add actions to the section to be able to respond to defined events.
- savedActions = mapisHandle->section->actions;
+ for(idx = 0; ctrlConfig->sections[idx].key != NULL; ++idx) {
+ if(! strcasecmp(ctrlConfig->sections[idx].key, "events")) {
+ savedActions = ctrlConfig->sections[idx].actions;
+ break;
+ }
+ }
newActions = ActionConfig(apiHandle, mapisHandle->eventsJ, 0);
if(savedActions) {
@@ -71,10 +77,10 @@ static int LoadOneMapi(void *data, AFB_ApiT apiHandle)
while(newActions[savedCount].uid != NULL && count <= total) {
mergedActions[count] = newActions[savedCount];
count++;
- savedActions++;
+ savedCount++;
}
- mapisHandle->section->actions = mergedActions;
+ ctrlConfig->sections[idx].actions = mergedActions;
// declare an event event manager for this API;
afb_dynapi_on_event(apiHandle, CtrlDispatchApiEvent);
@@ -96,8 +102,8 @@ static void OneMapiConfig(void *data, json_object *mapiJ) {
"lua", NULL,
"verbs", &mapisHandle->verbsJ,
"events", &mapisHandle->eventsJ)) {
- AFB_ApiError(mapisHandle->mainApiHandle, "Wrong mapis specification, missing uid|[info]|[spath]|libs|[lua]|verbs|[events] for %s", json_object_get_string(mapiJ));
- return;
+ AFB_ApiError(mapisHandle->mainApiHandle, "Wrong mapis specification, missing uid|[info]|[spath]|libs|[lua]|verbs|[events] for %s", json_object_get_string(mapiJ));
+ return;
}
json_object_get(mapisHandle->verbsJ);