thread_unittest.cc 2.82 KB
Newer Older
1
// Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
2
3
4
5
6
7
8
9
10
11
12
13
14
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

15
#include <util/threads/thread.h>
16
17
18
19
20
21
22
23
24
25
26
27

#include <boost/bind.hpp>

#include <gtest/gtest.h>

// This file tests the Thread class. It's hard to test an actual thread is
// started, but we at least check the function is run and exceptions are
// propagated as they should.
//
// We run some tests mutiple times to see if there happen to be a race
// condition (then it would have better chance showing up).
//
28
// The detached tests are not run as many times to prevent many threads being
29
30
31
// started in parallel (the other tests wait for the previous one to terminate
// before starting new one).

32
33
const size_t iterations = 200;
const size_t detached_iterations = 25;
34
35
36
37
38
39

using namespace isc::util::thread;

namespace {

void
40
41
doSomething(int* x) {
    delete[] x;
42
43
44
45
46
}

// We just test that we can forget about the thread and nothing
// bad will happen on our side.
TEST(ThreadTest, detached) {
47
    for (size_t i = 0; i < detached_iterations; ++i) {
48
49
50
51
52
53
54
55
56
        int* x = new int[10];
        Thread thread(boost::bind(&doSomething, x));
    }
}

void
markRun(bool* mark) {
    EXPECT_FALSE(*mark);
    *mark = true;
57
58
59
60
}

// Wait for a thread to end first. The variable must be set at the time.
TEST(ThreadTest, wait) {
61
    for (size_t i = 0; i < iterations; ++i) {
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
        bool mark = false;
        Thread thread(boost::bind(markRun, &mark));
        thread.wait();
        ASSERT_TRUE(mark) << "Not finished yet in " << i << "th iteration";
        // Can't wait second time
        ASSERT_THROW(thread.wait(), isc::InvalidOperation);
    }
}

void
throwSomething() {
    throw 42; // Throw something really unusual, to see everything is caught.
}

// Exception in the thread we forget about should not do anything to us
TEST(ThreadTest, detachedException) {
78
    for (size_t i = 0; i < detached_iterations; ++i) {
79
80
        Thread thread(throwSomething);
    }
81
82
83
84
}

// An uncaught exception in the thread should propagate through wait
TEST(ThreadTest, exception) {
85
    for (size_t i = 0; i < iterations; ++i) {
86
87
88
89
90
91
        Thread thread(throwSomething);
        ASSERT_THROW(thread.wait(), Thread::UncaughtException);
    }
}

}