File: error-test.c

package info (click to toggle)
snapd 2.72-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 80,412 kB
  • sloc: sh: 16,506; ansic: 16,211; python: 11,213; makefile: 1,919; exp: 190; awk: 58; xml: 22
file content (258 lines) | stat: -rw-r--r-- 9,847 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/*
 * Copyright (C) 2016 Canonical Ltd
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "error.h"
#include "error.c"

#include <errno.h>
#include <glib.h>

static void test_sc_error_init(void) {
    struct sc_error *err;
    // Create an error
    err = sc_error_init("domain", 42, "printer is on %s", "fire");
    g_assert_nonnull(err);
    g_test_queue_destroy((GDestroyNotify)sc_error_free, err);

    // Inspect the exposed attributes
    g_assert_cmpstr(sc_error_domain(err), ==, "domain");
    g_assert_cmpint(sc_error_code(err), ==, 42);
    g_assert_cmpstr(sc_error_msg(err), ==, "printer is on fire");
}

static void test_sc_error_init_from_errno(void) {
    struct sc_error *err;
    // Create an error
    err = sc_error_init_from_errno(ENOENT, "printer is on %s", "fire");
    g_assert_nonnull(err);
    g_test_queue_destroy((GDestroyNotify)sc_error_free, err);

    // Inspect the exposed attributes
    g_assert_cmpstr(sc_error_domain(err), ==, SC_ERRNO_DOMAIN);
    g_assert_cmpint(sc_error_code(err), ==, ENOENT);
    g_assert_cmpstr(sc_error_msg(err), ==, "printer is on fire");
}

static void test_sc_error_init_simple(void) {
    struct sc_error *err;
    // Create an error
    err = sc_error_init_simple("hello %s", "errors");
    g_assert_nonnull(err);
    g_test_queue_destroy((GDestroyNotify)sc_error_free, err);

    // Inspect the exposed attributes
    g_assert_cmpstr(sc_error_domain(err), ==, SC_LIBSNAP_DOMAIN);
    g_assert_cmpint(sc_error_code(err), ==, 0);
    g_assert_cmpstr(sc_error_msg(err), ==, "hello errors");
}

static void test_sc_error_init_api_misuse(void) {
    struct sc_error *err;
    // Create an error
    err = sc_error_init_api_misuse("foo cannot be %d", 42);
    g_assert_nonnull(err);
    g_test_queue_destroy((GDestroyNotify)sc_error_free, err);

    // Inspect the exposed attributes
    g_assert_cmpstr(sc_error_domain(err), ==, SC_LIBSNAP_DOMAIN);
    g_assert_cmpint(sc_error_code(err), ==, SC_API_MISUSE);
    g_assert_cmpstr(sc_error_msg(err), ==, "foo cannot be 42");
}

static void test_sc_error_cleanup(void) {
    // Check that sc_error_cleanup() is safe to use.

    // Cleanup is safe on NULL errors.
    struct sc_error *err = NULL;
    sc_cleanup_error(&err);

    // Cleanup is safe on non-NULL errors.
    err = sc_error_init("domain", 123, "msg");
    g_assert_nonnull(err);
    sc_cleanup_error(&err);
    g_assert_null(err);
}

static void test_sc_error_domain__NULL(void) {
    // Check that sc_error_domain() dies if called with NULL error.
    if (g_test_subprocess()) {
        // NOTE: the code below fools gcc 5.4 but your mileage may vary.
        struct sc_error *err = NULL;
        const char *domain = sc_error_domain(err);
        (void)(domain);
        g_test_message("expected not to reach this place");
        g_test_fail();
        return;
    }
    g_test_trap_subprocess(NULL, 0, 0);
    g_test_trap_assert_failed();
    g_test_trap_assert_stderr("cannot obtain error domain from NULL error\n");
}

static void test_sc_error_code__NULL(void) {
    // Check that sc_error_code() dies if called with NULL error.
    if (g_test_subprocess()) {
        // NOTE: the code below fools gcc 5.4 but your mileage may vary.
        struct sc_error *err = NULL;
        int code = sc_error_code(err);
        (void)(code);
        g_test_message("expected not to reach this place");
        g_test_fail();
        return;
    }
    g_test_trap_subprocess(NULL, 0, 0);
    g_test_trap_assert_failed();
    g_test_trap_assert_stderr("cannot obtain error code from NULL error\n");
}

static void test_sc_error_msg__NULL(void) {
    // Check that sc_error_msg() dies if called with NULL error.
    if (g_test_subprocess()) {
        // NOTE: the code below fools gcc 5.4 but your mileage may vary.
        struct sc_error *err = NULL;
        const char *msg = sc_error_msg(err);
        (void)(msg);
        g_test_message("expected not to reach this place");
        g_test_fail();
        return;
    }
    g_test_trap_subprocess(NULL, 0, 0);
    g_test_trap_assert_failed();
    g_test_trap_assert_stderr("cannot obtain error message from NULL error\n");
}

static void test_sc_die_on_error__NULL(void) {
    // Check that sc_die_on_error() does nothing if called with NULL error.
    if (g_test_subprocess()) {
        sc_die_on_error(NULL);
        return;
    }
    g_test_trap_subprocess(NULL, 0, 0);
    g_test_trap_assert_passed();
}

static void test_sc_die_on_error__regular(void) {
    // Check that sc_die_on_error() dies if called with an error.
    if (g_test_subprocess()) {
        struct sc_error *err = sc_error_init("domain", 42, "just testing");
        sc_die_on_error(err);
        return;
    }
    g_test_trap_subprocess(NULL, 0, 0);
    g_test_trap_assert_failed();
    g_test_trap_assert_stderr("just testing\n");
}

static void test_sc_die_on_error__errno(void) {
    // Check that sc_die_on_error() dies if called with an errno-based error.
    if (g_test_subprocess()) {
        struct sc_error *err = sc_error_init_from_errno(ENOENT, "just testing");
        sc_die_on_error(err);
        return;
    }
    g_test_trap_subprocess(NULL, 0, 0);
    g_test_trap_assert_failed();
    g_test_trap_assert_stderr("just testing: No such file or directory\n");
}

static void test_sc_error_forward__nothing(void) {
    // Check that forwarding NULL does exactly that.
    struct sc_error *recipient = (void *)0xDEADBEEF;
    struct sc_error *err = NULL;
    int rc;
    rc = sc_error_forward(&recipient, err);
    g_assert_null(recipient);
    g_assert_cmpint(rc, ==, 0);
}

static void test_sc_error_forward__something_somewhere(void) {
    // Check that forwarding a real error works OK.
    struct sc_error *recipient = NULL;
    struct sc_error *err = sc_error_init("domain", 42, "just testing");
    int rc;
    g_test_queue_destroy((GDestroyNotify)sc_error_free, err);
    g_assert_nonnull(err);
    rc = sc_error_forward(&recipient, err);
    g_assert_nonnull(recipient);
    g_assert_cmpint(rc, ==, -1);
}

static void test_sc_error_forward__something_nowhere(void) {
    // Check that forwarding a real error nowhere calls die()
    if (g_test_subprocess()) {
        // NOTE: the code below fools gcc 5.4 but your mileage may vary.
        struct sc_error **err_ptr = NULL;
        struct sc_error *err = sc_error_init("domain", 42, "just testing");
        g_test_queue_destroy((GDestroyNotify)sc_error_free, err);
        g_assert_nonnull(err);
        sc_error_forward(err_ptr, err);
        g_test_message("expected not to reach this place");
        g_test_fail();
        return;
    }
    g_test_trap_subprocess(NULL, 0, 0);
    g_test_trap_assert_failed();
    g_test_trap_assert_stderr("just testing\n");
}

static void test_sc_error_match__typical(void) {
    // NULL error doesn't match anything.
    g_assert_false(sc_error_match(NULL, "domain", 42));

    // Non-NULL error matches if domain and code both match.
    struct sc_error *err = sc_error_init("domain", 42, "just testing");
    g_test_queue_destroy((GDestroyNotify)sc_error_free, err);
    g_assert_true(sc_error_match(err, "domain", 42));
    g_assert_false(sc_error_match(err, "domain", 1));
    g_assert_false(sc_error_match(err, "other-domain", 42));
    g_assert_false(sc_error_match(err, "other-domain", 1));
}

static void test_sc_error_match__NULL_domain(void) {
    // Using a NULL domain is a fatal bug.
    if (g_test_subprocess()) {
        // NOTE: the code below fools gcc 5.4 but your mileage may vary.
        struct sc_error *err = NULL;
        const char *domain = NULL;
        g_assert_false(sc_error_match(err, domain, 42));
        g_test_message("expected not to reach this place");
        g_test_fail();
        return;
    }
    g_test_trap_subprocess(NULL, 0, 0);
    g_test_trap_assert_failed();
    g_test_trap_assert_stderr("cannot match error to a NULL domain\n");
}

static void __attribute__((constructor)) init(void) {
    g_test_add_func("/error/sc_error_init", test_sc_error_init);
    g_test_add_func("/error/sc_error_init_from_errno", test_sc_error_init_from_errno);
    g_test_add_func("/error/sc_error_init_simple", test_sc_error_init_simple);
    g_test_add_func("/error/sc_error_init_api_misue", test_sc_error_init_api_misuse);
    g_test_add_func("/error/sc_error_cleanup", test_sc_error_cleanup);
    g_test_add_func("/error/sc_error_domain/NULL", test_sc_error_domain__NULL);
    g_test_add_func("/error/sc_error_code/NULL", test_sc_error_code__NULL);
    g_test_add_func("/error/sc_error_msg/NULL", test_sc_error_msg__NULL);
    g_test_add_func("/error/sc_die_on_error/NULL", test_sc_die_on_error__NULL);
    g_test_add_func("/error/sc_die_on_error/regular", test_sc_die_on_error__regular);
    g_test_add_func("/error/sc_die_on_error/errno", test_sc_die_on_error__errno);
    g_test_add_func("/error/sc_error_formward/nothing", test_sc_error_forward__nothing);
    g_test_add_func("/error/sc_error_formward/something_somewhere", test_sc_error_forward__something_somewhere);
    g_test_add_func("/error/sc_error_formward/something_nowhere", test_sc_error_forward__something_nowhere);
    g_test_add_func("/error/sc_error_match/typical", test_sc_error_match__typical);
    g_test_add_func("/error/sc_error_match/NULL_domain", test_sc_error_match__NULL_domain);
}