diff options
author | Jose Bollo <jose.bollo@iot.bzh> | 2018-07-12 10:59:48 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2018-07-24 16:28:32 +0200 |
commit | e17ae412245ba9afb33ff6a0f1f665b4d66d4da4 (patch) | |
tree | 698628c58b541007033ede6b4343dae921214da6 /bindings/samples/hello3.c | |
parent | 4c0f6ce66c66d39dc61ec661d88277c51d2fd9ae (diff) |
coverage and test: Add tests
coverage values:
- lines: 70.5 %
- functions: 76.3 %
Change-Id: Iaf802e84bbfa57502bbbac8c3b567b14c01608b6
Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'bindings/samples/hello3.c')
-rw-r--r-- | bindings/samples/hello3.c | 312 |
1 files changed, 302 insertions, 10 deletions
diff --git a/bindings/samples/hello3.c b/bindings/samples/hello3.c index f49b3365..477e47bd 100644 --- a/bindings/samples/hello3.c +++ b/bindings/samples/hello3.c @@ -18,14 +18,24 @@ #include <stdio.h> #include <string.h> #include <pthread.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> #include <json-c/json.h> #define AFB_BINDING_VERSION 3 #include <afb/afb-binding.h> +#if !defined(APINAME) +#define APINAME "hello3" +#endif + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +/**************************************************************************/ + struct event { struct event *next; @@ -116,6 +126,30 @@ static int event_broadcast(struct json_object *args, const char *tag) return e ? afb_event_broadcast(e->event, json_object_get(args)) : -1; } +/**************************************************************************/ + +struct api +{ + struct api *next; + afb_api_t api; + char name[1]; +}; + +static struct api *apis = 0; + +/* search the api of name */ +static struct api *searchapi(const char *name, struct api ***previous) +{ + struct api *a, **p = &apis; + while((a = *p) && strcmp(a->name, name)) + p = &a->next; + if (previous) + *previous = p; + return a; +} + +/**************************************************************************/ + // Sample Generic Ping Debug API static void ping(afb_req_t request, json_object *jresp, const char *tag) { @@ -451,23 +485,107 @@ static void info (afb_req_t request) afb_req_reply(request, afb_req_get_client_info(request), NULL, NULL); } -static int preinit(afb_api_t api) +static void eventloop (afb_req_t request) { - AFB_NOTICE("hello binding comes to live"); - return 0; + afb_api_t api = afb_req_get_api(request); + struct sd_event *ev = afb_api_get_event_loop(api); + afb_req_reply(request, NULL, ev ? NULL : "no-event-loop", NULL); } -static int init(afb_api_t api) +static void dbus (afb_req_t request) { - AFB_NOTICE("hello binding starting"); - return 0; + afb_api_t api = afb_req_get_api(request); + json_object *json = afb_req_json(request); + struct sd_bus *bus = (json_object_get_boolean(json) ? afb_api_get_system_bus : afb_api_get_user_bus)(api); + afb_req_reply(request, NULL, bus ? NULL : "no-bus", NULL); } -static void onevent(afb_api_t api, const char *event, struct json_object *object) +static void replycount (afb_req_t request) { - AFB_NOTICE("received event %s(%s)", event, json_object_to_json_string(object)); + json_object *json = afb_req_json(request); + int count = json_object_get_int(json); + while (count-- > 0) + afb_req_reply(request, NULL, NULL, NULL); } +static void get(afb_req_t request) +{ + struct afb_arg arg = afb_req_get(request, "name"); + const char *name, *value, *path; + + if (!arg.name || !arg.value) + afb_req_reply(request, NULL, "invalid", "the parameter 'name' is missing"); + else { + name = arg.name; + value = afb_req_value(request, name); + path = afb_req_path(request, name); + afb_req_reply_f(request, NULL, NULL, "found for '%s': %s", name, value ?: path ?: "NULL"); + } +} + +static void ref(afb_req_t request) +{ + afb_req_addref(request); + afb_req_reply(request, NULL, NULL, NULL); + afb_req_unref(request); +} + +static void rootdir (afb_req_t request) +{ + ssize_t s; + afb_api_t api = afb_req_get_api(request); + int fd = afb_api_rootdir_get_fd(api); + char buffer[150], root[1025]; + sprintf(buffer, "/proc/self/fd/%d", fd); + s = readlink(buffer, root, sizeof root - 1); + if (s < 0) + afb_req_reply_f(request, NULL, "error", "can't readlink %s: %m", buffer); + else { + root[s] = 0; + afb_req_reply(request, json_object_new_string(root), NULL, NULL); + } +} + +static void locale (afb_req_t request) +{ + char buffer[150], root[1025]; + const char *lang, *file; + ssize_t s; + json_object *json = afb_req_json(request), *x; + afb_api_t api = afb_req_get_api(request); + int fd; + + lang = NULL; + if (json_object_is_type(json, json_type_string)) + file = json_object_get_string(json); + else { + if (!json_object_object_get_ex(json, "file", &x)) { + afb_req_reply(request, NULL, "invalid", "no file"); + return; + } + file = json_object_get_string(x); + if (json_object_object_get_ex(json, "lang", &x)) + lang = json_object_get_string(x); + } + + fd = afb_api_rootdir_open_locale(api, file, O_RDONLY, lang); + if (fd < 0) + afb_req_reply_f(request, NULL, "error", "can't open %s [%s]: %m", file?:"NULL", lang?:"NULL"); + else { + sprintf(buffer, "/proc/self/fd/%d", fd); + s = readlink(buffer, root, sizeof root - 1); + if (s < 0) + afb_req_reply_f(request, NULL, "error", "can't readlink %s: %m", buffer); + else { + root[s] = 0; + afb_req_reply(request, json_object_new_string(root), NULL, NULL); + } + close(fd); + } +} + +static void api (afb_req_t request); + // NOTE: this sample does not use session to keep test a basic as possible // in real application most APIs should be protected with AFB_SESSION_CHECK static const struct afb_verb_v3 verbs[]= { @@ -499,12 +617,186 @@ static const struct afb_verb_v3 verbs[]= { { .verb="setctxif", .callback=setctx, .vcbdata = (void*)(intptr_t)0 }, { .verb="getctx", .callback=getctx }, { .verb="info", .callback=info }, + { .verb="eventloop", .callback=eventloop }, + { .verb="dbus", .callback=dbus }, + { .verb="reply-count", .callback=replycount }, + { .verb="get", .callback=get}, + { .verb="ref", .callback=ref}, + { .verb="rootdir", .callback=rootdir}, + { .verb="locale", .callback=locale}, + { .verb="api", .callback=api}, { .verb=NULL} }; -#if !defined(APINAME) -#define APINAME "hello3" +static void pingSample2 (struct afb_req_x1 req) +{ + pingSample(req.closure); +} + +static const struct afb_verb_v2 apiverbs2[]= { + { .verb="ping", .callback=pingSample2 }, + { .verb="ping2", .callback=pingSample2 }, + { .verb=NULL } +}; + +static int apipreinit(void *closure, afb_api_t api) +{ + afb_api_set_verbs_v2(api, apiverbs2); + afb_api_set_verbs_v3(api, verbs); + return 0; +} + +static void apiverb (afb_req_t request) +{ + afb_req_reply_f(request, json_object_get(afb_req_json(request)), NULL, "api: %s, verb: %s", + afb_req_get_called_api(request), afb_req_get_called_verb(request)); +} + +static void apievhndl(void *closure, const char *event, struct json_object *args, afb_api_t api) +{ + struct json_object *obj = closure; + afb_api_verbose(api, 0, NULL, 0, NULL, "the handler of closure(%s) received the event %s(%s)", + json_object_get_string(obj), event, json_object_get_string(args)); +} + +static void api (afb_req_t request) +{ + struct api *sapi, **psapi; + const char *action, *apiname, *verbname, *pattern; + json_object *json = afb_req_json(request), *x, *closure; + afb_api_t api = afb_req_get_api(request), oapi; + + /* get the action */ + if (!json_object_object_get_ex(json, "action", &x)) { + afb_req_reply(request, NULL, "invalid", "no action"); + goto end; + } + action = json_object_get_string(x); + + /* get the verb */ + verbname = json_object_object_get_ex(json, "verb", &x) ? + json_object_get_string(x) : NULL; + + /* get the pattern */ + pattern = json_object_object_get_ex(json, "pattern", &x) ? + json_object_get_string(x) : NULL; + + /* get the closure */ + closure = NULL; + json_object_object_get_ex(json, "closure", &closure); + + /* get the api */ + if (json_object_object_get_ex(json, "api", &x)) { + apiname = json_object_get_string(x); + sapi = searchapi(apiname, &psapi); + oapi = sapi ? sapi->api : NULL; + } else { + oapi = api; + apiname = afb_api_name(api); + sapi = searchapi(apiname, &psapi); + } + + /* search the sapi */ + if (!strcasecmp(action, "create")) { + if (!apiname) { + afb_req_reply(request, NULL, "invalid", "no api"); + goto end; + } + if (sapi) { + afb_req_reply(request, NULL, "already-exist", NULL); + goto end; + } + sapi = malloc (sizeof * sapi + strlen(apiname)); + if (!sapi) { + afb_req_reply(request, NULL, "out-of-memory", NULL); + goto end; + } + sapi->api = afb_api_new_api(api, apiname, NULL, 1, apipreinit, NULL); + if (!sapi->api) { + afb_req_reply_f(request, NULL, "cant-create", "%m"); + goto end; + } + strcpy(sapi->name, apiname); + sapi->next = NULL; + *psapi = sapi; + } else { + if (!oapi) { + afb_req_reply(request, NULL, "cant-find-api", NULL); + goto end; + } + if (!strcasecmp(action, "destroy")) { + if (!sapi) { + afb_req_reply(request, NULL, "cant-destroy", NULL); + goto end; + } + afb_api_delete_api(oapi); + *psapi = sapi->next; + free(sapi); + } else if (!strcasecmp(action, "addverb")) { + if (!verbname){ + afb_req_reply(request, NULL, "invalid", "no verb"); + goto end; + } + afb_api_add_verb(oapi, verbname, NULL, apiverb, NULL, NULL, 0, !!strchr(verbname, '*')); + } else if (!strcasecmp(action, "delverb")) { + if (!verbname){ + afb_req_reply(request, NULL, "invalid", "no verb"); + goto end; + } + afb_api_del_verb(oapi, verbname, NULL); + } else if (!strcasecmp(action, "addhandler")) { + if (!pattern){ + afb_req_reply(request, NULL, "invalid", "no pattern"); + goto end; + } + afb_api_event_handler_add(oapi, pattern, apievhndl, json_object_get(closure)); + } else if (!strcasecmp(action, "delhandler")) { + if (!pattern){ + afb_req_reply(request, NULL, "invalid", "no pattern"); + goto end; + } + closure = NULL; + afb_api_event_handler_del(oapi, pattern, (void**)&closure); + json_object_put(closure); + } else if (!strcasecmp(action, "seal")) { + afb_api_seal(oapi); + } else { + afb_req_reply_f(request, NULL, "invalid", "unknown action %s", action ?: "NULL"); + goto end; + } + } + afb_req_reply(request, NULL, NULL, NULL); +end: return; +} + +/*************************************************************/ + +static int preinit(afb_api_t api) +{ + AFB_NOTICE("hello binding comes to live"); +#if defined(PREINIT_PROVIDE_CLASS) + afb_api_provide_class(api, PREINIT_PROVIDE_CLASS); +#endif +#if defined(PREINIT_REQUIRE_CLASS) + afb_api_require_class(api, PREINIT_REQUIRE_CLASS); +#endif + return 0; +} + +static int init(afb_api_t api) +{ + AFB_NOTICE("hello binding starting"); +#if defined(INIT_REQUIRE_API) + afb_api_require_api(api, INIT_REQUIRE_API, 1); #endif + afb_api_add_alias(api, api->apiname, "fakename"); + return 0; +} + +static void onevent(afb_api_t api, const char *event, struct json_object *object) +{ + AFB_NOTICE("received event %s(%s)", event, json_object_to_json_string(object)); +} const struct afb_binding_v3 afbBindingV3 = { .api = APINAME, |