From 27a5daae33616e662a36ed514c31618d51ad66e3 Mon Sep 17 00:00:00 2001 From: Niclas Eklund Date: Thu, 2 Sep 2010 16:15:32 +0200 Subject: Add test suite for ic --- lib/ic/test/ic_pp_SUITE.erl | 647 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 647 insertions(+) create mode 100644 lib/ic/test/ic_pp_SUITE.erl (limited to 'lib/ic/test/ic_pp_SUITE.erl') diff --git a/lib/ic/test/ic_pp_SUITE.erl b/lib/ic/test/ic_pp_SUITE.erl new file mode 100644 index 0000000000..d68242bf3a --- /dev/null +++ b/lib/ic/test/ic_pp_SUITE.erl @@ -0,0 +1,647 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. 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% +%% +%% +%%---------------------------------------------------------------------- +%% Purpose : Test suite for the IDL preprocessor +%%---------------------------------------------------------------------- + +-module(ic_pp_SUITE). +-include("test_server.hrl"). + + + +%% Standard options to the ic compiler, NOTE unholy use of OutDir + +-define(OUT(X), filename:join([?config(priv_dir, Config), gen, to_list(X)])). +-define(GCC, "g++"). +-define(GCC_VER, "2.95.3"). + +-export([all/1]). +-export([arg/1]). +-export([arg_norm/1]). +-export([cascade/1]). +-export([cascade_norm/1]). +-export([comment/1]). +-export([comment_norm/1]). +-export([concat/1]). +-export([concat_norm/1]). +-export([define/1]). +-export([define_norm/1]). +-export(['if'/1]). +-export([if_norm/1]). +-export([if_zero/1]). +-export([misc/1]). +-export([misc_norm/1]). +-export([improp_nest_constr/1]). +-export([improp_nest_constr_norm/1]). +-export([inc/1]). +-export([inc_norm/1]). +-export([line/1]). +-export([line_norm/1]). +-export([nopara/1]). +-export([nopara_norm/1]). +-export([predef/1]). +-export([predef_norm/1]). +-export([predef_time/1]). +-export([predef_time_norm/1]). +-export([self_ref/1]). +-export([self_ref_norm/1]). +-export([separate/1]). +-export([separate_norm/1]). +-export([swallow_sc/1]). +-export([swallow_sc_norm/1]). +-export([unintended_grp/1]). +-export([unintended_grp_norm/1]). +-export([cases/0, init_all/1, finish_all/1]). + + +all(doc) -> ["Preprocessing tests for IC"]; +all(suite) -> + {req, [], {conf, init_all, cases(), finish_all}}. + +init_all(Config) -> + if + is_list(Config) -> + case os:type() of + {win32, _} -> + {skipped, "Very unplesent to run on windows"}; + _ -> + check_gcc(Config) + end; + true -> + exit("Config not a list") + end. + +check_gcc(Config) -> + case os:find_executable(?GCC) of + false -> + {skipped, + lists:flatten(io_lib:format("Can not run without ~s in path", + [?GCC]))}; + _ -> + case trim(os:cmd(?GCC++" --version")) of + ?GCC_VER++[] -> + Config; + ?GCC_VER++[D|_] when is_integer(D), D>=$0, D=<$9 -> + fail_gcc(?GCC_VER++[D]); + ?GCC_VER++_ -> + Config; + Ver -> + fail_gcc(Ver) + end + end. + +fail_gcc(Ver) -> + {skipped, lists:flatten(io_lib:format("Need ~s v~s, not ~s", + [?GCC, ?GCC_VER, Ver]))}. + +trim(S) -> lists:reverse(skip_white(lists:reverse(skip_white(S)))). + +skip_white([$\s|T]) -> skip_white(T); +skip_white([$\n|T]) -> skip_white(T); +skip_white([$\r|T]) -> skip_white(T); +skip_white([$\t|T]) -> skip_white(T); +skip_white(L) -> L. + + +finish_all(Config) -> + Config. + + +cases() -> + [arg, cascade, comment, concat, define, misc, 'if', improp_nest_constr, inc, + line, nopara, predef, predef_time, self_ref, separate, swallow_sc, + unintended_grp]. + + + +%%-------------------------------------------------------------------- +%% arg +%%-------------------------------------------------------------------- + +arg(suite) -> [arg_norm]; +arg(doc) -> ["Check #define with some arguments"]. + +arg_norm(doc) -> ["Checks arguments for #define."]; +arg_norm(suite) -> []; +arg_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(arg_norm), + File = filename:join(DataDir, arg), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% cascade +%%-------------------------------------------------------------------- + +cascade(suite) -> [cascade_norm]; +cascade(doc) -> ["Check cascade #define"]. + +cascade_norm(doc) -> ["Check cascade #define."]; +cascade_norm(suite) -> []; +cascade_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(cascade_norm), + File = filename:join(DataDir, cascade), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% comment +%%-------------------------------------------------------------------- + +comment(suite) -> [comment_norm]; +comment(doc) -> ["Check comments"]. + +comment_norm(doc) -> ["Check comments."]; +comment_norm(suite) -> []; +comment_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(comment_norm), + File = filename:join(DataDir, comment), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% concat +%%-------------------------------------------------------------------- + +concat(suite) -> [concat_norm]; +concat(doc) -> ["Check concatinations, i.e ## "]. + +concat_norm(doc) -> ["Check concatinations, i.e ## ."]; +concat_norm(suite) -> []; +concat_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(concat_norm), + File = filename:join(DataDir, concat), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% define +%%-------------------------------------------------------------------- + +define(suite) -> [define_norm]; +define(doc) -> ["Check misceleaneous #define"]. + +define_norm(doc) -> ["Check misceleaneous #define."]; +define_norm(suite) -> []; +define_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(define_norm), + File = filename:join(DataDir, define), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% if +%%-------------------------------------------------------------------- + +'if'(suite) -> [if_norm, if_zero]; +'if'(doc) -> ["Check #if, #elif, and #endif. Note these are not implementen and will ~n + result in an error message from internal_pp"]. + +if_norm(doc) -> ["Check #if, #elif, and #endif. ."]; +if_norm(suite) -> []; +if_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(if_norm), + File = filename:join(DataDir, 'if'), + + ?line ok = test_file(File, DataDir), + ok. + +if_zero(doc) -> ["Check #if 0"]; +if_zero(suite) -> []; +if_zero(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(if_zero), + File = filename:join(DataDir, if_zero), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% inc +%%-------------------------------------------------------------------- + +inc(suite) -> [inc_norm]; +inc(doc) -> ["Check #include"]. + +inc_norm(doc) -> ["Check #include."]; +inc_norm(suite) -> []; +inc_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(inc_norm), + File = filename:join(DataDir, inc), + + ?line ok = test_file(File, DataDir), + ok. + + + +%%-------------------------------------------------------------------- +%% improp_nest_constr +%%-------------------------------------------------------------------- + +improp_nest_constr(suite) -> [improp_nest_constr_norm]; +improp_nest_constr(doc) -> ["Check improperly nested constructs"]. + +improp_nest_constr_norm(doc) -> ["Check improperly nested constructs."]; +improp_nest_constr_norm(suite) -> []; +improp_nest_constr_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(improp_nest_constr_norm), + File = filename:join(DataDir, improp_nest_constr), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% misc +%%-------------------------------------------------------------------- + +misc(suite) -> [misc_norm]; +misc(doc) -> ["Misceleaneous checks"]. + +misc_norm(doc) -> ["Misceleaneous checks."]; +misc_norm(suite) -> []; +misc_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(misc_norm), + File = filename:join(DataDir, misc), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% line +%%-------------------------------------------------------------------- + +line(suite) -> [line_norm]; +line(doc) -> ["Checks #line"]. + +line_norm(doc) -> ["Checks #line."]; +line_norm(suite) -> []; +line_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(line_norm), + File = filename:join(DataDir, line), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% nopara +%%-------------------------------------------------------------------- + +nopara(suite) -> [nopara_norm]; +nopara(doc) -> ["Checks #define with no parameters"]. + +nopara_norm(doc) -> ["Checks #define with no parameters."]; +nopara_norm(suite) -> []; +nopara_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(nopara_norm), + File = filename:join(DataDir, nopara), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% predef +%%-------------------------------------------------------------------- + +predef(suite) -> [predef_norm]; +predef(doc) -> ["Checks predefined macros. Note: not __TIME__ and __DATE__"]. + +predef_norm(doc) -> ["Checks predefined macros. Note: not __TIME__ and __DATE__."]; +predef_norm(suite) -> []; +predef_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(predef_norm), + File = filename:join(DataDir, predef), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% predef_time +%%-------------------------------------------------------------------- + +predef_time(suite) -> [predef_time_norm]; +predef_time(doc) -> ["Checks the predefined macros __TIME__ and __DATE__"]. + +predef_time_norm(doc) -> ["Checks the predefined macros __TIME__ and __DATE__."]; +predef_time_norm(suite) -> []; +predef_time_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(predef_time_norm), + File = filename:join(DataDir, predef_time), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% self_ref +%%-------------------------------------------------------------------- + +self_ref(suite) -> [self_ref_norm]; +self_ref(doc) -> ["Checks self referring macros"]. + +self_ref_norm(doc) -> ["Checks self referring macros."]; +self_ref_norm(suite) -> []; +self_ref_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(self_ref_norm), + File = filename:join(DataDir, self_ref), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% separate +%%-------------------------------------------------------------------- + +separate(suite) -> [separate_norm]; +separate(doc) -> ["Checks separete expansion of macro arguments"]. + +separate_norm(doc) -> ["Checks separete expansion of macro arguments."]; +separate_norm(suite) -> []; +separate_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(separate_norm), + File = filename:join(DataDir, separate), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% swallow_sc +%%-------------------------------------------------------------------- + +swallow_sc(suite) -> [swallow_sc_norm]; +swallow_sc(doc) -> ["Checks swallowing an undesirable semicolon"]. + +swallow_sc_norm(doc) -> ["Checks swallowing an undesirable semicolon."]; +swallow_sc_norm(suite) -> []; +swallow_sc_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(swallow_sc_norm), + File = filename:join(DataDir, swallow_sc), + + ?line ok = test_file(File, DataDir), + ok. + + +%%-------------------------------------------------------------------- +%% unintended_grp +%%-------------------------------------------------------------------- + +unintended_grp(suite) -> [unintended_grp_norm]; +unintended_grp(doc) -> ["Checks unintended grouping of arithmetic"]. + +unintended_grp_norm(doc) -> ["Checks unintended grouping of arithmetic."]; +unintended_grp_norm(suite) -> []; +unintended_grp_norm(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + _OutDir = ?OUT(unintended_grp_norm), + File = filename:join(DataDir, unintended_grp), + + ?line ok = test_file(File, DataDir), + ok. + + + + + +test_file(FileT, DataDir) -> + case test_file_1(FileT, DataDir) of + ok -> ok; + Chars -> + io:put_chars(Chars), + {error,{FileT,DataDir}} + end. + +test_file_1(FileT, DataDir) -> + Tok = string:tokens(FileT, "/"), + FileName = lists:last(Tok), + File = FileT++".idl", + + ?line test_server:format("File ~p~n",[File]), + ?line test_server:format("FileName ~p~n",[FileName]), + + Flags = "-I"++DataDir, + + ?line test_server:format("Flags ~p~n",[Flags]), + + ?line Erl = pp_erl(File, Flags), + ?line Gcc = pp_gcc(File, Flags), + + ?line case Erl of + {error,_ErlError} -> + ?line test_server:format("Internal_pp Result ~n==================~n~p~n~n",[Erl]); + {warning, _ErlWar} -> + ?line test_server:format("Internal_pp Result ~n==================~n~p~n~n",[Erl]); + _ -> + ?line test_server:format("Internal_pp Result ~n==================~n~s~n~n",[Erl]) + end, + + ?line case Gcc of + {error,GccError} -> + Error = string:tokens(GccError, "\n"), + ?line test_server:format(?GCC" Result ~n==========~n~p~n~n", + [Error]); + _ -> + ?line test_server:format(?GCC" Result ~n==========~n~s~n~n",[Gcc]) + end, + + + + ?line case {Erl,Gcc} of + {{warning,W}, {error,X}} -> + ?line case is_ok(W,X) of + yes -> + ok; + no -> + io_lib:format("Internal_pp found Warning = ~p ~n" + ?GCC" found Error = ~p~n",[W,X]) + end; + + + {{warning,W}, _} -> + io_lib:format(?GCC" did not find warnings while ~n" + "Internal_pp found the following Warning = ~p~n",[W]); + + {{error,E}, {error,X}} -> + ?line case is_ok(E,X) of + yes -> + ok; + no -> + io_lib:format("Internal_pp found Error = ~p ~n" + ?GCC" found Error = ~p~n",[E,X]) + end; + + {{error,E}, _} -> + ?line case FileName of + "if" -> + ?line case if_res(E) of + ok -> + ok; + _ -> + io_lib:format(?GCC" did not find errors while ~n" + "Internal_pp found the following Error = ~p~n",[E]) + end; + _ -> + io_lib:format(?GCC" did not find errors while ~n" + "Internal_pp found the following Error = ~p~n",[lists:flatten(E)]) + end; + + {_, {error,X}} -> + io_lib:format("Internal_pp did not find errors while ~n" + ?GCC" found the following Error = ~p~n",[X]); + + _ -> + + ?line file:write_file("/tmp/Erl.pp",list_to_binary(Erl)), + ?line file:write_file("/tmp/Gcc.pp",list_to_binary(Gcc)), + + ?line Res = os:cmd("diff -b -w /tmp/Erl.pp /tmp/Gcc.pp"), + ?line test_server:format("///////////{error,E} E ~p FileName~p~n",[Res,FileName]), + ?line case {Res, FileName} of + {[], _} -> + ?line test_server:format("Diff = [] OK!!!!!!~n"), + ok; + {_, "predef_time"} -> + Tokens = string:tokens(Res,"\n"), + ?line test_server:format("///////////{error,E} Tokens~p~n",[Tokens]), + case Tokens of + ["3c3",_,"---",_,"5c5",_,"---",_,"9c9",_,"---",_] -> + ok; + _ -> + io_lib:format("Diff Result = ~p~n",[Res]) + end; + _ -> + io_lib:format("Diff Result = ~p~n",[Res]) + end + end. + + + + + +pp_erl(File, Flags) -> + case ic_pp:run(File,Flags) of + {ok, [$#, $ , $1 | Rest], []} -> + [$#, $ , $1 | Rest]; + {ok, [$#, $ , $1 | _Rest], Warning} -> + {warning,Warning}; + {error,Error} -> + {error,Error} + end. + +pp_gcc(File, Flags) -> + Cmd = ?GCC" -x c++ -E", + Line = Cmd++" "++Flags++" "++File, + + case os:cmd(Line) of + [$#, $ , $1 | Rest] -> + [$#, $ , $1 | Rest]; + Res -> + + case string:str(Res,"# 1 \"") of + 0 -> + {error,Res}; + X -> + {error, string:sub_string(Res, 1, X-1)} + end + end. + + +is_ok([],_Gcc) -> + yes; +is_ok([{FileName,Line,Text}|T],Gcc) -> + Str = FileName++":"++integer_to_list(Line)++": "++Text, + case string:str(Gcc,Str) of + 0 -> + io:format("~n is_ok Internal_pp missed Error = ~s~n",[Str]), + no; + _X -> + is_ok(T,Gcc) + end; +is_ok([Str|T],Gcc) -> + case string:str(Gcc,Str) of + 0 -> + io:format("~n is_ok Internal_pp missed Error = ~s~n",[Str]), + no; + _X -> + is_ok(T,Gcc) + end. + + +to_list(X) when is_atom(X) -> atom_to_list(X); +to_list(X) -> X. + + + +if_res(E) -> + if_res(E,1). + +if_res([H|T],Nr) -> + %% Dir = "/clearcase/otp/libraries/ic/test/ic_pp_SUITE_data/if.idl", + case {Nr, H} of + {1, {_Dir, 2, "only '#if 0' is implemented at present"}} -> + if_res(T,Nr+1); + {2, {_Dir, 3, "only '#if 0' is implemented at present"}} -> + if_res(T,Nr+1); + {3, {_Dir, 5, "`else' command is not implemented at present"}} -> + if_res(T,Nr+1); + {4, {_Dir, 9, "`elif' command is not implemented at present"}} -> + if_res(T,Nr+1); + {5, {_Dir, 11, "`else' command is not implemented at present"}} -> + ok; + _ -> + error + end; +if_res(_, _) -> + error. + + + -- cgit v1.2.3