aboutsummaryrefslogblamecommitdiffstats
path: root/lib/inets/test/inets_test_lib.erl
blob: 609bc89e159ac4b69d2c08d9c72e390a9fdbfc7f (plain) (tree)
1
2
3
4


                   
                                                        





























                                                                           






                                             




                                       













































                                                                               



































































































































































































































































                                                                               


                             
%%
%% %CopyrightBegin%
%% 
%% Copyright Ericsson AB 2001-2011. All Rights Reserved.
%% 
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%% 
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%% 
%% %CopyrightEnd%
%%
%%
-module(inets_test_lib).

-include("inets_test_lib.hrl").

%% Various small utility functions
-export([start_http_server/1, start_http_server_ssl/1]).
-export([hostname/0]).
-export([connect_bin/3, connect_byte/3, send/3, close/2]).
-export([copy_file/3, copy_files/2, copy_dirs/2, del_dirs/1]).
-export([info/4, log/4, debug/4, print/4]).
-export([check_body/1]).
-export([millis/0, millis_diff/2, hours/1, minutes/1, seconds/1, sleep/1]).
-export([non_pc_tc_maybe_skip/4, os_based_skip/1]).

start_http_server(Conf) ->
    ?DEBUG("start_http_server -> entry with"
	   "~n   Conf: ~p", [Conf]),
    inets_ensure_loaded(), 
    inets_set_env(services, [{httpd, Conf}]),
    inets_ensure_started(),
    ok.


start_http_server_ssl(FileName) ->
    application:start(ssl),	       
    catch start_http_server(FileName).

inets_ensure_loaded() ->
    ensure_loaded(inets).

ensure_loaded(App) ->
    case application:load(App) of
	ok ->
	    ok;
	{error, {already_loaded, _}} ->
	    ok;
	LoadRes ->
	    ?LOG("start_http_server -> failed loading ~p: ~p", [App, LoadRes]),
	    tsf({failed_loading, LoadRes})
    end.


inets_set_env(Service, Config) ->
    app_set_env(inets, Service, Config).

app_set_env(App, Param, Value) ->
    case application:set_env(App, Param, Value) of
	ok ->
	    ?DEBUG("start_http_server -> env set", []),
	    ok;
	SetEnvRes ->
	    ?LOG("start_http_server -> failed set env for ~p: ~p", 
		 [App, SetEnvRes]),
	    exit({failed_set_env, App, SetEnvRes})
    end.

inets_ensure_started() ->
    ensure_app_started(inets).

ensure_app_started(App) ->
    case application:start(App) of
	ok ->
	    ?DEBUG("start_http_server -> ~p started", [App]),
	    ok;
	{error, {already_started, _}} ->
	    ok;
	StartRes ->
	    ?LOG("start_http_server -> failed starting ~p: ~p", 
		 [App, StartRes]),
	    exit({failed_starting, App, StartRes})
    end.


%% ----------------------------------------------------------------------
%% print functions
%%

info(F, A, Mod, Line) ->
    print("INF ", F, A, Mod, Line).

log(F, A, Mod, Line) ->
    print("LOG ", F, A, Mod, Line).

debug(F, A, Mod, Line) ->
    print("DBG ", F, A, Mod, Line).

print(P, F, A, Mod, Line) ->
    io:format("~s[~p:~p:~p] : " ++ F ++ "~n", [P, self(), Mod, Line| A]).

print(F, A, Mod, Line) ->
    print("", F, A, Mod, Line).

hostname() ->
    from($@, atom_to_list(node())).
from(H, [H | T]) -> T;
from(H, [_ | T]) -> from(H, T);
from(_, []) -> [].


copy_file(File, From, To) ->
    file:copy(filename:join(From, File), filename:join(To, File)).

copy_files(FromDir, ToDir) -> 
    {ok, Files} = file:list_dir(FromDir),
    lists:foreach(fun(File) -> 
			  FullPath = filename:join(FromDir, File),
			  case filelib:is_file(FullPath) of
			      true ->
				  file:copy(FullPath,
					    filename:join(ToDir, File));
			      false ->
				  ok
			  end
		  end, Files).


copy_dirs(FromDirRoot, ToDirRoot) ->
%%     io:format("~w:copy_dirs -> entry with"
%% 	      "~n   FromDirRoot: ~p"
%% 	      "~n   ToDirRoot:   ~p"
%% 	      "~n", [?MODULE, FromDirRoot, ToDirRoot]), 
    {ok, Files} = file:list_dir(FromDirRoot),
    lists:foreach(
      fun(FileOrDir) -> 
	      %% Check if it's a directory or a file
%% 	      io:format("~w:copy_dirs -> check ~p"
%% 			"~n", [?MODULE, FileOrDir]), 
	      case filelib:is_dir(filename:join(FromDirRoot, FileOrDir)) of
		  true ->
%% 		      io:format("~w:copy_dirs -> ~p is a directory"
%% 				"~n", [?MODULE, FileOrDir]), 
		      FromDir = filename:join([FromDirRoot, FileOrDir]),
		      ToDir   = filename:join([ToDirRoot, FileOrDir]),
		      ok      = file:make_dir(ToDir),
		      copy_dirs(FromDir, ToDir);
		  false ->
%% 		      io:format("~w:copy_dirs -> ~p is a file"
%% 				"~n", [?MODULE, FileOrDir]), 
		      copy_file(FileOrDir, FromDirRoot, ToDirRoot)
	      end
      end, Files).

