1/* refcount.c: Tests for reference counting types
2 *
3 * Copyright 2018 Emmanuele Bassi
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <stdlib.h>
20#include <glib.h>
21
22/* test_grefcount: test the behavior of the grefcount API */
23static void
24test_grefcount (void)
25{
26 grefcount a, b;
27
28 /* init(a): 1 */
29 g_ref_count_init (rc: &a);
30 if (g_test_verbose ())
31 g_test_message (format: "init(a) := %d\n", (int) a);
32 g_assert_true (g_ref_count_compare (&a, 1));
33
34 /* inc(a): 2 */
35 g_ref_count_inc (rc: &a);
36 if (g_test_verbose ())
37 g_test_message (format: "inc(a) := %d\n", (int) a);
38 g_assert_false (g_ref_count_compare (&a, 1));
39 g_assert_false (g_ref_count_compare (&a, G_MAXINT));
40
41 /* b = a = 2 */
42 b = a;
43 if (g_test_verbose ())
44 g_test_message (format: "a := %d, b := %d\n", (int) a, (int) b);
45
46 /* inc(a): 3 */
47 g_ref_count_inc (rc: &a);
48 if (g_test_verbose ())
49 g_test_message (format: "inc(a) := %d\n", (int) a);
50
51 /* dec(b) = 1 */
52 if (g_test_verbose ())
53 g_test_message (format: "dec(b) := %d + 1\n", (int) b);
54 g_assert_false (g_ref_count_dec (&b));
55
56 /* dec(a) = 2 */
57 if (g_test_verbose ())
58 g_test_message (format: "dec(a) := %d + 1\n", (int) a);
59 g_assert_false (g_ref_count_dec (&a));
60
61 /* dec(b) = 0 */
62 if (g_test_verbose ())
63 g_test_message (format: "dec(b) := %d + 1\n", (int) b);
64 g_assert_true (g_ref_count_dec (&b));
65
66 /* dec(a) = 1 */
67 if (g_test_verbose ())
68 g_test_message (format: "dec(a) := %d + 1\n", (int) a);
69 g_assert_false (g_ref_count_dec (&a));
70
71 /* dec(a) = 0 */
72 if (g_test_verbose ())
73 g_test_message (format: "dec(a) := %d + 1\n", (int) a);
74 g_assert_true (g_ref_count_dec (&a));
75}
76
77/* test_grefcount_saturation: Saturating a grefcount counter
78 * does not cause an overflow; additionally, if we're building
79 * with checks enabled or with non-GCC compilers, it'll cause a
80 * warning
81 */
82static void
83test_grefcount_saturation (void)
84{
85 if (g_test_subprocess ())
86 {
87 grefcount a;
88
89 /* We're breaking abstraction here for convenience */
90 a = G_MININT + 1;
91
92 g_ref_count_inc (rc: &a);
93 g_assert_true (a == G_MININT);
94
95 g_ref_count_inc (rc: &a);
96 g_assert_true (a == G_MININT);
97
98 exit (status: 0);
99 }
100
101 g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 0);
102
103#if defined (G_DISABLE_CHECKS) && defined (__GNUC__)
104 /* With checks disabled we don't get any warning */
105 g_test_trap_assert_passed ();
106#else
107 /* Ensure that we got a warning when building with checks or with
108 * non-GCC compilers; the test will fail because of the critical
109 * warning being caught by GTest
110 */
111 g_test_trap_assert_failed ();
112 g_test_trap_assert_stderr ("*saturation*");
113#endif
114}
115
116/* test_gatomicrefcount: test the behavior of the gatomicrefcount API */
117static void
118test_gatomicrefcount (void)
119{
120 gatomicrefcount a, b;
121
122 /* init(a): 1 */
123 g_atomic_ref_count_init (arc: &a);
124 if (g_test_verbose ())
125 g_test_message (format: "init(a) := %d\n", (int) a);
126 g_assert_true (g_atomic_ref_count_compare (&a, 1));
127
128 /* inc(a): 2 */
129 g_atomic_ref_count_inc (arc: &a);
130 if (g_test_verbose ())
131 g_test_message (format: "inc(a) := %d\n", (int) a);
132 g_assert_false (g_atomic_ref_count_compare (&a, 1));
133 g_assert_false (g_atomic_ref_count_compare (&a, G_MAXINT));
134
135 /* b = a = 2 */
136 b = a;
137 if (g_test_verbose ())
138 g_test_message (format: "a := %d, b := %d\n", (int) a, (int) b);
139
140 /* inc(a): 3 */
141 g_atomic_ref_count_inc (arc: &a);
142 if (g_test_verbose ())
143 g_test_message (format: "inc(a) := %d\n", (int) a);
144
145 /* dec(b) = 1 */
146 if (g_test_verbose ())
147 g_test_message (format: "dec(b) := %d + 1\n", (int) b);
148 g_assert_false (g_atomic_ref_count_dec (&b));
149
150 /* dec(a) = 2 */
151 if (g_test_verbose ())
152 g_test_message (format: "dec(a) := %d + 1\n", (int) a);
153 g_assert_false (g_atomic_ref_count_dec (&a));
154
155 /* dec(b) = 0 */
156 if (g_test_verbose ())
157 g_test_message (format: "dec(b) := %d + 1\n", (int) b);
158 g_assert_true (g_atomic_ref_count_dec (&b));
159
160 /* dec(a) = 1 */
161 if (g_test_verbose ())
162 g_test_message (format: "dec(a) := %d + 1\n", (int) a);
163 g_assert_false (g_atomic_ref_count_dec (&a));
164
165 /* dec(a) = 0 */
166 if (g_test_verbose ())
167 g_test_message (format: "dec(a) := %d + 1\n", (int) a);
168 g_assert_true (g_atomic_ref_count_dec (&a));
169}
170
171/* test_gatomicrefcount_saturation: Saturating a gatomicrefcount counter
172 * does not cause an overflow; additionally, if we're building with
173 * checks enabled or with non-GCC compilers, it'll cause a warning
174 */
175static void
176test_gatomicrefcount_saturation (void)
177{
178 if (g_test_subprocess ())
179 {
180 gatomicrefcount a;
181
182 /* We're breaking abstraction here for convenience */
183 a = G_MAXINT - 1;
184
185 g_atomic_ref_count_inc (arc: &a);
186 g_assert_true (a == G_MAXINT);
187
188 g_atomic_ref_count_inc (arc: &a);
189 g_assert_true (a == G_MAXINT);
190
191 exit (status: 0);
192 }
193
194 g_test_trap_subprocess (NULL, usec_timeout: 0, test_flags: 0);
195
196#if defined (G_DISABLE_CHECKS) && defined (__GNUC__)
197 /* With checks disabled we don't get any warning */
198 g_test_trap_assert_passed ();
199#else
200 /* Ensure that we got a warning when building with checks or with
201 * non-GCC compilers; the test will fail because of the critical
202 * warning being caught by GTest
203 */
204 g_test_trap_assert_failed ();
205 g_test_trap_assert_stderr ("*saturation*");
206#endif
207}
208
209int
210main (int argc,
211 char *argv[])
212{
213 g_test_init (argc: &argc, argv: &argv, NULL);
214
215 g_test_add_func (testpath: "/refcount/grefcount", test_func: test_grefcount);
216 g_test_add_func (testpath: "/refcount/grefcount/saturation", test_func: test_grefcount_saturation);
217
218 g_test_add_func (testpath: "/refcount/gatomicrefcount", test_func: test_gatomicrefcount);
219 g_test_add_func (testpath: "/refcount/gatomicrefcount/saturation", test_func: test_gatomicrefcount_saturation);
220
221 return g_test_run ();
222}
223

source code of gtk/subprojects/glib/glib/tests/refcount.c