struct pthreadpool_tevent_test {
struct tevent_context *ev;
- struct pthreadpool_tevent *pool;
+ struct pthreadpool_tevent *upool;
+ struct pthreadpool_tevent *spool;
+ struct pthreadpool_tevent *opool;
};
static int setup_pthreadpool_tevent(void **state)
{
struct pthreadpool_tevent_test *t;
int ret;
+ size_t max_threads;
- t = talloc(NULL, struct pthreadpool_tevent_test);
+ t = talloc_zero(NULL, struct pthreadpool_tevent_test);
assert_non_null(t);
t->ev = tevent_context_init(t);
assert_non_null(t->ev);
- ret = pthreadpool_tevent_init(t->ev, UINT_MAX, &t->pool);
+ ret = pthreadpool_tevent_init(t->ev, UINT_MAX, &t->upool);
assert_return_code(ret, 0);
+ max_threads = pthreadpool_tevent_max_threads(t->upool);
+ assert_int_equal(max_threads, UINT_MAX);
+
+ ret = pthreadpool_tevent_init(t->ev, 1, &t->opool);
+ assert_return_code(ret, 0);
+
+ max_threads = pthreadpool_tevent_max_threads(t->opool);
+ assert_int_equal(max_threads, 1);
+
+ ret = pthreadpool_tevent_init(t->ev, 0, &t->spool);
+ assert_return_code(ret, 0);
+
+ max_threads = pthreadpool_tevent_max_threads(t->spool);
+ assert_int_equal(max_threads, 0);
+
*state = t;
return 0;
static int test_create_do(struct tevent_context *ev,
struct pthreadpool_tevent *pool,
+ bool *executed,
bool *in_main_thread)
{
struct tevent_req *req;
- pthread_t main_thread, worker_thread;
+ pthread_t zero_thread;
+ pthread_t main_thread;
+ pthread_t worker_thread;
bool ok;
int ret;
+ *executed = false;
+ *in_main_thread = false;
+
+ memset(&zero_thread, 0, sizeof(zero_thread));
main_thread = pthread_self();
+ worker_thread = zero_thread;
req = pthreadpool_tevent_job_send(
ev, ev, pool, test_job_threadid, &worker_thread);
if (req == NULL) {
fprintf(stderr, "pthreadpool_tevent_job_send failed\n");
- TALLOC_FREE(ev);
return ENOMEM;
}
ret = errno;
fprintf(stderr, "tevent_req_poll failed: %s\n",
strerror(ret));
- TALLOC_FREE(ev);
+ *executed = !pthread_equal(worker_thread, zero_thread);
+ *in_main_thread = pthread_equal(worker_thread, main_thread);
return ret;
}
ret = pthreadpool_tevent_job_recv(req);
TALLOC_FREE(req);
+ *executed = !pthread_equal(worker_thread, zero_thread);
+ *in_main_thread = pthread_equal(worker_thread, main_thread);
if (ret != 0) {
fprintf(stderr, "tevent_req_recv failed: %s\n",
strerror(ret));
- TALLOC_FREE(ev);
return ret;
}
- *in_main_thread = pthread_equal(worker_thread, main_thread);
return 0;
}
static void test_create(void **state)
{
struct pthreadpool_tevent_test *t = *state;
+ bool executed;
bool in_main_thread;
int ret;
* this job will run in the sync fallback in the main thread.
*/
will_return(__wrap_pthread_create, EAGAIN);
- ret = test_create_do(t->ev, t->pool, &in_main_thread);
- assert_return_code(ret, 0);
+ ret = test_create_do(t->ev, t->upool, &executed, &in_main_thread);
+ assert_int_equal(ret, EAGAIN);
+ assert_false(executed);
+ assert_false(in_main_thread);
+
+ /*
+ * The sync pool won't trigger pthread_create()
+ * It will be triggered by the one pool.
+ */
+ will_return(__wrap_pthread_create, EAGAIN);
+
+ ret = test_create_do(t->ev, t->spool, &executed, &in_main_thread);
+ assert_int_equal(ret, 0);
+ assert_true(executed);
assert_true(in_main_thread);
+ ret = test_create_do(t->ev, t->opool, &executed, &in_main_thread);
+ assert_int_equal(ret, EAGAIN);
+ assert_false(executed);
+ assert_false(in_main_thread);
+
/*
* When a thread can be created, the job will run in the worker thread.
*/
will_return(__wrap_pthread_create, 0);
- ret = test_create_do(t->ev, t->pool, &in_main_thread);
- assert_return_code(ret, 0);
+ ret = test_create_do(t->ev, t->upool, &executed, &in_main_thread);
+ assert_int_equal(ret, 0);
+ assert_true(executed);
assert_false(in_main_thread);
poll(NULL, 0, 10);
* running another job will also use the worker thread, even
* if a new thread cannot be created.
*/
- ret = test_create_do(t->ev, t->pool, &in_main_thread);
- assert_return_code(ret, 0);
+ ret = test_create_do(t->ev, t->upool, &executed, &in_main_thread);
+ assert_int_equal(ret, 0);
+ assert_true(executed);
+ assert_false(in_main_thread);
+
+ /*
+ * When a thread can be created, the job will run in the worker thread.
+ */
+ will_return(__wrap_pthread_create, 0);
+ ret = test_create_do(t->ev, t->opool, &executed, &in_main_thread);
+ assert_int_equal(ret, 0);
+ assert_true(executed);
+ assert_false(in_main_thread);
+
+ poll(NULL, 0, 10);
+
+ /*
+ * Workerthread will still be active for a second; immediately
+ * running another job will also use the worker thread, even
+ * if a new thread cannot be created.
+ */
+ ret = test_create_do(t->ev, t->opool, &executed, &in_main_thread);
+ assert_int_equal(ret, 0);
+ assert_true(executed);
assert_false(in_main_thread);
}