del_dirs(Dir) ->
    case file:list_dir(Dir) of
	{ok, []} ->
	    file:del_dir(Dir);
	{ok, Files} ->
	    lists:foreach(fun(File) ->
				  FullPath = filename:join(Dir,File),
				  case filelib:is_dir(FullPath) of
				      true ->
					  del_dirs(FullPath),
					  file:del_dir(FullPath);	       
				      false ->
					  file:delete(FullPath)
				  end 
			  end, Files);
	_ ->
	    ok
    end.

check_body(Body) ->
    case string:rstr(Body, "</html>") of
	0 ->
	    case string:rstr(Body, "</HTML>") of
		0 ->
		    test_server:format("Body ~p~n", [Body]),
		    test_server:fail(did_not_receive_whole_body);
		_ ->
		    ok
	    end;
	_ ->
	    ok
    end.

%% ----------------------------------------------------------------
%% Conditional skip of testcases
%%

non_pc_tc_maybe_skip(Config, Condition, File, Line)
  when is_list(Config) andalso is_function(Condition) ->
    %% Check if we shall skip the skip
    case os:getenv("TS_OS_BASED_SKIP") of
        "false" ->
            ok;
        _ ->
            case lists:keysearch(ts, 1, Config) of
                {value, {ts, inets}} ->
                    %% Always run the testcase if we are using our own
                    %% test-server...
                    ok;
                _ ->
                    case (catch Condition()) of
                        true ->
                            skip(non_pc_testcase, File, Line);
                        _ ->
                            ok
                    end
            end
    end.


os_based_skip(any) ->
    true;
os_based_skip(Skippable) when is_list(Skippable) ->
    {OsFam, OsName} =
        case os:type() of
            {_Fam, _Name} = FamAndName ->
                FamAndName;
            Fam ->
                {Fam, undefined}
        end,
    case lists:member(OsFam, Skippable) of
        true ->
            true;
        false ->
            case lists:keysearch(OsFam, 1, Skippable) of
                {value, {OsFam, OsName}} ->
                    true;
                {value, {OsFam, OsNames}} when is_list(OsNames) ->
                    lists:member(OsName, OsNames);
                _ ->
                    false
            end
    end;
os_based_skip(_) ->
    false.


%% ----------------------------------------------------------------------
%% Socket functions:
%% open(SocketType, Host, Port) -> {ok, Socket} | {error, Reason}
%% SocketType -> ssl | ip_comm
%% Host       -> atom() | string() | {A, B, C, D} 
%% Port       -> integer()

connect_bin(ssl, Host, Port) ->
    ssl:start(),
    %% Does not support ipv6 in old ssl 
    case ssl:connect(Host, Port, [binary, {packet,0}]) of
	{ok, Socket} ->
	    {ok, Socket};
	{error, Reason} ->
	    {error, Reason};
	Error ->
	    Error
    end;
connect_bin(ip_comm, Host, Port) ->
    Opts = [inet6, binary, {packet,0}],
    connect(ip_comm, Host, Port, Opts).
    

connect(ip_comm, Host, Port, Opts) ->
    test_server:format("gen_tcp:connect(~p, ~p, ~p) ~n", [Host, Port, Opts]),
    case gen_tcp:connect(Host,Port, Opts) of
	{ok, Socket} ->
	    test_server:format("connect success~n", []),
	    {ok, Socket};
	{error, nxdomain} ->
	    test_server:format("nxdomain opts: ~p~n", [Opts]),
	    connect(ip_comm, Host, Port, lists:delete(inet6, Opts));
	{error, eafnosupport}  ->
	    test_server:format("eafnosupport opts: ~p~n", [Opts]),
	    connect(ip_comm, Host, Port, lists:delete(inet6, Opts));
	{error, {enfile,_}} ->
	    test_server:format("Error enfile~n", []),
	    {error, enfile};
	Error ->
	    test_server:format("Unexpected error: "
			       "~n   Error: ~p"
			       "~nwhen"
			       "~n   Host:  ~p"
			       "~n   Port:  ~p"
			       "~n   Opts:  ~p"
			       "~n", [Error, Host, Port, Opts]),
	    Error
    end.

connect_byte(ip_comm, Host, Port) ->
    Opts = [inet6, {packet,0}],
    connect(ip_comm, Host, Port, Opts);

connect_byte(ssl, Host, Port) ->
    ssl:start(),
    %% Does not support ipv6 in old ssl 
    case ssl:connect(Host,Port,[{packet,0}]) of
	{ok,Socket} ->
	    {ok,Socket};
	{error,{enfile,_}} ->
	    {error, enfile};
	Error ->
	    Error
    end.   

send(ssl, Socket, Data) ->
    ssl:send(Socket, Data);
send(ip_comm,Socket,Data) ->
    gen_tcp:send(Socket,Data).


close(ssl,Socket) ->
    catch ssl:close(Socket);
close(ip_comm,Socket) ->
    catch gen_tcp:close(Socket).

millis() ->
    erlang:now().

millis_diff(A,B) ->
    T1 = (element(1,A)*1000000) + element(2,A) + (element(3,A)/1000000),
    T2 = (element(1,B)*1000000) + element(2,B) + (element(3,B)/1000000),
    T1 - T2.

hours(N)   -> trunc(N * 1000 * 60 * 60).
minutes(N) -> trunc(N * 1000 * 60).
seconds(N) -> trunc(N * 1000).


sleep(infinity) ->
    receive
    after infinity ->
            ok
    end;
sleep(MSecs) ->
    receive
    after trunc(MSecs) ->
            ok
    end,
    ok.


skip(Reason, File, Line) ->
    exit({skipped, {Reason, File, Line}}).

tsf(Reason) ->
    test_server:fail(Reason).