diff options
Diffstat (limited to 'test/testglobalmutex.c')
-rw-r--r-- | test/testglobalmutex.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/test/testglobalmutex.c b/test/testglobalmutex.c new file mode 100644 index 0000000..c79884c --- /dev/null +++ b/test/testglobalmutex.c @@ -0,0 +1,143 @@ +/* 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 "testglobalmutex.h" +#include "apr_thread_proc.h" +#include "apr_global_mutex.h" +#include "apr_strings.h" +#include "apr_errno.h" +#include "testutil.h" + +static void launch_child(abts_case *tc, apr_lockmech_e mech, + apr_proc_t *proc, apr_pool_t *p) +{ + apr_procattr_t *procattr; + const char *args[3]; + apr_status_t rv; + + rv = apr_procattr_create(&procattr, p); + APR_ASSERT_SUCCESS(tc, "Couldn't create procattr", rv); + + rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE, + APR_NO_PIPE); + APR_ASSERT_SUCCESS(tc, "Couldn't set io in procattr", rv); + + rv = apr_procattr_error_check_set(procattr, 1); + APR_ASSERT_SUCCESS(tc, "Couldn't set error check in procattr", rv); + + args[0] = "globalmutexchild" EXTENSION; + args[1] = (const char*)apr_itoa(p, (int)mech); + args[2] = NULL; + rv = apr_proc_create(proc, TESTBINPATH "globalmutexchild" EXTENSION, args, NULL, + procattr, p); + APR_ASSERT_SUCCESS(tc, "Couldn't launch program", rv); +} + +static int wait_child(abts_case *tc, apr_proc_t *proc) +{ + int exitcode; + apr_exit_why_e why; + + ABTS_ASSERT(tc, "Error waiting for child process", + apr_proc_wait(proc, &exitcode, &why, APR_WAIT) == APR_CHILD_DONE); + + ABTS_ASSERT(tc, "child didn't terminate normally", why == APR_PROC_EXIT); + return exitcode; +} + +/* return symbolic name for a locking meechanism */ +static const char *mutexname(apr_lockmech_e mech) +{ + switch (mech) { + case APR_LOCK_FCNTL: return "fcntl"; + case APR_LOCK_FLOCK: return "flock"; + case APR_LOCK_SYSVSEM: return "sysvsem"; + case APR_LOCK_PROC_PTHREAD: return "proc_pthread"; + case APR_LOCK_POSIXSEM: return "posixsem"; + case APR_LOCK_DEFAULT: return "default"; + case APR_LOCK_DEFAULT_TIMED: return "default_timed"; + default: return "unknown"; + } +} + +static void test_exclusive(abts_case *tc, void *data) +{ + apr_lockmech_e mech = *(apr_lockmech_e *)data; + apr_proc_t p1, p2, p3, p4; + apr_status_t rv; + apr_global_mutex_t *global_lock; + int x = 0; + abts_log_message("lock mechanism is: "); + abts_log_message(mutexname(mech)); + + rv = apr_global_mutex_create(&global_lock, LOCKNAME, mech, p); + if (rv == APR_ENOTIMPL) { + /* MacOS lacks TIMED implementation, so don't fail for ENOTIMPL */ + ABTS_NOT_IMPL(tc, "global mutex TIMED not implemented"); + return; + } + APR_ASSERT_SUCCESS(tc, "Error creating mutex", rv); + + launch_child(tc, mech, &p1, p); + launch_child(tc, mech, &p2, p); + launch_child(tc, mech, &p3, p); + launch_child(tc, mech, &p4, p); + + x += wait_child(tc, &p1); + x += wait_child(tc, &p2); + x += wait_child(tc, &p3); + x += wait_child(tc, &p4); + + if (x != MAX_COUNTER) { + char buf[200]; + sprintf(buf, "global mutex '%s' failed: %d not %d", + mutexname(mech), x, MAX_COUNTER); + abts_fail(tc, buf, __LINE__); + } +} + +abts_suite *testglobalmutex(abts_suite *suite) +{ + apr_lockmech_e mech = APR_LOCK_DEFAULT; + + suite = ADD_SUITE(suite) + abts_run_test(suite, test_exclusive, &mech); +#if APR_HAS_POSIXSEM_SERIALIZE + mech = APR_LOCK_POSIXSEM; + abts_run_test(suite, test_exclusive, &mech); +#endif +#if APR_HAS_SYSVSEM_SERIALIZE + mech = APR_LOCK_SYSVSEM; + abts_run_test(suite, test_exclusive, &mech); +#endif +#if APR_HAS_PROC_PTHREAD_SERIALIZE + mech = APR_LOCK_PROC_PTHREAD; + abts_run_test(suite, test_exclusive, &mech); +#endif +#if APR_HAS_FCNTL_SERIALIZE + mech = APR_LOCK_FCNTL; + abts_run_test(suite, test_exclusive, &mech); +#endif +#if APR_HAS_FLOCK_SERIALIZE + mech = APR_LOCK_FLOCK; + abts_run_test(suite, test_exclusive, &mech); +#endif + mech = APR_LOCK_DEFAULT_TIMED; + abts_run_test(suite, test_exclusive, &mech); + + return suite; +} + |