mirror of
https://github.com/radareorg/radare2
synced 2026-08-22 20:23:32 -04:00
203 lines
5.1 KiB
C
203 lines
5.1 KiB
C
#include <r_th.h>
|
|
#include "minunit.h"
|
|
|
|
// Shared data for testing
|
|
static int test_data = 0;
|
|
|
|
static RThreadFunctionRet test_thread_function(RThread *th) {
|
|
// Simple increment of shared data
|
|
test_data++;
|
|
return R_TH_STOP;
|
|
}
|
|
|
|
static RThreadFunctionRet test_thread_repeat_function(RThread *th) {
|
|
// Increment test_data and return REPEAT to be called again
|
|
test_data++;
|
|
if (test_data < 5) {
|
|
return R_TH_REPEAT;
|
|
}
|
|
return R_TH_STOP;
|
|
}
|
|
|
|
static RThreadFunctionRet test_thread_delay_function(RThread *th) {
|
|
// Just increment the counter after delay
|
|
test_data++;
|
|
return R_TH_STOP;
|
|
}
|
|
|
|
bool test_thread_basic(void) {
|
|
// Reset test data
|
|
test_data = 0;
|
|
|
|
// Create a new thread
|
|
RThread *th = r_th_new(test_thread_function, NULL, 0);
|
|
mu_assert_notnull(th, "Thread creation failed");
|
|
|
|
// Start the thread
|
|
bool res = r_th_start(th);
|
|
mu_assert_eq(res, true, "Thread start failed");
|
|
|
|
// Wait for thread to finish
|
|
r_th_wait(th);
|
|
|
|
// Verify thread executed
|
|
mu_assert_eq(test_data, 1, "Thread function didn't execute correctly");
|
|
|
|
// Free thread
|
|
r_th_free(th);
|
|
|
|
mu_end;
|
|
}
|
|
|
|
bool test_thread_is_running(void) {
|
|
// Create a new thread but don't start it yet
|
|
RThread *th = r_th_new(test_thread_function, NULL, 0);
|
|
mu_assert_notnull(th, "Thread creation failed");
|
|
|
|
// Should be running (not started, but thread is alive)
|
|
bool running = r_th_is_running(th);
|
|
mu_assert_eq(running, true, "Thread should be marked as running after creation");
|
|
|
|
// Explicitly set running to false
|
|
r_th_set_running(th, false);
|
|
running = r_th_is_running(th);
|
|
mu_assert_eq(running, false, "Thread should not be running after setting to false");
|
|
|
|
// Set it back to true
|
|
r_th_set_running(th, true);
|
|
running = r_th_is_running(th);
|
|
mu_assert_eq(running, true, "Thread should be running after setting to true");
|
|
|
|
// Kill and free thread properly
|
|
r_th_break(th); // Signal thread to break
|
|
r_th_wait(th); // Wait for thread to finish
|
|
r_th_free(th); // Now free the thread
|
|
|
|
mu_end;
|
|
}
|
|
|
|
bool test_thread_repeat(void) {
|
|
// Reset test data
|
|
test_data = 0;
|
|
|
|
// Create thread with repeat function
|
|
RThread *th = r_th_new(test_thread_repeat_function, NULL, 0);
|
|
mu_assert_notnull(th, "Thread creation failed");
|
|
|
|
// Start the thread
|
|
bool res = r_th_start(th);
|
|
mu_assert_eq(res, true, "Thread start failed");
|
|
|
|
// Wait for thread to finish
|
|
r_th_wait(th);
|
|
|
|
// Verify thread repeated correctly
|
|
mu_assert_eq(test_data, 5, "Thread function didn't repeat correctly");
|
|
|
|
// Free thread
|
|
r_th_free(th);
|
|
|
|
mu_end;
|
|
}
|
|
|
|
bool test_thread_break(void) {
|
|
// Reset test data
|
|
test_data = 0;
|
|
|
|
// Create thread with repeat function
|
|
RThread *th = r_th_new(test_thread_repeat_function, NULL, 0);
|
|
mu_assert_notnull(th, "Thread creation failed");
|
|
|
|
// Start the thread
|
|
bool res = r_th_start(th);
|
|
mu_assert_eq(res, true, "Thread start failed");
|
|
|
|
// Break the thread immediately
|
|
r_th_break(th);
|
|
|
|
// Wait for thread to finish
|
|
r_th_wait(th);
|
|
|
|
// Verify thread was broken before completing all repeats
|
|
mu_assert_neq(test_data, 5, "Thread was not broken correctly");
|
|
|
|
// Free thread
|
|
r_th_free(th);
|
|
|
|
mu_end;
|
|
}
|
|
|
|
bool test_thread_delay(void) {
|
|
// Reset test data
|
|
test_data = 0;
|
|
|
|
// Create thread with shorter delay (100ms instead of 500ms) to make test faster
|
|
RThread *th = r_th_new(test_thread_delay_function, NULL, 100);
|
|
mu_assert_notnull(th, "Thread creation failed");
|
|
|
|
// Start the thread
|
|
bool res = r_th_start(th);
|
|
mu_assert_eq(res, true, "Thread start failed");
|
|
|
|
// Verify data hasn't changed yet
|
|
mu_assert_eq(test_data, 0, "Thread executed before delay");
|
|
|
|
// Instead of waiting indefinitely, use a timeout approach
|
|
// Sleep for a bit longer than the delay to ensure the thread has time to complete
|
|
r_sys_usleep(150000); // 150ms (50ms longer than the delay)
|
|
|
|
// Verify thread executed after delay
|
|
mu_assert_eq(test_data, 1, "Thread didn't execute after delay");
|
|
|
|
// Use kill with force=false to just break and wait for the thread
|
|
r_th_break(th);
|
|
r_th_wait(th);
|
|
|
|
// Free thread
|
|
r_th_free(th);
|
|
|
|
mu_end;
|
|
}
|
|
|
|
bool test_thread_kill(void) {
|
|
// Reset test data
|
|
test_data = 0;
|
|
|
|
// Create thread with delay to ensure it's still running when we kill it
|
|
// Keep delay short for faster test execution
|
|
RThread *th = r_th_new(test_thread_delay_function, NULL, 100);
|
|
mu_assert_notnull(th, "Thread creation failed");
|
|
|
|
// Start the thread
|
|
bool res = r_th_start(th);
|
|
mu_assert_eq(res, true, "Thread start failed");
|
|
|
|
// First verify the thread hasn't executed yet (due to delay)
|
|
mu_assert_eq(test_data, 0, "Thread executed before delay");
|
|
|
|
// Force kill the thread
|
|
bool killed = r_th_kill(th, true);
|
|
mu_assert_eq(killed, false, "Thread kill should return false");
|
|
|
|
// Verify thread didn't execute after being killed
|
|
mu_assert_eq(test_data, 0, "Thread executed after being killed");
|
|
|
|
// Free thread after it's been fully killed
|
|
r_th_free(th);
|
|
|
|
mu_end;
|
|
}
|
|
|
|
int all_tests(void) {
|
|
mu_run_test(test_thread_basic);
|
|
mu_run_test(test_thread_is_running);
|
|
mu_run_test(test_thread_repeat);
|
|
mu_run_test(test_thread_break);
|
|
// BROKEN mu_run_test(test_thread_delay);
|
|
mu_run_test(test_thread_kill);
|
|
return tests_passed != tests_run;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
return all_tests();
|
|
}
|