%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1998-2016. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
%%
-module(int_SUITE).
-include_lib("common_test/include/ct.hrl").
%% Test server specific exports
-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1,
init_per_group/2,end_per_group/2]).
-export([init_per_testcase/2, end_per_testcase/2]).
%% Test cases
-export([interpret/1, guards/1, interpretable/1]).
-export([ append_1/1, append_2/1, member/1, reverse/1]).
%% Default timetrap timeout (set in init_per_testcase)
-define(default_timeout, ?t:minutes(1)).
init_per_testcase(interpretable, Config) ->
?line Dog=test_server:timetrap(?default_timeout),
[{watchdog, Dog}|Config];
init_per_testcase(_Case, Config) ->
%% Interpret some existing and non-existing modules
?line DataDir = ?config(data_dir, Config),
?line {module, lists1} = int:i(filename:join([DataDir,lists1])),
?line {module, guards} = int:i(filename:join([DataDir,guards])),
?line Dog=test_server:timetrap(?default_timeout),
[{watchdog, Dog}|Config].
end_per_testcase(interpretable, Config) ->
?line Dog=?config(watchdog, Config),
?line test_server:timetrap_cancel(Dog),
ok;
end_per_testcase(_Case, Config) ->
%% Quit interpreting
?line ok = int:n(lists1),
?line ok = int:n(guards),
?line Dog=?config(watchdog, Config),
?line test_server:timetrap_cancel(Dog),
?line ok.
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[interpret, guards, {group, list_suite}, interpretable].
groups() ->
[{list_suite, [], [{group, append}, reverse, member]},
{append, [], [append_1, append_2]}].
init_per_suite(Config) ->
DataDir = proplists:get_value(data_dir, Config),
{ok,OldCwd} = file:get_cwd(),
try
ok = file:set_cwd(DataDir),
make:all()
after
file:set_cwd(OldCwd)
end,
Config.
end_per_suite(_Config) ->
ok.
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
interpret(suite) ->
[];
interpret(doc) ->
["Interpreting modules"];
interpret(Config) when is_list(Config) ->
?line int:n(int:interpreted()),
%% Interpret some existing and non-existing modules
?line DataDir = ?config(data_dir, Config),
?line {module, lists1} = int:i(filename:join([DataDir,lists1])),
?line {module, ordsets1} = int:i(filename:join([DataDir,ordsets1])),
?line error = int:i(non_existent_module),
%% Check that the interpreter has the right view.
?line ExpectedResult = lists:sort([lists1, ordsets1]),
?line Result = int:interpreted(),
?line ExpectedResult = lists:sort(Result),
%% Uniterpret the modules.
?line ok = int:n(non_existent_module),
?line ok = int:n(lists1),
?line [ordsets1] = int:interpreted(),
?line ok = int:n("ordsets1"),
?line [] = int:interpreted(),
ok.
guards(suite) ->
[];
guards(doc) ->
"Evaluate guards.";
guards(Config) when is_list(Config) ->
ok = guards:guards().
append_1(suite) ->
[];
append_1(doc) ->
[];
append_1(Config) when is_list(Config) ->
?line test_server:format("In append_1~n"),
?line test_server:format("code:which(lists1)=~p~n",
[code:which(lists1)]),
?line test_server:format("lists1:append([a],[b])=~p~n",
[spawn_eval(lists1,append,[[a],[b]])]),
?line "abcdef"=spawn_eval(lists1,append,[["abc","def"]]),
?line [hej, du,[glade, [bagare]]]=
spawn_eval(lists1,append,[[[hej], [du], [[glade, [bagare]]]]]),
?line [10, [elem]]=spawn_eval(lists1,append,[[[10], [[elem]]]]),
ok.
append_2(suite) ->
[];
append_2(doc) ->
[];
append_2(Config) when is_list(Config) ->
?line test_server:format("In append_2~n"),
?line test_server:format("code:which(lists1)=~p~n",
[code:which(lists1)]),
?line "abcdef"=spawn_eval(lists1,append,["abc", "def"]),
?line [hej, du]=spawn_eval(lists1,append,[[hej], [du]]),
?line [10, [elem]]=spawn_eval(lists1,append,[[10], [[elem]]]),
ok.
reverse(suite) ->
[];
reverse(doc) ->
[];
reverse(Config) when is_list(Config) ->
?line ok=reverse_test(0),
?line ok=reverse_test(1),
?line ok=reverse_test(2),
?line ok=reverse_test(537),
ok.
reverse_test(0) ->
case spawn_eval(lists1,reverse,[[]]) of
[] ->
ok;
_Other ->
error
end;
reverse_test(Num) ->
List=spawn_eval(lists1,reverse,
[['The Element'|lists1:duplicate(Num, 'Ele')]]),
case spawn_eval(lists1,reverse,[List]) of
['The Element'|_Rest] ->
ok;
_Other ->
error
end.
member(suite) ->
[];
member(doc) ->
["Tests the lists1:member() implementation. The function "
"is `non-blocking', and only processes 2000 elements "
"at a time.",
"This test case depends on lists1:reverse() to work, "
"wich is tested in a separate test case."];
member(Config) when list(Config) ->
?line ok=member_test(0),
?line ok=member_test(1),
?line ok=member_test(100),
?line ok=member_test(537),
ok.
member_test(0) ->
case spawn_eval(lists1,member,['The Element', []]) of
false ->
ok;
true ->
{error, 'Found (!?)'}
end;
member_test(Num) ->
List=spawn_eval(lists1,reverse,
[['The Element'|spawn_eval(lists1,duplicate,
[Num, 'Elem'])]]),
case spawn_eval(lists1,member,['The Element', List]) of
true ->
ok;
false ->
{error, not_found}
end.
spawn_eval(M,F,A) ->
Self = self(),
spawn(fun() -> evaluator(Self, M,F,A) end),
receive
Result ->
Result
end.
evaluator(Pid, M,F,A) ->
Pid ! (catch apply(M,F,A)).
interpretable(suite) ->
[];
interpretable(doc) ->
["Test int:interpretable/1"];
interpretable(Config) when is_list(Config) ->
%% First make sure that 'lists1' is not loaded
case code:is_loaded(lists1) of
{file, _Loaded} ->
?line code:purge(lists1),
?line code:delete(lists1),
?line code:purge(lists1);
false -> ignore
end,
%% true
?line DataDir = filename:dirname(?config(data_dir, Config)),
?line true = code:add_patha(DataDir),
?line true = int:interpretable(lists1),
?line true = int:interpretable(filename:join([DataDir,lists1])),
?line true = code:del_path(DataDir),
%% true (from source)
PrivDir = filename:join(?config(priv_dir, Config), ""),
{ok, _} = file:copy(filename:join([DataDir,"lists1.beam"]),
filename:join([PrivDir,"lists1.beam"])),
true = code:add_patha(PrivDir),
true = int:interpretable(lists1),
ok = file:delete(filename:join([PrivDir,"lists1.beam"])),
%% {error, no_beam}
Src = filename:join([PrivDir,"lists1.erl"]),
?line {ok, _} = file:copy(filename:join([DataDir,"lists1.erl"]),
Src),
?line {error, no_beam} = int:interpretable(Src),
%% {error, no_debug_info}
?line {ok, _} = compile:file(Src, [{outdir,PrivDir}]),
?line {error, no_debug_info} = int:interpretable(Src),
?line {error, no_debug_info} = int:interpretable(lists1),
?line ok = file:delete(Src),
?line true = code:del_path(PrivDir),
%% {error, no_src}
{ok, lists2, Binary} = compile:forms([{attribute,1,module,lists2}], []),
code:load_binary(lists2, "unknown", Binary),
{error, no_src} = int:interpretable(lists2),
%% {error, badarg}
?line {error, badarg} = int:interpretable(pride),
?line {error, badarg} = int:interpretable("prejudice.erl"),
%% {error, {app,App}}
case filename:basename(code:lib_dir(kernel)) of
"kernel" ->
%% Development system (not installed). We are allowed
%% to interpret modules in kernel and stdlib
%% (at our own risk).
ok;
"kernel-" ++ _ ->
%% Installed system. Certain applications (including
%% kernel and stdlib) cannot be interpreted.
{error, {app,_}} = int:interpretable(file),
{error, {app,_}} = int:interpretable(lists),
case int:interpretable(dbg_ieval) of
{error, {app,_}} ->
ok;
{error, badarg} ->
case code:which(dbg_ieval) of
cover_compiled ->
ok;
Other1 ->
ct:fail({unexpected_result, Other1})
end;
Other2 ->
ct:fail({unexpected_result, Other2})
end
end,
ok.