blob: 781ec1a40727c2dbabbaa04194f0e2747c84e19d [file] [log] [blame]
James E. King, III00d42522017-04-04 09:32:45 -04001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20// This is linked into the UnitTests test executable
21
22#include <boost/test/unit_test.hpp>
23
24#include "thrift/concurrency/Exception.h"
25#include "thrift/concurrency/Mutex.h"
26
27using boost::unit_test::test_suite;
28using boost::unit_test::framework::master_test_suite;
29
30using namespace apache::thrift::concurrency;
31
32struct LFAT
33{
34 LFAT()
35 : uut(Mutex::ERRORCHECK_INITIALIZER)
36 {
37 BOOST_CHECK_EQUAL(0, pthread_mutex_init(&mx, 0));
38 BOOST_CHECK_EQUAL(0, pthread_cond_init(&cv, 0));
39 }
40
41 Mutex uut;
42 pthread_mutex_t mx;
43 pthread_cond_t cv;
44};
45
46// Helper for testing mutex behavior when locked by another thread
47void * lockFromAnotherThread(void *ptr)
48{
49 struct LFAT *lfat = (LFAT *)ptr;
50 BOOST_CHECK_EQUAL (0, pthread_mutex_lock(&lfat->mx)); // synchronize with testing thread
51 BOOST_CHECK_NO_THROW( lfat->uut.lock());
52 BOOST_CHECK_EQUAL (0, pthread_cond_signal(&lfat->cv)); // tell testing thread we have locked the mutex
53 BOOST_CHECK_EQUAL (0, pthread_cond_wait(&lfat->cv, &lfat->mx)); // wait for testing thread to signal condition variable telling us to unlock
54 BOOST_CHECK_NO_THROW( lfat->uut.unlock());
55 return ptr; // testing thread should join to ensure completeness
56}
57
58BOOST_AUTO_TEST_SUITE(MutexTest)
59
60BOOST_AUTO_TEST_CASE(happy_path)
61{
62 Mutex uut(Mutex::ERRORCHECK_INITIALIZER); // needed to test unlocking twice without undefined behavior
63
64 BOOST_CHECK_NO_THROW( uut.lock());
65 BOOST_CHECK_THROW ( uut.lock(), SystemResourceException); // EDEADLK (this thread owns it)
66 BOOST_CHECK_NO_THROW( uut.unlock());
67}
68
69BOOST_AUTO_TEST_CASE(recursive_happy_path)
70{
71 Mutex uut(Mutex::RECURSIVE_INITIALIZER);
72
73 BOOST_CHECK_NO_THROW( uut.lock());
74 BOOST_CHECK_NO_THROW( uut.lock());
75 BOOST_CHECK_NO_THROW( uut.unlock());
76 BOOST_CHECK_NO_THROW( uut.lock());
77 BOOST_CHECK_NO_THROW( uut.lock());
78 BOOST_CHECK_NO_THROW( uut.unlock());
79 BOOST_CHECK_NO_THROW( uut.lock());
80 BOOST_CHECK_NO_THROW( uut.unlock());
81 BOOST_CHECK_NO_THROW( uut.unlock());
82 BOOST_CHECK_NO_THROW( uut.unlock());
83}
84
85BOOST_AUTO_TEST_CASE(trylock)
86{
87 Mutex uut(Mutex::ADAPTIVE_INITIALIZER); // just using another initializer for coverage
88
89 BOOST_CHECK ( uut.trylock());
90 BOOST_CHECK (!uut.trylock());
91 BOOST_CHECK_NO_THROW( uut.unlock());
92}
93
94BOOST_AUTO_TEST_CASE(timedlock)
95{
96 pthread_t th;
97 struct LFAT lfat;
98
99 BOOST_CHECK ( lfat.uut.timedlock(100));
100 BOOST_CHECK_THROW ( lfat.uut.timedlock(100),
101 SystemResourceException); // EDEADLK (current thread owns mutex - logic error)
102 BOOST_CHECK_NO_THROW( lfat.uut.unlock());
103
104 BOOST_CHECK_EQUAL (0, pthread_mutex_lock(&lfat.mx)); // synchronize with helper thread
105 BOOST_CHECK_EQUAL (0, pthread_create(&th, NULL,
106 lockFromAnotherThread, &lfat)); // create helper thread
107 BOOST_CHECK_EQUAL (0, pthread_cond_wait(&lfat.cv, &lfat.mx)); // wait for helper thread to lock mutex
108
109 BOOST_CHECK (!lfat.uut.timedlock(100)); // false: another thread owns the lock
110
111 BOOST_CHECK_EQUAL (0, pthread_cond_signal(&lfat.cv)); // tell helper thread we are done
112 BOOST_CHECK_EQUAL (0, pthread_mutex_unlock(&lfat.mx)); // let helper thread clean up
113 BOOST_CHECK_EQUAL (0, pthread_join(th, 0)); // wait for testing thread to unlock and be done
114}
115
116BOOST_AUTO_TEST_CASE(underlying)
117{
118 Mutex uut;
119
120 BOOST_CHECK ( uut.getUnderlyingImpl());
121}
122
123BOOST_AUTO_TEST_SUITE_END()