nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* Unit tests for GThread |
2 | * Copyright (C) 2011 Red Hat, Inc |
||
3 | * Author: Matthias Clasen |
||
4 | * |
||
5 | * This work is provided "as is"; redistribution and modification |
||
6 | * in whole or in part, in any medium, physical or electronic is |
||
7 | * permitted without restriction. |
||
8 | * |
||
9 | * This work is distributed in the hope that it will be useful, |
||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
12 | * |
||
13 | * In no event shall the authors or contributors be liable for any |
||
14 | * direct, indirect, incidental, special, exemplary, or consequential |
||
15 | * damages (including, but not limited to, procurement of substitute |
||
16 | * goods or services; loss of use, data, or profits; or business |
||
17 | * interruption) however caused and on any theory of liability, whether |
||
18 | * in contract, strict liability, or tort (including negligence or |
||
19 | * otherwise) arising in any way out of the use of this software, even |
||
20 | * if advised of the possibility of such damage. |
||
21 | */ |
||
22 | |||
23 | #include <config.h> |
||
24 | |||
25 | #ifdef HAVE_SYS_TIME_H |
||
26 | #include <sys/time.h> |
||
27 | #endif |
||
28 | #include <sys/types.h> |
||
29 | #ifdef HAVE_SYS_PRCTL_H |
||
30 | #include <sys/prctl.h> |
||
31 | #endif |
||
32 | |||
33 | #include <glib.h> |
||
34 | |||
35 | #ifdef G_OS_UNIX |
||
36 | #include <unistd.h> |
||
37 | #include <sys/resource.h> |
||
38 | #endif |
||
39 | |||
40 | static gpointer |
||
41 | thread1_func (gpointer data) |
||
42 | { |
||
43 | g_thread_exit (GINT_TO_POINTER (1)); |
||
44 | |||
45 | g_assert_not_reached (); |
||
46 | |||
47 | return NULL; |
||
48 | } |
||
49 | |||
50 | /* test that g_thread_exit() works */ |
||
51 | static void |
||
52 | test_thread1 (void) |
||
53 | { |
||
54 | gpointer result; |
||
55 | GThread *thread; |
||
56 | GError *error = NULL; |
||
57 | |||
58 | thread = g_thread_try_new ("test", thread1_func, NULL, &error); |
||
59 | g_assert_no_error (error); |
||
60 | |||
61 | result = g_thread_join (thread); |
||
62 | |||
63 | g_assert_cmpint (GPOINTER_TO_INT (result), ==, 1); |
||
64 | } |
||
65 | |||
66 | static gpointer |
||
67 | thread2_func (gpointer data) |
||
68 | { |
||
69 | return g_thread_self (); |
||
70 | } |
||
71 | |||
72 | /* test that g_thread_self() works */ |
||
73 | static void |
||
74 | test_thread2 (void) |
||
75 | { |
||
76 | gpointer result; |
||
77 | GThread *thread; |
||
78 | |||
79 | thread = g_thread_new ("test", thread2_func, NULL); |
||
80 | |||
81 | g_assert (g_thread_self () != thread); |
||
82 | |||
83 | result = g_thread_join (thread); |
||
84 | |||
85 | g_assert (result == thread); |
||
86 | } |
||
87 | |||
88 | static gpointer |
||
89 | thread3_func (gpointer data) |
||
90 | { |
||
91 | GThread *peer = data; |
||
92 | gint retval; |
||
93 | |||
94 | retval = 3; |
||
95 | |||
96 | if (peer) |
||
97 | { |
||
98 | gpointer result; |
||
99 | |||
100 | result = g_thread_join (peer); |
||
101 | |||
102 | retval += GPOINTER_TO_INT (result); |
||
103 | } |
||
104 | |||
105 | return GINT_TO_POINTER (retval); |
||
106 | } |
||
107 | |||
108 | /* test that g_thread_join() works across peers */ |
||
109 | static void |
||
110 | test_thread3 (void) |
||
111 | { |
||
112 | gpointer result; |
||
113 | GThread *thread1, *thread2, *thread3; |
||
114 | |||
115 | thread1 = g_thread_new ("a", thread3_func, NULL); |
||
116 | thread2 = g_thread_new ("b", thread3_func, thread1); |
||
117 | thread3 = g_thread_new ("c", thread3_func, thread2); |
||
118 | |||
119 | result = g_thread_join (thread3); |
||
120 | |||
121 | g_assert_cmpint (GPOINTER_TO_INT(result), ==, 9); |
||
122 | } |
||
123 | |||
124 | /* test that thread creation fails as expected, |
||
125 | * by setting RLIMIT_NPROC ridiculously low |
||
126 | */ |
||
127 | static void |
||
128 | test_thread4 (void) |
||
129 | { |
||
130 | #ifdef HAVE_PRLIMIT |
||
131 | struct rlimit ol, nl; |
||
132 | GThread *thread; |
||
133 | GError *error; |
||
134 | gint ret; |
||
135 | |||
136 | /* Linux CAP_SYS_RESOURCE overrides RLIMIT_NPROC, and probably similar |
||
137 | * things are true on other systems. |
||
138 | */ |
||
139 | if (getuid () == 0 || geteuid () == 0) |
||
140 | return; |
||
141 | |||
142 | getrlimit (RLIMIT_NPROC, &nl); |
||
143 | nl.rlim_cur = 1; |
||
144 | |||
145 | if ((ret = prlimit (getpid(), RLIMIT_NPROC, &nl, &ol)) != 0) |
||
146 | g_error ("prlimit failed: %s\n", g_strerror (ret)); |
||
147 | |||
148 | error = NULL; |
||
149 | thread = g_thread_try_new ("a", thread1_func, NULL, &error); |
||
150 | g_assert (thread == NULL); |
||
151 | g_assert_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN); |
||
152 | g_error_free (error); |
||
153 | |||
154 | if ((ret = prlimit (getpid (), RLIMIT_NPROC, &ol, NULL)) != 0) |
||
155 | g_error ("resetting RLIMIT_NPROC failed: %s\n", g_strerror (ret)); |
||
156 | #endif |
||
157 | } |
||
158 | |||
159 | static void |
||
160 | test_thread5 (void) |
||
161 | { |
||
162 | GThread *thread; |
||
163 | |||
164 | thread = g_thread_new ("a", thread3_func, NULL); |
||
165 | g_thread_ref (thread); |
||
166 | g_thread_join (thread); |
||
167 | g_thread_unref (thread); |
||
168 | } |
||
169 | |||
170 | static gpointer |
||
171 | thread6_func (gpointer data) |
||
172 | { |
||
173 | #ifdef HAVE_PTHREAD_SETNAME_NP_WITH_TID |
||
174 | char name[16]; |
||
175 | |||
176 | pthread_getname_np (pthread_self(), name, 16); |
||
177 | |||
178 | g_assert_cmpstr (name, ==, data); |
||
179 | #endif |
||
180 | |||
181 | return NULL; |
||
182 | } |
||
183 | |||
184 | static void |
||
185 | test_thread6 (void) |
||
186 | { |
||
187 | GThread *thread; |
||
188 | |||
189 | thread = g_thread_new ("abc", thread6_func, "abc"); |
||
190 | g_thread_join (thread); |
||
191 | } |
||
192 | |||
193 | int |
||
194 | main (int argc, char *argv[]) |
||
195 | { |
||
196 | g_test_init (&argc, &argv, NULL); |
||
197 | |||
198 | g_test_add_func ("/thread/thread1", test_thread1); |
||
199 | g_test_add_func ("/thread/thread2", test_thread2); |
||
200 | g_test_add_func ("/thread/thread3", test_thread3); |
||
201 | g_test_add_func ("/thread/thread4", test_thread4); |
||
202 | g_test_add_func ("/thread/thread5", test_thread5); |
||
203 | g_test_add_func ("/thread/thread6", test_thread6); |
||
204 | |||
205 | return g_test_run (); |
||
206 | } |