source: trunk/debathena/third/schroot/test/sbuild-lock.cc @ 24167

Revision 24167, 7.2 KB checked in by broder, 15 years ago (diff)
Import schroot upstream into subversion.
Line 
1/* Copyright © 2006-2007  Roger Leigh <rleigh@debian.org>
2 *
3 * schroot is free software: you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * schroot is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program.  If not, see
15 * <http://www.gnu.org/licenses/>.
16 *
17 *********************************************************************/
18
19#include <sbuild/sbuild-lock.h>
20
21#include <iostream>
22
23#include <sys/types.h>
24#include <sys/wait.h>
25#include <unistd.h>
26
27#ifdef SBUILD_FEATURE_DEVLOCK
28#include <lockdev.h>
29#endif // SBUILD_FEATURE_DEVLOCK
30
31#include <cppunit/extensions/HelperMacros.h>
32
33using namespace CppUnit;
34
35class test_file_lock : public TestFixture
36{
37  CPPUNIT_TEST_SUITE(test_file_lock);
38  CPPUNIT_TEST(test_none_none_lock);
39  CPPUNIT_TEST(test_none_shr_lock);
40  CPPUNIT_TEST(test_none_excl_lock);
41  CPPUNIT_TEST(test_shr_none_lock);
42  CPPUNIT_TEST(test_shr_shr_lock);
43  CPPUNIT_TEST_EXCEPTION(test_shr_excl_lock, sbuild::lock::error);
44  CPPUNIT_TEST(test_excl_none_lock);
45  CPPUNIT_TEST_EXCEPTION(test_excl_shr_lock, sbuild::lock::error);
46  CPPUNIT_TEST_EXCEPTION(test_excl_excl_lock, sbuild::lock::error);
47  CPPUNIT_TEST_SUITE_END();
48
49protected:
50  int fd;
51  sbuild::file_lock *lck;
52
53public:
54  test_file_lock():
55    TestFixture(),
56    fd(-1),
57    lck(0)
58  {
59    // Remove test file if it exists.
60    unlink(TESTDATADIR "/filelock.ex1");
61  }
62
63  virtual ~test_file_lock()
64  {}
65
66  void setUp()
67  {
68    this->fd = open(TESTDATADIR "/filelock.ex1", O_RDWR|O_EXCL|O_CREAT, 0600);
69    CPPUNIT_ASSERT(this->fd >= 0);
70
71    ssize_t wsize = write(this->fd,
72                         "This file exists in order to test "
73                          "sbuild::file_lock locking.\n", 61);
74    CPPUNIT_ASSERT(wsize == 61);
75
76    this->lck = new sbuild::file_lock(this->fd);
77    CPPUNIT_ASSERT(lck != 0);
78  }
79
80  void tearDown()
81  {
82    CPPUNIT_ASSERT(lck != 0);
83    this->lck->unset_lock();
84    delete this->lck;
85
86    CPPUNIT_ASSERT(close(this->fd) == 0);
87    CPPUNIT_ASSERT(unlink(TESTDATADIR "/filelock.ex1") == 0);
88  }
89
90  void test(sbuild::lock::type initial,
91            sbuild::lock::type establish)
92  {
93    this->lck->unset_lock();
94    int pid = fork();
95    CPPUNIT_ASSERT(pid >= 0);
96    if (pid == 0)
97      {
98        try
99          {
100            this->lck->set_lock(initial, 1);
101            // Note: can cause unexpected success if < 4.  Set to 8 to
102            // allow for slow or heavily-loaded machines.
103            sleep(4);
104            this->lck->unset_lock();
105          }
106        catch (std::exception const& e)
107          {
108            try
109              {
110                this->lck->unset_lock();
111              }
112            catch (std::exception const& ignore)
113              {
114              }
115            std::cerr << "Child fail: " << e.what() << std::endl;
116            _exit(EXIT_FAILURE);
117          }
118        _exit(EXIT_SUCCESS);
119      }
120    else
121      {
122        try
123          {
124            sleep(2);
125            this->lck->set_lock(establish, 1);
126
127            int status;
128            CPPUNIT_ASSERT(waitpid(pid, &status, 0) >= 0);
129            CPPUNIT_ASSERT(WIFEXITED(status) && WEXITSTATUS(status) == 0);
130          }
131        catch (std::exception const& e)
132          {
133            int status;
134            waitpid(pid, &status, 0);
135            throw;
136          }
137      }
138  }
139
140  void test_none_none_lock()
141  {
142    test(sbuild::lock::LOCK_NONE, sbuild::lock::LOCK_NONE);
143  }
144
145  void test_none_shr_lock()
146  {
147    test(sbuild::lock::LOCK_NONE, sbuild::lock::LOCK_SHARED);
148  }
149
150  void test_none_excl_lock()
151  {
152    test(sbuild::lock::LOCK_NONE, sbuild::lock::LOCK_EXCLUSIVE);
153  }
154
155  void test_shr_none_lock()
156  {
157    test(sbuild::lock::LOCK_SHARED, sbuild::lock::LOCK_NONE);
158  }
159
160  void test_shr_shr_lock()
161  {
162    test(sbuild::lock::LOCK_SHARED, sbuild::lock::LOCK_SHARED);
163  }
164
165  void test_shr_excl_lock()
166  {
167    test(sbuild::lock::LOCK_SHARED, sbuild::lock::LOCK_EXCLUSIVE);
168  }
169
170  void test_excl_none_lock()
171  {
172    test(sbuild::lock::LOCK_EXCLUSIVE, sbuild::lock::LOCK_NONE);
173  }
174
175  void test_excl_shr_lock()
176  {
177    test(sbuild::lock::LOCK_EXCLUSIVE, sbuild::lock::LOCK_SHARED);
178  }
179
180  void test_excl_excl_lock()
181  {
182    test(sbuild::lock::LOCK_EXCLUSIVE, sbuild::lock::LOCK_EXCLUSIVE);
183  }
184};
185
186CPPUNIT_TEST_SUITE_REGISTRATION(test_file_lock);
187
188#ifdef SBUILD_FEATURE_DEVLOCK
189class test_dev_lock : public TestFixture
190{
191  CPPUNIT_TEST_SUITE(test_dev_lock);
192  CPPUNIT_TEST(test_none_none_lock);
193  CPPUNIT_TEST(test_none_shr_lock);
194  CPPUNIT_TEST(test_none_excl_lock);
195  CPPUNIT_TEST(test_shr_none_lock);
196  CPPUNIT_TEST_EXCEPTION(test_shr_shr_lock, sbuild::lock::error);
197  CPPUNIT_TEST_EXCEPTION(test_shr_excl_lock, sbuild::lock::error);
198  CPPUNIT_TEST(test_excl_none_lock);
199  CPPUNIT_TEST_EXCEPTION(test_excl_shr_lock, sbuild::lock::error);
200  CPPUNIT_TEST_EXCEPTION(test_excl_excl_lock, sbuild::lock::error);
201  CPPUNIT_TEST_SUITE_END();
202
203protected:
204  sbuild::device_lock *lck;
205
206public:
207  test_dev_lock():
208    TestFixture(),
209    lck(0)
210  {}
211
212  virtual ~test_dev_lock()
213  {
214    unlock();
215  }
216
217  void unlock()
218  {
219    CPPUNIT_ASSERT(dev_unlock("/dev/null", 0) == 0);
220  }
221
222  void setUp()
223  {
224    unlock();
225    this->lck = new sbuild::device_lock("/dev/null");
226  }
227
228  void tearDown()
229  {
230    delete this->lck;
231    this->lck = 0;
232  }
233
234  void test(sbuild::lock::type initial,
235            sbuild::lock::type establish)
236  {
237    unlock();
238    int pid = fork();
239    CPPUNIT_ASSERT(pid >= 0);
240    if (pid == 0)
241      {
242        try
243          {
244            this->lck->set_lock(initial, 1);
245            // Note: can cause unexpected success if < 4.  Set to 8 to
246            // allow for slow or heavily-loaded machines.
247            sleep(4);
248            this->lck->unset_lock();
249          }
250        catch (std::exception const& e)
251          {
252            try
253              {
254                this->lck->unset_lock();
255              }
256            catch (std::exception const& ignore)
257              {
258              }
259            std::cerr << "Child fail: " << e.what() << std::endl;
260            _exit(EXIT_FAILURE);
261          }
262        _exit(EXIT_SUCCESS);
263      }
264    else
265      {
266        try
267          {
268            sleep(2);
269            this->lck->set_lock(establish, 1);
270            this->lck->unset_lock();
271
272            int status;
273            CPPUNIT_ASSERT(waitpid(pid, &status, 0) >= 0);
274            CPPUNIT_ASSERT(WIFEXITED(status) && WEXITSTATUS(status) == 0);
275          }
276        catch (std::exception const& e)
277          {
278            int status;
279            waitpid(pid, &status, 0);
280            throw;
281          }
282      }
283  }
284
285  void test_none_none_lock()
286  {
287    test(sbuild::lock::LOCK_NONE, sbuild::lock::LOCK_NONE);
288  }
289
290  void test_none_shr_lock()
291  {
292    test(sbuild::lock::LOCK_NONE, sbuild::lock::LOCK_SHARED);
293  }
294
295  void test_none_excl_lock()
296  {
297    test(sbuild::lock::LOCK_NONE, sbuild::lock::LOCK_EXCLUSIVE);
298  }
299
300  void test_shr_none_lock()
301  {
302    test(sbuild::lock::LOCK_SHARED, sbuild::lock::LOCK_NONE);
303  }
304
305  void test_shr_shr_lock()
306  {
307    test(sbuild::lock::LOCK_SHARED, sbuild::lock::LOCK_SHARED);
308  }
309
310  void test_shr_excl_lock()
311  {
312    test(sbuild::lock::LOCK_SHARED, sbuild::lock::LOCK_EXCLUSIVE);
313  }
314
315  void test_excl_none_lock()
316  {
317    test(sbuild::lock::LOCK_EXCLUSIVE, sbuild::lock::LOCK_NONE);
318  }
319
320  void test_excl_shr_lock()
321  {
322    test(sbuild::lock::LOCK_EXCLUSIVE, sbuild::lock::LOCK_SHARED);
323  }
324
325  void test_excl_excl_lock()
326  {
327    test(sbuild::lock::LOCK_EXCLUSIVE, sbuild::lock::LOCK_EXCLUSIVE);
328  }
329};
330
331CPPUNIT_TEST_SUITE_REGISTRATION(test_dev_lock);
332#endif // SBUILD_FEATURE_DEVLOCK
Note: See TracBrowser for help on using the repository browser.