added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / impl / simulated_failure.hpp
1 /*************************************************************************
2  *
3  * Copyright 2016 Realm Inc.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  **************************************************************************/
18
19 #ifndef REALM_IMPL_SIMULATED_FAILURE_HPP
20 #define REALM_IMPL_SIMULATED_FAILURE_HPP
21
22 #include <cstdint>
23 #include <system_error>
24
25 #include <realm/util/features.h>
26
27 #ifdef REALM_DEBUG
28 #define REALM_ENABLE_SIMULATED_FAILURE
29 #endif
30
31 namespace realm {
32 namespace _impl {
33
34 class SimulatedFailure : public std::system_error {
35 public:
36     enum FailureType {
37         generic,
38         slab_alloc__reset_free_space_tracking,
39         slab_alloc__remap,
40         shared_group__grow_reader_mapping,
41         sync_client__read_head,
42         sync_server__read_head,
43         _num_failure_types
44     };
45
46     class OneShotPrimeGuard;
47     class RandomPrimeGuard;
48
49     /// Prime the specified failure type on the calling thread for triggering
50     /// once.
51     static void prime_one_shot(FailureType);
52
53     /// Prime the specified failure type on the calling thread for triggering
54     /// randomly \a n out of \a m times.
55     static void prime_random(FailureType, int n, int m, uint_fast64_t seed = 0);
56
57     /// Unprime the specified failure type on the calling thread.
58     static void unprime(FailureType) noexcept;
59
60     /// Returns true according to the mode of priming of the specified failure
61     /// type on the calling thread, but only if REALM_ENABLE_SIMULATED_FAILURE
62     /// was defined during compilation. If REALM_ENABLE_SIMULATED_FAILURE was
63     /// not defined, this function always return false.
64     static bool check_trigger(FailureType) noexcept;
65
66     /// The specified error code is set to `make_error_code(failure_type)` if
67     /// check_trigger() returns true. Otherwise it is set to
68     /// `std::error_code()`. Returns a copy of the updated error code.
69     static std::error_code trigger(FailureType failure_type, std::error_code&) noexcept;
70
71     /// Throws SimulatedFailure if check_trigger() returns true. The exception
72     /// will be constructed with an error code equal to
73     /// `make_error_code(failure_type)`.
74     static void trigger(FailureType failure_type);
75
76     /// Returns true when, and only when REALM_ENABLE_SIMULATED_FAILURE was
77     /// defined during compilation.
78     static constexpr bool is_enabled();
79
80     SimulatedFailure(std::error_code);
81
82 private:
83 #ifdef REALM_ENABLE_SIMULATED_FAILURE
84     static void do_prime_one_shot(FailureType);
85     static void do_prime_random(FailureType, int n, int m, uint_fast64_t seed);
86     static void do_unprime(FailureType) noexcept;
87     static bool do_check_trigger(FailureType) noexcept;
88 #endif
89 };
90
91 std::error_code make_error_code(SimulatedFailure::FailureType) noexcept;
92     
93 class SimulatedFailure::OneShotPrimeGuard {
94 public:
95     OneShotPrimeGuard(FailureType);
96     ~OneShotPrimeGuard() noexcept;
97
98 private:
99     const FailureType m_type;
100 };
101
102
103 class SimulatedFailure::RandomPrimeGuard {
104 public:
105     RandomPrimeGuard(FailureType, int n, int m, uint_fast64_t seed = 0);
106     ~RandomPrimeGuard() noexcept;
107
108 private:
109     const FailureType m_type;
110 };
111
112 std::error_code make_error_code(SimulatedFailure::FailureType) noexcept;
113
114 } // namespace _impl
115 } // namespace realm
116
117 namespace std {
118
119 template<> struct is_error_code_enum<realm::_impl::SimulatedFailure::FailureType> {
120     static const bool value = true;
121 };
122
123 } // namespace std
124
125 namespace realm {
126 namespace _impl {
127
128
129 // Implementation
130
131 inline void SimulatedFailure::prime_one_shot(FailureType failure_type)
132 {
133 #ifdef REALM_ENABLE_SIMULATED_FAILURE
134     do_prime_one_shot(failure_type);
135 #else
136     static_cast<void>(failure_type);
137 #endif
138 }
139
140 inline void SimulatedFailure::prime_random(FailureType failure_type, int n, int m, uint_fast64_t seed)
141 {
142 #ifdef REALM_ENABLE_SIMULATED_FAILURE
143     do_prime_random(failure_type, n, m, seed);
144 #else
145     static_cast<void>(failure_type);
146     static_cast<void>(n);
147     static_cast<void>(m);
148     static_cast<void>(seed);
149 #endif
150 }
151
152 inline void SimulatedFailure::unprime(FailureType failure_type) noexcept
153 {
154 #ifdef REALM_ENABLE_SIMULATED_FAILURE
155     do_unprime(failure_type);
156 #else
157     static_cast<void>(failure_type);
158 #endif
159 }
160
161 inline bool SimulatedFailure::check_trigger(FailureType failure_type) noexcept
162 {
163 #ifdef REALM_ENABLE_SIMULATED_FAILURE
164     return do_check_trigger(failure_type);
165 #else
166     static_cast<void>(failure_type);
167     return false;
168 #endif
169 }
170
171 inline std::error_code SimulatedFailure::trigger(FailureType failure_type, std::error_code& ec) noexcept
172 {
173     if (check_trigger(failure_type)) {
174         ec = make_error_code(failure_type);
175     }
176     else {
177         ec = std::error_code();
178     }
179     return ec;
180 }
181
182 inline void SimulatedFailure::trigger(FailureType failure_type)
183 {
184     if (check_trigger(failure_type))
185         throw SimulatedFailure(make_error_code(failure_type));
186 }
187
188 inline constexpr bool SimulatedFailure::is_enabled()
189 {
190 #ifdef REALM_ENABLE_SIMULATED_FAILURE
191     return true;
192 #else
193     return false;
194 #endif
195 }
196
197 inline SimulatedFailure::SimulatedFailure(std::error_code ec)
198     : std::system_error(ec)
199 {
200 }
201
202 inline SimulatedFailure::OneShotPrimeGuard::OneShotPrimeGuard(FailureType failure_type)
203     : m_type(failure_type)
204 {
205     prime_one_shot(m_type);
206 }
207
208 inline SimulatedFailure::OneShotPrimeGuard::~OneShotPrimeGuard() noexcept
209 {
210     unprime(m_type);
211 }
212
213 inline SimulatedFailure::RandomPrimeGuard::RandomPrimeGuard(FailureType failure_type, int n, int m,
214                                                             uint_fast64_t seed)
215     : m_type(failure_type)
216 {
217     prime_random(m_type, n, m, seed);
218 }
219
220 inline SimulatedFailure::RandomPrimeGuard::~RandomPrimeGuard() noexcept
221 {
222     unprime(m_type);
223 }
224
225 } // namespace _impl
226 } // namespace realm
227
228 #endif // REALM_IMPL_SIMULATED_FAILURE_HPP