diff options
Diffstat (limited to 'erts/test/erlc_SUITE.erl')
-rw-r--r-- | erts/test/erlc_SUITE.erl | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl new file mode 100644 index 0000000000..ce64ef1a75 --- /dev/null +++ b/erts/test/erlc_SUITE.erl @@ -0,0 +1,286 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-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% +%% +-module(erlc_SUITE). + +%% Tests the erlc command by compiling various types of files. + +-export([all/1, compile_erl/1, compile_yecc/1, compile_script/1, + compile_mib/1, good_citizen/1, deep_cwd/1]). + +-include("test_server.hrl"). + +all(suite) -> + [compile_erl, compile_yecc, compile_script, compile_mib, + good_citizen, deep_cwd]. + +%% Copy from erlc_SUITE_data/include/erl_test.hrl. + +-record(person, {name, shoe_size}). + +%% Tests that compiling Erlang source code works. + +compile_erl(Config) when is_list(Config) -> + ?line {SrcDir, OutDir, Cmd} = get_cmd(Config), + ?line FileName = filename:join(SrcDir, "erl_test_ok.erl"), + + %% By default, warnings are now turned on. + ?line run(Config, Cmd, FileName, "", + ["Warning: function foo/0 is unused\$", + "_OK_"]), + + %% Test that the compiled file is where it should be, + %% and that it is runnable. + + ?line {module, erl_test_ok} = code:load_abs(filename:join(OutDir, + "erl_test_ok")), + ?line 42 = erl_test_ok:shoe_size(#person{shoe_size=42}), + ?line code:purge(erl_test_ok), + + %% Try disabling warnings. + + ?line run(Config, Cmd, FileName, "-W0", ["_OK_"]), + + %% Check a bad file. + + ?line BadFile = filename:join(SrcDir, "erl_test_bad.erl"), + ?line run(Config, Cmd, BadFile, "", ["function non_existing/1 undefined\$", + "_ERROR_"]), + + ok. + +%% Test that compiling yecc source code works. + +compile_yecc(Config) when is_list(Config) -> + ?line {SrcDir, _, OutDir} = get_dirs(Config), + ?line Cmd = erlc() ++ " -o" ++ OutDir ++ " ", + ?line FileName = filename:join(SrcDir, "yecc_test_ok.yrl"), + ?line run(Config, Cmd, FileName, "-W0", ["_OK_"]), + ?line true = exists(filename:join(OutDir, "yecc_test_ok.erl")), + + ?line BadFile = filename:join(SrcDir, "yecc_test_bad.yrl"), + ?line run(Config, Cmd, BadFile, "-W0", + ["rootsymbol form is not a nonterminal\$", + "undefined nonterminal: form\$", + "Nonterminals is missing\$", + "_ERROR_"]), + ?line exists(filename:join(OutDir, "yecc_test_ok.erl")), + + ok. + +%% Test that compiling start scripts works. + +compile_script(Config) when is_list(Config) -> + ?line {SrcDir, OutDir, Cmd} = get_cmd(Config), + ?line FileName = filename:join(SrcDir, "start_ok.script"), + ?line run(Config, Cmd, FileName, "", ["_OK_"]), + ?line true = exists(filename:join(OutDir, "start_ok.boot")), + + ?line BadFile = filename:join(SrcDir, "start_bad.script"), + ?line run(Config, Cmd, BadFile, "", ["syntax error before:", "_ERROR_"]), + ok. + +%% Test that compiling SNMP mibs works. + +compile_mib(Config) when is_list(Config) -> + ?line {SrcDir, OutDir, Cmd} = get_cmd(Config), + ?line FileName = filename:join(SrcDir, "GOOD-MIB.mib"), + ?line run(Config, Cmd, FileName, "", ["_OK_"]), + ?line Output = filename:join(OutDir, "GOOD-MIB.bin"), + ?line true = exists(Output), + + %% Try -W option. + + ?line ok = file:delete(Output), + ?line run(Config, Cmd, FileName, "-W", + ["_OK_"]), + ?line true = exists(Output), + + %% Try -W option and more verbose. + + ?line ok = file:delete(Output), + ?line case test_server:os_type() of + {unix,_} -> + ?line run(Config, Cmd, FileName, "-W +'{verbosity,info}'", + ["GOOD-MIB.mib: Info. No accessfunction for 'sysDescr'", + "_OK_"]), + ?line true = exists(Output), + ?line ok = file:delete(Output); + _ -> ok %Don't bother -- too much work. + end, + + %% Try a bad file. + + ?line BadFile = filename:join(SrcDir, "BAD-MIB.mib"), + ?line run(Config, Cmd, BadFile, "", + ["Error: syntax error before: mibs\$", "compilation_failed_ERROR_"]), + + %% Make sure that no -I option works. + + ?line NewCmd = erlc() ++ " -o" ++ OutDir ++ " ", + ?line run(Config, NewCmd, FileName, "", ["_OK_"]), + ?line true = exists(Output), + + ok. + +%% Checks that 'erlc' doesn't eat any input (important when called from a +%% shell script with redirected input). +good_citizen(Config) when is_list(Config) -> + case os:type() of + {unix, _} -> + ?line PrivDir = ?config(priv_dir, Config), + ?line Answer = filename:join(PrivDir, "answer"), + ?line Script = filename:join(PrivDir, "test_script"), + ?line Test = filename:join(PrivDir, "test.erl"), + ?line S = ["#! /bin/sh\n", "erlc ", Test, "\n", + "read reply\n", "echo $reply\n"], + ?line ok = file:write_file(Script, S), + ?line ok = file:write_file(Test, "-module(test).\n"), + ?line Cmd = "echo y | sh " ++ Script ++ " > " ++ Answer, + ?line os:cmd(Cmd), + ?line {ok, Answer0} = file:read_file(Answer), + ?line [$y|_] = binary_to_list(Answer0), + ok; + _ -> + {skip, "Unix specific"} + end. + +%% Make sure that compiling an Erlang module deep down in +%% in a directory with more than 255 characters works. +deep_cwd(Config) when is_list(Config) -> + case os:type() of + {unix, _} -> + PrivDir = ?config(priv_dir, Config), + deep_cwd_1(PrivDir); + _ -> + {skip, "Only a problem on Unix"} + end. + +deep_cwd_1(PrivDir) -> + ?line DeepDir0 = filename:join(PrivDir, lists:duplicate(128, $a)), + ?line DeepDir = filename:join(DeepDir0, lists:duplicate(128, $b)), + ?line ok = file:make_dir(DeepDir0), + ?line ok = file:make_dir(DeepDir), + ?line ok = file:set_cwd(DeepDir), + ?line ok = file:write_file("test.erl", "-module(test).\n\n"), + ?line io:format("~s\n", [os:cmd("erlc test.erl")]), + ?line true = filelib:is_file("test.beam"), + ok. + +erlc() -> + case os:find_executable("erlc") of + false -> + test_server:fail("Can't find erlc"); + Erlc -> + Erlc + end. + +%% Runs a command. + +run(Config, Cmd0, Name, Options, Expect) -> + Cmd = Cmd0 ++ " " ++ Options ++ " " ++ Name, + io:format("~s", [Cmd]), + Result = run_command(Config, Cmd), + Messages = split(Result, [], []), + io:format("Result: ~p", [Messages]), + io:format("Expected: ~p", [Expect]), + match_messages(Messages, Expect). + +split([$\n|Rest], Current, Lines) -> + split(Rest, [], [lists:reverse(Current)|Lines]); +split([$\r|Rest], Current, Lines) -> + split(Rest, Current, Lines); +split([Char|Rest], Current, Lines) -> + split(Rest, [Char|Current], Lines); +split([], [], Lines) -> + lists:reverse(Lines); +split([], Current, Lines) -> + split([], [], [lists:reverse(Current)|Lines]). + +match_messages([Msg|Rest1], [Regexp|Rest2]) -> + case re:run(Msg, Regexp, [{capture,none}]) of + match -> + ok; + nomatch -> + io:format("Not matching: ~s\n", [Msg]), + io:format("Regexp : ~s\n", [Regexp]), + test_server:fail(message_mismatch) + end, + match_messages(Rest1, Rest2); +match_messages([], [Expect|Rest]) -> + test_server:fail({too_few_messages, [Expect|Rest]}); +match_messages([Msg|Rest], []) -> + test_server:fail({too_many_messages, [Msg|Rest]}); +match_messages([], []) -> + ok. + +get_cmd(Cfg) -> + ?line {SrcDir, IncDir, OutDir} = get_dirs(Cfg), + ?line Cmd = erlc() ++ " -I" ++ IncDir ++ " -o" ++ OutDir ++ " ", + {SrcDir, OutDir, Cmd}. + +get_dirs(Cfg) -> + ?line DataDir = ?config(data_dir, Cfg), + ?line PrivDir = ?config(priv_dir, Cfg), + ?line SrcDir = filename:join(DataDir, "src"), + ?line IncDir = filename:join(DataDir, "include"), + {SrcDir, IncDir, PrivDir}. + +exists(Name) -> + filelib:is_file(Name). + +%% Runs the command using os:cmd/1. +%% +%% Returns the output from the command (as a list of characters with +%% embedded newlines). The very last line will indicate the +%% exit status of the command, where _OK_ means zero, and _ERROR_ +%% a non-zero exit status. + +run_command(Config, Cmd) -> + TmpDir = filename:join(?config(priv_dir, Config), "tmp"), + file:make_dir(TmpDir), + {RunFile, Run, Script} = run_command(TmpDir, os:type(), Cmd), + ok = file:write_file(filename:join(TmpDir, RunFile), Script), + os:cmd(Run). + +run_command(Dir, {win32, _}, Cmd) -> + BatchFile = filename:join(Dir, "run.bat"), + Run = re:replace(filename:rootname(BatchFile), "/", "\\", + [global,{return,list}]), + {BatchFile, + Run, + ["@echo off\r\n", + "set ERLC_EMULATOR=", atom_to_list(lib:progname()), "\r\n", + Cmd, "\r\n", + "if errorlevel 1 echo _ERROR_\r\n", + "if not errorlevel 1 echo _OK_\r\n"]}; +run_command(Dir, {unix, _}, Cmd) -> + Name = filename:join(Dir, "run"), + {Name, + "/bin/sh " ++ Name, + ["#!/bin/sh\n", + "ERLC_EMULATOR='", atom_to_list(lib:progname()), "'\n", + "export ERLC_EMULATOR\n", + Cmd, "\n", + "case $? in\n", + " 0) echo '_OK_';;\n", + " *) echo '_ERROR_';;\n", + "esac\n"]}; +run_command(_Dir, Other, _Cmd) -> + M = io_lib:format("Don't know how to test exit code for ~p", [Other]), + test_server:fail(lists:flatten(M)). |