auser-poolparty 0.2.71 → 0.2.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. data/History.txt +3 -0
  2. data/Manifest.txt +38 -81
  3. data/PostInstall.txt +1 -1
  4. data/README.txt +1 -0
  5. data/lib/erlang/messenger/Makefile +15 -0
  6. data/lib/erlang/messenger/lib/eunit/Makefile +28 -0
  7. data/lib/erlang/messenger/lib/eunit/ebin/autoload.beam +0 -0
  8. data/lib/erlang/messenger/lib/eunit/ebin/code_monitor.beam +0 -0
  9. data/lib/erlang/messenger/lib/eunit/ebin/eunit.beam +0 -0
  10. data/lib/erlang/messenger/lib/eunit/ebin/eunit_autoexport.beam +0 -0
  11. data/lib/erlang/messenger/lib/eunit/ebin/eunit_data.beam +0 -0
  12. data/lib/erlang/messenger/lib/eunit/ebin/eunit_lib.beam +0 -0
  13. data/lib/erlang/messenger/lib/eunit/ebin/eunit_proc.beam +0 -0
  14. data/lib/erlang/messenger/lib/eunit/ebin/eunit_serial.beam +0 -0
  15. data/lib/erlang/messenger/lib/eunit/ebin/eunit_server.beam +0 -0
  16. data/lib/erlang/messenger/lib/eunit/ebin/eunit_striptests.beam +0 -0
  17. data/lib/erlang/messenger/lib/eunit/ebin/eunit_test.beam +0 -0
  18. data/lib/erlang/messenger/lib/eunit/ebin/eunit_tests.beam +0 -0
  19. data/lib/erlang/messenger/lib/eunit/ebin/eunit_tty.beam +0 -0
  20. data/lib/erlang/messenger/lib/eunit/ebin/file_monitor.beam +0 -0
  21. data/lib/erlang/messenger/lib/eunit/src/Makefile +46 -0
  22. data/lib/poolparty/dependency_resolutions/puppet.rb +1 -0
  23. data/lib/poolparty/modules/resourcing_dsl.rb +5 -5
  24. data/lib/poolparty/plugins/deploydirectory.rb +1 -1
  25. data/lib/poolparty/pool/resource.rb +12 -3
  26. data/lib/poolparty/spec/core/string.rb +8 -2
  27. data/lib/poolparty/spec/matchers/a_spec_extensions_base.rb +3 -1
  28. data/lib/poolparty/spec/matchers/have_deploydirectory.rb +11 -11
  29. data/lib/poolparty/spec/matchers/have_gempackage.rb +1 -1
  30. data/lib/poolparty/version.rb +1 -1
  31. data/lib/poolpartyspec.rb +1 -3
  32. data/poolparty.gemspec +44 -87
  33. data/spec/poolparty/plugins/deploydirectory_spec.rb +1 -0
  34. data/spec/poolparty/pool/resource_spec.rb +13 -0
  35. data/spec/poolparty/spec/core/string_spec.rb +57 -0
  36. data/website/index.html +2 -2
  37. metadata +43 -86
  38. data/lib/erlang/messenger/lib/eunit/.svn/all-wcprops +0 -53
  39. data/lib/erlang/messenger/lib/eunit/.svn/entries +0 -140
  40. data/lib/erlang/messenger/lib/eunit/.svn/format +0 -1
  41. data/lib/erlang/messenger/lib/eunit/.svn/prop-base/NOTES.svn-base +0 -5
  42. data/lib/erlang/messenger/lib/eunit/.svn/text-base/AUTHORS.svn-base +0 -2
  43. data/lib/erlang/messenger/lib/eunit/.svn/text-base/CHANGELOG.svn-base +0 -14
  44. data/lib/erlang/messenger/lib/eunit/.svn/text-base/COPYING.svn-base +0 -504
  45. data/lib/erlang/messenger/lib/eunit/.svn/text-base/NOTES.svn-base +0 -276
  46. data/lib/erlang/messenger/lib/eunit/.svn/text-base/README.svn-base +0 -3
  47. data/lib/erlang/messenger/lib/eunit/.svn/text-base/sys.config.svn-base +0 -9
  48. data/lib/erlang/messenger/lib/eunit/.svn/text-base/vsn.mk.svn-base +0 -1
  49. data/lib/erlang/messenger/lib/eunit/doc/.svn/all-wcprops +0 -59
  50. data/lib/erlang/messenger/lib/eunit/doc/.svn/entries +0 -142
  51. data/lib/erlang/messenger/lib/eunit/doc/.svn/format +0 -1
  52. data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/erlang.png.svn-base +0 -5
  53. data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/eunit.html.svn-base +0 -5
  54. data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/index.html.svn-base +0 -5
  55. data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/modules-frame.html.svn-base +0 -5
  56. data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/overview-summary.html.svn-base +0 -5
  57. data/lib/erlang/messenger/lib/eunit/doc/.svn/prop-base/packages-frame.html.svn-base +0 -5
  58. data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/edoc-info.svn-base +0 -3
  59. data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/erlang.png.svn-base +0 -0
  60. data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/eunit.html.svn-base +0 -172
  61. data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/index.html.svn-base +0 -17
  62. data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/modules-frame.html.svn-base +0 -12
  63. data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/overview-summary.html.svn-base +0 -984
  64. data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/overview.edoc.svn-base +0 -980
  65. data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/packages-frame.html.svn-base +0 -11
  66. data/lib/erlang/messenger/lib/eunit/doc/.svn/text-base/stylesheet.css.svn-base +0 -55
  67. data/lib/erlang/messenger/lib/eunit/ebin/.svn/all-wcprops +0 -5
  68. data/lib/erlang/messenger/lib/eunit/ebin/.svn/dir-prop-base +0 -8
  69. data/lib/erlang/messenger/lib/eunit/ebin/.svn/entries +0 -28
  70. data/lib/erlang/messenger/lib/eunit/ebin/.svn/format +0 -1
  71. data/lib/erlang/messenger/lib/eunit/examples/.svn/all-wcprops +0 -23
  72. data/lib/erlang/messenger/lib/eunit/examples/.svn/entries +0 -66
  73. data/lib/erlang/messenger/lib/eunit/examples/.svn/format +0 -1
  74. data/lib/erlang/messenger/lib/eunit/examples/.svn/prop-base/eunit_examples.erl.svn-base +0 -5
  75. data/lib/erlang/messenger/lib/eunit/examples/.svn/prop-base/fib.erl.svn-base +0 -5
  76. data/lib/erlang/messenger/lib/eunit/examples/.svn/text-base/eunit_examples.erl.svn-base +0 -339
  77. data/lib/erlang/messenger/lib/eunit/examples/.svn/text-base/fib.erl.svn-base +0 -19
  78. data/lib/erlang/messenger/lib/eunit/examples/.svn/text-base/tests.txt.svn-base +0 -1
  79. data/lib/erlang/messenger/lib/eunit/include/.svn/all-wcprops +0 -11
  80. data/lib/erlang/messenger/lib/eunit/include/.svn/entries +0 -41
  81. data/lib/erlang/messenger/lib/eunit/include/.svn/format +0 -1
  82. data/lib/erlang/messenger/lib/eunit/include/.svn/prop-base/eunit.hrl.svn-base +0 -5
  83. data/lib/erlang/messenger/lib/eunit/include/.svn/text-base/eunit.hrl.svn-base +0 -313
  84. data/lib/erlang/messenger/lib/eunit/src/.svn/all-wcprops +0 -113
  85. data/lib/erlang/messenger/lib/eunit/src/.svn/entries +0 -259
  86. data/lib/erlang/messenger/lib/eunit/src/.svn/format +0 -1
  87. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/autoload.erl.svn-base +0 -5
  88. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/code_monitor.erl.svn-base +0 -5
  89. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit.erl.svn-base +0 -5
  90. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_autoexport.erl.svn-base +0 -5
  91. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_data.erl.svn-base +0 -5
  92. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_internal.hrl.svn-base +0 -5
  93. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_lib.erl.svn-base +0 -5
  94. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_proc.erl.svn-base +0 -5
  95. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_serial.erl.svn-base +0 -5
  96. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_server.erl.svn-base +0 -5
  97. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_striptests.erl.svn-base +0 -5
  98. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_test.erl.svn-base +0 -5
  99. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_tests.erl.svn-base +0 -5
  100. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/eunit_tty.erl.svn-base +0 -5
  101. data/lib/erlang/messenger/lib/eunit/src/.svn/prop-base/file_monitor.erl.svn-base +0 -5
  102. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/autoload.erl.svn-base +0 -388
  103. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/code_monitor.erl.svn-base +0 -243
  104. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit.app.src.svn-base +0 -21
  105. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit.appup.src.svn-base +0 -1
  106. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit.erl.svn-base +0 -196
  107. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_autoexport.erl.svn-base +0 -102
  108. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_data.erl.svn-base +0 -798
  109. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_internal.hrl.svn-base +0 -48
  110. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_lib.erl.svn-base +0 -682
  111. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_proc.erl.svn-base +0 -552
  112. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_serial.erl.svn-base +0 -157
  113. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_server.erl.svn-base +0 -340
  114. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_striptests.erl.svn-base +0 -64
  115. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_test.erl.svn-base +0 -334
  116. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_tests.erl.svn-base +0 -45
  117. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/eunit_tty.erl.svn-base +0 -272
  118. data/lib/erlang/messenger/lib/eunit/src/.svn/text-base/file_monitor.erl.svn-base +0 -409
