df7bbc094f
Fix bug #185 - Args of !commands lost/damaged. All string arguments were incorrectly freed after being added to the argument list for a command. Instead this fix makes sure it is properly copied into a new string, and by doing so this requires a new API for dealing with hub command arguments in a type safe manner, and also allows for each argument to be cleaned up properly when the command is no longer needed. This also fixes issues with parse errors for certain types, and optional arguments (previously it was impossible to tell the difference for an integer with value 0 or if no integer was given). All arguments can now be accessed through the new functions hub_command_arg_reset() and hub_command_arg_next(). These functions are also exposed to plug-ins. The argument type notations for 'n' has changed to mean nick (string), and 'u' is used for a user (struct hub_user - must be online).
232 lines
8.1 KiB
C++
232 lines
8.1 KiB
C++
#include <uhub.h>
|
|
|
|
static struct hub_info* hub = NULL;
|
|
static struct hub_user user;
|
|
static struct command_base* cbase = NULL;
|
|
static struct command_handle* c_test1 = NULL;
|
|
static struct command_handle* c_test2 = NULL;
|
|
static struct command_handle* c_test3 = NULL;
|
|
static struct command_handle* c_test4 = NULL;
|
|
static struct command_handle* c_test5 = NULL;
|
|
static struct command_handle* c_test6 = NULL;
|
|
static struct command_handle* c_test7 = NULL;
|
|
|
|
// for results:
|
|
static int result = 0;
|
|
|
|
EXO_TEST(setup, {
|
|
hub = hub_malloc_zero(sizeof(struct hub_info));
|
|
cbase = command_initialize(hub);
|
|
return cbase && hub && uman_init(hub) == 0;
|
|
});
|
|
|
|
static int test_handler(struct command_base* cbase, struct hub_user* user, struct hub_command* hcmd)
|
|
{
|
|
printf("test_handler\n");
|
|
result = 1;
|
|
return 0;
|
|
}
|
|
|
|
static struct command_handle* create_handler(const char* prefix, const char* args, enum auth_credentials cred)
|
|
{
|
|
struct command_handle* c = hub_malloc_zero(sizeof(struct command_handle));
|
|
c->prefix = prefix;
|
|
c->length = strlen(prefix);
|
|
c->args = args;
|
|
c->cred = cred;
|
|
c->handler = test_handler;
|
|
c->description = "A handler added by autotest.";
|
|
c->origin = "exotic test";
|
|
c->ptr = &c->ptr;
|
|
return c;
|
|
}
|
|
|
|
EXO_TEST(command_setup_user, {
|
|
memset(&user, 0, sizeof(user));
|
|
user.id.sid = 1;
|
|
strcpy(user.id.nick, "tester");
|
|
strcpy(user.id.cid, "3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY");
|
|
user.credentials = auth_cred_guest;
|
|
return 1;
|
|
});
|
|
|
|
#define ADD_TEST(var, prefix, args, cred) \
|
|
var = create_handler(prefix, args, cred); \
|
|
if (!command_add(cbase, var, NULL)) \
|
|
return 0;
|
|
|
|
#define DEL_TEST(var) \
|
|
if (var) \
|
|
{ \
|
|
if (!command_del(cbase, var)) \
|
|
return 0; \
|
|
hub_free(var); \
|
|
var = NULL; \
|
|
}
|
|
|
|
EXO_TEST(command_create, {
|
|
ADD_TEST(c_test1, "test1", "", auth_cred_guest);
|
|
ADD_TEST(c_test2, "test2", "", auth_cred_operator);
|
|
ADD_TEST(c_test3, "test3", "N?N?N", auth_cred_guest);
|
|
ADD_TEST(c_test4, "test4", "u", auth_cred_guest);
|
|
ADD_TEST(c_test5, "test5", "i", auth_cred_guest);
|
|
ADD_TEST(c_test6, "test6", "?c", auth_cred_guest);
|
|
ADD_TEST(c_test6, "test7", "C", auth_cred_guest);
|
|
return 1;
|
|
});
|
|
|
|
extern void command_destroy(struct hub_command* cmd);
|
|
|
|
static int verify(const char* str, enum command_parse_status expected)
|
|
{
|
|
struct hub_command* cmd = command_parse(cbase, &user, str);
|
|
enum command_parse_status status = cmd->status;
|
|
command_free(cmd);
|
|
return status == expected;
|
|
}
|
|
|
|
static struct hub_command_arg_data* verify_argument(struct hub_command* cmd, enum hub_command_arg_type type)
|
|
{
|
|
return hub_command_arg_next(cmd, type);
|
|
}
|
|
|
|
static int verify_arg_integer(struct hub_command* cmd, int expected)
|
|
{
|
|
struct hub_command_arg_data* data = verify_argument(cmd, type_integer);
|
|
return data->data.integer == expected;
|
|
}
|
|
|
|
static int verify_arg_user(struct hub_command* cmd, struct hub_user* expected)
|
|
{
|
|
struct hub_command_arg_data* data = verify_argument(cmd, type_user);
|
|
return data->data.user == expected;
|
|
}
|
|
|
|
static int verify_arg_cred(struct hub_command* cmd, enum auth_credentials cred)
|
|
{
|
|
struct hub_command_arg_data* data = verify_argument(cmd, type_credentials);
|
|
return data->data.credentials == cred;
|
|
}
|
|
|
|
|
|
EXO_TEST(command_access_1, { return verify("!test1", cmd_status_ok); });
|
|
EXO_TEST(command_access_2, { return verify("!test2", cmd_status_access_error); });
|
|
EXO_TEST(command_access_3, { user.credentials = auth_cred_operator; return verify("!test2", cmd_status_ok); });
|
|
|
|
EXO_TEST(command_syntax_1, { return verify("", cmd_status_syntax_error); });
|
|
EXO_TEST(command_syntax_2, { return verify("!", cmd_status_syntax_error); });
|
|
|
|
EXO_TEST(command_missing_args_1, { return verify("!test3", cmd_status_missing_args); });
|
|
EXO_TEST(command_missing_args_2, { return verify("!test3 12345", cmd_status_ok); });
|
|
EXO_TEST(command_missing_args_3, { return verify("!test3 1 2 345", cmd_status_ok); });
|
|
EXO_TEST(command_number_1, { return verify("!test3 abc", cmd_status_arg_number); });
|
|
EXO_TEST(command_number_2, { return verify("!test3 -", cmd_status_arg_number); });
|
|
EXO_TEST(command_number_3, { return verify("!test3 -12", cmd_status_ok); });
|
|
|
|
EXO_TEST(command_user_1, { return verify("!test4 tester", cmd_status_arg_nick); });
|
|
EXO_TEST(command_user_2, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_arg_cid); });
|
|
EXO_TEST(command_user_3, { return uman_add(hub, &user) == 0; });
|
|
EXO_TEST(command_user_4, { return verify("!test4 tester", cmd_status_ok); });
|
|
EXO_TEST(command_user_5, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_ok); });
|
|
|
|
EXO_TEST(command_command_1, { return verify("!test6 test1", cmd_status_ok); });
|
|
EXO_TEST(command_command_2, { return verify("!test6 test2", cmd_status_ok); });
|
|
EXO_TEST(command_command_3, { return verify("!test6 test3", cmd_status_ok); });
|
|
EXO_TEST(command_command_4, { return verify("!test6 test4", cmd_status_ok); });
|
|
EXO_TEST(command_command_5, { return verify("!test6 test5", cmd_status_ok); });
|
|
EXO_TEST(command_command_6, { return verify("!test6 test6", cmd_status_ok); });
|
|
EXO_TEST(command_command_7, { return verify("!test6 fail", cmd_status_arg_command); });
|
|
EXO_TEST(command_command_8, { return verify("!test6", cmd_status_ok); });
|
|
|
|
EXO_TEST(command_cred_1, { return verify("!test7 guest", cmd_status_ok); });
|
|
EXO_TEST(command_cred_2, { return verify("!test7 user", cmd_status_ok); });
|
|
EXO_TEST(command_cred_3, { return verify("!test7 operator", cmd_status_ok); });
|
|
EXO_TEST(command_cred_4, { return verify("!test7 super", cmd_status_ok); });
|
|
EXO_TEST(command_cred_5, { return verify("!test7 admin", cmd_status_ok); });
|
|
EXO_TEST(command_cred_6, { return verify("!test7 nobody", cmd_status_arg_cred); });
|
|
EXO_TEST(command_cred_7, { return verify("!test7 bot", cmd_status_ok); });
|
|
EXO_TEST(command_cred_8, { return verify("!test7 link", cmd_status_ok); });
|
|
|
|
|
|
#if 0
|
|
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
|
|
};
|
|
#endif
|
|
|
|
// command not found
|
|
EXO_TEST(command_parse_3, { return verify("!fail", cmd_status_not_found); });
|
|
|
|
// built-in command
|
|
EXO_TEST(command_parse_4, { return verify("!help", cmd_status_ok); });
|
|
|
|
|
|
EXO_TEST(command_argument_integer_1, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test3");
|
|
return verify_argument(cmd, type_integer) == NULL;
|
|
});
|
|
|
|
EXO_TEST(command_argument_integer_2, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test3 10 42");
|
|
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_argument(cmd, type_integer) == NULL;
|
|
});
|
|
|
|
EXO_TEST(command_argument_integer_3, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test3 10 42 6784");
|
|
return verify_arg_integer(cmd, 10) && verify_arg_integer(cmd, 42) && verify_arg_integer(cmd, 6784);
|
|
});
|
|
|
|
EXO_TEST(command_argument_user_1, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test4 tester");
|
|
return verify_arg_user(cmd, &user) ;
|
|
});
|
|
|
|
EXO_TEST(command_argument_cid_1, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY");
|
|
return verify_arg_user(cmd, &user) ;
|
|
});
|
|
|
|
EXO_TEST(command_argument_cred_1, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test7 admin");
|
|
return verify_arg_cred(cmd, auth_cred_admin);;
|
|
});
|
|
|
|
EXO_TEST(command_argument_cred_2, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test7 op");
|
|
return verify_arg_cred(cmd, auth_cred_operator);;
|
|
});
|
|
|
|
EXO_TEST(command_argument_cred_3, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test7 operator");
|
|
return verify_arg_cred(cmd, auth_cred_operator);
|
|
});
|
|
|
|
EXO_TEST(command_argument_cred_4, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test7 super");
|
|
return verify_arg_cred(cmd, auth_cred_super);
|
|
});
|
|
|
|
EXO_TEST(command_argument_cred_5, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test7 guest");
|
|
return verify_arg_cred(cmd, auth_cred_guest);
|
|
});
|
|
|
|
EXO_TEST(command_argument_cred_6, {
|
|
struct hub_command* cmd = command_parse(cbase, &user, "!test7 user");
|
|
return verify_arg_cred(cmd, auth_cred_user);
|
|
});
|
|
|
|
|
|
EXO_TEST(command_user_destroy, { return uman_remove(hub, &user) == 0; });
|
|
|
|
EXO_TEST(command_destroy, {
|
|
|
|
DEL_TEST(c_test1);
|
|
DEL_TEST(c_test2);
|
|
DEL_TEST(c_test3);
|
|
DEL_TEST(c_test4);
|
|
DEL_TEST(c_test5);
|
|
DEL_TEST(c_test6);
|
|
DEL_TEST(c_test7);
|
|
return 1;
|
|
});
|