diff options
Diffstat (limited to 'lib/eunit/src')
-rw-r--r-- | lib/eunit/src/Makefile | 4 | ||||
-rw-r--r-- | lib/eunit/src/eunit.erl | 5 | ||||
-rw-r--r-- | lib/eunit/src/eunit_data.erl | 282 | ||||
-rw-r--r-- | lib/eunit/src/eunit_internal.hrl | 1 | ||||
-rw-r--r-- | lib/eunit/src/eunit_lib.erl | 23 | ||||
-rw-r--r-- | lib/eunit/src/eunit_proc.erl | 12 | ||||
-rw-r--r-- | lib/eunit/src/eunit_server.erl | 3 |
7 files changed, 161 insertions, 169 deletions
diff --git a/lib/eunit/src/Makefile b/lib/eunit/src/Makefile index 32f75202a0..f4eaf6807a 100644 --- a/lib/eunit/src/Makefile +++ b/lib/eunit/src/Makefile @@ -73,7 +73,7 @@ APPUP_TARGET= $(EBIN)/$(APPUP_FILE) $(TARGET_FILES): $(BEHAVIOUR_TARGET_FILES) -debug opt: $(PARSE_TRANSFORM_BIN) $(OBJECTS) +$(TYPES): $(PARSE_TRANSFORM_BIN) $(OBJECTS) docs: @@ -121,7 +121,7 @@ release_spec: opt $(INSTALL_DIR) "$(RELSYSDIR)/ebin" $(INSTALL_DATA) $(PARSE_TRANSFORM_BIN) $(OBJECTS) "$(RELSYSDIR)/ebin" $(INSTALL_DIR) "$(RELSYSDIR)/src" - $(INSTALL_DATA) $(PARSE_TRANSFORM) $(SOURCES) "$(RELSYSDIR)/src" + $(INSTALL_DATA) $(PARSE_TRANSFORM) $(SOURCES) $(BEHAVIOUR_SOURCES) "$(RELSYSDIR)/src" $(INSTALL_DATA) $(INTERNAL_HRL_FILES) "$(RELSYSDIR)/src" $(INSTALL_DIR) "$(RELSYSDIR)/include" $(INSTALL_DATA) $(INCLUDE_DELIVERABLES) "$(RELSYSDIR)/include" diff --git a/lib/eunit/src/eunit.erl b/lib/eunit/src/eunit.erl index 0238885708..f30c238366 100644 --- a/lib/eunit/src/eunit.erl +++ b/lib/eunit/src/eunit.erl @@ -135,6 +135,11 @@ test(Tests) -> %% <dd>Displays more details about the running tests.</dd> %% <dt>`print_depth'</dt> %% <dd>Maximum depth to which terms are printed in case of error.</dd> +%% <dt>`exact_execution'</dt> +%% <dd>If this boolean flag is set to `true' framework will +%% not automatically execute tests found in related module suffixed with "_tests". +%% This behaviour might be unwanted if execution of modules found in a folder +%% is ordered while it contains both source and test modules.</dd> %% </dl> %% %% Options in the environment variable EUNIT are also included last in diff --git a/lib/eunit/src/eunit_data.erl b/lib/eunit/src/eunit_data.erl index a16faf2e80..f85e047f33 100644 --- a/lib/eunit/src/eunit_data.erl +++ b/lib/eunit/src/eunit_data.erl @@ -31,10 +31,8 @@ -include_lib("kernel/include/file.hrl"). --export([iter_init/2, iter_next/1, iter_prev/1, iter_id/1, - enter_context/3, get_module_tests/1]). - --import(lists, [foldr/3]). +-export([iter_init/3, iter_next/1, iter_prev/1, iter_id/1, + enter_context/3, get_module_tests/2]). -define(TICKS_PER_SECOND, 1000). @@ -105,7 +103,7 @@ %% @type fileName() = string() %% TODO: Can we mark up tests as known-failures? -%% TODO: Is it possible to handle known timout/setup failures? +%% TODO: Is it possible to handle known timeout/setup failures? %% TODO: Add diagnostic tests which never fail, but may cause warnings? %% --------------------------------------------------------------------- @@ -115,14 +113,15 @@ {prev = [], next = [], tests = [], + options, pos = 0, parent = []}). %% @spec (tests(), [integer()]) -> testIterator() %% @type testIterator() -iter_init(Tests, ParentID) -> - #iter{tests = Tests, parent = lists:reverse(ParentID)}. +iter_init(Tests, ParentID, Options) -> + #iter{tests = Tests, parent = lists:reverse(ParentID), options = Options}. %% @spec (testIterator()) -> [integer()] @@ -131,8 +130,8 @@ iter_id(#iter{pos = N, parent = Ns}) -> %% @spec (testIterator()) -> none | {testItem(), testIterator()} -iter_next(I = #iter{next = []}) -> - case next(I#iter.tests) of +iter_next(I = #iter{next = [], options = Options}) -> + case next(I#iter.tests, Options) of {T, Tests} -> {T, I#iter{prev = [T | I#iter.prev], tests = Tests, @@ -169,12 +168,12 @@ iter_prev(#iter{prev = [T | Ts]} = I) -> %% | {file_read_error, {Reason::atom(), Message::string(), %% fileName()}} -next(Tests) -> +next(Tests, Options) -> case eunit_lib:dlist_next(Tests) of [T | Ts] -> - case parse(T) of + case parse(T, Options) of {data, T1} -> - next([T1 | Ts]); + next([T1 | Ts], Options); T1 -> {T1, Ts} end; @@ -182,18 +181,21 @@ next(Tests) -> none end. +%% Temporary suppression +-compile([{nowarn_deprecated_function,[{slave,start_link,3},{slave,stop,1}]}]). + %% this returns either a #test{} or #group{} record, or {data, T} to %% signal that T has been substituted for the given representation -parse({foreach, S, Fs}) when is_function(S), is_list(Fs) -> - parse({foreach, S, fun ok/1, Fs}); -parse({foreach, S, C, Fs}) +parse({foreach, S, Fs}, Options) when is_function(S), is_list(Fs) -> + parse({foreach, S, fun ok/1, Fs}, Options); +parse({foreach, S, C, Fs}, Options) when is_function(S), is_function(C), is_list(Fs) -> - parse({foreach, ?DEFAULT_SETUP_PROCESS, S, C, Fs}); -parse({foreach, P, S, Fs}) + parse({foreach, ?DEFAULT_SETUP_PROCESS, S, C, Fs}, Options); +parse({foreach, P, S, Fs}, Options) when is_function(S), is_list(Fs) -> - parse({foreach, P, S, fun ok/1, Fs}); -parse({foreach, P, S, C, Fs} = T) + parse({foreach, P, S, fun ok/1, Fs}, Options); +parse({foreach, P, S, C, Fs} = T, _Options) when is_function(S), is_function(C), is_list(Fs) -> check_arity(S, 0, T), check_arity(C, 1, T), @@ -203,15 +205,15 @@ parse({foreach, P, S, C, Fs} = T) [] -> {data, []} end; -parse({foreachx, S1, Ps}) when is_function(S1), is_list(Ps) -> - parse({foreachx, S1, fun ok/2, Ps}); -parse({foreachx, S1, C1, Ps}) +parse({foreachx, S1, Ps}, Options) when is_function(S1), is_list(Ps) -> + parse({foreachx, S1, fun ok/2, Ps}, Options); +parse({foreachx, S1, C1, Ps}, Options) when is_function(S1), is_function(C1), is_list(Ps) -> - parse({foreachx, ?DEFAULT_SETUP_PROCESS, S1, C1, Ps}); -parse({foreachx, P, S1, Ps}) + parse({foreachx, ?DEFAULT_SETUP_PROCESS, S1, C1, Ps}, Options); +parse({foreachx, P, S1, Ps}, Options) when is_function(S1), is_list(Ps) -> - parse({foreachx, P, S1, fun ok/2, Ps}); -parse({foreachx, P, S1, C1, Ps} = T) + parse({foreachx, P, S1, fun ok/2, Ps}, Options); +parse({foreachx, P, S1, C1, Ps} = T, _Options) when is_function(S1), is_function(C1), is_list(Ps) -> check_arity(S1, 1, T), check_arity(C1, 2, T), @@ -227,12 +229,12 @@ parse({foreachx, P, S1, C1, Ps} = T) [] -> {data, []} end; -parse({generator, F}) when is_function(F) -> +parse({generator, F}, Options) when is_function(F) -> {module, M} = erlang:fun_info(F, module), {name, N} = erlang:fun_info(F, name), {arity, A} = erlang:fun_info(F, arity), - parse({generator, F, {M,N,A}}); -parse({generator, F, {M,N,A}} = T) + parse({generator, F, {M,N,A}}, Options); +parse({generator, F, {M,N,A}} = T, _Options) when is_function(F), is_atom(M), is_atom(N), is_integer(A) -> check_arity(F, 0, T), %% use run_testfun/1 to handle wrapper exceptions @@ -246,38 +248,38 @@ parse({generator, F, {M,N,A}} = T) {error, {Class, Reason, Trace}} -> throw({generator_failed, {{M,N,A}, {Class, Reason, Trace}}}) end; -parse({generator, M, F}) when is_atom(M), is_atom(F) -> - parse({generator, eunit_test:mf_wrapper(M, F), {M,F,0}}); -parse({inorder, T}) -> - group(#group{tests = T, order = inorder}); -parse({inparallel, T}) -> - parse({inparallel, 0, T}); -parse({inparallel, N, T}) when is_integer(N), N >= 0 -> - group(#group{tests = T, order = {inparallel, N}}); -parse({timeout, N, T}) when is_number(N), N >= 0 -> - group(#group{tests = T, timeout = round(N * ?TICKS_PER_SECOND)}); -parse({spawn, T}) -> - group(#group{tests = T, spawn = local}); -parse({spawn, N, T}) when is_atom(N) -> - group(#group{tests = T, spawn = {remote, N}}); -parse({setup, S, I}) when is_function(S); is_list(S) -> - parse({setup, ?DEFAULT_SETUP_PROCESS, S, I}); -parse({setup, S, C, I}) when is_function(S), is_function(C) -> - parse({setup, ?DEFAULT_SETUP_PROCESS, S, C, I}); -parse({setup, P, S, I}) when is_function(S) -> - parse({setup, P, S, fun ok/1, I}); -parse({setup, P, L, I} = T) when is_list(L) -> +parse({generator, M, F}, Options) when is_atom(M), is_atom(F) -> + parse({generator, eunit_test:mf_wrapper(M, F), {M,F,0}}, Options); +parse({inorder, T}, Options) -> + group(#group{tests = T, options = Options, order = inorder}); +parse({inparallel, T}, Options) -> + parse({inparallel, 0, T}, Options); +parse({inparallel, N, T}, Options) when is_integer(N), N >= 0 -> + group(#group{tests = T, options = Options, order = {inparallel, N}}); +parse({timeout, N, T}, Options) when is_number(N), N >= 0 -> + group(#group{tests = T, options = Options, timeout = round(N * ?TICKS_PER_SECOND)}); +parse({spawn, T}, Options) -> + group(#group{tests = T, options = Options, spawn = local}); +parse({spawn, N, T}, Options) when is_atom(N) -> + group(#group{tests = T, options = Options, spawn = {remote, N}}); +parse({setup, S, I}, Options) when is_function(S); is_list(S) -> + parse({setup, ?DEFAULT_SETUP_PROCESS, S, I}, Options); +parse({setup, S, C, I}, Options) when is_function(S), is_function(C) -> + parse({setup, ?DEFAULT_SETUP_PROCESS, S, C, I}, Options); +parse({setup, P, S, I}, Options) when is_function(S) -> + parse({setup, P, S, fun ok/1, I}, Options); +parse({setup, P, L, I} = T, Options) when is_list(L) -> check_setup_list(L, T), {S, C} = eunit_test:multi_setup(L), - parse({setup, P, S, C, I}); -parse({setup, P, S, C, I} = T) + parse({setup, P, S, C, I}, Options); +parse({setup, P, S, C, I} = T, Options) when is_function(S), is_function(C), is_function(I) -> check_arity(S, 0, T), check_arity(C, 1, T), case erlang:fun_info(I, arity) of {arity, 0} -> %% if I is nullary, it is a plain test - parse({setup, S, C, fun (_) -> I end}); + parse({setup, S, C, fun (_) -> I end}, Options); _ -> %% otherwise, I must be an instantiator function check_arity(I, 1, T), @@ -287,17 +289,17 @@ parse({setup, P, S, C, I} = T) {spawn, N} when is_atom(N) -> ok; _ -> bad_test(T) end, - group(#group{tests = I, + group(#group{tests = I, options = Options, context = #context{setup = S, cleanup = C, process = P}}) end; -parse({setup, P, S, C, {with, As}}) when is_list(As) -> - parse({setup, P, S, C, fun (X) -> {with, X, As} end}); -parse({setup, P, S, C, T}) when is_function(S), is_function(C) -> - parse({setup, P, S, C, fun (_) -> T end}); -parse({node, N, T}) when is_atom(N) -> - parse({node, N, "", T}); -parse({node, N, A, T1}=T) when is_atom(N) -> +parse({setup, P, S, C, {with, As}}, Options) when is_list(As) -> + parse({setup, P, S, C, fun (X) -> {with, X, As} end}, Options); +parse({setup, P, S, C, T}, Options) when is_function(S), is_function(C) -> + parse({setup, P, S, C, fun (_) -> T end}, Options); +parse({node, N, T}, Options) when is_atom(N) -> + parse({node, N, "", T}, Options); +parse({node, N, A, T1}=T, Options) when is_atom(N) -> case eunit_lib:is_string(A) of true -> %% TODO: better stack traces for internal funs like these @@ -333,14 +335,14 @@ parse({node, N, A, T1}=T) when is_atom(N) -> false -> ok end end, - T1}); + T1}, Options); false -> bad_test(T) end; -parse({module, M}) when is_atom(M) -> - {data, {"module '" ++ atom_to_list(M) ++ "'", get_module_tests(M)}}; -parse({application, A}) when is_atom(A) -> - try parse({file, atom_to_list(A)++".app"}) +parse({module, M}, Options) when is_atom(M) -> + {data, {"module '" ++ atom_to_list(M) ++ "'", get_module_tests(M, Options)}}; +parse({application, A}, Options) when is_atom(A) -> + try parse({file, atom_to_list(A)++".app"}, Options) catch {file_read_error,{enoent,_,_}} -> case code:lib_dir(A) of @@ -349,15 +351,15 @@ parse({application, A}) when is_atom(A) -> BinDir = filename:join(Dir, "ebin"), case file:read_file_info(BinDir) of {ok, #file_info{type=directory}} -> - parse({dir, BinDir}); + parse({dir, BinDir}, Options); _ -> - parse({dir, Dir}) + parse({dir, Dir}, Options) end; _ -> throw({application_not_found, A}) end end; -parse({application, A, Info}=T) when is_atom(A) -> +parse({application, A, Info}=T, _Options) when is_atom(A) -> case proplists:get_value(modules, Info) of Ms when is_list(Ms) -> case [M || M <- Ms, not is_atom(M)] of @@ -369,14 +371,14 @@ parse({application, A, Info}=T) when is_atom(A) -> _ -> bad_test(T) end; -parse({file, F} = T) when is_list(F) -> +parse({file, F} = T, _Options) when is_list(F) -> case eunit_lib:is_string(F) of true -> {data, {"file \"" ++ F ++ "\"", get_file_tests(F)}}; false -> bad_test(T) end; -parse({dir, D}=T) when is_list(D) -> +parse({dir, D}=T, _Options) when is_list(D) -> case eunit_lib:is_string(D) of true -> {data, {"directory \"" ++ D ++ "\"", @@ -384,45 +386,45 @@ parse({dir, D}=T) when is_list(D) -> false -> bad_test(T) end; -parse({with, X, As}=T) when is_list(As) -> +parse({with, X, As}=T, _Options) when is_list(As) -> case As of [A | As1] -> check_arity(A, 1, T), - {data, [{eunit_lib:fun_parent(A), fun () -> A(X) end}, + {data, [{erlang:fun_info_mfa(A), fun () -> A(X) end}, {with, X, As1}]}; [] -> {data, []} end; -parse({S, T1} = T) when is_list(S) -> +parse({S, T1} = T, Options) when is_list(S) -> case eunit_lib:is_string(S) of true -> - group(#group{tests = T1, desc = unicode:characters_to_binary(S)}); + group(#group{tests = T1, options = Options, desc = unicode:characters_to_binary(S)}); false -> bad_test(T) end; -parse({S, T1}) when is_binary(S) -> - group(#group{tests = T1, desc = S}); -parse(T) when is_tuple(T), size(T) > 2, is_list(element(1, T)) -> +parse({S, T1}, Options) when is_binary(S) -> + group(#group{tests = T1, options = Options, desc = S}); +parse(T, Options) when tuple_size(T) > 2, is_list(element(1, T)) -> [S | Es] = tuple_to_list(T), - parse({S, list_to_tuple(Es)}); -parse(T) when is_tuple(T), size(T) > 2, is_binary(element(1, T)) -> + parse({S, list_to_tuple(Es)}, Options); +parse(T, Options) when tuple_size(T) > 2, is_binary(element(1, T)) -> [S | Es] = tuple_to_list(T), - parse({S, list_to_tuple(Es)}); -parse(M) when is_atom(M) -> - parse({module, M}); -parse(T) when is_list(T) -> + parse({S, list_to_tuple(Es)}, Options); +parse(M, Options) when is_atom(M) -> + parse({module, M}, Options); +parse(T, Options) when is_list(T) -> case eunit_lib:is_string(T) of true -> - try parse({dir, T}) + try parse({dir, T}, Options) catch {file_read_error,{R,_,_}} when R =:= enotdir; R =:= enoent -> - parse({file, T}) + parse({file, T}, Options) end; false -> bad_test(T) end; -parse(T) -> +parse(T, _Options) -> parse_simple(T). %% parse_simple always produces a #test{} record @@ -436,7 +438,7 @@ parse_simple(F) -> parse_function(F) when is_function(F) -> check_arity(F, 0, F), - #test{f = F, location = eunit_lib:fun_parent(F)}; + #test{f = F, location = erlang:fun_info_mfa(F)}; parse_function({test, M, F}) when is_atom(M), is_atom(F) -> #test{f = eunit_test:mf_wrapper(M, F), location = {M, F, 0}}; parse_function({M, F}) when is_atom(M), is_atom(F) -> @@ -478,10 +480,10 @@ group(#group{context = #context{}} = G) -> %% suitable for lookahead (and anyway, properties of the setup %% should not be merged with properties of its body, e.g. spawn) G; -group(#group{tests = T0, desc = Desc, order = Order, context = Context, - spawn = Spawn, timeout = Timeout} = G) -> - {T1, Ts} = lookahead(T0), - {T2, _} = lookahead(Ts), +group(#group{tests = T0, desc = Desc, options = Options, order = Order, + context = Context, spawn = Spawn, timeout = Timeout} = G) -> + {T1, Ts} = lookahead(T0, Options), + {T2, _} = lookahead(Ts, Options), case T1 of #test{desc = Desc1, timeout = Timeout1} when T2 =:= none, Spawn =:= undefined, Context =:= undefined, @@ -526,8 +528,8 @@ group(#group{tests = T0, desc = Desc, order = Order, context = Context, G end. -lookahead(T) -> - case next(T) of +lookahead(T, Options) -> + case next(T, Options) of {T1, Ts} -> {T1, Ts}; none -> {none, []} end. @@ -556,58 +558,62 @@ push_order(_, _, G) -> %% @throws {module_not_found, moduleName()} -get_module_tests(M) -> - try M:module_info(exports) of - Es -> - Fs = get_module_tests_1(M, Es), - W = ?DEFAULT_MODULE_WRAPPER_NAME, - case lists:member({W,1}, Es) of - false -> Fs; - true -> {generator, fun () -> M:W(Fs) end} +get_module_tests(Module, Options) -> + try Module:module_info(exports) of + Exports -> + TestFuns = extract_module_tests(Module, Exports, Options), + case lists:member({?DEFAULT_MODULE_WRAPPER_NAME, 1}, Exports) of + false -> TestFuns; + true -> {generator, + fun() -> + Module:?DEFAULT_MODULE_WRAPPER_NAME(TestFuns) + end} end catch - error:undef -> - throw({module_not_found, M}) + error:undef -> + throw({module_not_found, Module}) end. -get_module_tests_1(M, Es) -> - Fs = testfuns(Es, M, ?DEFAULT_TEST_SUFFIX, - ?DEFAULT_GENERATOR_SUFFIX), - Name = atom_to_list(M), - case lists:suffix(?DEFAULT_TESTMODULE_SUFFIX, Name) of - false -> - Name1 = Name ++ ?DEFAULT_TESTMODULE_SUFFIX, - M1 = list_to_atom(Name1), - try get_module_tests(M1) of - Fs1 -> - Fs ++ [{"module '" ++ Name1 ++ "'", Fs1}] +extract_module_tests(Module, Exports, Options) -> + TestFuns = extract_testfuns(Exports, Module, ?DEFAULT_TEST_SUFFIX, + ?DEFAULT_GENERATOR_SUFFIX), + ModuleName = atom_to_list(Module), + Exact = proplists:get_bool(exact_execution, Options), + case {lists:suffix(?DEFAULT_TESTMODULE_SUFFIX, ModuleName), + Exact} of + {false, false} -> + ModuleNameWithSuffix = ModuleName ++ ?DEFAULT_TESTMODULE_SUFFIX, + ModuleWithSuffix = list_to_atom(ModuleNameWithSuffix), + try get_module_tests(ModuleWithSuffix, Options) of + MoreTestFuns -> + TestFuns ++ [{"module '" ++ ModuleNameWithSuffix ++ "'", + MoreTestFuns}] catch - {module_not_found, M1} -> - Fs + {module_not_found, ModuleWithSuffix} -> + TestFuns end; - true -> - Fs + _ -> + TestFuns end. -testfuns(Es, M, TestSuffix, GeneratorSuffix) -> - foldr(fun ({F, 0}, Fs) -> - N = atom_to_list(F), - case lists:suffix(TestSuffix, N) of - true -> - [{test, M, F} | Fs]; - false -> - case lists:suffix(GeneratorSuffix, N) of - true -> - [{generator, M, F} | Fs]; - false -> - Fs - end - end; - (_, Fs) -> - Fs - end, - [], - Es). +extract_testfuns(Exports, Module, TestSuffix, GeneratorSuffix) -> + GetTestFun = fun({Function, 0}, Acc) -> + FunctionName = atom_to_list(Function), + case lists:suffix(TestSuffix, FunctionName) of + true -> + [{test, Module, Function} | Acc]; + false -> + case lists:suffix(GeneratorSuffix, FunctionName) of + true -> + [{generator, Module, Function} | Acc]; + false -> + Acc + end + end; + (_, Acc) -> + Acc + end, + lists:foldr(GetTestFun, [], Exports). %% --------------------------------------------------------------------- diff --git a/lib/eunit/src/eunit_internal.hrl b/lib/eunit/src/eunit_internal.hrl index 65f4c433e7..217d4a304c 100644 --- a/lib/eunit/src/eunit_internal.hrl +++ b/lib/eunit/src/eunit_internal.hrl @@ -50,6 +50,7 @@ }). -record(group, {desc = undefined, + options = undefined, order = undefined, % run in order or in parallel timeout = undefined, context = undefined, % setup-context record diff --git a/lib/eunit/src/eunit_lib.erl b/lib/eunit/src/eunit_lib.erl index c7555597c2..e3129eb30f 100644 --- a/lib/eunit/src/eunit_lib.erl +++ b/lib/eunit/src/eunit_lib.erl @@ -32,7 +32,7 @@ -include("eunit_internal.hrl"). --export([dlist_next/1, uniq/1, fun_parent/1, is_string/1, command/1, +-export([dlist_next/1, uniq/1, is_string/1, command/1, command/2, command/3, trie_new/0, trie_store/2, trie_match/2, split_node/1, consult_file/1, list_dir/1, format_exit_term/1, format_exception/1, format_exception/2, format_error/1, format_error/2, @@ -378,27 +378,6 @@ split_node_2(As, Cs) -> {list_to_atom(lists:reverse(As)), list_to_atom(Cs)}. %% --------------------------------------------------------------------- -%% Get the name of the containing function for a fun. (This is encoded -%% in the name of the generated function that implements the fun.) -fun_parent(F) -> - {module, M} = erlang:fun_info(F, module), - {name, N} = erlang:fun_info(F, name), - case erlang:fun_info(F, type) of - {type, external} -> - {arity, A} = erlang:fun_info(F, arity), - {M, N, A}; - {type, local} -> - [$-|S] = atom_to_list(N), - [S2, T] = string:split(S, "/", trailing), - {M, list_to_atom(S2), element(1, string:to_integer(T))} - end. - --ifdef(TEST). -fun_parent_test() -> - {?MODULE,fun_parent_test,0} = fun_parent(fun (A) -> {ok,A} end). --endif. - -%% --------------------------------------------------------------------- %% Ye olde uniq function uniq([X, X | Xs]) -> uniq([X | Xs]); diff --git a/lib/eunit/src/eunit_proc.erl b/lib/eunit/src/eunit_proc.erl index 7622bab2a9..48254f53a3 100644 --- a/lib/eunit/src/eunit_proc.erl +++ b/lib/eunit/src/eunit_proc.erl @@ -29,13 +29,12 @@ -include("eunit.hrl"). -include("eunit_internal.hrl"). --export([start/4, get_output/0]). +-export([start/5, get_output/0]). %% This must be exported; see new_group_leader/1 for details. -export([group_leader_process/1]). --record(procstate, {ref, id, super, insulator, parent, order}). - +-record(procstate, {ref, id, super, insulator, parent, order, options}). %% Spawns test process and returns the process Pid; sends {done, %% Reference, Pid} to caller when finished. See the function @@ -44,12 +43,13 @@ %% The `Super' process receives a stream of status messages; see %% message_super/3 for details. -start(Tests, Order, Super, Reference) +start(Tests, Order, Super, Reference, Options) when is_pid(Super), is_reference(Reference) -> St = #procstate{ref = Reference, id = [], super = Super, - order = Order}, + order = Order, + options = Options}, spawn_group(local, #group{tests = Tests}, St). %% Fetches the output captured by the eunit group leader. This is @@ -436,7 +436,7 @@ wait_for_tasks(PidSet, St) -> %% TODO: Flow control, starting new job as soon as slot is available tests(T, St) -> - I = eunit_data:iter_init(T, St#procstate.id), + I = eunit_data:iter_init(T, St#procstate.id, St#procstate.options), case St#procstate.order of inorder -> tests_inorder(I, St); inparallel -> tests_inparallel(I, 0, St); diff --git a/lib/eunit/src/eunit_server.erl b/lib/eunit/src/eunit_server.erl index e46394d88c..6fb44e0170 100644 --- a/lib/eunit/src/eunit_server.erl +++ b/lib/eunit/src/eunit_server.erl @@ -243,7 +243,8 @@ start_job(Job, From, Reference, St) -> From ! {start, Reference}, %% The default is to run tests in order unless otherwise specified Order = proplists:get_value(order, Job#job.options, inorder), - eunit_proc:start(Job#job.test, Order, Job#job.super, Reference), + eunit_proc:start(Job#job.test, Order, Job#job.super, Reference, + Job#job.options), St#state{jobs = dict:store(Reference, From, St#state.jobs)}. handle_done(Reference, St) -> |