Minor reformatting/whitespace removal

Signed-off-by: Jordan Wilberding <jwilberding@gmail.com>
This commit is contained in:
Eric Merritt 2011-09-26 11:48:14 -05:00 committed by Jordan Wilberding
parent 284ada2bd9
commit 694e805012
5 changed files with 279 additions and 279 deletions

View file

@ -7,38 +7,38 @@
-module(ec_file). -module(ec_file).
-export([ -export([
copy/2, copy/2,
copy/3, copy/3,
mkdtemp/0, mkdtemp/0,
mkdir_path/1, mkdir_path/1,
find/2, find/2,
is_symlink/1, is_symlink/1,
remove/1, remove/1,
remove/2, remove/2,
md5sum/1, md5sum/1,
read/1, read/1,
write/2, write/2,
write_term/2, write_term/2,
consult/1 consult/1
]). ]).
-export_type([ -export_type([
path/0, path/0,
option/0 option/0
]). ]).
-include_lib("kernel/include/file.hrl"). -include_lib("kernel/include/file.hrl").
%% User friendly exception message (remove line and module info once we %% User friendly exception message (remove line and module info once we
%% get them in stack traces) %% get them in stack traces)
-define(UEX(Exception, UMSG, UVARS), -define(UEX(Exception, UMSG, UVARS),
{uex, {?MODULE, {uex, {?MODULE,
?LINE, ?LINE,
Exception, Exception,
lists:flatten(io_lib:fwrite(UMSG, UVARS))}}). lists:flatten(io_lib:fwrite(UMSG, UVARS))}}).
-define(CHECK_PERMS_MSG, -define(CHECK_PERMS_MSG,
"Try checking that you have the correct permissions and try again~n"). "Try checking that you have the correct permissions and try again~n").
%%============================================================================ %%============================================================================
%% Types %% Types
@ -55,20 +55,20 @@ copy(From, To, []) ->
copy(From, To); copy(From, To);
copy(From, To, [recursive] = Options) -> copy(From, To, [recursive] = Options) ->
case filelib:is_dir(From) of case filelib:is_dir(From) of
false -> false ->
copy(From, To); copy(From, To);
true -> true ->
make_dir_if_dir(To), make_dir_if_dir(To),
copy_subfiles(From, To, Options) copy_subfiles(From, To, Options)
end. end.
%% @doc copy a file including timestamps,ownership and mode etc. %% @doc copy a file including timestamps,ownership and mode etc.
-spec copy(From::string(), To::string()) -> ok. -spec copy(From::string(), To::string()) -> ok.
copy(From, To) -> copy(From, To) ->
try try
ec_file_copy(From, To) ec_file_copy(From, To)
catch catch
_C:E -> throw(?UEX({copy_failed, E}, ?CHECK_PERMS_MSG, [])) _C:E -> throw(?UEX({copy_failed, E}, ?CHECK_PERMS_MSG, []))
end. end.
%% @doc return an md5 checksum string or a binary. Same as unix utility of %% @doc return an md5 checksum string or a binary. Same as unix utility of
@ -84,9 +84,9 @@ md5sum(Value) ->
-spec remove(path(), Options::[option()]) -> ok | {error, Reason::term()}. -spec remove(path(), Options::[option()]) -> ok | {error, Reason::term()}.
remove(Path, Options) -> remove(Path, Options) ->
try try
ok = ec_file_remove(Path, Options) ok = ec_file_remove(Path, Options)
catch catch
_C:E -> throw(?UEX({remove_failed, E}, ?CHECK_PERMS_MSG, [])) _C:E -> throw(?UEX({remove_failed, E}, ?CHECK_PERMS_MSG, []))
end. end.
%% @doc delete a file. %% @doc delete a file.
@ -98,10 +98,10 @@ remove(Path) ->
-spec is_symlink(path()) -> boolean(). -spec is_symlink(path()) -> boolean().
is_symlink(Path) -> is_symlink(Path) ->
case file:read_link_info(Path) of case file:read_link_info(Path) of
{ok, #file_info{type = symlink}} -> {ok, #file_info{type = symlink}} ->
true; true;
_ -> _ ->
false false
end. end.
@ -111,27 +111,27 @@ is_symlink(Path) ->
mkdtemp() -> mkdtemp() ->
UniqueNumber = integer_to_list(element(3, now())), UniqueNumber = integer_to_list(element(3, now())),
TmpDirPath = TmpDirPath =
filename:join([tmp(), lists:flatten([".tmp_dir", UniqueNumber])]), filename:join([tmp(), lists:flatten([".tmp_dir", UniqueNumber])]),
try try
ok = mkdir_path(TmpDirPath), ok = mkdir_path(TmpDirPath),
TmpDirPath TmpDirPath
catch catch
_C:E -> throw(?UEX({mkdtemp_failed, E}, ?CHECK_PERMS_MSG, [])) _C:E -> throw(?UEX({mkdtemp_failed, E}, ?CHECK_PERMS_MSG, []))
end. end.
%% @doc Makes a directory including parent dirs if they are missing. %% @doc Makes a directory including parent dirs if they are missing.
-spec mkdir_path(path()) -> ok. -spec mkdir_path(path()) -> ok.
mkdir_path(Path) -> mkdir_path(Path) ->
% We are exploiting a feature of ensuredir that that creates all % We are exploiting a feature of ensuredir that that creates all
% directories up to the last element in the filename, then ignores % directories up to the last element in the filename, then ignores
% that last element. This way we ensure that the dir is created % that last element. This way we ensure that the dir is created
% and not have any worries about path names % and not have any worries about path names
DirName = filename:join([filename:absname(Path), "tmp"]), DirName = filename:join([filename:absname(Path), "tmp"]),
try try
ok = filelib:ensure_dir(DirName) ok = filelib:ensure_dir(DirName)
catch catch
_C:E -> throw(?UEX({mkdir_path_failed, E}, ?CHECK_PERMS_MSG, [])) _C:E -> throw(?UEX({mkdir_path_failed, E}, ?CHECK_PERMS_MSG, []))
end. end.
@ -140,43 +140,43 @@ mkdir_path(Path) ->
-spec consult(FilePath::path()) -> term(). -spec consult(FilePath::path()) -> term().
consult(FilePath) -> consult(FilePath) ->
case file:consult(FilePath) of case file:consult(FilePath) of
{ok, [Term]} -> {ok, [Term]} ->
Term; Term;
{error, Error} -> {error, Error} ->
Msg = "The file at ~p~n" ++ Msg = "The file at ~p~n" ++
"is either not a valid Erlang term, does not to exist~n" ++ "is either not a valid Erlang term, does not to exist~n" ++
"or you lack the permissions to read it. Please check~n" ++ "or you lack the permissions to read it. Please check~n" ++
"to see if the file exists and that it has the correct~n" ++ "to see if the file exists and that it has the correct~n" ++
"permissions~n", "permissions~n",
throw(?UEX({failed_to_consult_file, {FilePath, Error}}, throw(?UEX({failed_to_consult_file, {FilePath, Error}},
Msg, [FilePath])) Msg, [FilePath]))
end. end.
%% @doc read a file from the file system. Provide UEX exeption on failure. %% @doc read a file from the file system. Provide UEX exeption on failure.
-spec read(FilePath::string()) -> binary(). -spec read(FilePath::string()) -> binary().
read(FilePath) -> read(FilePath) ->
try try
{ok, FileBin} = file:read_file(FilePath), {ok, FileBin} = file:read_file(FilePath),
FileBin FileBin
catch catch
_C:E -> throw(?UEX({read_failed, {FilePath, E}}, _C:E -> throw(?UEX({read_failed, {FilePath, E}},
"Read failed for the file ~p with ~p~n" ++ "Read failed for the file ~p with ~p~n" ++
?CHECK_PERMS_MSG, ?CHECK_PERMS_MSG,
[FilePath, E])) [FilePath, E]))
end. end.
%% @doc write a file to the file system. Provide UEX exeption on failure. %% @doc write a file to the file system. Provide UEX exeption on failure.
-spec write(FileName::string(), Contents::string()) -> ok. -spec write(FileName::string(), Contents::string()) -> ok.
write(FileName, Contents) -> write(FileName, Contents) ->
case file:write_file(FileName, Contents) of case file:write_file(FileName, Contents) of
ok -> ok ->
ok; ok;
{error, Reason} -> {error, Reason} ->
Msg = "Writing the file ~s to disk failed with reason ~p.~n" ++ Msg = "Writing the file ~s to disk failed with reason ~p.~n" ++
?CHECK_PERMS_MSG, ?CHECK_PERMS_MSG,
throw(?UEX({write_file_failure, {FileName, Reason}}, throw(?UEX({write_file_failure, {FileName, Reason}},
Msg, Msg,
[FileName, Reason])) [FileName, Reason]))
end. end.
%% @doc write a term out to a file so that it can be consulted later. %% @doc write a term out to a file so that it can be consulted later.
@ -191,18 +191,18 @@ find([], _) ->
[]; [];
find(FromDir, TargetPattern) -> find(FromDir, TargetPattern) ->
case filelib:is_dir(FromDir) of case filelib:is_dir(FromDir) of
false -> false ->
case re:run(FromDir, TargetPattern) of case re:run(FromDir, TargetPattern) of
{match, _} -> [FromDir]; {match, _} -> [FromDir];
_ -> [] _ -> []
end; end;
true -> true ->
FoundDir = case re:run(FromDir, TargetPattern) of FoundDir = case re:run(FromDir, TargetPattern) of
{match, _} -> [FromDir]; {match, _} -> [FromDir];
_ -> [] _ -> []
end, end,
List = find_in_subdirs(FromDir, TargetPattern), List = find_in_subdirs(FromDir, TargetPattern),
FoundDir ++ List FoundDir ++ List
end. end.
%%%=================================================================== %%%===================================================================
%%% Internal Functions %%% Internal Functions
@ -210,53 +210,53 @@ find(FromDir, TargetPattern) ->
-spec find_in_subdirs(path(), string()) -> [path()]. -spec find_in_subdirs(path(), string()) -> [path()].
find_in_subdirs(FromDir, TargetPattern) -> find_in_subdirs(FromDir, TargetPattern) ->
lists:foldl(fun(CheckFromDir, Acc) lists:foldl(fun(CheckFromDir, Acc)
when CheckFromDir == FromDir -> when CheckFromDir == FromDir ->
Acc; Acc;
(ChildFromDir, Acc) -> (ChildFromDir, Acc) ->
case find(ChildFromDir, TargetPattern) of case find(ChildFromDir, TargetPattern) of
[] -> Acc; [] -> Acc;
Res -> Res ++ Acc Res -> Res ++ Acc
end end
end, end,
[], [],
filelib:wildcard(filename:join(FromDir, "*"))). filelib:wildcard(filename:join(FromDir, "*"))).
-spec ec_file_remove(path(), [{atom(), any()}]) -> ok. -spec ec_file_remove(path(), [{atom(), any()}]) -> ok.
ec_file_remove(Path, Options) -> ec_file_remove(Path, Options) ->
case lists:member(recursive, Options) of case lists:member(recursive, Options) of
false -> file:delete(Path); false -> file:delete(Path);
true -> remove_recursive(Path, Options) true -> remove_recursive(Path, Options)
end. end.
-spec remove_recursive(path(), Options::list()) -> ok. -spec remove_recursive(path(), Options::list()) -> ok.
remove_recursive(Path, Options) -> remove_recursive(Path, Options) ->
case filelib:is_dir(Path) of case filelib:is_dir(Path) of
false -> false ->
file:delete(Path); file:delete(Path);
true -> true ->
lists:foreach(fun(ChildPath) -> lists:foreach(fun(ChildPath) ->
remove_recursive(ChildPath, Options) remove_recursive(ChildPath, Options)
end, filelib:wildcard(filename:join(Path, "*"))), end, filelib:wildcard(filename:join(Path, "*"))),
ok = file:del_dir(Path) ok = file:del_dir(Path)
end. end.
-spec tmp() -> path(). -spec tmp() -> path().
tmp() -> tmp() ->
case erlang:system_info(system_architecture) of case erlang:system_info(system_architecture) of
"win32" -> "win32" ->
"./tmp"; "./tmp";
_SysArch -> _SysArch ->
"/tmp" "/tmp"
end. end.
%% Copy the subfiles of the From directory to the to directory. %% Copy the subfiles of the From directory to the to directory.
-spec copy_subfiles(path(), path(), [option()]) -> ok. -spec copy_subfiles(path(), path(), [option()]) -> ok.
copy_subfiles(From, To, Options) -> copy_subfiles(From, To, Options) ->
Fun = Fun =
fun(ChildFrom) -> fun(ChildFrom) ->
ChildTo = filename:join([To, filename:basename(ChildFrom)]), ChildTo = filename:join([To, filename:basename(ChildFrom)]),
copy(ChildFrom, ChildTo, Options) copy(ChildFrom, ChildTo, Options)
end, end,
lists:foreach(Fun, filelib:wildcard(filename:join(From, "*"))). lists:foreach(Fun, filelib:wildcard(filename:join(From, "*"))).
-spec ec_file_copy(path(), path()) -> ok. -spec ec_file_copy(path(), path()) -> ok.
@ -268,8 +268,8 @@ ec_file_copy(From, To) ->
-spec make_dir_if_dir(path()) -> ok. -spec make_dir_if_dir(path()) -> ok.
make_dir_if_dir(File) -> make_dir_if_dir(File) ->
case filelib:is_dir(File) of case filelib:is_dir(File) of
true -> ok; true -> ok;
false -> ok = mkdir_path(File) false -> ok = mkdir_path(File)
end. end.
%% @doc convert a list of integers into hex. %% @doc convert a list of integers into hex.
@ -298,10 +298,10 @@ hex0(I) -> $0 + I.
setup_test() -> setup_test() ->
case filelib:is_dir("/tmp/ec_file") of case filelib:is_dir("/tmp/ec_file") of
true -> true ->
remove("/tmp/ec_file", [recursive]); remove("/tmp/ec_file", [recursive]);
false -> false ->
ok ok
end, end,
mkdir_path("/tmp/ec_file/dir"), mkdir_path("/tmp/ec_file/dir"),
?assertMatch(false, is_symlink("/tmp/ec_file/dir")), ?assertMatch(false, is_symlink("/tmp/ec_file/dir")),
@ -318,8 +318,8 @@ file_test() ->
?assertMatch("term", consult(TermFile)), ?assertMatch("term", consult(TermFile)),
?assertMatch(<<"\"term\". ">>, read(TermFile)), ?assertMatch(<<"\"term\". ">>, read(TermFile)),
copy(filename:dirname(TermFile), copy(filename:dirname(TermFile),
filename:dirname(TermFileCopy), filename:dirname(TermFileCopy),
[recursive]), [recursive]),
?assertMatch("term", consult(TermFileCopy)). ?assertMatch("term", consult(TermFileCopy)).
teardown_test() -> teardown_test() ->
@ -343,18 +343,18 @@ setup_base_and_target() ->
{BaseDir, SourceDir, {Name1, Name2, Name3, NoName}}. {BaseDir, SourceDir, {Name1, Name2, Name3, NoName}}.
find_test() -> find_test() ->
% Create a directory in /tmp for the test. Clean everything afterwards % Create a directory in /tmp for the test. Clean everything afterwards
{setup, {setup,
fun setup_base_and_target/0, fun setup_base_and_target/0,
fun ({BaseDir, _, _}) -> fun ({BaseDir, _, _}) ->
ewl_file:delete_dir(BaseDir) ewl_file:delete_dir(BaseDir)
end, end,
fun ({BaseDir, _, {Name1, Name2, Name3, _}}) -> fun ({BaseDir, _, {Name1, Name2, Name3, _}}) ->
?assertMatch([Name2, ?assertMatch([Name2,
Name3, Name3,
Name1], Name1],
ewl_file:find(BaseDir, "file[a-z]+\$")) ewl_file:find(BaseDir, "file[a-z]+\$"))
end}. end}.
-endif. -endif.

View file

@ -42,10 +42,10 @@ search(_, []) ->
-spec find(fun(), list()) -> {ok, term()} | error. -spec find(fun(), list()) -> {ok, term()} | error.
find(Fun, [Head|Tail]) when is_function(Fun) -> find(Fun, [Head|Tail]) when is_function(Fun) ->
case Fun(Head) of case Fun(Head) of
true -> true ->
{ok, Head}; {ok, Head};
false -> false ->
find(Fun, Tail) find(Fun, Tail)
end; end;
find(_Fun, []) -> find(_Fun, []) ->
error. error.
@ -57,10 +57,10 @@ find(_Fun, []) ->
-spec fetch(fun(), list()) -> term(). -spec fetch(fun(), list()) -> term().
fetch(Fun, List) when is_list(List), is_function(Fun) -> fetch(Fun, List) when is_list(List), is_function(Fun) ->
case find(Fun, List) of case find(Fun, List) of
{ok, Head} -> {ok, Head} ->
Head; Head;
error -> error ->
throw(not_found) throw(not_found)
end. end.
%%%=================================================================== %%%===================================================================
@ -73,60 +73,60 @@ fetch(Fun, List) when is_list(List), is_function(Fun) ->
find1_test() -> find1_test() ->
TestData = [1, 2, 3, 4, 5, 6], TestData = [1, 2, 3, 4, 5, 6],
Result = find(fun(5) -> Result = find(fun(5) ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData), TestData),
?assertMatch({ok, 5}, Result), ?assertMatch({ok, 5}, Result),
Result2 = find(fun(37) -> Result2 = find(fun(37) ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData), TestData),
?assertMatch(error, Result2). ?assertMatch(error, Result2).
find2_test() -> find2_test() ->
TestData = ["one", "two", "three", "four", "five", "six"], TestData = ["one", "two", "three", "four", "five", "six"],
Result = find(fun("five") -> Result = find(fun("five") ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData), TestData),
?assertMatch({ok, "five"}, Result), ?assertMatch({ok, "five"}, Result),
Result2 = find(fun(super_duper) -> Result2 = find(fun(super_duper) ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData), TestData),
?assertMatch(error, Result2). ?assertMatch(error, Result2).
find3_test() -> find3_test() ->
TestData = [{"one", 1}, {"two", 2}, {"three", 3}, {"four", 5}, {"five", 5}, TestData = [{"one", 1}, {"two", 2}, {"three", 3}, {"four", 5}, {"five", 5},
{"six", 6}], {"six", 6}],
Result = find(fun({"one", 1}) -> Result = find(fun({"one", 1}) ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData), TestData),
?assertMatch({ok, {"one", 1}}, Result), ?assertMatch({ok, {"one", 1}}, Result),
Result2 = find(fun([fo, bar, baz]) -> Result2 = find(fun([fo, bar, baz]) ->
true; true;
({"onehundred", 100}) -> ({"onehundred", 100}) ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData), TestData),
?assertMatch(error, Result2). ?assertMatch(error, Result2).
@ -134,48 +134,48 @@ find3_test() ->
fetch1_test() -> fetch1_test() ->
TestData = [1, 2, 3, 4, 5, 6], TestData = [1, 2, 3, 4, 5, 6],
Result = fetch(fun(5) -> Result = fetch(fun(5) ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData), TestData),
?assertMatch(5, Result), ?assertMatch(5, Result),
?assertThrow(not_found, ?assertThrow(not_found,
fetch(fun(37) -> fetch(fun(37) ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData)). TestData)).
fetch2_test() -> fetch2_test() ->
TestData = ["one", "two", "three", "four", "five", "six"], TestData = ["one", "two", "three", "four", "five", "six"],
Result = fetch(fun("five") -> Result = fetch(fun("five") ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData), TestData),
?assertMatch("five", Result), ?assertMatch("five", Result),
?assertThrow(not_found, ?assertThrow(not_found,
fetch(fun(super_duper) -> fetch(fun(super_duper) ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData)). TestData)).
fetch3_test() -> fetch3_test() ->
TestData = [{"one", 1}, {"two", 2}, {"three", 3}, {"four", 5}, {"five", 5}, TestData = [{"one", 1}, {"two", 2}, {"three", 3}, {"four", 5}, {"five", 5},
{"six", 6}], {"six", 6}],
Result = fetch(fun({"one", 1}) -> Result = fetch(fun({"one", 1}) ->
true; true;
(_) -> (_) ->
false false
end, end,
TestData), TestData),
?assertMatch({"one", 1}, Result), ?assertMatch({"one", 1}, Result),
?assertThrow(not_found, ?assertThrow(not_found,

View file

@ -69,14 +69,14 @@ filter(Fun, List, Timeout) ->
run_list_fun_in_parallel(ListFun, Fun, List, Timeout) -> run_list_fun_in_parallel(ListFun, Fun, List, Timeout) ->
LocalPid = self(), LocalPid = self(),
Pids = Pids =
lists:map(fun(E) -> lists:map(fun(E) ->
Pid = Pid =
proc_lib:spawn(fun() -> proc_lib:spawn(fun() ->
wait(LocalPid, Fun, wait(LocalPid, Fun,
E, Timeout) E, Timeout)
end), end),
{Pid, E} {Pid, E}
end, List), end, List),
gather(ListFun, Pids). gather(ListFun, Pids).
-spec wait(pid(), fun(), any(), integer()) -> any(). -spec wait(pid(), fun(), any(), integer()) -> any().
@ -110,13 +110,13 @@ gather(filter, PidElementList) ->
map_gather([{Pid, _E} | Rest]) -> map_gather([{Pid, _E} | Rest]) ->
receive receive
{Pid, {value, Ret}} -> {Pid, {value, Ret}} ->
[Ret|map_gather(Rest)]; [Ret|map_gather(Rest)];
% timeouts fall here too. Should timeouts be a return value % timeouts fall here too. Should timeouts be a return value
% or an exception? I lean toward return value, but the code % or an exception? I lean toward return value, but the code
% is easier with the exception. Thoughts? % is easier with the exception. Thoughts?
{Pid, Exception} -> {Pid, Exception} ->
killall(Rest), killall(Rest),
throw(Exception) throw(Exception)
end; end;
map_gather([]) -> map_gather([]) ->
[]. [].
@ -133,15 +133,15 @@ ftmap_gather([]) ->
filter_gather([{Pid, E} | Rest]) -> filter_gather([{Pid, E} | Rest]) ->
receive receive
{Pid, {value, false}} -> {Pid, {value, false}} ->
filter_gather(Rest); filter_gather(Rest);
{Pid, {value, true}} -> {Pid, {value, true}} ->
[E|filter_gather(Rest)]; [E|filter_gather(Rest)];
{Pid, {value, NotBool}} -> {Pid, {value, NotBool}} ->
killall(Rest), killall(Rest),
throw({bad_return_value, NotBool}); throw({bad_return_value, NotBool});
{Pid, Exception} -> {Pid, Exception} ->
killall(Rest), killall(Rest),
throw(Exception) throw(Exception)
end; end;
filter_gather([]) -> filter_gather([]) ->
[]. [].
@ -153,9 +153,9 @@ do_f(Parent, F, E) ->
Parent ! {self(), {value, Result}} Parent ! {self(), {value, Result}}
catch catch
_Class:Exception -> _Class:Exception ->
% Losing class info here, but since throw does not accept % Losing class info here, but since throw does not accept
% that arg anyhow and forces a class of throw it does not % that arg anyhow and forces a class of throw it does not
% matter. % matter.
Parent ! {self(), Exception} Parent ! {self(), Exception}
end. end.
@ -183,9 +183,9 @@ map_good_test() ->
ftmap_good_test() -> ftmap_good_test() ->
Results = ftmap(fun(_) -> Results = ftmap(fun(_) ->
ok ok
end, end,
lists:seq(1, 3), infinity), lists:seq(1, 3), infinity),
?assertMatch([{value, ok}, {value, ok}, {value, ok}], ?assertMatch([{value, ok}, {value, ok}, {value, ok}],
Results). Results).
@ -199,59 +199,59 @@ filter_good_test() ->
map_timeout_test() -> map_timeout_test() ->
Results = Results =
try try
map(fun(T) -> map(fun(T) ->
timer:sleep(T), timer:sleep(T),
T T
end, end,
[1, 100], 10) [1, 100], 10)
catch catch
C:E -> {C, E} C:E -> {C, E}
end, end,
?assertMatch({throw, timeout}, Results). ?assertMatch({throw, timeout}, Results).
ftmap_timeout_test() -> ftmap_timeout_test() ->
Results = ftmap(fun(X) -> Results = ftmap(fun(X) ->
timer:sleep(X), timer:sleep(X),
true true
end, end,
[100, 1], 10), [100, 1], 10),
?assertMatch([timeout, {value, true}], Results). ?assertMatch([timeout, {value, true}], Results).
filter_timeout_test() -> filter_timeout_test() ->
Results = Results =
try try
filter(fun(T) -> filter(fun(T) ->
timer:sleep(T), timer:sleep(T),
T == 1 T == 1
end, end,
[1, 100], 10) [1, 100], 10)
catch catch
C:E -> {C, E} C:E -> {C, E}
end, end,
?assertMatch({throw, timeout}, Results). ?assertMatch({throw, timeout}, Results).
map_bad_test() -> map_bad_test() ->
Results = Results =
try try
map(fun(_) -> map(fun(_) ->
throw(test_exception) throw(test_exception)
end, end,
lists:seq(1, 5), infinity) lists:seq(1, 5), infinity)
catch catch
C:E -> {C, E} C:E -> {C, E}
end, end,
?assertMatch({throw, test_exception}, Results). ?assertMatch({throw, test_exception}, Results).
ftmap_bad_test() -> ftmap_bad_test() ->
Results = Results =
ftmap(fun(2) -> ftmap(fun(2) ->
throw(test_exception); throw(test_exception);
(N) -> (N) ->
N N
end, end,
lists:seq(1, 5), infinity), lists:seq(1, 5), infinity),
?assertMatch([{value, 1}, test_exception, {value, 3}, ?assertMatch([{value, 1}, test_exception, {value, 3},
{value, 4}, {value, 5}] , Results). {value, 4}, {value, 5}] , Results).
-endif. -endif.

View file

@ -8,12 +8,12 @@
-module(ec_semver). -module(ec_semver).
-exports([ -exports([
compare/2 compare/2
]). ]).
-export_type([ -export_type([
semvar/0 semvar/0
]). ]).
%%%=================================================================== %%%===================================================================
%%% Public Types %%% Public Types
@ -21,9 +21,9 @@
-type semvar() :: string(). -type semvar() :: string().
-type parsed_semvar() :: {MajorVsn::string(), -type parsed_semvar() :: {MajorVsn::string(),
MinorVsn::string(), MinorVsn::string(),
PatchVsn::string(), PatchVsn::string(),
PathString::string()}. PathString::string()}.
%%%=================================================================== %%%===================================================================
%%% API %%% API
@ -48,13 +48,13 @@ tokens(Vsn) ->
{MajorVsn, MinorVsn, PatchVsn, PatchString}. {MajorVsn, MinorVsn, PatchVsn, PatchString}.
-spec split_patch(string()) -> -spec split_patch(string()) ->
{PatchVsn::string(), PatchStr::string()}. {PatchVsn::string(), PatchStr::string()}.
split_patch(RawPatch) -> split_patch(RawPatch) ->
{PatchVsn, PatchStr} = split_patch(RawPatch, {"", ""}), {PatchVsn, PatchStr} = split_patch(RawPatch, {"", ""}),
{lists:reverse(PatchVsn), PatchStr}. {lists:reverse(PatchVsn), PatchStr}.
-spec split_patch(string(), {AccPatchVsn::string(), AccPatchStr::string()}) -> -spec split_patch(string(), {AccPatchVsn::string(), AccPatchStr::string()}) ->
{PatchVsn::string(), PatchStr::string()}. {PatchVsn::string(), PatchStr::string()}.
split_patch([], Acc) -> split_patch([], Acc) ->
Acc; Acc;
split_patch([Dig|T], {PatchVsn, PatchStr}) when Dig >= $0 andalso Dig =< $9 -> split_patch([Dig|T], {PatchVsn, PatchStr}) when Dig >= $0 andalso Dig =< $9 ->
@ -65,7 +65,7 @@ split_patch(PatchStr, {PatchVsn, ""}) ->
-spec compare_toks(parsed_semvar(), parsed_semvar()) -> boolean(). -spec compare_toks(parsed_semvar(), parsed_semvar()) -> boolean().
compare_toks({MajA, MinA, PVA, PSA}, {MajB, MinB, PVB, PSB}) -> compare_toks({MajA, MinA, PVA, PSA}, {MajB, MinB, PVB, PSB}) ->
compare_toks2({to_int(MajA), to_int(MinA), to_int(PVA), PSA}, compare_toks2({to_int(MajA), to_int(MinA), to_int(PVA), PSA},
{to_int(MajB), to_int(MinB), to_int(PVB), PSB}). {to_int(MajB), to_int(MinB), to_int(PVB), PSB}).
-spec compare_toks2(parsed_semvar(), parsed_semvar()) -> boolean(). -spec compare_toks2(parsed_semvar(), parsed_semvar()) -> boolean().
compare_toks2({MajA, _MinA, _PVA, _PSA}, {MajB, _MinB, _PVB, _PSB}) compare_toks2({MajA, _MinA, _PVA, _PSA}, {MajB, _MinB, _PVB, _PSB})
@ -89,10 +89,10 @@ compare_toks2(_ToksA, _ToksB) ->
-spec to_int(string()) -> integer(). -spec to_int(string()) -> integer().
to_int(String) -> to_int(String) ->
try try
list_to_integer(String) list_to_integer(String)
catch catch
error:badarg -> error:badarg ->
throw(invalid_semver_string) throw(invalid_semver_string)
end. end.
%%%=================================================================== %%%===================================================================

View file

@ -7,8 +7,8 @@
-module(ec_string). -module(ec_string).
-export([ -export([
compare_versions/2 compare_versions/2
]). ]).
%%%=================================================================== %%%===================================================================
%%% API %%% API
%%%=================================================================== %%%===================================================================
@ -39,7 +39,7 @@ compare([Str|TA], [Str|TB]) ->
compare(TA, TB); compare(TA, TB);
compare([StrA|TA], [StrB|TB]) -> compare([StrA|TA], [StrB|TB]) ->
fine_compare(split_numeric_alpha(StrA), TA, fine_compare(split_numeric_alpha(StrA), TA,
split_numeric_alpha(StrB), TB); split_numeric_alpha(StrB), TB);
compare([], [Str]) -> compare([], [Str]) ->
not compare_against_nothing(Str); not compare_against_nothing(Str);
compare([Str], []) -> compare([Str], []) ->
@ -54,14 +54,14 @@ compare([], []) ->
-spec compare_against_nothing(string()) -> boolean(). -spec compare_against_nothing(string()) -> boolean().
compare_against_nothing(Str) -> compare_against_nothing(Str) ->
case split_numeric_alpha(Str) of case split_numeric_alpha(Str) of
{_StrDig, ""} -> true; {_StrDig, ""} -> true;
{"", _StrAlpha} -> false; {"", _StrAlpha} -> false;
{_StrDig, _StrAlpha} -> true {_StrDig, _StrAlpha} -> true
end. end.
-spec fine_compare({string(), string()}, string(), -spec fine_compare({string(), string()}, string(),
{string(), string()}, string()) -> {string(), string()}, string()) ->
boolean(). boolean().
fine_compare({_StrDigA, StrA}, TA, {_StrDigB, _StrB}, _TB) fine_compare({_StrDigA, StrA}, TA, {_StrDigB, _StrB}, _TB)
when StrA /= "", TA /= [] -> when StrA /= "", TA /= [] ->
throw(invalid_version_string); throw(invalid_version_string);
@ -84,14 +84,14 @@ fine_compare({StrDigA, _StrA}, _TA, {StrDigB, _StrB}, _TB) ->
%% In the case of a version sub part with a numeric then an alpha, %% In the case of a version sub part with a numeric then an alpha,
%% split out the numeric and alpha "24alpha" becomes {"24", "alpha"} %% split out the numeric and alpha "24alpha" becomes {"24", "alpha"}
-spec split_numeric_alpha(string()) -> -spec split_numeric_alpha(string()) ->
{PatchVsn::string(), PatchStr::string()}. {PatchVsn::string(), PatchStr::string()}.
split_numeric_alpha(RawVsn) -> split_numeric_alpha(RawVsn) ->
{Num, Str} = split_numeric_alpha(RawVsn, {"", ""}), {Num, Str} = split_numeric_alpha(RawVsn, {"", ""}),
{lists:reverse(Num), Str}. {lists:reverse(Num), Str}.
-spec split_numeric_alpha(string(), {PatchVsnAcc::string(), -spec split_numeric_alpha(string(), {PatchVsnAcc::string(),
PatchStrAcc::string()}) -> PatchStrAcc::string()}) ->
{PatchVsn::string(), PatchStr::string()}. {PatchVsn::string(), PatchStr::string()}.
split_numeric_alpha([], Acc) -> split_numeric_alpha([], Acc) ->
Acc; Acc;
split_numeric_alpha([Dig|T], {PatchVsn, PatchStr}) split_numeric_alpha([Dig|T], {PatchVsn, PatchStr})