From fbafdc99ef2cef11a1a28e795ffe965cb53ef7fa Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 18 Jul 2018 10:21:22 +0200 Subject: [PATCH] pthreadpool: add tests for pthreadpool_tevent_[current_job_]per_thread_cwd() Note this currently this doesn't enforce the support for unshare(CLONE_FS) as some contraint container environment (e.g. docker) reject the whole unshare() system call. Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- lib/pthreadpool/tests_cmocka.c | 144 +++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/lib/pthreadpool/tests_cmocka.c b/lib/pthreadpool/tests_cmocka.c index dc7b1150b5c..5c7f6ab6904 100644 --- a/lib/pthreadpool/tests_cmocka.c +++ b/lib/pthreadpool/tests_cmocka.c @@ -244,6 +244,147 @@ static void test_create(void **state) assert_false(in_main_thread); } +static void test_per_thread_cwd_job(void *ptr) +{ + const bool *per_thread_cwd_ptr = ptr; + bool per_thread_cwd; + char cwdbuf[PATH_MAX] = {0,}; + char *cwdstr = NULL; + int ret; + + /* + * This needs to be consistent. + */ + per_thread_cwd = pthreadpool_tevent_current_job_per_thread_cwd(); + assert_int_equal(per_thread_cwd, *per_thread_cwd_ptr); + + if (!per_thread_cwd) { + return; + } + + /* + * Check we're not already in "/". + */ + cwdstr = getcwd(cwdbuf, sizeof(cwdbuf)); + assert_non_null(cwdstr); + assert_string_not_equal(cwdstr, "/"); + + ret = chdir("/"); + assert_int_equal(ret, 0); + + /* + * Check we're in "/" now. + */ + cwdstr = getcwd(cwdbuf, sizeof(cwdbuf)); + assert_non_null(cwdstr); + assert_string_equal(cwdstr, "/"); +} + +static int test_per_thread_cwd_do(struct tevent_context *ev, + struct pthreadpool_tevent *pool) +{ + struct tevent_req *req; + bool per_thread_cwd; + bool ok; + int ret; + per_thread_cwd = pthreadpool_tevent_per_thread_cwd(pool); + + req = pthreadpool_tevent_job_send( + ev, ev, pool, test_per_thread_cwd_job, &per_thread_cwd); + if (req == NULL) { + fprintf(stderr, "pthreadpool_tevent_job_send failed\n"); + return ENOMEM; + } + + ok = tevent_req_poll(req, ev); + if (!ok) { + ret = errno; + fprintf(stderr, "tevent_req_poll failed: %s\n", + strerror(ret)); + return ret; + } + + ret = pthreadpool_tevent_job_recv(req); + TALLOC_FREE(req); + if (ret != 0) { + fprintf(stderr, "tevent_req_recv failed: %s\n", + strerror(ret)); + return ret; + } + + return 0; +} + +static void test_per_thread_cwd(void **state) +{ + struct pthreadpool_tevent_test *t = *state; + int ret; + bool per_thread_cwd_u; + bool per_thread_cwd_o; + bool per_thread_cwd_s; + char cwdbuf1[PATH_MAX] = {0,}; + char *cwdstr1 = NULL; + char cwdbuf2[PATH_MAX] = {0,}; + char *cwdstr2 = NULL; + + /* + * The unlimited and one pools + * should be consistent. + * + * We can't enforce this as some constraint + * container environments disable unshare() + * completely, even just with CLONE_FS. + */ + per_thread_cwd_u = pthreadpool_tevent_per_thread_cwd(t->upool); + per_thread_cwd_o = pthreadpool_tevent_per_thread_cwd(t->opool); + assert_int_equal(per_thread_cwd_u, per_thread_cwd_o); + + /* + * The sync pool should never support this. + */ + per_thread_cwd_s = pthreadpool_tevent_per_thread_cwd(t->spool); + assert_false(per_thread_cwd_s); + + /* + * Check we're not already in "/". + */ + cwdstr1 = getcwd(cwdbuf1, sizeof(cwdbuf1)); + assert_non_null(cwdstr1); + assert_string_not_equal(cwdstr1, "/"); + + will_return(__wrap_pthread_create, 0); + ret = test_per_thread_cwd_do(t->ev, t->upool); + assert_int_equal(ret, 0); + + /* + * Check we're still in the same directory. + */ + cwdstr2 = getcwd(cwdbuf2, sizeof(cwdbuf2)); + assert_non_null(cwdstr2); + assert_string_equal(cwdstr2, cwdstr1); + + will_return(__wrap_pthread_create, 0); + ret = test_per_thread_cwd_do(t->ev, t->opool); + assert_int_equal(ret, 0); + + /* + * Check we're still in the same directory. + */ + cwdstr2 = getcwd(cwdbuf2, sizeof(cwdbuf2)); + assert_non_null(cwdstr2); + assert_string_equal(cwdstr2, cwdstr1); + + ret = test_per_thread_cwd_do(t->ev, t->spool); + assert_int_equal(ret, 0); + + /* + * Check we're still in the same directory. + */ + cwdstr2 = getcwd(cwdbuf2, sizeof(cwdbuf2)); + assert_non_null(cwdstr2); + assert_string_equal(cwdstr2, cwdstr1); +} + struct test_cancel_job { int fdm; /* the main end of socketpair */ int fdj; /* the job end of socketpair */ @@ -670,6 +811,9 @@ int main(int argc, char **argv) cmocka_unit_test_setup_teardown(test_create, setup_pthreadpool_tevent, teardown_pthreadpool_tevent), + cmocka_unit_test_setup_teardown(test_per_thread_cwd, + setup_pthreadpool_tevent, + teardown_pthreadpool_tevent), cmocka_unit_test_setup_teardown(test_cancel_job, setup_pthreadpool_tevent, teardown_pthreadpool_tevent), -- 2.47.3