1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <errno.h>
17#include <signal.h>
18
19#include "test.h"
20
21static int handler_count = 0;
22const int sig = SIGALRM;
23
24void handler(int sig)
25{
26    handler_count++;
27}
28
29int prepare(sigset_t *set)
30{
31    handler_count = 0;
32
33    struct sigaction act = {.sa_flags = 0, .sa_handler = handler};
34    struct sigaction old_act = {0};
35    int result = sigaction(sig, &act, &old_act);
36    if (result != 0) {
37        return result;
38    }
39
40    if (handler_count != 0) {
41        return -1;
42    }
43
44    result = raise(sig);
45    if (result != 0) {
46        return result;
47    }
48
49    if (handler_count != 1) {
50        return -1;
51    }
52
53    result = sigemptyset(set);
54    if (result != 0) {
55        return result;
56    }
57
58    result = sigaddset(set, sig);
59    if (result != 0) {
60        return result;
61    }
62
63    result = sigprocmask(SIG_BLOCK, NULL, set);
64    if (result != 0) {
65        return result;
66    }
67
68    return 0;
69}
70
71/**
72 * @tc.name      : sigset_0100
73 * @tc.desc      : modifies the disposition of the signal sig with a handler
74 * @tc.level     : Level 0
75 */
76void sigset_0100(void)
77{
78    sigset_t set;
79    int result = prepare(&set);
80    if (result != 0) {
81        t_error("%s failed: result = %d\n", __func__, result);
82    }
83
84    result = sigemptyset(&set);
85    if (result != 0) {
86        t_error("%s failed: result = %d\n", __func__, result);
87    }
88
89    errno = 0;
90    sigset(sig, handler);
91    if (errno != 0) {
92        t_error("%s failed: errno = %d\n", __func__, errno);
93    }
94
95    result = sigprocmask(SIG_BLOCK, NULL, &set);
96    if (result != 0) {
97        t_error("%s failed: result = %d\n", __func__, result);
98    }
99
100    result = sigismember(&set, sig);
101    if (result != 0) {
102        t_error("%s failed: result = %d\n", __func__, result);
103    }
104}
105
106/**
107 * @tc.name      : sigset_0200
108 * @tc.desc      : modifies the disposition of the signal sig with SIG_IGN
109 * @tc.level     : Level 1
110 */
111void sigset_0200(void)
112{
113    sigset_t set;
114    int result = prepare(&set);
115    if (result != 0) {
116        t_error("%s failed: result = %d\n", __func__, result);
117    }
118
119    result = sigemptyset(&set);
120    if (result != 0) {
121        t_error("%s failed: result = %d\n", __func__, result);
122    }
123
124    errno = 0;
125    sigset(sig, SIG_IGN);
126    if (errno != 0) {
127        t_error("%s failed: errno = %d\n", __func__, errno);
128    }
129
130    result = sigprocmask(SIG_BLOCK, NULL, &set);
131    if (result != 0) {
132        t_error("%s failed: result = %d\n", __func__, result);
133    }
134
135    result = sigismember(&set, sig);
136    if (result != 0) {
137        t_error("%s failed: result = %d\n", __func__, result);
138    }
139}
140
141/**
142 * @tc.name      : sigset_0300
143 * @tc.desc      : modifies the disposition of the signal sig with SIG_DFL
144 * @tc.level     : Level 1
145 */
146void sigset_0300(void)
147{
148    sigset_t set;
149    int result = prepare(&set);
150    if (result != 0) {
151        t_error("%s failed: result = %d\n", __func__, result);
152    }
153
154    result = sigemptyset(&set);
155    if (result != 0) {
156        t_error("%s failed: result = %d\n", __func__, result);
157    }
158
159    errno = 0;
160    sigset(sig, SIG_DFL);
161    if (errno != 0) {
162        t_error("%s failed: errno = %d\n", __func__, errno);
163    }
164
165    result = sigprocmask(SIG_BLOCK, NULL, &set);
166    if (result != 0) {
167        t_error("%s failed: result = %d\n", __func__, result);
168    }
169
170    result = sigismember(&set, sig);
171    if (result != 0) {
172        t_error("%s failed: result = %d\n", __func__, result);
173    }
174}
175
176/**
177 * @tc.name      : sigset_0400
178 * @tc.desc      : modifies the disposition of the signal sig with SIG_HOLD
179 * @tc.level     : Level 1
180 */
181void sigset_0400(void)
182{
183    sigset_t set;
184    int result = prepare(&set);
185    if (result != 0) {
186        t_error("%s failed: result = %d\n", __func__, result);
187    }
188
189    result = sigemptyset(&set);
190    if (result != 0) {
191        t_error("%s failed: result = %d\n", __func__, result);
192    }
193
194    errno = 0;
195    sigset(sig, SIG_HOLD);
196    if (errno != 0) {
197        t_error("%s failed: errno = %d\n", __func__, errno);
198    }
199
200    result = sigprocmask(SIG_BLOCK, NULL, &set);
201    if (result != 0) {
202        t_error("%s failed: result = %d\n", __func__, result);
203    }
204
205    result = sigismember(&set, sig);
206    if (result == 0) {
207        t_error("%s failed: result = %d\n", __func__, result);
208    }
209}
210
211/**
212 * @tc.name      : sigset_0500
213 * @tc.desc      : modifies the disposition of the invalid signal sig
214 * @tc.level     : Level 2
215 */
216void sigset_0500(void)
217{
218    errno = 0;
219    int sig = 99999;
220
221    sigset(sig, SIG_DFL);
222    if (errno == 0) {
223        t_error("%s failed: errno = %d\n", __func__, errno);
224    }
225}
226
227int main(int argc, char *argv[])
228{
229    sigset_0100();
230    sigset_0200();
231    sigset_0300();
232    sigset_0400();
233    sigset_0500();
234
235    return t_status;
236}
237