pthreadpool: test pthreadpool_tevent_max_threads() returns the expected result
[samba.git] / lib / pthreadpool / tests_cmocka.c
index 33952442e1d6238c059a0186c8328cafbc33e2d5..e2fb8439428537890b2718b74859914de41100fd 100644 (file)
 
 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;
@@ -91,20 +109,27 @@ static void test_job_threadid(void *ptr)
 
 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;
        }
 
@@ -113,20 +138,21 @@ static int test_create_do(struct tevent_context *ev,
                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;
 }
@@ -134,6 +160,7 @@ static int test_create_do(struct tevent_context *ev,
 static void test_create(void **state)
 {
        struct pthreadpool_tevent_test *t = *state;
+       bool executed;
        bool in_main_thread;
        int ret;
 
@@ -142,16 +169,34 @@ static void test_create(void **state)
         * 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);
@@ -161,8 +206,30 @@ static void test_create(void **state)
         * 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);
 }