Transunit repository
Revision | 7b5efa55618cf2e1e21d5504036ba47c26e1cc42 (tree) |
---|---|
Zeit | 2019-05-19 09:34:08 |
Autor | AlaskanEmily <emily@alas...> |
Commiter | AlaskanEmily |
Add infinitely repeating producing mock
@@ -19,7 +19,7 @@ | ||
19 | 19 | % 3. This notice may not be removed or altered from any source distribution. |
20 | 20 | % |
21 | 21 | |
22 | -:- module mock. | |
22 | +:- module transunit.mock. | |
23 | 23 | |
24 | 24 | %=============================================================================% |
25 | 25 | % Implementation of a basic mock type. This is useful for implementing a |
@@ -38,6 +38,10 @@ | ||
38 | 38 | :- type mock(T). |
39 | 39 | |
40 | 40 | %-----------------------------------------------------------------------------% |
41 | +% Determines if a mock will repeat its contents or not. | |
42 | +:- type mock_option ---> repeat ; oneshot. | |
43 | + | |
44 | +%-----------------------------------------------------------------------------% | |
41 | 45 | % Determines if the mock considers any form of contention to be a fatal error. |
42 | 46 | % not_threadsafe will avoid a deadlock in incorrect usage of state_mocks, but |
43 | 47 | % is not suitable for multi-threaded use. |
@@ -58,22 +62,51 @@ | ||
58 | 62 | :- type maybe_state_mock(T) == state_mock(maybe.maybe(T)). |
59 | 63 | |
60 | 64 | %-----------------------------------------------------------------------------% |
61 | -% Creates a mock from a list of inputs. | |
65 | +% Creates a oneshot mock from a list of inputs. | |
62 | 66 | :- func init_mock(list(T)) = mock(T). |
63 | 67 | |
64 | 68 | %-----------------------------------------------------------------------------% |
65 | -% Creates a mock from an array of inputs. | |
69 | +% Creates a mock from a list of inputs. | |
70 | +:- func init_mock(mock_option, list(T)) = mock(T). | |
71 | + | |
72 | +%-----------------------------------------------------------------------------% | |
73 | +% Creates a oneshot mock from an array of inputs. | |
66 | 74 | :- func init_mock_from_array(array.array(T)) = mock(T). |
67 | 75 | |
68 | 76 | %-----------------------------------------------------------------------------% |
69 | -% Creates a state_mock from a list of inputs. | |
70 | -:- pred init_state_mock(list(T), state_option, state_mock(T), io.io, io.io). | |
77 | +% Creates a mock from an array of inputs. | |
78 | +:- func init_mock_from_array(mock_option, array.array(T)) = mock(T). | |
79 | + | |
80 | +%-----------------------------------------------------------------------------% | |
81 | +% Creates a oneshot state_mock from a list of inputs. | |
82 | +:- pred init_state_mock(state_option, | |
83 | + list(T), | |
84 | + state_mock(T), | |
85 | + io.io, io.io). | |
71 | 86 | :- mode init_state_mock(in, in, out, di, uo) is det. |
72 | 87 | |
73 | 88 | %-----------------------------------------------------------------------------% |
89 | +% Creates a state_mock from a list of inputs. | |
90 | +:- pred init_state_mock(state_option, | |
91 | + mock_option, | |
92 | + list(T), | |
93 | + state_mock(T), | |
94 | + io.io, io.io). | |
95 | +:- mode init_state_mock(in, in, in, out, di, uo) is det. | |
96 | + | |
97 | +%-----------------------------------------------------------------------------% | |
74 | 98 | % Creates a state_mock from an array of inputs. |
75 | -:- pred init_state_mock_from_array(array.array(T), | |
76 | - state_option, | |
99 | +:- pred init_state_mock_from_array(state_option, | |
100 | + mock_option, | |
101 | + array.array(T), | |
102 | + state_mock(T), | |
103 | + io.io, io.io). | |
104 | +:- mode init_state_mock_from_array(in, in, in, out, di, uo) is det. | |
105 | + | |
106 | +%-----------------------------------------------------------------------------% | |
107 | +% Creates a oneshot state_mock from an array of inputs. | |
108 | +:- pred init_state_mock_from_array(state_option, | |
109 | + array.array(T), | |
77 | 110 | state_mock(T), |
78 | 111 | io.io, io.io). |
79 | 112 | :- mode init_state_mock_from_array(in, in, out, di, uo) is det. |
@@ -120,17 +153,28 @@ | ||
120 | 153 | %=============================================================================% |
121 | 154 | |
122 | 155 | :- use_module exception. |
156 | +:- use_module int. | |
123 | 157 | :- use_module thread. |
158 | +:- use_module std_util. | |
124 | 159 | :- use_module thread.mvar. |
125 | 160 | |
126 | 161 | %-----------------------------------------------------------------------------% |
127 | 162 | |
128 | -:- type mock(T) ---> mock(list(T)). | |
163 | +:- type mock(T) ---> | |
164 | + repeat(array.array(T), int) ; | |
165 | + oneshot(list(T)). | |
166 | + | |
129 | 167 | :- type state_mock(T) ---> state_mock(thread.mvar.mvar(mock(T)), state_option). |
130 | 168 | |
131 | 169 | %-----------------------------------------------------------------------------% |
132 | 170 | |
133 | -init_mock(List) = mock(List). | |
171 | +init_mock(List) = oneshot(List). | |
172 | + | |
173 | +%-----------------------------------------------------------------------------% | |
174 | + | |
175 | +init_mock(oneshot, List) = oneshot(List). | |
176 | +init_mock(repeat, []) = oneshot([]). | |
177 | +init_mock(repeat, List) = repeat(array.array(List), 0) :- List = [_|_]. | |
134 | 178 | |
135 | 179 | %-----------------------------------------------------------------------------% |
136 | 180 |
@@ -138,36 +182,89 @@ init_mock_from_array(A) = init_mock(array.to_list(A)). | ||
138 | 182 | |
139 | 183 | %-----------------------------------------------------------------------------% |
140 | 184 | |
141 | -init_state_mock(List, Option, state_mock(Mvar, Option), !IO) :- | |
185 | +init_mock_from_array(oneshot, A) = oneshot(array.to_list(A)). | |
186 | +init_mock_from_array(repeat, A) = Result :- | |
187 | + array.bounds(A, Low, High), | |
188 | + builtin.compare(Cmp, Low, High), | |
189 | + ( | |
190 | + Cmp = (=), Result = oneshot([]) | |
191 | + ; | |
192 | + Cmp = (<), Result = repeat(array.copy(A), Low) | |
193 | + ; | |
194 | + Cmp = (>), | |
195 | + exception.throw(exception.software_error("Invalid array bounds")) | |
196 | + ). | |
197 | + | |
198 | +%-----------------------------------------------------------------------------% | |
199 | + | |
200 | +init_state_mock(Option, List, state_mock(Mvar, Option), !IO) :- | |
142 | 201 | thread.mvar.init(init_mock(List), Mvar, !IO). |
143 | 202 | |
144 | 203 | %-----------------------------------------------------------------------------% |
145 | 204 | |
146 | -init_state_mock_from_array(A, Option, Out, !IO) :- | |
147 | - init_state_mock(array.to_list(A), Option, Out, !IO). | |
205 | +init_state_mock(Option, MockOption, List, state_mock(Mvar, Option), !IO) :- | |
206 | + thread.mvar.init(init_mock(MockOption, List), Mvar, !IO). | |
207 | + | |
208 | +%-----------------------------------------------------------------------------% | |
209 | + | |
210 | +init_state_mock_from_array(Option, A, state_mock(Mvar, Option), !IO) :- | |
211 | + thread.mvar.init(init_mock_from_array(A), Mvar, !IO). | |
212 | + | |
213 | +%-----------------------------------------------------------------------------% | |
214 | + | |
215 | +init_state_mock_from_array(Option, MockOption, A, state_mock(Mvar, Option), !IO) :- | |
216 | + thread.mvar.init(init_mock_from_array(MockOption, A), Mvar, !IO). | |
217 | + | |
218 | +%-----------------------------------------------------------------------------% | |
219 | + | |
220 | +:- pred repeat_mock_retrieve(array.array(T), int, T, mock(T)). | |
221 | +:- mode repeat_mock_retrieve(in, in, out, out) is det. | |
222 | + | |
223 | +repeat_mock_retrieve(A, I, T, repeat(A, N)) :- | |
224 | + array.unsafe_lookup(A, I, T), | |
225 | + array.bounds(A, Low, High), | |
226 | + M = int.plus(I, 1), | |
227 | + builtin.compare(Cmp, M, High), | |
228 | + ( | |
229 | + Cmp = (=), N = Low | |
230 | + ; | |
231 | + Cmp = (<), N = M | |
232 | + ; | |
233 | + Cmp = (>), | |
234 | + exception.throw(exception.software_error("Invalid repeat index")) | |
235 | + ). | |
148 | 236 | |
149 | 237 | %-----------------------------------------------------------------------------% |
150 | 238 | |
151 | -mock_retrieve(maybe.no, mock([]), mock([])). | |
152 | -mock_retrieve(maybe.yes(T), mock([T|List]), mock(List)). | |
239 | +mock_retrieve(maybe.no, oneshot([]), oneshot([])). | |
240 | +mock_retrieve(maybe.yes(T), oneshot([T|List]), oneshot(List)). | |
241 | +mock_retrieve(maybe.yes(T), repeat(A, I), Out) :- | |
242 | + repeat_mock_retrieve(A, I, T, Out). | |
153 | 243 | |
154 | 244 | %-----------------------------------------------------------------------------% |
155 | 245 | |
156 | -maybe_mock_retrieve(maybe.no, mock([]), mock([])). | |
157 | -maybe_mock_retrieve(T, mock([T|List]), mock(List)). | |
246 | +maybe_mock_retrieve(maybe.no, oneshot([]), oneshot([])). | |
247 | +maybe_mock_retrieve(T, oneshot([T|List]), oneshot(List)). | |
248 | +maybe_mock_retrieve(T, repeat(A, I), Out) :- | |
249 | + repeat_mock_retrieve(A, I, T, Out). | |
158 | 250 | |
159 | 251 | %-----------------------------------------------------------------------------% |
160 | 252 | |
161 | -mock_try_retrieve(T, mock([T|List]), mock(List)). | |
253 | +mock_try_retrieve(T, oneshot([T|List]), oneshot(List)). | |
254 | +mock_try_retrieve(T, In, Out) :- | |
255 | + require_det ( | |
256 | + In = repeat(A, I), | |
257 | + repeat_mock_retrieve(A, I, T, Out) | |
258 | + ). | |
162 | 259 | |
163 | 260 | %-----------------------------------------------------------------------------% |
164 | 261 | % Gets the mock from a state_mock. |
165 | 262 | % - In threadsafe mode this will block for the mock to be available. |
166 | 263 | % - In not-threadsafe mode this will error if the mock is not available. |
167 | -:- pred get_mock(state_mock(T), mock(T), thread.mvar.mvar(mock(T)), io.io, io.io). | |
264 | +:- pred get_mock(state_mock(T), thread.mvar.mvar(mock(T)), mock(T), io.io, io.io). | |
168 | 265 | :- mode get_mock(in, out, out, di, uo) is det. |
169 | 266 | |
170 | -get_mock(state_mock(Mvar, not_threadsafe), Mock, Mvar, !IO) :- | |
267 | +get_mock(state_mock(Mvar, not_threadsafe), Mvar, Mock, !IO) :- | |
171 | 268 | thread.mvar.try_take(Mvar, MaybeMock, !IO), |
172 | 269 | ( |
173 | 270 | MaybeMock = maybe.yes(Mock) |
@@ -176,20 +273,19 @@ get_mock(state_mock(Mvar, not_threadsafe), Mock, Mvar, !IO) :- | ||
176 | 273 | MaybeMock = maybe.no, |
177 | 274 | exception.throw(exception.software_error("Invalid state in state_mock")) |
178 | 275 | ). |
179 | -get_mock(state_mock(Mvar, threadsafe), Mock, Mvar, !IO) :- | |
276 | +get_mock(state_mock(Mvar, threadsafe), Mvar, Mock, !IO) :- | |
180 | 277 | thread.mvar.take(Mvar, Mock, !IO). |
181 | 278 | |
182 | 279 | %-----------------------------------------------------------------------------% |
183 | 280 | |
184 | 281 | state_mock_retrieve(StateMock, Out, !IO) :- |
185 | - get_mock(StateMock, MockIn, Mvar, !IO), | |
282 | + get_mock(StateMock, Mvar, MockIn, !IO), | |
186 | 283 | mock_retrieve(Out, MockIn, MockOut), |
187 | 284 | thread.mvar.put(Mvar, MockOut, !IO). |
188 | 285 | |
189 | 286 | %-----------------------------------------------------------------------------% |
190 | 287 | |
191 | 288 | maybe_state_mock_retrieve(StateMock, Out, !IO) :- |
192 | - get_mock(StateMock, MockIn, Mvar, !IO), | |
289 | + get_mock(StateMock, Mvar, MockIn, !IO), | |
193 | 290 | maybe_mock_retrieve(Out, MockIn, MockOut), |
194 | 291 | thread.mvar.put(Mvar, MockOut, !IO). |
195 | - |