diff options
Diffstat (limited to 'subversion/tests/libsvn_subr/root-pools-test.c')
-rw-r--r-- | subversion/tests/libsvn_subr/root-pools-test.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/subversion/tests/libsvn_subr/root-pools-test.c b/subversion/tests/libsvn_subr/root-pools-test.c new file mode 100644 index 0000000..8116418 --- /dev/null +++ b/subversion/tests/libsvn_subr/root-pools-test.c @@ -0,0 +1,137 @@ +/* + * root-pools-test.c -- test the svn_root_pools__* API + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include <apr_pools.h> +#include <apr_thread_proc.h> +#include <apr_thread_cond.h> + +#include "private/svn_atomic.h" +#include "private/svn_subr_private.h" + +#include "../svn_test.h" + +/* do a few allocations of various sizes from POOL */ +static void +do_some_allocations(apr_pool_t *pool) +{ + int i; + apr_size_t fib = 1, fib1 = 0, fib2 = 0; + for (i = 0; i < 25; ++i) /* fib(25) = 75025 */ + { + apr_pcalloc(pool, fib1); + fib2 = fib1; + fib1 = fib; + fib += fib2; + } +} + +/* allocate, use and recycle a pool from POOLs a few times */ +static void +use_root_pool(svn_root_pools__t *pools) +{ + int i; + for (i = 0; i < 1000; ++i) + { + apr_pool_t *pool = svn_root_pools__acquire_pool(pools); + do_some_allocations(pool); + svn_root_pools__release_pool(pool, pools); + } +} + +#if APR_HAS_THREADS +static void * +APR_THREAD_FUNC thread_func(apr_thread_t *tid, void *data) +{ + /* give all threads a good chance to get started by the scheduler */ + apr_thread_yield(); + + use_root_pool(data); + apr_thread_exit(tid, APR_SUCCESS); + + return NULL; +} +#endif + +static svn_error_t * +test_root_pool(apr_pool_t *pool) +{ + svn_root_pools__t *pools; + SVN_ERR(svn_root_pools__create(&pools)); + use_root_pool(pools); + + return SVN_NO_ERROR; +} + +#define APR_ERR(expr) \ + do { \ + apr_status_t status = (expr); \ + if (status) \ + return svn_error_wrap_apr(status, NULL); \ + } while (0) + +static svn_error_t * +test_root_pool_concurrency(apr_pool_t *pool) +{ +#if APR_HAS_THREADS + /* The svn_root_pools__t container is supposed to be thread-safe. + Do some multi-threaded access and hope that there are no segfaults. + */ + enum { THREAD_COUNT = 10 }; + svn_root_pools__t *pools; + apr_thread_t *threads[THREAD_COUNT]; + int i; + + SVN_ERR(svn_root_pools__create(&pools)); + + for (i = 0; i < THREAD_COUNT; ++i) + APR_ERR(apr_thread_create(&threads[i], NULL, thread_func, pools, pool)); + + /* wait for the threads to finish */ + for (i = 0; i < THREAD_COUNT; ++i) + { + apr_status_t retval; + APR_ERR(apr_thread_join(&retval, threads[i])); + APR_ERR(retval); + } +#endif + + return SVN_NO_ERROR; +} + + +/* The test table. */ + +static int max_threads = 1; + +static struct svn_test_descriptor_t test_funcs[] = + { + SVN_TEST_NULL, + SVN_TEST_PASS2(test_root_pool, + "test root pool recycling"), + SVN_TEST_SKIP2(test_root_pool_concurrency, + ! APR_HAS_THREADS, + "test concurrent root pool recycling"), + SVN_TEST_NULL + }; + +SVN_TEST_MAIN |