mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 05:09:43 +00:00
Redesign the REvent API ##api
This commit is contained in:
parent
face0fc5df
commit
89faa9a7a2
@ -1,8 +1,6 @@
|
||||
/* radare - LGPL - Copyright 2018 - thestr4ng3r */
|
||||
/* radare - LGPL - Copyright 2018-2024 - thestr4ng3r */
|
||||
|
||||
#include <r_anal.h>
|
||||
#include <r_vector.h>
|
||||
#include <r_util.h>
|
||||
|
||||
static void r_anal_class_base_delete_class(RAnal *anal, const char *class_name);
|
||||
static void r_anal_class_method_delete_class(RAnal *anal, const char *class_name);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2018 - pancake */
|
||||
/* radare - LGPL - Copyright 2018-2024 - pancake */
|
||||
|
||||
#ifndef R_EVENT_H
|
||||
#define R_EVENT_H
|
||||
@ -8,37 +8,181 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sdb/ht_up.h>
|
||||
#include <r_vector.h>
|
||||
|
||||
typedef struct r_event_t {
|
||||
void *user;
|
||||
bool incall;
|
||||
HtUP *callbacks;
|
||||
RVector all_callbacks;
|
||||
int next_handle;
|
||||
} REvent;
|
||||
|
||||
typedef struct r_event_callback_handle_t {
|
||||
int handle;
|
||||
int type;
|
||||
} REventCallbackHandle;
|
||||
|
||||
typedef void (*REventCallback)(REvent *ev, int type, void *user, void *data);
|
||||
#include <r_vec.h>
|
||||
|
||||
typedef enum {
|
||||
R_EVENT_ALL = 0,
|
||||
R_EVENT_META_SET, // REventMeta
|
||||
R_EVENT_META_DEL, // REventMeta
|
||||
R_EVENT_META_CLEAR, // REventMeta
|
||||
R_EVENT_CLASS_NEW, // REventClass
|
||||
R_EVENT_CLASS_DEL, // REventClass
|
||||
R_EVENT_CLASS_RENAME, // REventClassRename
|
||||
R_EVENT_CLASS_ATTR_SET, // REventClassAttr
|
||||
R_EVENT_CLASS_ATTR_DEL, // REventClassAttrSet
|
||||
R_EVENT_CLASS_ATTR_RENAME, // REventClassAttrRename
|
||||
R_EVENT_DEBUG_PROCESS_FINISHED, // REventDebugProcessFinished
|
||||
R_EVENT_IO_WRITE, // REventIOWrite
|
||||
R_EVENT_MAX,
|
||||
R_EVENT_META_SET,
|
||||
R_EVENT_META_DEL,
|
||||
R_EVENT_META_CLEAR,
|
||||
R_EVENT_CLASS_NEW,
|
||||
R_EVENT_CLASS_DEL,
|
||||
R_EVENT_CLASS_RENAME,
|
||||
R_EVENT_CLASS_ATTR_SET,
|
||||
R_EVENT_CLASS_ATTR_DEL,
|
||||
R_EVENT_CLASS_ATTR_RENAME,
|
||||
R_EVENT_DEBUG_PROCESS_FINISHED,
|
||||
|
||||
R_EVENT_ANALYSIS_START,
|
||||
R_EVENT_ANALYSIS_END,
|
||||
R_EVENT_ANALYSIS_FUNCTION_ADDED,
|
||||
R_EVENT_ANALYSIS_BLOCK_ADDED,
|
||||
R_EVENT_ANALYSIS_BLOCK_REMOVED,
|
||||
|
||||
R_EVENT_DEBUG_START,
|
||||
R_EVENT_DEBUG_STOP,
|
||||
R_EVENT_DEBUG_STEP,
|
||||
R_EVENT_DEBUG_BREAKPOINT_HIT,
|
||||
R_EVENT_DEBUG_EXCEPTION,
|
||||
|
||||
R_EVENT_IO_READ,
|
||||
R_EVENT_IO_WRITE,
|
||||
R_EVENT_IO_OPEN,
|
||||
R_EVENT_IO_CLOSE,
|
||||
|
||||
R_EVENT_PLUGIN_LOAD,
|
||||
R_EVENT_PLUGIN_UNLOAD,
|
||||
|
||||
R_EVENT_SEARCH_START,
|
||||
R_EVENT_SEARCH_END,
|
||||
R_EVENT_SEARCH_HIT,
|
||||
|
||||
R_EVENT_CHILD_SYSCALL,
|
||||
R_EVENT_CHILD_SIGNAL_RECEIVED,
|
||||
|
||||
R_EVENT_BINARY_START,
|
||||
R_EVENT_BINARY_LOADED,
|
||||
|
||||
R_EVENT_IO_MAP_ADDED,
|
||||
R_EVENT_IO_MAP_REMOVED,
|
||||
R_EVENT_MEMORY_ACCESS_VIOLATION,
|
||||
|
||||
R_EVENT_CHILD_REGISTERS_UPDATED,
|
||||
R_EVENT_DEBUG_REGISTER_READ,
|
||||
R_EVENT_DEBUG_REGISTER_WRITE,
|
||||
|
||||
R_EVENT_FLAGS_ADDED,
|
||||
R_EVENT_FLAGS_REMOVED,
|
||||
|
||||
R_EVENT_ANALYSIS_VARIABLE_ADD,
|
||||
R_EVENT_ANALYSIS_VARIABLE_DELETE,
|
||||
|
||||
R_EVENT_TRACE_START,
|
||||
R_EVENT_TRACE_END,
|
||||
R_EVENT_TRACE_POINT_HIT,
|
||||
|
||||
R_EVENT_BREAKPOINT_ADDED,
|
||||
R_EVENT_BREAKPOINT_REMOVED,
|
||||
|
||||
R_EVENT_WATCHPOINT_ADDED,
|
||||
R_EVENT_WATCHPOINT_REMOVED,
|
||||
|
||||
R_EVENT_STEP_OVER,
|
||||
R_EVENT_STEP_IN,
|
||||
R_EVENT_STEP_OUT,
|
||||
|
||||
R_EVENT_DISASSEMBLY_STARTED,
|
||||
R_EVENT_DISASSEMBLY_ENDED,
|
||||
R_EVENT_INSTRUCTION_DECODED,
|
||||
|
||||
R_EVENT_EXECUTION_PAUSED,
|
||||
R_EVENT_EXECUTION_RESUMED,
|
||||
|
||||
R_EVENT_MEMORY_READ,
|
||||
R_EVENT_MEMORY_WRITE,
|
||||
|
||||
R_EVENT_MEMORY_ALLOCATED,
|
||||
R_EVENT_MEMORY_FREED,
|
||||
|
||||
R_EVENT_FILE_OPEN,
|
||||
R_EVENT_FILE_CLOSE,
|
||||
|
||||
R_EVENT_NETWORK_CONNECTION_OPEN,
|
||||
R_EVENT_NETWORK_CONNECTION_CLOSE,
|
||||
|
||||
R_EVENT_NETWORK_DATA_RECEIVED,
|
||||
R_EVENT_NETWORK_DATA_SENT,
|
||||
|
||||
R_EVENT_PLUGIN_INITIALIZED,
|
||||
R_EVENT_PLUGIN_FINALIZED,
|
||||
|
||||
R_EVENT_BINARY_ANALYZED,
|
||||
R_EVENT_SIGNATURE_MATCH_FOUND,
|
||||
R_EVENT_CRC_CHECKSUM_COMPUTED,
|
||||
|
||||
R_EVENT_PROCESS_START,
|
||||
R_EVENT_PROCESS_EXIT,
|
||||
|
||||
R_EVENT_THREAD_START,
|
||||
R_EVENT_THREAD_STOP,
|
||||
|
||||
R_EVENT_MODULE_LOADED,
|
||||
R_EVENT_MODULE_UNLOADED,
|
||||
|
||||
R_EVENT_SYMBOL_ADDED,
|
||||
R_EVENT_SYMBOL_REMOVED,
|
||||
|
||||
R_EVENT_RELOCATIONS_PROCESSED,
|
||||
R_EVENT_SECTION_ADDED,
|
||||
|
||||
R_EVENT_BINARY_DUMP_STARTED,
|
||||
R_EVENT_BINARY_DUMP_FINISHED,
|
||||
|
||||
R_EVENT_EMULATION_STARTED,
|
||||
R_EVENT_EMULATION_STOPPED,
|
||||
|
||||
R_EVENT_BINARY_HASH_COMPUTED,
|
||||
R_EVENT_STRING_DETECTED,
|
||||
R_EVENT_HEX_PATTERN_MATCHED,
|
||||
|
||||
R_EVENT_DECOMPILATION_STARTED,
|
||||
R_EVENT_DECOMPILATION_ENDED,
|
||||
|
||||
R_EVENT_INLINE_PATCH_ADDED,
|
||||
R_EVENT_INLINE_PATCH_REMOVED,
|
||||
|
||||
R_EVENT_SYMBOL_RESOLVED,
|
||||
R_EVENT_SYMBOL_UNRESOLVED,
|
||||
|
||||
R_EVENT_SECTION_MAPPED,
|
||||
R_EVENT_SECTION_UNMAPPED,
|
||||
|
||||
R_EVENT_CACHE_HIT,
|
||||
R_EVENT_CACHE_MISS,
|
||||
|
||||
R_EVENT_CODE_SIGNATURE_VERIFIED,
|
||||
R_EVENT_CODE_SIGNATURE_INVALID,
|
||||
|
||||
R_EVENT_EXCEPTION_RAISED,
|
||||
R_EVENT_EXCEPTION_HANDLED,
|
||||
|
||||
R_EVENT_HARDWARE_BREAKPOINT_SET,
|
||||
R_EVENT_HARDWARE_BREAKPOINT_REMOVED,
|
||||
|
||||
R_EVENT_WATCHPOINT_HIT,
|
||||
R_EVENT_WATCHPOINT_IGNORED,
|
||||
|
||||
R_EVENT_INTERRUPT_RAISED,
|
||||
R_EVENT_INTERRUPT_HANDLED,
|
||||
|
||||
R_EVENT_PLUGIN_CONFIGURATION_UPDATED,
|
||||
R_EVENT_BINARY_RELOCATED,
|
||||
|
||||
R_EVENT_ANALYSIS_RESTART,
|
||||
R_EVENT_ANALYSIS_ABORTED,
|
||||
|
||||
R_EVENT_GADGET_FOUND,
|
||||
R_EVENT_GADGET_EXECUTED,
|
||||
|
||||
R_EVENT_REGISTER_STATE_SAVED,
|
||||
R_EVENT_REGISTER_STATE_RESTORED,
|
||||
|
||||
R_EVENT_FILE_RELOCATED,
|
||||
R_EVENT_BINARY_CHECKSUM_VERIFIED,
|
||||
|
||||
R_EVENT_FUNCTION_CALLED,
|
||||
R_EVENT_FUNCTION_RETURNED,
|
||||
R_EVENT_LAST,
|
||||
} REventType;
|
||||
|
||||
typedef struct r_event_meta_t {
|
||||
@ -82,11 +226,41 @@ typedef struct r_event_io_write_t {
|
||||
int len;
|
||||
} REventIOWrite;
|
||||
|
||||
typedef struct r_event_msg_t {
|
||||
ut32 type;
|
||||
void *data;
|
||||
size_t data_len;
|
||||
} REventMessage;
|
||||
|
||||
typedef struct r_event_t REvent;
|
||||
typedef void (*REventCallback)(REvent *ev, int type, void *user, void *data);
|
||||
typedef struct r_event_hook_t {
|
||||
ut32 event_type;
|
||||
REventCallback cb;
|
||||
void *user;
|
||||
} REventHook;
|
||||
|
||||
// R_VEC_TYPE(RVecREventCallback, REventCallback);
|
||||
R_VEC_TYPE(RVecREventHook, REventHook);
|
||||
|
||||
typedef struct r_event_t {
|
||||
void *user;
|
||||
RVecREventHook all_events;
|
||||
RVecREventHook known_events[R_EVENT_LAST];
|
||||
HtUP *other_events; // when event id > R_EVENT_LAST
|
||||
RThreadLock *lock;
|
||||
} REvent;
|
||||
|
||||
typedef struct r_event_callback_handle_t {
|
||||
int handle;
|
||||
int type;
|
||||
} REventCallbackHandle;
|
||||
|
||||
R_API REvent *r_event_new(void *user);
|
||||
R_API void r_event_free(REvent *ev);
|
||||
R_API REventCallbackHandle r_event_hook(REvent *ev, int type, REventCallback cb, void *user);
|
||||
R_API void r_event_unhook(REvent *ev, REventCallbackHandle handle);
|
||||
R_API void r_event_send(REvent *ev, int type, void *data);
|
||||
R_API void r_event_hook(REvent *ev, ut32 type, REventCallback cb, void *data);
|
||||
R_API bool r_event_unhook(R_NULLABLE REvent *ev, ut32 event_hook, REventCallback cb);
|
||||
R_API void r_event_send(REvent *ev, ut32 type, void *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,16 +1,10 @@
|
||||
/* radare2 - MIT - Copyright 2018 - pancake */
|
||||
/* radare2 - MIT - Copyright 2018-2024 - pancake */
|
||||
|
||||
#include <r_util.h>
|
||||
#include <r_vector.h>
|
||||
|
||||
typedef struct r_event_callback_hook_t {
|
||||
REventCallback cb;
|
||||
void *user;
|
||||
int handle;
|
||||
} REventCallbackHook;
|
||||
|
||||
static void ht_callback_free(HtUPKv *kv) {
|
||||
r_vector_free ((RVector *)kv->value);
|
||||
RVecREventHook_fini (kv->value);
|
||||
}
|
||||
|
||||
R_API REvent *r_event_new(void *user) {
|
||||
@ -18,109 +12,124 @@ R_API REvent *r_event_new(void *user) {
|
||||
if (!ev) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ev->user = user;
|
||||
ev->next_handle = 0;
|
||||
ev->callbacks = ht_up_new (NULL, ht_callback_free, NULL);
|
||||
if (!ev->callbacks) {
|
||||
goto err;
|
||||
ut32 i;
|
||||
for (i = 0; i < R_EVENT_LAST; i++) {
|
||||
RVecREventHook_init (&ev->known_events[i]);
|
||||
}
|
||||
ev->lock = r_th_lock_new (false);
|
||||
ev->other_events = ht_up_new (NULL, ht_callback_free, NULL);
|
||||
if (R_UNLIKELY (!ev->other_events)) {
|
||||
r_event_free (ev);
|
||||
ev = NULL;
|
||||
}
|
||||
r_vector_init (&ev->all_callbacks, sizeof (REventCallbackHook), NULL, NULL);
|
||||
return ev;
|
||||
err:
|
||||
r_event_free (ev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
R_API void r_event_free(REvent *ev) {
|
||||
if (!ev) {
|
||||
return;
|
||||
}
|
||||
ht_up_free (ev->callbacks);
|
||||
r_vector_clear (&ev->all_callbacks);
|
||||
r_th_lock_enter (ev->lock);
|
||||
ht_up_free (ev->other_events);
|
||||
RVecREventHook_fini (&ev->all_events);
|
||||
ut32 i;
|
||||
for (i = 0; i < R_EVENT_LAST; i++) {
|
||||
RVecREventHook_fini (&ev->known_events[i]);
|
||||
}
|
||||
r_th_lock_leave (ev->lock);
|
||||
r_th_lock_free (ev->lock);
|
||||
free (ev);
|
||||
}
|
||||
|
||||
static RVector *get_cbs(REvent *ev, int type) {
|
||||
RVector *cbs = ht_up_find (ev->callbacks, (ut64)type, NULL);
|
||||
static RVecREventHook *get_cbs(REvent *ev, int type) {
|
||||
RVecREventHook *cbs = ht_up_find (ev->other_events, (ut64)type, NULL);
|
||||
if (!cbs) {
|
||||
cbs = r_vector_new (sizeof (REventCallbackHook), NULL, NULL);
|
||||
if (cbs) {
|
||||
ht_up_insert (ev->callbacks, (ut64)type, cbs);
|
||||
cbs = R_NEW0 (RVecREventHook);
|
||||
RVecREventHook_init (cbs);
|
||||
if (R_LIKELY (cbs)) {
|
||||
ht_up_insert (ev->other_events, (ut64)type, cbs);
|
||||
}
|
||||
}
|
||||
return cbs;
|
||||
}
|
||||
|
||||
R_API REventCallbackHandle r_event_hook(REvent *ev, int type, REventCallback cb, void *user) {
|
||||
REventCallbackHandle handle = {0};
|
||||
REventCallbackHook hook;
|
||||
|
||||
R_RETURN_VAL_IF_FAIL (ev, handle);
|
||||
hook.cb = cb;
|
||||
hook.user = user;
|
||||
hook.handle = ev->next_handle++;
|
||||
if (type == R_EVENT_ALL) {
|
||||
r_vector_push (&ev->all_callbacks, &hook);
|
||||
} else {
|
||||
RVector *cbs = get_cbs (ev, type);
|
||||
if (!cbs) {
|
||||
return handle;
|
||||
}
|
||||
r_vector_push (cbs, &hook);
|
||||
}
|
||||
handle.handle = hook.handle;
|
||||
handle.type = type;
|
||||
return handle;
|
||||
}
|
||||
|
||||
static bool del_hook(void *user, const ut64 k, const void *v) {
|
||||
int handle = *(int *)user;
|
||||
RVector *cbs = (RVector *)v;
|
||||
REventCallbackHook *hook;
|
||||
size_t i;
|
||||
R_RETURN_VAL_IF_FAIL (cbs, false);
|
||||
r_vector_enumerate (cbs, hook, i) {
|
||||
if (hook->handle == handle) {
|
||||
r_vector_remove_at (cbs, i, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
R_API void r_event_unhook(REvent *ev, REventCallbackHandle handle) {
|
||||
R_RETURN_IF_FAIL (ev);
|
||||
if (handle.type == R_EVENT_ALL) {
|
||||
// try to delete it both from each list of callbacks and from
|
||||
// the "all_callbacks" vector
|
||||
ht_up_foreach (ev->callbacks, del_hook, &handle.handle);
|
||||
del_hook (&handle.handle, 0, &ev->all_callbacks);
|
||||
} else {
|
||||
RVector *cbs = ht_up_find (ev->callbacks, (ut64)handle.type, NULL);
|
||||
R_RETURN_IF_FAIL (cbs);
|
||||
del_hook (&handle.handle, 0, cbs);
|
||||
}
|
||||
}
|
||||
|
||||
R_API void r_event_send(REvent *ev, int type, void *data) {
|
||||
REventCallbackHook *hook;
|
||||
R_RETURN_IF_FAIL (ev && !ev->incall);
|
||||
|
||||
// send to both the per-type callbacks and to the all_callbacks
|
||||
ev->incall = true;
|
||||
r_vector_foreach (&ev->all_callbacks, hook) {
|
||||
hook->cb (ev, type, hook->user, data);
|
||||
}
|
||||
ev->incall = false;
|
||||
|
||||
RVector *cbs = ht_up_find (ev->callbacks, (ut64)type, NULL);
|
||||
if (!cbs) {
|
||||
R_API void r_event_hook(R_NULLABLE REvent *ev, ut32 type, REventCallback cb, void *user) {
|
||||
if (!ev) {
|
||||
return;
|
||||
}
|
||||
ev->incall = true;
|
||||
r_vector_foreach (cbs, hook) {
|
||||
hook->cb (ev, type, hook->user, data);
|
||||
r_th_lock_enter (ev->lock);
|
||||
REventHook hook = { type, cb, user };
|
||||
|
||||
if (type == R_EVENT_ALL) {
|
||||
RVecREventHook_push_back (&ev->all_events, &hook);
|
||||
} else {
|
||||
if (type < R_EVENT_LAST) {
|
||||
RVecREventHook_push_back (&ev->known_events[type], &hook);
|
||||
} else {
|
||||
RVecREventHook *cbs = get_cbs (ev, type);
|
||||
if (R_LIKELY (cbs)) {
|
||||
RVecREventHook_push_back (cbs, &hook);
|
||||
}
|
||||
}
|
||||
}
|
||||
ev->incall = false;
|
||||
r_th_lock_leave (ev->lock);
|
||||
}
|
||||
|
||||
static inline bool del_hook(RVecREventHook *hooks, const ut64 k, REventCallback cb) {
|
||||
REventHook *hook;
|
||||
size_t n = 0;
|
||||
R_VEC_FOREACH (hooks, hook) {
|
||||
if (hook->cb == cb) {
|
||||
RVecREventHook_remove (hooks, n);
|
||||
return true;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
R_API bool r_event_unhook(R_NULLABLE REvent *ev, ut32 event_type, REventCallback cb) {
|
||||
bool res = false;
|
||||
if (!ev) {
|
||||
return res;
|
||||
}
|
||||
r_th_lock_enter (ev->lock);
|
||||
if (event_type == R_EVENT_ALL) {
|
||||
res = del_hook (&ev->all_events, 0, cb);
|
||||
} else if (event_type < R_EVENT_LAST) {
|
||||
res = del_hook (&ev->known_events[event_type], 0, cb);
|
||||
} else {
|
||||
RVecREventHook *hooks = ht_up_find (ev->other_events, (ut64)event_type, NULL);
|
||||
if (hooks != NULL) {
|
||||
res = del_hook (hooks, 0, cb);
|
||||
}
|
||||
}
|
||||
r_th_lock_leave (ev->lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
// r_event_send (core->ev, R_EVENT_ANALYSIS_START, "");
|
||||
R_API void r_event_send(R_NULLABLE REvent *ev, ut32 event_type, void *data) {
|
||||
if (!ev || event_type == R_EVENT_ALL) {
|
||||
return;
|
||||
}
|
||||
REventHook *hook;
|
||||
r_th_lock_enter (ev->lock);
|
||||
|
||||
R_VEC_FOREACH (&ev->all_events, hook) {
|
||||
hook->cb (ev, event_type, hook->user, data);
|
||||
}
|
||||
RVecREventHook *eh = NULL;
|
||||
if (R_LIKELY (event_type < R_EVENT_LAST)) {
|
||||
eh = &ev->known_events[event_type];
|
||||
} else {
|
||||
eh = ht_up_find (ev->other_events, (ut64)event_type, NULL);
|
||||
}
|
||||
if (R_LIKELY (eh)) {
|
||||
R_VEC_FOREACH (eh, hook) {
|
||||
hook->cb (ev, event_type, hook->user, data);
|
||||
}
|
||||
}
|
||||
r_th_lock_leave (ev->lock);
|
||||
}
|
||||
|
@ -23,8 +23,10 @@ bool test_r_event(void) {
|
||||
EventTestAcc acc_all = {0};
|
||||
EventTestAcc acc_specific = {0};
|
||||
|
||||
REventCallbackHandle handle_all = r_event_hook (ev, R_EVENT_ALL, callback_test, &acc_all);
|
||||
REventCallbackHandle handle_specific = r_event_hook (ev, R_EVENT_META_SET, callback_test, &acc_specific);
|
||||
// REventCallbackHandle handle_all =
|
||||
r_event_hook (ev, R_EVENT_ALL, callback_test, &acc_all);
|
||||
// REventCallbackHandle handle_specific =
|
||||
r_event_hook (ev, R_EVENT_META_SET, callback_test, &acc_specific);
|
||||
|
||||
r_event_send (ev, R_EVENT_META_DEL, (void *)0x4242);
|
||||
|
||||
@ -35,7 +37,7 @@ bool test_r_event(void) {
|
||||
|
||||
r_event_send (ev, R_EVENT_META_SET, (void *)0xdeadbeef);
|
||||
|
||||
mu_assert_eq (acc_all.count, 2, "all count after event");
|
||||
mu_assert_eq (acc_all.count, 2, "all count after event second metaset");
|
||||
mu_assert_eq (acc_all.last_type, R_EVENT_META_SET, "all type after event");
|
||||
mu_assert_ptreq (acc_all.last_data, (void *)0xdeadbeef, "all type after event");
|
||||
|
||||
@ -43,7 +45,7 @@ bool test_r_event(void) {
|
||||
mu_assert_eq (acc_specific.last_type, R_EVENT_META_SET, "specific type after event");
|
||||
mu_assert_ptreq (acc_specific.last_data, (void *)0xdeadbeef, "specific type after event");
|
||||
|
||||
r_event_unhook (ev, handle_all);
|
||||
r_event_unhook (ev, R_EVENT_ALL, callback_test); // handle_all);
|
||||
r_event_send (ev, R_EVENT_META_SET, (void *)0xc0ffee);
|
||||
|
||||
mu_assert_eq (acc_all.count, 2, "all count after event after being removed");
|
||||
@ -54,7 +56,7 @@ bool test_r_event(void) {
|
||||
mu_assert_eq (acc_specific.last_type, R_EVENT_META_SET, "specific type after event");
|
||||
mu_assert_ptreq (acc_specific.last_data, (void *)0xc0ffee, "specific type after event");
|
||||
|
||||
r_event_unhook (ev, handle_specific);
|
||||
r_event_unhook (ev, R_EVENT_META_SET, callback_test);
|
||||
r_event_send (ev, R_EVENT_META_SET, (void *)0xc0ffee);
|
||||
|
||||
mu_assert_eq (acc_specific.count, 2, "specific count after event after being removed");
|
||||
|
Loading…
Reference in New Issue
Block a user