kicad/thirdparty/sentry-native/tests/unit/test_sync.c

154 lines
3.8 KiB
C
Raw Normal View History

#include "sentry_core.h"
#include "sentry_sync.h"
#include "sentry_testsupport.h"
#ifdef SENTRY_PLATFORM_WINDOWS
# include <windows.h>
# define sleep_s(SECONDS) Sleep((SECONDS)*1000)
#else
# include <unistd.h>
# define sleep_s(SECONDS) sleep(SECONDS)
#endif
struct task_state {
int executed;
bool running;
};
static void
task_func(void *data, void *UNUSED(state))
{
struct task_state *state = data;
state->executed++;
}
static void
cleanup_func(void *data)
{
struct task_state *state = data;
state->running = false;
}
SENTRY_TEST(background_worker)
{
for (size_t i = 0; i < 100; i++) {
sentry_bgworker_t *bgw = sentry__bgworker_new(NULL, NULL);
TEST_CHECK(!!bgw);
sentry__bgworker_start(bgw);
struct task_state ts;
ts.executed = 0;
ts.running = true;
for (size_t j = 0; j < 10; j++) {
sentry__bgworker_submit(bgw, task_func, cleanup_func, &ts);
}
TEST_CHECK_INT_EQUAL(sentry__bgworker_shutdown(bgw, 5000), 0);
sentry__bgworker_decref(bgw);
TEST_CHECK_INT_EQUAL(ts.executed, 10);
TEST_CHECK(!ts.running);
}
}
static void
sleep_task(void *UNUSED(data), void *UNUSED(state))
{
sleep_s(1);
}
static void
trailing_task(void *data, void *UNUSED(state))
{
bool *executed = (bool *)data;
*executed = true;
}
static bool
drop_lessthan(void *task, void *data)
{
return (size_t)task < (size_t)data;
}
static bool
drop_greaterthan(void *task, void *data)
{
return (size_t)task > (size_t)data;
}
static bool
collect(void *task, void *data)
{
sentry_value_t *list = (sentry_value_t *)data;
sentry_value_append(*list, sentry_value_new_int32((int32_t)(size_t)task));
return true;
}
SENTRY_TEST(task_queue)
{
sentry_bgworker_t *bgw = sentry__bgworker_new(NULL, NULL);
sentry__bgworker_submit(bgw, sleep_task, NULL, NULL);
sentry__bgworker_decref(bgw);
bgw = sentry__bgworker_new(NULL, NULL);
// submit before starting
for (size_t i = 0; i < 20; i++) {
sentry__bgworker_submit(bgw, sleep_task, NULL, (void *)(i % 10));
}
sentry__bgworker_start(bgw);
size_t dropped = 0;
dropped = sentry__bgworker_foreach_matching(
bgw, sleep_task, drop_lessthan, (void *)4);
TEST_CHECK_INT_EQUAL(dropped, 8);
dropped = sentry__bgworker_foreach_matching(
bgw, sleep_task, drop_greaterthan, (void *)6);
TEST_CHECK_INT_EQUAL(dropped, 6);
int shutdown = sentry__bgworker_shutdown(bgw, 500);
TEST_CHECK_INT_EQUAL(shutdown, 1);
// submit another task to the worker which is still in shutdown
bool executed_after_shutdown = false;
sentry__bgworker_submit(bgw, trailing_task, NULL, &executed_after_shutdown);
sentry_value_t list = sentry_value_new_list();
dropped
= sentry__bgworker_foreach_matching(bgw, sleep_task, collect, &list);
TEST_CHECK_INT_EQUAL(dropped, 6);
TEST_CHECK_JSON_VALUE(list, "[4,5,6,4,5,6]");
sentry_value_decref(list);
sentry__bgworker_decref(bgw);
// the worker is still "executing" one task, so lets sleep here as well so
// we dont leak
sleep_s(1);
// the worker will still execute tasks as long as there are some, even if it
// was instructed to shut down
TEST_CHECK(executed_after_shutdown);
}
SENTRY_TEST(bgworker_flush)
{
sentry_bgworker_t *bgw = sentry__bgworker_new(NULL, NULL);
sentry__bgworker_submit(bgw, sleep_task, NULL, NULL);
sentry__bgworker_start(bgw);
// first flush times out
int flush = sentry__bgworker_flush(bgw, 500);
TEST_CHECK_INT_EQUAL(flush, 1);
// second flush succeeds
flush = sentry__bgworker_flush(bgw, 1000);
TEST_CHECK_INT_EQUAL(flush, 0);
int shutdown = sentry__bgworker_shutdown(bgw, 500);
TEST_CHECK_INT_EQUAL(shutdown, 0);
sentry__bgworker_decref(bgw);
}