065c783312af2e04e471cd47df8e85201b55882a
[android-sdk/platform-bionic.git] / tests / setjmp_test.cpp
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
17 #include <gtest/gtest.h>
19 #include <setjmp.h>
20 #include <stdlib.h>
22 TEST(setjmp, setjmp_smoke) {
23   int value;
24   jmp_buf jb;
25   if ((value = setjmp(jb)) == 0) {
26     longjmp(jb, 123);
27     FAIL(); // Unreachable.
28   } else {
29     ASSERT_EQ(123, value);
30   }
31 }
33 TEST(setjmp, _setjmp_smoke) {
34   int value;
35   jmp_buf jb;
36   if ((value = _setjmp(jb)) == 0) {
37     _longjmp(jb, 456);
38     FAIL(); // Unreachable.
39   } else {
40     ASSERT_EQ(456, value);
41   }
42 }
44 TEST(setjmp, sigsetjmp_0_smoke) {
45   int value;
46   sigjmp_buf jb;
47   if ((value = sigsetjmp(jb, 0)) == 0) {
48     siglongjmp(jb, 789);
49     FAIL(); // Unreachable.
50   } else {
51     ASSERT_EQ(789, value);
52   }
53 }
55 TEST(setjmp, sigsetjmp_1_smoke) {
56   int value;
57   sigjmp_buf jb;
58   if ((value = sigsetjmp(jb, 0)) == 0) {
59     siglongjmp(jb, 0xabc);
60     FAIL(); // Unreachable.
61   } else {
62     ASSERT_EQ(0xabc, value);
63   }
64 }
66 static sigset_t SigSetOf(int signal) {
67   sigset_t ss;
68   sigemptyset(&ss);
69   sigaddset(&ss, signal);
70   return ss;
71 }
73 TEST(setjmp, _setjmp_signal_mask) {
74   // _setjmp/_longjmp do not save/restore the signal mask.
75   sigset_t ss1(SigSetOf(SIGUSR1));
76   sigset_t ss2(SigSetOf(SIGUSR2));
77   sigprocmask(SIG_SETMASK, &ss1, NULL);
78   jmp_buf jb;
79   if (_setjmp(jb) == 0) {
80     sigprocmask(SIG_SETMASK, &ss2, NULL);
81     _longjmp(jb, 1);
82     FAIL(); // Unreachable.
83   } else {
84     sigset_t ss;
85     sigprocmask(SIG_SETMASK, NULL, &ss);
86     EXPECT_TRUE(sigismember(&ss, SIGUSR2));
87   }
88 }
90 TEST(setjmp, setjmp_signal_mask) {
91   // setjmp/longjmp do save/restore the signal mask on bionic, but not on glibc.
92   // This is a BSD versus System V historical accident. POSIX leaves the
93   // behavior unspecified, so any code that cares needs to use sigsetjmp.
94   sigset_t ss1(SigSetOf(SIGUSR1));
95   sigset_t ss2(SigSetOf(SIGUSR2));
96   sigprocmask(SIG_SETMASK, &ss1, NULL);
97   jmp_buf jb;
98   if (setjmp(jb) == 0) {
99     sigprocmask(SIG_SETMASK, &ss2, NULL);
100     longjmp(jb, 1);
101     FAIL(); // Unreachable.
102   } else {
103     sigset_t ss;
104     sigprocmask(SIG_SETMASK, NULL, &ss);
105 #if defined(__BIONIC__)
106     // bionic behaves like BSD and does save/restore the signal mask.
107     EXPECT_TRUE(sigismember(&ss, SIGUSR1));
108 #else
109     // glibc behaves like System V and doesn't save/restore the signal mask.
110     EXPECT_TRUE(sigismember(&ss, SIGUSR2));
111 #endif
112   }
115 TEST(setjmp, sigsetjmp_0_signal_mask) {
116   // sigsetjmp(0)/siglongjmp do not save/restore the signal mask.
117   sigset_t ss1(SigSetOf(SIGUSR1));
118   sigset_t ss2(SigSetOf(SIGUSR2));
119   sigprocmask(SIG_SETMASK, &ss1, NULL);
120   sigjmp_buf sjb;
121   if (sigsetjmp(sjb, 0) == 0) {
122     sigprocmask(SIG_SETMASK, &ss2, NULL);
123     siglongjmp(sjb, 1);
124     FAIL(); // Unreachable.
125   } else {
126     sigset_t ss;
127     sigprocmask(SIG_SETMASK, NULL, &ss);
128     EXPECT_TRUE(sigismember(&ss, SIGUSR2));
129   }
132 TEST(setjmp, sigsetjmp_1_signal_mask) {
133   // sigsetjmp(1)/siglongjmp does save/restore the signal mask.
134   sigset_t ss1(SigSetOf(SIGUSR1));
135   sigset_t ss2(SigSetOf(SIGUSR2));
136   sigprocmask(SIG_SETMASK, &ss1, NULL);
137   sigjmp_buf sjb;
138   if (sigsetjmp(sjb, 1) == 0) {
139     sigprocmask(SIG_SETMASK, &ss2, NULL);
140     siglongjmp(sjb, 1);
141     FAIL(); // Unreachable.
142   } else {
143     sigset_t ss;
144     sigprocmask(SIG_SETMASK, NULL, &ss);
145     EXPECT_TRUE(sigismember(&ss, SIGUSR1));
146   }