@@ -1,798 +0,0 @@
1
- %% This library is free software; you can redistribute it and/or modify
2
- %% it under the terms of the GNU Lesser General Public License as
3
- %% published by the Free Software Foundation; either version 2 of the
4
- %% License, or (at your option) any later version.
5
- %%
6
- %% This library is distributed in the hope that it will be useful, but
7
- %% WITHOUT ANY WARRANTY; without even the implied warranty of
8
- %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9
- %% Lesser General Public License for more details.
10
- %%
11
- %% You should have received a copy of the GNU Lesser General Public
12
- %% License along with this library; if not, write to the Free Software
13
- %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
14
- %% USA
15
- %%
16
- %% $Id$
17
- %%
18
- %% @author Richard Carlsson <richardc@it.uu.se>
19
- %% @copyright 2006 Richard Carlsson
20
- %% @private
21
- %% @see eunit
22
- %% @doc Interpretation of symbolic test representation
23
-
24
- -module(eunit_data).
25
-
26
- -include("eunit.hrl").
27
- -include("eunit_internal.hrl").
28
-
29
- -include_lib("kernel/include/file.hrl").
30
-
31
- -export([list/1, iter_init/2, iter_next/2, iter_prev/2, iter_id/1,
32
- list_size/1, enter_context/3]).
33
-
34
- -import(lists, [foldr/3]).
35
-
36
- -define(TICKS_PER_SECOND, 1000).
37
-
38
- %% @type tests() =
39
- %% SimpleTest
40
- %% | [tests()]
41
- %% | moduleName()
42
- %% | {module, moduleName()}
43
- %% | {application, appName()}
44
- %% | {application, appName(), [term()]}
45
- %% | fileName()
46
- %% | {file, fileName()}
47
- %% | {string(), tests()}
48
- %% | {generator, () -> tests()}
49
- %% | {generator, M::moduleName(), F::functionName()}
50
- %% | {spawn, tests()}
51
- %% | {spawn, Node::atom(), tests()}
52
- %% | {timeout, T::number(), tests()}
53
- %% | {inorder, tests()}
54
- %% | {inparallel, tests()}
55
- %% | {inparallel, N::integer(), tests()}
56
- %% | {with, X::any(), [AbstractTestFunction]}
57
- %% | {setup, Where::local | spawn | {spawn, Node::atom()},
58
- %% Setup::() -> (R::any()),
59
- %% Cleanup::(R::any()) -> any(),
60
- %% tests() | Instantiator
61
- %% }
62
- %% | {setup, Setup, Cleanup, tests() | Instantiator}
63
- %% | {setup, Where, Setup, tests() | Instantiator}
64
- %% | {setup, Setup, tests() | Instantiator}
65
- %% | {foreach, Where::local | spawn | {spawn, Node::atom()},
66
- %% Setup::() -> (R::any()),
67
- %% Cleanup::(R::any()) -> any(),
68
- %% [tests() | Instantiator]
69
- %% }
70
- %% | {foreach, Setup, Cleanup, [tests() | Instantiator]}
71
- %% | {foreach, Where, Setup, [tests() | Instantiator]}
72
- %% | {foreach, Setup, [tests() | Instantiator]}
73
- %% | {foreachx, Where::local | spawn | {spawn, Node::atom()},
74
- %% SetupX::(X::any()) -> (R::any()),
75
- %% CleanupX::(X::any(), R::any()) -> any(),
76
- %% Pairs::[{X::any(),
77
- %% (X::any(), R::any()) -> tests()}]
78
- %% }
79
- %% | {foreachx, SetupX, CleanupX, Pairs}
80
- %% | {foreachx, Where, SetupX, Pairs}
81
- %% | {foreachx, SetupX, Pairs}
82
- %% | {node, Node::atom(), tests() | Instantiator}
83
- %% | {node, Node, Args::string(), tests() | Instantiator}
84
- %%
85
- %% SimpleTest = TestFunction | {Line::integer(), SimpleTest}
86
- %%
87
- %% TestFunction = () -> any()
88
- %% | {M::moduleName(), F::functionName()}.
89
- %%
90
- %% AbstractTestFunction = (X::any()) -> any()
91
- %%
92
- %% Instantiator = (R::any()) -> tests()
93
- %% | {with, [AbstractTestFunction]}
94
- %%
95
- %% Note that `{string(), ...}' is a short-hand for `{string(), {...}}'
96
- %% if the tuple contains more than two elements.
97
- %%
98
- %% @type moduleName() = atom()
99
- %% @type functionName() = atom()
100
- %% @type appName() = atom()
101
- %% @type fileName() = string()
102
-
103
- %% ---------------------------------------------------------------------
104
- %% Abstract test set iterator
105
-
106
- -record(iter,
107
- {prev = [],
108
- next = [],
109
- tests = [],
110
- pos = 0,
111
- parent = []}).
112
-
113
- %% @spec (tests(), [integer()]) -> testIterator()
114
- %% @type testIterator()
115
-
116
- iter_init(Tests, ParentID) ->
117
- #iter{tests = Tests, parent = lists:reverse(ParentID)}.
118
-
119
- %% @spec (testIterator()) -> [integer()]
120
-
121
- iter_id(#iter{pos = N, parent = Ns}) ->
122
- lists:reverse(Ns, [N]).
123
-
124
- %% @spec (testIterator(), Handler) -> none | {testItem(), testIterator()}
125
- %% Handler = (term()) -> term()
126
-
127
- iter_next(I, H) ->
128
- iter_do(fun iter_next/1, I, H).
129
-
130
- iter_do(F, I, H) ->
131
- try F(I)
132
- catch
133
- throw:R -> H(R)
134
- end.
135
-
136
- iter_next(I = #iter{next = []}) ->
137
- case next(I#iter.tests) of
138
- {T, Tests} ->
139
- {T, I#iter{prev = [T | I#iter.prev],
140
- tests = Tests,
141
- pos = I#iter.pos + 1}};
142
- none ->
143
- none
144
- end;
145
- iter_next(I = #iter{next = [T | Ts]}) ->
146
- {T, I#iter{next = Ts,
147
- prev = [T | I#iter.prev],
148
- pos = I#iter.pos + 1}}.
149
-
150
- %% @spec (testIterator(), Handler) -> none | {testItem(), testIterator()}
151
- %% Handler = (term()) -> term()
152
-
153
- iter_prev(I, H) ->
154
- iter_do(fun iter_prev/1, I, H).
155
-
156
- iter_prev(#iter{prev = []}) ->
157
- none;
158
- iter_prev(#iter{prev = [T | Ts]} = I) ->
159
- {T, I#iter{prev = Ts,
160
- next = [T | I#iter.next],
161
- pos = I#iter.pos - 1}}.
162
-
163
-
164
- %% ---------------------------------------------------------------------
165
- %% Concrete test set representation iterator
166
-
167
- %% @spec (tests()) -> none | {testItem(), tests()}
168
- %% @type testItem() = #test{} | #group{}
169
- %% @throws {bad_test, term()}
170
- %% | {generator_failed, exception()}
171
- %% | {no_such_function, eunit_lib:mfa()}
172
- %% | {module_not_found, moduleName()}
173
- %% | {application_not_found, appName()}
174
- %% | {file_read_error, {Reason::atom(), Message::string(),
175
- %% fileName()}}
176
-
177
- next(Tests) ->
178
- case eunit_lib:dlist_next(Tests) of
179
- [T | Ts] ->
180
- case parse(T) of
181
- {data, T1} ->
182
- next([T1 | Ts]);
183
- T1 ->
184
- {T1, Ts}
185
- end;
186
- [] ->
187
- none
188
- end.
189
-
190
- %% this returns either a #test{} or #group{} record, or {data, T} to
191
- %% signal that T has been substituted for the given representation
192
-
193
- parse({foreach, S, Fs}) when is_function(S), is_list(Fs) ->
194
- parse({foreach, S, fun ok/1, Fs});
195
- parse({foreach, S, C, Fs})
196
- when is_function(S), is_function(C), is_list(Fs) ->
197
- parse({foreach, ?DEFAULT_SETUP_PROCESS, S, C, Fs});
198
- parse({foreach, P, S, Fs})
199
- when is_function(S), is_list(Fs) ->
200
- parse({foreach, P, S, fun ok/1, Fs});
201
- parse({foreach, P, S, C, Fs} = T)
202
- when is_function(S), is_function(C), is_list(Fs) ->
203
- check_arity(S, 0, T),
204
- check_arity(C, 1, T),
205
- case Fs of
206
- [F | Fs1] ->
207
- {data, [{setup, P, S, C, F}, {foreach, P, S, C, Fs1}]};
208
- [] ->
209
- {data, []}
210
- end;
211
- parse({foreachx, S1, Ps}) when is_function(S1), is_list(Ps) ->
212
- parse({foreachx, S1, fun ok/2, Ps});
213
- parse({foreachx, S1, C1, Ps})
214
- when is_function(S1), is_function(C1), is_list(Ps) ->
215
- parse({foreachx, ?DEFAULT_SETUP_PROCESS, S1, C1, Ps});
216
- parse({foreachx, P, S1, Ps})
217
- when is_function(S1), is_list(Ps) ->
218
- parse({foreachx, P, S1, fun ok/2, Ps});
219
- parse({foreachx, P, S1, C1, Ps} = T)
220
- when is_function(S1), is_function(C1), is_list(Ps) ->
221
- check_arity(S1, 1, T),
222
- check_arity(C1, 2, T),
223
- case Ps of
224
- [{X, F1} | Ps1] when is_function(F1) ->
225
- check_arity(F1, 2, T),
226
- S = fun () -> S1(X) end,
227
- C = fun (R) -> C1(X, R) end,
228
- F = fun (R) -> F1(X, R) end,
229
- {data, [{setup, P, S, C, F}, {foreachx, P, S1, C1, Ps1}]};
230
- [_|_] ->
231
- bad_test(T);
232
- [] ->
233
- {data, []}
234
- end;
235
- parse({generator, F} = T) when is_function(F) ->
236
- check_arity(F, 0, T),
237
- %% use run_testfun/1 to handle wrapper exceptions
238
- case eunit_test:run_testfun(F) of
239
- {ok, T1} ->
240
- {data, T1};
241
- {error, {Class, Reason, Trace}} ->
242
- throw({generator_failed, {Class, Reason, Trace}})
243
- end;
244
- parse({generator, M, F}) when is_atom(M), is_atom(F) ->
245
- parse({generator, eunit_test:function_wrapper(M, F)});
246
- parse({inorder, T}) ->
247
- group(#group{tests = T, order = inorder});
248
- parse({inparallel, T}) ->
249
- parse({inparallel, 0, T});
250
- parse({inparallel, N, T}) when is_integer(N), N >= 0 ->
251
- group(#group{tests = T, order = {inparallel, N}});
252
- parse({timeout, N, T}) when is_number(N), N >= 0 ->
253
- group(#group{tests = T, timeout = round(N * ?TICKS_PER_SECOND)});
254
- parse({spawn, T}) ->
255
- group(#group{tests = T, spawn = local});
256
- parse({spawn, N, T}) when is_atom(N) ->
257
- group(#group{tests = T, spawn = {remote, N}});
258
- parse({setup, S, I}) when is_function(S); is_list(S) ->
259
- parse({setup, ?DEFAULT_SETUP_PROCESS, S, I});
260
- parse({setup, S, C, I}) when is_function(S), is_function(C) ->
261
- parse({setup, ?DEFAULT_SETUP_PROCESS, S, C, I});
262
- parse({setup, P, S, I}) when is_function(S) ->
263
- parse({setup, P, S, fun ok/1, I});
264
- parse({setup, P, L, I} = T) when is_list(L) ->
265
- check_setup_list(L, T),
266
- {S, C} = eunit_test:multi_setup(L),
267
- parse({setup, P, S, C, I});
268
- parse({setup, P, S, C, I} = T)
269
- when is_function(S), is_function(C), is_function(I) ->
270
- check_arity(S, 0, T),
271
- check_arity(C, 1, T),
272
- case erlang:fun_info(I, arity) of
273
- {arity, 0} ->
274
- %% if I is nullary, it is a plain test
275
- parse({setup, S, C, fun (_) -> I end});
276
- _ ->
277
- %% otherwise, I must be an instantiator function
278
- check_arity(I, 1, T),
279
- case P of
280
- local -> ok;
281
- spawn -> ok;
282
- {spawn, N} when is_atom(N) -> ok;
283
- _ -> bad_test(T)
284
- end,
285
- group(#group{tests = I,
286
- context = #context{setup = S, cleanup = C,
287
- process = P}})
288
- end;
289
- parse({setup, P, S, C, {with, As}}) when is_list(As) ->
290
- parse({setup, P, S, C, fun (X) -> {with, X, As} end});
291
- parse({setup, P, S, C, T}) when is_function(S), is_function(C) ->
292
- parse({setup, P, S, C, fun (_) -> T end});
293
- parse({node, N, T}) when is_atom(N) ->
294
- parse({node, N, "", T});
295
- parse({node, N, A, T1}=T) when is_atom(N) ->
296
- case eunit_lib:is_string(A) of
297
- true ->
298
- %% TODO: better stack traces for internal funs like these
299
- parse({setup,
300
- fun () ->
301
- %% TODO: auto-start net_kernel if needed
302
- StartedNet = false,
303
- %% The following is commented out because of problems when running
304
- %% eunit as part of the init sequence (from the command line):
305
- %% StartedNet =
306
- %% case whereis(net_kernel) of
307
- %% undefined ->
308
- %% M = list_to_atom(atom_to_list(N)
309
- %% ++ "_master"),
310
- %% case net_kernel:start([M]) of
311
- %% {ok, _} ->
312
- %% true;
313
- %% {error, E} ->
314
- %% throw({net_kernel_start, E})
315
- %% end;
316
- %% _ -> false
317
- %% end,
318
- %% ?debugVal({started, StartedNet}),
319
- {Name, Host} = eunit_lib:split_node(N),
320
- {ok, Node} = slave:start_link(Host, Name, A),
321
- {Node, StartedNet}
322
- end,
323
- fun ({Node, StopNet}) ->
324
- %% ?debugVal({stop, StopNet}),
325
- slave:stop(Node),
326
- case StopNet of
327
- true -> net_kernel:stop();
328
- false -> ok
329
- end
330
- end,
331
- T1});
332
- false ->
333
- bad_test(T)
334
- end;
335
- parse({module, M}) when is_atom(M) ->
336
- {data, {"module '" ++ atom_to_list(M) ++ "'", get_module_tests(M)}};
337
- parse({application, A}) when is_atom(A) ->
338
- try parse({file, atom_to_list(A)++".app"})
339
- catch
340
- {file_read_error,{enoent,_,_}} ->
341
- case code:lib_dir(A) of
342
- Dir when is_list(Dir) ->
343
- %% add "ebin" if it exists, like code_server does
344
- BinDir = filename:join(Dir, "ebin"),
345
- case file:read_file_info(BinDir) of
346
- {ok, #file_info{type=directory}} ->
347
- parse({dir, BinDir});
348
- _ ->
349
- parse({dir, Dir})
350
- end;
351
- _ ->
352
- throw({application_not_found, A})
353
- end
354
- end;
355
- parse({application, A, Info}=T) when is_atom(A) ->
356
- case proplists:get_value(modules, Info) of
357
- Ms when is_list(Ms) ->
358
- case [M || M <- Ms, not is_atom(M)] of
359
- [] ->
360
- {data, {"application '" ++ atom_to_list(A) ++ "'", Ms}};
361
- _ ->
362
- bad_test(T)
363
- end;
364
- _ ->
365
- bad_test(T)
366
- end;
367
- parse({file, F} = T) when is_list(F) ->
368
- case eunit_lib:is_string(F) of
369
- true ->
370
- {data, {"file \"" ++ F ++ "\"", get_file_tests(F)}};
371
- false ->
372
- bad_test(T)
373
- end;
374
- parse({dir, D}=T) when is_list(D) ->
375
- case eunit_lib:is_string(D) of
376
- true ->
377
- {data, {"directory \"" ++ D ++ "\"", get_directory_modules(D)}};
378
- false ->
379
- bad_test(T)
380
- end;
381
- parse({with, X, As}=T) when is_list(As) ->
382
- case As of
383
- [A | As1] ->
384
- check_arity(A, 1, T),
385
- {data, [fun () -> A(X) end, {with, X, As1}]};
386
- [] ->
387
- {data, []}
388
- end;
389
- parse({S, T1} = T) when is_list(S) ->
390
- case eunit_lib:is_string(S) of
391
- true ->
392
- group(#group{tests = T1, desc = S});
393
- false ->
394
- bad_test(T)
395
- end;
396
- parse(T) when is_tuple(T), size(T) > 2, is_list(element(1, T)) ->
397
- [S | Es] = tuple_to_list(T),
398
- parse({S, list_to_tuple(Es)});
399
- parse(M) when is_atom(M) ->
400
- parse({module, M});
401
- parse(T) when is_list(T) ->
402
- case eunit_lib:is_string(T) of
403
- true ->
404
- try parse({dir, T})
405
- catch
406
- {file_read_error,{R,_,_}}
407
- when R =:= enotdir; R =:= enoent ->
408
- parse({file, T})
409
- end;
410
- false ->
411
- bad_test(T)
412
- end;
413
- parse(T) ->
414
- parse_simple(T).
415
-
416
- %% parse_simple always produces a #test{} record
417
-
418
- parse_simple({L, F}) when is_integer(L), L >= 0 ->
419
- (parse_simple(F))#test{line = L};
420
- parse_simple(F) ->
421
- parse_function(F).
422
-
423
- parse_function(F) when is_function(F) ->
424
- check_arity(F, 0, F),
425
- {module, M} = erlang:fun_info(F, module),
426
- #test{f = F, module = M, name = eunit_lib:fun_parent(F)};
427
- parse_function({M,F}) when is_atom(M), is_atom(F) ->
428
- #test{f = eunit_test:function_wrapper(M, F), module = M, name = F};
429
- parse_function(F) ->
430
- bad_test(F).
431
-
432
- check_arity(F, N, T) when is_function(F) ->
433
- case erlang:fun_info(F, arity) of
434
- {arity, N} ->
435
- ok;
436
- _ ->
437
- bad_test(T)
438
- end;
439
- check_arity(_, _, T) ->
440
- bad_test(T).
441
-
442
- check_setup_list([{Tag, S, C} | Es], T)
443
- when is_atom(Tag), is_function(S), is_function(C) ->
444
- check_arity(S, 0, T),
445
- check_arity(C, 1, T),
446
- check_setup_list(Es, T);
447
- check_setup_list([{Tag, S} | Es], T)
448
- when is_atom(Tag), is_function(S) ->
449
- check_arity(S, 0, T),
450
- check_setup_list(Es, T);
451
- check_setup_list([], _T) ->
452
- ok;
453
- check_setup_list(_, T) ->
454
- bad_test(T).
455
-
456
- bad_test(T) ->
457
- throw({bad_test, T}).
458
-
459
- ok(_) -> ok.
460
- ok(_, _) -> ok.
461
-
462
- %% This does some look-ahead and folds nested groups and tests where
463
- %% possible. E.g., {String, Test} -> Test#test{desc = String}.
464
-
465
- group(#group{context = #context{}} = G) ->
466
- %% leave as it is - the test body is an instantiator, which is not
467
- %% suitable for lookahead (and anyway, properties of the setup
468
- %% should not be merged with properties of its body, e.g. spawn)
469
- G;
470
- group(#group{tests = T0, desc = Desc, order = Order, context = Context,
471
- spawn = Spawn, timeout = Timeout} = G) ->
472
- {T1, Ts} = lookahead(T0),
473
- {T2, _} = lookahead(Ts),
474
- case T1 of
475
- #test{desc = Desc1, timeout = Timeout1}
476
- when T2 =:= none, Spawn =:= undefined, Context =:= undefined,
477
- ((Desc =:= undefined) or (Desc1 =:= undefined)),
478
- ((Timeout =:= undefined) or (Timeout1 =:= undefined)) ->
479
- %% a single test within a non-spawn/setup group: put the
480
- %% information directly on the test; drop the order
481
- T1#test{desc = join_properties(Desc, Desc1),
482
- timeout = join_properties(Timeout, Timeout1)};
483
-
484
- #test{timeout = undefined}
485
- when T2 =:= none, Timeout =/= undefined, Context =:= undefined ->
486
- %% a single test without timeout, within a non-joinable
487
- %% group with a timeout and no fixture: push the timeout to
488
- %% the test
489
- G#group{tests = {timeout, (Timeout div ?TICKS_PER_SECOND), T0},
490
- timeout = undefined};
491
-
492
- #group{desc = Desc1, order = Order1, context = Context1,
493
- spawn = Spawn1, timeout = Timeout1}
494
- when T2 =:= none,
495
- ((Desc =:= undefined) or (Desc1 =:= undefined)),
496
- ((Order =:= undefined) or (Order1 =:= undefined)),
497
- ((Context =:= undefined) or (Context1 =:= undefined)),
498
- ((Spawn =:= undefined) or (Spawn1 =:= undefined)),
499
- ((Timeout =:= undefined) or (Timeout1 =:= undefined)) ->
500
- %% two nested groups with non-conflicting properties
501
- group(T1#group{desc = join_properties(Desc, Desc1),
502
- order = join_properties(Order, Order1),
503
- context = join_properties(Context, Context1),
504
- spawn = join_properties(Spawn, Spawn1),
505
- timeout = join_properties(Timeout, Timeout1)});
506
-
507
- #group{order = Order1, timeout = Timeout1}
508
- when T2 =:= none ->
509
- %% two nested groups that cannot be joined: try to push the
510
- %% timeout and ordering properties to the inner group
511
- push_order(Order, Order1, push_timeout(Timeout, Timeout1, G));
512
-
513
- _ ->
514
- %% leave the group as it is and discard the lookahead
515
- G
516
- end.
517
-
518
- lookahead(T) ->
519
- case next(T) of
520
- {T1, Ts} -> {T1, Ts};
521
- none -> {none, []}
522
- end.
523
-
524
- join_properties(undefined, X) -> X;
525
- join_properties(X, undefined) -> X.
526
-
527
- push_timeout(Timeout, undefined, G=#group{context=undefined})
528
- when Timeout =/= undefined ->
529
- %% A timeout on a context (fixture) includes the setup/cleanup time
530
- %% and must not be propagated into the body
531
- G#group{tests = {timeout, (Timeout div ?TICKS_PER_SECOND), G#group.tests},
532
- timeout = undefined};
533
- push_timeout(_, _, G) ->
534
- G.
535
-
536
- push_order(inorder, undefined, G) ->
537
- G#group{tests = {inorder, G#group.tests}, order = undefined};
538
- push_order({inparallel, N}, undefined, G) ->
539
- G#group{tests = {inparallel, N, G#group.tests}, order = undefined};
540
- push_order(_, _, G) ->
541
- G.
542
-
543
- %% ---------------------------------------------------------------------
544
- %% Extracting test funs from a module
545
-
546
- %% @throws {module_not_found, moduleName()}
547
-
548
- get_module_tests(M) ->
549
- TestSuffix = ?DEFAULT_TEST_SUFFIX,
550
- GeneratorSuffix = ?DEFAULT_GENERATOR_SUFFIX,
551
- try M:module_info(exports) of
552
- Es ->
553
- Fs = testfuns(Es, M, TestSuffix, GeneratorSuffix),
554
- Name = atom_to_list(M),
555
- case lists:suffix(?DEFAULT_TESTMODULE_SUFFIX, Name) of
556
- false ->
557
- Name1 = Name ++ ?DEFAULT_TESTMODULE_SUFFIX,
558
- M1 = list_to_atom(Name1),
559
- try get_module_tests(M1) of
560
- Fs1 ->
561
- Fs ++ [{"module '" ++ Name1 ++ "'", Fs1}]
562
- catch
563
- {module_not_found, M1} ->
564
- Fs
565
- end;
566
- true ->
567
- Fs
568
- end
569
- catch
570
- error:undef ->
571
- throw({module_not_found, M})
572
- end.
573
-
574
- testfuns(Es, M, TestSuffix, GeneratorSuffix) ->
575
- foldr(fun ({F, 0}, Fs) ->
576
- N = atom_to_list(F),
577
- case lists:suffix(TestSuffix, N) of
578
- true ->
579
- [{M,F} | Fs];
580
- false ->
581
- case lists:suffix(GeneratorSuffix, N) of
582
- true ->
583
- [{generator, M, F} | Fs];
584
- false ->
585
- Fs
586
- end
587
- end;
588
- (_, Fs) ->
589
- Fs
590
- end,
591
- [],
592
- Es).
593
-
594
-
595
- %% ---------------------------------------------------------------------
596
- %% Getting a test set from a file
597
-
598
- %% @throws {file_read_error, {Reason::atom(), Message::string(),
599
- %% fileName()}}
600
-
601
- get_file_tests(F) ->
602
- case is_module_filename(F) of
603
- true ->
604
- %% look relative to current dir first
605
- case file:read_file_info(F) of
606
- {ok, #file_info{type=file}} ->
607
- objfile_test(F);
608
- _ ->
609
- %% (where_is_file/1 does not take a path argument)
610
- case code:where_is_file(F) of
611
- non_existing ->
612
- %% this will produce a suitable error message
613
- objfile_test(F);
614
- Path ->
615
- objfile_test(Path)
616
- end
617
- end;
618
- false ->
619
- eunit_lib:consult_file(F)
620
- end.
621
-
622
- is_module_filename(F) ->
623
- filename:extension(F) =:= code:objfile_extension().
624
-
625
- objfile_test(File) ->
626
- try
627
- {value, {module, M}} =
628
- lists:keysearch(module, 1, beam_lib:info(File)),
629
- {setup,
630
- fun () ->
631
- %% TODO: better error/stacktrace for this internal fun
632
- code:purge(M),
633
- {module,M} = code:load_abs(filename:rootname(File)),
634
- ok
635
- end,
636
- {module, M}}
637
- catch
638
- _:_ ->
639
- throw({file_read_error,
640
- {undefined, "extracting module name failed", File}})
641
- end.
642
-
643
-
644
- %% ---------------------------------------------------------------------
645
- %% Getting a list of module names from object files in a directory
646
-
647
- %% @throws {file_read_error, {Reason::atom(), Message::string(),
648
- %% fileName()}}
649
-
650
- %% TODO: handle packages (recursive search for files)
651
-
652
- get_directory_modules(D) ->
653
- [objfile_test(filename:join(D, F))
654
- || F <- eunit_lib:list_dir(D), is_module_filename(F)].
655
-
656
-
657
-
658
- %% ---------------------------------------------------------------------
659
- %% Entering a setup-context, with guaranteed cleanup.
660
-
661
- %% @spec (Tests::#context{}, Instantiate, Callback) -> any()
662
- %% Instantiate = (any()) -> tests()
663
- %% Callback = (tests()) -> any()
664
- %% @throws {context_error, Error, eunit_lib:exception()}
665
- %% Error = setup_failed | instantiation_failed | cleanup_failed
666
-
667
- enter_context(#context{setup = S, cleanup = C, process = P}, I, F) ->
668
- F1 = case P of
669
- local -> F;
670
- spawn -> fun (X) -> F({spawn, X}) end;
671
- {spawn, N} -> fun (T) -> F({spawn, N, T}) end
672
- end,
673
- eunit_test:enter_context(S, C, I, F1).
674
-
675
-
676
- %% ---------------------------------------------------------------------
677
- %% Returns a symbolic listing of a set of tests
678
- %%
679
- %% @type testInfoList() = [Entry]
680
- %% Entry = {item, testId(), Description, testName()}
681
- %% | {group, testId(), Description, testInfoList}
682
- %% Description = string()
683
- %% @type testId() = [integer()]
684
- %% @type testName() = {moduleName(), functionName()}
685
- %% | {moduleName(), functionName(), lineNumber()}
686
- %% @type lineNumber() = integer(). Proper line numbers are always >= 1.
687
- %%
688
- %% @throws {bad_test, term()}
689
- %% | {generator_failed, exception()}
690
- %% | {no_such_function, eunit_lib:mfa()}
691
- %% | {module_not_found, moduleName()}
692
- %% | {application_not_found, appName()}
693
- %% | {file_read_error, {Reason::atom(), Message::string(),
694
- %% fileName()}}
695
- %% | {context_error, instantiation_failed, eunit_lib:exception()}
696
-
697
- list(T) ->
698
- list(T, []).
699
-
700
- list(T, ParentID) ->
701
- list_loop(iter_init(T, ParentID)).
702
-
703
- list_loop(I) ->
704
- case iter_next(I, fun (R) -> throw({error, R}) end) of
705
- {T, I1} ->
706
- Id = iter_id(I1),
707
- case T of
708
- #test{} ->
709
- Name = case T#test.line of
710
- 0 -> {T#test.module, T#test.name};
711
- Line -> {T#test.module, T#test.name, Line}
712
- end,
713
- [{item, Id, desc_string(T#test.desc), Name}
714
- | list_loop(I1)];
715
- #group{context = Context} ->
716
- [{group, Id, desc_string(T#group.desc),
717
- list_context(Context, T#group.tests, Id)}
718
- | list_loop(I1)]
719
- end;
720
- none ->
721
- []
722
- end.
723
-
724
- desc_string(undefined) -> "";
725
- desc_string(S) -> S.
726
-
727
- list_context(undefined, T, ParentId) ->
728
- list(T, ParentId);
729
- list_context(#context{process = local}, T, ParentId) ->
730
- browse_context(T, fun (T) -> list(T, ParentId) end);
731
- list_context(#context{process = spawn}, T, ParentId) ->
732
- browse_context(T, fun (T) -> list({spawn, T}, ParentId) end);
733
- list_context(#context{process = {spawn, N}}, T, ParentId) ->
734
- browse_context(T, fun (T) -> list({spawn, N, T}, ParentId) end).
735
-
736
- browse_context(T, F) ->
737
- eunit_test:browse_context(T, F).
738
-
739
- list_size({item, _, _, _}) -> 1;
740
- list_size({group, _, _, Es}) -> list_size(Es);
741
- list_size(Es) when is_list(Es) ->
742
- lists:foldl(fun (E, N) -> N + list_size(E) end, 0, Es).
743
-
744
- -ifdef(TEST).
745
- generator_exported_() ->
746
- generator().
747
-
748
- generator() ->
749
- T = ?_test(ok),
750
- [T, T, T].
751
-
752
- echo_proc() ->
753
- receive {P,X} -> P ! X, echo_proc() end.
754
-
755
- ping(P) ->
756
- P ! {self(),ping}, receive ping -> ok end.
757
-
758
- data_test_() ->
759
- Setup = fun () -> spawn(fun echo_proc/0) end,
760
- Cleanup = fun (Pid) -> exit(Pid, kill) end,
761
- Fail = ?_test(throw(eunit)),
762
- T = ?_test(ok),
763
- Tests = [T,T,T],
764
- [?_assertMatch(ok, eunit:test(T)),
765
- ?_assertMatch(error, eunit:test(Fail)),
766
- ?_assertMatch(ok, eunit:test({generator, fun () -> Tests end})),
767
- ?_assertMatch(ok, eunit:test({generator, fun generator/0})),
768
- ?_assertMatch(ok, eunit:test({generator, ?MODULE, generator_exported_})),
769
- ?_assertMatch(ok, eunit:test({inorder, Tests})),
770
- ?_assertMatch(ok, eunit:test({inparallel, Tests})),
771
- ?_assertMatch(ok, eunit:test({timeout, 10, Tests})),
772
- ?_assertMatch(ok, eunit:test({spawn, Tests})),
773
- ?_assertMatch(ok, eunit:test({setup, Setup, Cleanup,
774
- fun (P) -> ?_test(ok = ping(P)) end})),
775
- %%?_assertMatch(ok, eunit:test({node, test@localhost, Tests})),
776
- ?_assertMatch(ok, eunit:test({module, eunit_lib})),
777
- ?_assertMatch(ok, eunit:test(eunit_lib)),
778
- ?_assertMatch(ok, eunit:test("examples/tests.txt"))
779
-
780
- %%?_test({foreach, Setup, [T, T, T]})
781
- ].
782
-
783
- lazy_test_() ->
784
- {spawn, [?_test(undefined = put(count, 0)),
785
- lazy_gen(7),
786
- ?_assertMatch(7, get(count))]}.
787
-
788
- lazy_gen(N) ->
789
- {generator,
790
- fun () ->
791
- if N > 0 ->
792
- [?_test(put(count,1+get(count)))
793
- | lazy_gen(N-1)];
794
- true ->
795
- []
796
- end
797
- end}.
798
- -endif.