diff options
Diffstat (limited to 'src/plugins/plugin-test.c')
-rw-r--r-- | src/plugins/plugin-test.c | 810 |
1 files changed, 810 insertions, 0 deletions
diff --git a/src/plugins/plugin-test.c b/src/plugins/plugin-test.c new file mode 100644 index 0000000..3885c4f --- /dev/null +++ b/src/plugins/plugin-test.c @@ -0,0 +1,810 @@ +/* + * Copyright (c) 2012, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <errno.h> + +#include <murphy/common/macros.h> +#include <murphy/common/json.h> +#include <murphy/core/plugin.h> +#include <murphy/core/console.h> +#include <murphy/core/auth.h> +#include <murphy/core/domain.h> + + +typedef struct { + mrp_event_watch_t *w; +} test_data_t; + + +enum { + ARG_STRING1, + ARG_STRING2, + ARG_BOOLEAN1, + ARG_BOOLEAN2, + ARG_UINT321, + ARG_INT321, + ARG_DOUBLE1, + ARG_FAILINIT, + ARG_FAILEXIT, + ARG_OBJECT, + ARG_REST, +}; + + +void one_cb(mrp_console_t *c, void *user_data, int argc, char **argv); +void two_cb(mrp_console_t *c, void *user_data, int argc, char **argv); +void three_cb(mrp_console_t *c, void *user_data, int argc, char **argv); +void four_cb(mrp_console_t *c, void *user_data, int argc, char **argv); +void resolve_cb(mrp_console_t *c, void *user_data, int argc, char **argv); +void auth_cb(mrp_console_t *c, void *user_data, int argc, char **argv); +void ping_cb(mrp_console_t *c, void *user_data, int argc, char **argv); +void invoke_cb(mrp_console_t *c, void *user_data, int argc, char **argv); + +MRP_CONSOLE_GROUP(test_group, "test", NULL, NULL, { + MRP_TOKENIZED_CMD("one" , one_cb , TRUE, + "one [args]", "command 1", "description 1"), + MRP_TOKENIZED_CMD("two" , two_cb , FALSE, + "two [args]", "command 2", "description 2"), + MRP_TOKENIZED_CMD("three", three_cb, FALSE, + "three [args]", "command 3", "description 3"), + MRP_TOKENIZED_CMD("four" , four_cb , TRUE, + "four [args]", "command 4", "description 4"), + MRP_TOKENIZED_CMD("update" , resolve_cb , TRUE, + "update <target>", "update target", "update target"), + MRP_TOKENIZED_CMD("auth-test", auth_cb, TRUE, + "auth-test [@backend] target mode id [token]", + "test authentication", "test authentication"), + MRP_TOKENIZED_CMD("ping", ping_cb, FALSE, + "ping domain", + "ping the given domain", "ping a domain"), + MRP_TOKENIZED_CMD("invoke", invoke_cb, TRUE, + "invoke domain method [ərguments]", + "invoke the given domain method", + "invoke a domain method") +}); + + +void one_cb(mrp_console_t *c, void *user_data, int argc, char **argv) +{ + int i; + + MRP_UNUSED(c); + MRP_UNUSED(user_data); + + for (i = 0; i < argc; i++) { + printf("%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]); + } +} + + +void two_cb(mrp_console_t *c, void *user_data, int argc, char **argv) +{ + int i; + + MRP_UNUSED(c); + MRP_UNUSED(user_data); + + for (i = 0; i < argc; i++) { + printf("%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]); + } +} + + +void three_cb(mrp_console_t *c, void *user_data, int argc, char **argv) +{ + int i; + + MRP_UNUSED(c); + MRP_UNUSED(user_data); + + for (i = 0; i < argc; i++) { + printf("%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]); + } +} + + +void four_cb(mrp_console_t *c, void *user_data, int argc, char **argv) +{ + int i; + + MRP_UNUSED(c); + MRP_UNUSED(user_data); + + for (i = 0; i < argc; i++) { + printf("%s(): #%d: '%s'\n", __FUNCTION__, i, argv[i]); + } +} + + +void resolve_cb(mrp_console_t *c, void *user_data, int argc, char **argv) +{ + mrp_context_t *ctx = c->ctx; + const char *target; + + MRP_UNUSED(c); + MRP_UNUSED(user_data); + + if (argc == 3) { + target = argv[2]; + + if (ctx->r != NULL) { + if (mrp_resolver_update_target(ctx->r, target, NULL) > 0) + printf("'%s' updated OK.\n", target); + else + printf("Failed to update '%s'.\n", target); + } + else + printf("Resolver/ruleset is not available.\n"); + } + else { + printf("Usage: %s %s <target-name>\n", argv[0], argv[1]); + } +} + + +void auth_cb(mrp_console_t *c, void *user_data, int argc, char **argv) +{ + mrp_context_t *ctx = c->ctx; + const char *backend, *target, *id, *token, *p; + int idx, mode, status; + + MRP_UNUSED(user_data); + + if (argc < 4) { + error: + printf("Usage: %s %s [@backend] target mode id [token]\n", argv[0], + argv[1]); + return; + } + + if (argv[2][0] == '@') { + if (argc < 5) + goto error; + + backend = argv[2] + 1; + idx = 3; + } + else { + backend = NULL; + idx = 2; + } + + target = argv[idx++]; + + p = argv[idx++]; + + for (mode = 0; *p; p++) { + switch(*p) { + case 'r': mode |= MRP_AUTH_MODE_READ; break; + case 'w': mode |= MRP_AUTH_MODE_WRITE; break; + case 'x': mode |= MRP_AUTH_MODE_EXEC; break; + case '-': break; + default: + printf("Invalid character '%c' in mode.\n", *p); + goto error; + } + } + + if (mode == 0) + mode = MRP_AUTH_MODE_READ; + + id = argv[idx++]; + + if (idx >= argc - 1) + token = NULL; + else { + if (idx == argc - 1) + token = argv[idx]; + else + goto error; + } + + status = mrp_authenticate(ctx, backend, target, mode, id, token); + + printf("authentication status: %d\n", status); +} + + +void pong_cb(int error, int retval, int narg, mrp_domctl_arg_t *args, + void *user_data) +{ + mrp_console_t *c = (mrp_console_t *)user_data; + int i; + + MRP_UNUSED(c); + + if (error) { + printf("ping failed with error code %d\n", error); + } + + printf("pong (return value %d)\n", retval); + + for (i = 0; i < narg; i++) { + switch (args[i].type) { + case MRP_DOMCTL_STRING: + printf(" #%d: %s\n", i, args[i].str); + break; + case MRP_DOMCTL_UINT32: + printf(" #%d: %u\n", i, args[i].u32); + break; + default: + if (MRP_DOMCTL_IS_ARRAY(args[i].type)) { + uint32_t j; + + printf(" #%d: array of %u items:\n", i, args[i].size); + for (j = 0; j < args[i].size; j++) { + switch (MRP_DOMCTL_ARRAY_TYPE(args[i].type)) { + case MRP_DOMCTL_STRING: + printf(" #%d: '%s'\n", j, + ((char **)args[i].arr)[j]); + break; + case MRP_DOMCTL_UINT32: + printf(" #%d: %u\n", j, + ((uint32_t *)args[i].arr)[j]); + break; + default: + printf(" #%d: <type 0x%x\n", j, + MRP_DOMCTL_ARRAY_TYPE(args[i].type)); + break; + } + } + } + else + printf(" <type 0x%x>\n", args[i].type); + } + } +} + + +void ping_cb(mrp_console_t *c, void *user_data, int argc, char **argv) +{ + static uint32_t cnt = 1; + const char *domain; + char *strings[] = { "foo", "bar", "foobar", "barfoo" }; + uint32_t uints[] = { 69, 96, 696, 969 }; + mrp_domctl_arg_t args[32]; + int narg, i; + + MRP_UNUSED(user_data); + + if (argc < 3) { + printf("Usage: %s domain\n", argv[0]); + return; + } + + domain = argv[2]; + narg = MRP_ARRAY_SIZE(args); + + args[0].type = MRP_DOMCTL_UINT32; + args[0].u32 = cnt++; + args[1].type = MRP_DOMCTL_ARRAY(STRING); + args[1].arr = strings; + args[1].size = MRP_ARRAY_SIZE(strings); + args[2].type = MRP_DOMCTL_ARRAY(UINT32); + args[2].arr = uints; + args[2].size = MRP_ARRAY_SIZE(uints); + + for (i = 3; i < narg; i++) { + if (i + 2 < argc) { + args[i].type = MRP_DOMCTL_STRING; + args[i].str = argv[i + 2]; + } + else { + args[i].type = MRP_DOMCTL_UINT32; + args[i].u32 = i; + } + } + + if (!mrp_invoke_domain(c->ctx, domain, "ping", narg, args, pong_cb, c)) + printf("Failed to ping domain '%s'.\n", domain); +} + + +void invoke_reply(int error, int retval, int narg, mrp_domctl_arg_t *args, + void *user_data) +{ + mrp_console_t *c = (mrp_console_t *)user_data; + int i; + + if (error) { + mrp_console_printf(c, "invoked method failed with error code %d\n", + error); + return; + } + + mrp_console_printf(c, "invoked method returned (return value %d)\n", retval); + + for (i = 0; i < narg; i++) { + switch (args[i].type) { + case MRP_DOMCTL_STRING: + mrp_console_printf(c, " #%d: %s\n", i, args[i].str); + break; + case MRP_DOMCTL_UINT16: + mrp_console_printf(c, " #%d: %u\n", i, args[i].u16); + break; + case MRP_DOMCTL_INT16: + mrp_console_printf(c, " #%d: %u\n", i, args[i].s16); + break; + case MRP_DOMCTL_UINT32: + mrp_console_printf(c, " #%d: %u\n", i, args[i].u32); + break; + case MRP_DOMCTL_INT32: + mrp_console_printf(c, " #%d: %u\n", i, args[i].s32); + break; + default: + mrp_console_printf(c, " #%d: <type 0x%x\n", i, args[i].type); + break; + } + } +} + + +void invoke_cb(mrp_console_t *c, void *user_data, int argc, char **argv) +{ + const char *domain, *method, *type, *value; + mrp_domctl_arg_t args[32]; + int tlen, narg, i; + + MRP_UNUSED(user_data); + + if (argc < 4) { + printf("Usage: %s %s <domain> <method> [args]\n", argv[0], argv[1]); + return; + } + + domain = argv[2]; + method = argv[3]; + narg = MRP_ARRAY_SIZE(args); + + for (i = 4, narg = 0; + i < argc && narg < (int)MRP_ARRAY_SIZE(args); + i++, narg++) { + type = argv[i]; + value = strchr(type, ':'); + + if (value == NULL) { + value = type; + type = "string"; + tlen = 6; + } + else { + tlen = value - type; + value++; + } + + if (!strncmp(type, "string", tlen)) { + args[narg].type = MRP_DOMCTL_STRING; + args[narg].str = value; + } + else if (!strncmp(type, "u16" , tlen) || + !strncmp(type, "uint16_t", tlen)) { + args[narg].type = MRP_DOMCTL_UINT16; + args[narg].u16 = (uint16_t)strtoul(value, NULL, 0); + } + else if (!strncmp(type, "u16" , tlen) || + !strncmp(type, "uint16_t", tlen)) { + args[narg].type = MRP_DOMCTL_INT16; + args[narg].s16 = (int16_t)strtol(value, NULL, 0); + } + else if (!strncmp(type, "u32" , tlen) || + !strncmp(type, "uint32_t", tlen)) { + args[narg].type = MRP_DOMCTL_UINT32; + args[narg].u32 = (uint32_t)strtoul(value, NULL, 0); + } + else if (!strncmp(type, "u32" , tlen) || + !strncmp(type, "uint32_t", tlen)) { + args[narg].type = MRP_DOMCTL_INT32; + args[narg].s32 = (int32_t)strtol(value, NULL, 0); + } + else { + printf("invalid typecast in %s\n", argv[i]); + return; + } + } + + printf("Invoking domain method '%s.%s' with %d args...\n", domain, method, + narg); + + if (!mrp_invoke_domain(c->ctx, domain, method, narg, args, invoke_reply, c)) + printf("Failed to invoke '%s.%s'.\n", domain, method); +} + + +MRP_EXPORTABLE(char *, method1, (int arg1, char *arg2, double arg3)) +{ + MRP_UNUSED(arg1); + MRP_UNUSED(arg2); + MRP_UNUSED(arg3); + + mrp_log_info("%s()...", __FUNCTION__); + + return "method1 was here..."; +} + +static int boilerplate1(mrp_plugin_t *plugin, + const char *name, mrp_script_env_t *env) +{ + MRP_UNUSED(plugin); + MRP_UNUSED(name); + MRP_UNUSED(env); + + method1(1, "foo", 9.81); + + return TRUE; +} + +MRP_EXPORTABLE(int, method2, (char *arg1, double arg2, int arg3)) +{ + MRP_UNUSED(arg1); + MRP_UNUSED(arg2); + MRP_UNUSED(arg3); + + mrp_log_info("%s()...", __FUNCTION__); + + return 313; +} + +static int boilerplate2(mrp_plugin_t *plugin, + const char *name, mrp_script_env_t *env) +{ + MRP_UNUSED(plugin); + MRP_UNUSED(name); + MRP_UNUSED(env); + + return -1; +} + + +MRP_IMPORTABLE(char *, method1ptr, (int arg1, char *arg2, double arg3)); +MRP_IMPORTABLE(int, method2ptr, (char *arg1, double arg2, int arg3)); + +#if 0 +static int export_methods(mrp_plugin_t *plugin) +{ + mrp_method_descr_t methods[] = { + { "method1", "char *(int arg1, char *arg2, double arg3)", + method1, boilerplate1, plugin }, + { "method2", "int (char *arg1, double arg2, int arg3)", + method2, boilerplate2, plugin }, + { NULL, NULL, NULL, NULL, NULL } + }; + mrp_method_descr_t *m; + + for (m = methods; m->name != NULL; m++) + if (mrp_export_method(m) < 0) + return FALSE; + else + mrp_log_info("Successfully exported method '%s'...", m->name); + + return TRUE; +} + + +static int remove_methods(mrp_plugin_t *plugin) +{ + mrp_method_descr_t methods[] = { + { "method1", "char *(int arg1, char *arg2, double arg3)", + method1, boilerplate1, plugin }, + { "method2", "int (char *arg1, double arg2, int arg3)", + method2, boilerplate2, plugin }, + { NULL, NULL, NULL, NULL, NULL } + }; + mrp_method_descr_t *m; + + for (m = methods; m->name != NULL; m++) + if (mrp_remove_method(m) < 0) + mrp_log_info("Failed to remove method '%s'...", m->name); + else + mrp_log_info("Failed to remove method '%s'...", m->name); + + return TRUE; +} + + +static int import_methods(mrp_plugin_t *plugin) +{ + mrp_method_descr_t methods[] = { + { "method1", "char *(int arg1, char *arg2, double arg3)", + method1, boilerplate1, plugin }, + { "method2", "int (char *arg1, double arg2, int arg3)", + method2, boilerplate2, plugin }, + { NULL, NULL, NULL, NULL, NULL } + }; + + void *native_check[] = { method1, method2 }; + void *script_check[] = { boilerplate1, boilerplate2 }; + int i; + + mrp_method_descr_t *m; + + const char *name, *sig; + char buf[512]; + void *native; + int (*script)(mrp_plugin_t *, const char *, mrp_script_env_t *); + + for (i = 0, m = methods; m->name != NULL; i++, m++) { + name = m->name; + sig = m->signature; + + if (mrp_import_method(name, sig, &native, &script) < 0) + return FALSE; + + if (native != native_check[i] || script != script_check[i]) + return FALSE; + + mrp_log_info("%s imported as %p, %p...", name, native, script); + + snprintf(buf, sizeof(buf), "%s.%s", plugin->instance, m->name); + name = buf; + + if (mrp_import_method(name, sig, &native, &script) < 0) + return FALSE; + + if (native != native_check[i] || script != script_check[i]) + return FALSE; + + mrp_log_info("%s imported as %p, %p...", name, native, script); + } + + return TRUE; +} + + +static int release_methods(mrp_plugin_t *plugin) +{ + mrp_method_descr_t methods[] = { + { "method1", "char *(int arg1, char *arg2, double arg3)", + method1, boilerplate1, plugin }, + { "method2", "int (char *arg1, double arg2, int arg3)", + method2, boilerplate2, plugin }, + { NULL, NULL, NULL, NULL, NULL } + }; + const char *name, *sig; + char buf[512]; + mrp_method_descr_t *m; + void *native, *natives[] = { method1 , method2 }; + int (*script)(mrp_plugin_t *, const char *, mrp_script_env_t *); + void *scripts[] = { boilerplate1, boilerplate2 }; + int i; + + for (i = 0, m = methods; m->name != NULL; i++, m++) { + name = m->name; + sig = m->signature; + native = natives[i]; + script = scripts[i]; + + if (mrp_release_method(name, sig, &native, &script) < 0) + mrp_log_error("Failed to release method '%s'...", name); + else + mrp_log_info("Successfully released method '%s'...", name); + + snprintf(buf, sizeof(buf), "%s.%s", plugin->instance, m->name); + name = buf; + native = natives[i]; + script = scripts[i]; + + if (mrp_release_method(name, sig, &native, &script) < 0) + mrp_log_error("Failed to release method '%s'...", name); + else + mrp_log_info("Successfully released method '%s'...", name); + } + + return TRUE; +} + +#endif + +int test_imports(void) +{ + if (method1ptr == NULL || method2ptr == NULL) { + mrp_log_error("Failed to import methods..."); + return FALSE; + } + + mrp_log_info("method1ptr returned '%s'...", method1ptr(1, "foo", 3.141)); + mrp_log_info("method2ptr returned '%d'...", method2ptr("bar", 9.81, 2)); + + return TRUE; +} + + +static void event_cb(mrp_event_watch_t *w, uint32_t id, int format, + void *event_data, void *user_data) +{ + mrp_plugin_t *plugin = (mrp_plugin_t *)user_data; + + MRP_UNUSED(w); + MRP_UNUSED(format); + + mrp_log_info("%s: got event 0x%x (%s):", plugin->instance, id, + mrp_event_name(id)); + mrp_msg_dump(event_data, stdout); +} + + +static int subscribe_events(mrp_plugin_t *plugin) +{ + mrp_mainloop_t *ml = plugin->ctx->ml; + mrp_event_bus_t *bus = mrp_event_bus_get(ml, MRP_PLUGIN_BUS); + test_data_t *data = (test_data_t *)plugin->data; + mrp_event_mask_t events = MRP_MASK_EMPTY; + + + mrp_mask_set(&events, mrp_event_id(MRP_PLUGIN_EVENT_LOADED)); + mrp_mask_set(&events, mrp_event_id(MRP_PLUGIN_EVENT_STARTED)); + mrp_mask_set(&events, mrp_event_id(MRP_PLUGIN_EVENT_FAILED)); + mrp_mask_set(&events, mrp_event_id(MRP_PLUGIN_EVENT_STOPPING)); + mrp_mask_set(&events, mrp_event_id(MRP_PLUGIN_EVENT_STOPPED)); + mrp_mask_set(&events, mrp_event_id(MRP_PLUGIN_EVENT_UNLOADED)); + + data->w = mrp_event_add_watch_mask(bus, &events, event_cb, plugin); + + return (data->w != NULL); +} + + +static void unsubscribe_events(mrp_plugin_t *plugin) +{ + test_data_t *data = (test_data_t *)plugin->data; + + mrp_event_del_watch(data->w); + data->w = NULL; +} + + +static int test_init(mrp_plugin_t *plugin) +{ + mrp_plugin_arg_t *args, *arg; + mrp_json_t *json; + test_data_t *data; + + mrp_log_info("%s() called for test instance '%s'...", __FUNCTION__, + plugin->instance); + + args = plugin->args; + json = args[ARG_OBJECT].obj.json; + printf(" string1: %s\n", args[ARG_STRING1].str); + printf(" string2: %s\n", args[ARG_STRING2].str); + printf("boolean1: %s\n", args[ARG_BOOLEAN1].bln ? "TRUE" : "FALSE"); + printf("boolean2: %s\n", args[ARG_BOOLEAN2].bln ? "TRUE" : "FALSE"); + printf(" uint32: %u\n", args[ARG_UINT321].u32); + printf(" int32: %d\n", args[ARG_INT321].i32); + printf(" double: %f\n", args[ARG_DOUBLE1].dbl); + printf("init fail: %s\n", args[ARG_FAILINIT].bln ? "TRUE" : "FALSE"); + printf("exit fail: %s\n", args[ARG_FAILEXIT].bln ? "TRUE" : "FALSE"); + printf(" object: %s\n", mrp_json_object_to_string(json)); + + mrp_plugin_foreach_undecl_arg(&args[ARG_REST], arg) { + mrp_log_info("got argument %s of type 0x%x", arg->key, arg->type); + } + + { + char *rkeys[] = { "foo", "bar", "foobar", "barfoo", NULL }; + int i; + + for (i = 0; rkeys[i] != NULL; i++) { + arg = mrp_plugin_find_undecl_arg(&args[ARG_REST], rkeys[i], 0); + + if (arg != NULL) + mrp_log_info("found undeclared arg '%s' (type 0x%x)", arg->key, + arg->type); + else + mrp_log_info("undeclared arg '%s' not found", rkeys[i]); + } + } + + +#if 0 + if (!export_methods(plugin)) + return FALSE; + + if (!import_methods(plugin)) + return FALSE; +#endif + + data = mrp_allocz(sizeof(*data)); + + if (data == NULL) { + mrp_log_error("Failed to allocate private data for test plugin " + "instance %s.", plugin->instance); + return FALSE; + } + else + plugin->data = data; + + test_imports(); + + subscribe_events(plugin); + + return !args[ARG_FAILINIT].bln; +} + + +static void test_exit(mrp_plugin_t *plugin) +{ + mrp_log_info("%s() called for test instance '%s'...", __FUNCTION__, + plugin->instance); + + unsubscribe_events(plugin); + +#if 0 + release_methods(plugin); + remove_methods(plugin); +#endif + + /*return !args[ARG_FAILINIT].bln;*/ +} + + +#define TEST_DESCRIPTION "A primitive plugin just to test the plugin infra." +#define TEST_HELP "Just a load/unload test." +#define TEST_VERSION MRP_VERSION_INT(0, 0, 1) +#define TEST_AUTHORS "D. Duck <donald.duck@ducksburg.org>" + +#define DEFAULT_OBJECT "{\n" \ + " 'foo': 'this is json.foo',\n" \ + " 'bar': 'this is json.bar',\n" \ + " 'one': 1,\n" \ + " 'two': 2,\n" \ + " 'pi': 3.141,\n" \ + " 'array': [ 1, 2, 'three', 'four', 5 ]\n" \ + "}\n" + +static mrp_plugin_arg_t args[] = { + MRP_PLUGIN_ARGIDX(ARG_STRING1 , STRING, "string1" , "default string1"), + MRP_PLUGIN_ARGIDX(ARG_STRING2 , STRING, "string2" , "default string2"), + MRP_PLUGIN_ARGIDX(ARG_BOOLEAN1, BOOL , "boolean1", TRUE ), + MRP_PLUGIN_ARGIDX(ARG_BOOLEAN2, BOOL , "boolean2", FALSE ), + MRP_PLUGIN_ARGIDX(ARG_UINT321 , UINT32, "uint32" , 3141 ), + MRP_PLUGIN_ARGIDX(ARG_INT321 , INT32 , "int32" , -3141 ), + MRP_PLUGIN_ARGIDX(ARG_DOUBLE1 , DOUBLE, "double" , -3.141 ), + MRP_PLUGIN_ARGIDX(ARG_FAILINIT, BOOL , "failinit", FALSE ), + MRP_PLUGIN_ARGIDX(ARG_FAILEXIT, BOOL , "failexit", FALSE ), + MRP_PLUGIN_ARGIDX(ARG_OBJECT , OBJECT, "object" , DEFAULT_OBJECT ), + MRP_PLUGIN_ARGIDX(ARG_REST , UNDECL, NULL , NULL ), +}; + +static mrp_method_descr_t exports[] = { + MRP_GENERIC_METHOD("method1", method1, boilerplate1), + MRP_GENERIC_METHOD("method2", method2, boilerplate2), +}; + +static mrp_method_descr_t imports[] = { + MRP_IMPORT_METHOD("method1", method1ptr), + MRP_IMPORT_METHOD("method2", method2ptr), +}; + + +MURPHY_REGISTER_PLUGIN("test", + TEST_VERSION, TEST_DESCRIPTION, TEST_AUTHORS, TEST_HELP, + MRP_MULTIPLE, test_init, test_exit, + args, MRP_ARRAY_SIZE(args), + exports, MRP_ARRAY_SIZE(exports), + imports, MRP_ARRAY_SIZE(imports), + &test_group); |