Merge remote-tracking branch 'canonical/next'
* canonical/next: massively expand the documentation in the README bring ec_plists up to erlware standards replace ec_plists with Stephan's plists add Stephen Marsh's plists to the system reorder default tasks so dialyzer is run after compile add a clean and rebuild task to makefile add fullpath to the makefile enable the rebar semver plugin on erlware_commons cleanup the rebar config support non-numeric versions in major/minor/patch/minor-patch support reasonable versioning for erlware_commons add exists to ec_file fix bug in ec_file:copy/3 spec export mkdir_p (this should have been done already) support four primary version numbers of in parsing minor whitespace cleanup for ec_semver provide the ability to format a version into a string as well as parse a version make sure the docs get run as part of a bare make fixes for edoc compilation compilation utilities for the implementors
This commit is contained in:
commit
1a39438f3c
10 changed files with 1469 additions and 300 deletions
11
Makefile
11
Makefile
|
@ -14,9 +14,10 @@ endif
|
|||
|
||||
ERLWARE_COMMONS_PLT=$(CURDIR)/.erlware_commons_plt
|
||||
|
||||
.PHONY: all compile doc clean test dialyzer typer shell distclean pdf get-deps escript
|
||||
.PHONY: all compile doc clean test dialyzer typer shell distclean pdf get-deps \
|
||||
rebuild
|
||||
|
||||
all: compile test dialyzer
|
||||
all: compile dialyzer doc test
|
||||
|
||||
get-deps:
|
||||
$(REBAR) get-deps
|
||||
|
@ -34,11 +35,11 @@ test: compile
|
|||
$(ERLWARE_COMMONS_PLT):
|
||||
@echo Building local plt at $(ERLWARE_COMMONS_PLT)
|
||||
@echo
|
||||
- dialyzer --output_plt $(ERLWARE_COMMONS_PLT) --build_plt \
|
||||
- dialyzer --fullpath --output_plt $(ERLWARE_COMMONS_PLT) --build_plt \
|
||||
--apps erts kernel stdlib eunit -r deps
|
||||
|
||||
dialyzer: $(ERLWARE_COMMONS_PLT)
|
||||
dialyzer --plt $(ERLWARE_COMMONS_PLT) -Wrace_conditions --src src
|
||||
dialyzer --fullpath --plt $(ERLWARE_COMMONS_PLT) -Wrace_conditions --src src
|
||||
|
||||
typer:
|
||||
typer --plt $(ERLWARE_COMMONS_PLT) -r ./src
|
||||
|
@ -62,3 +63,5 @@ clean:
|
|||
distclean: clean
|
||||
rm -rf $(ERLWARE_COMMONS_PLT)
|
||||
rm -rvf $(CURDIR)/deps/*
|
||||
|
||||
rebuild: distclean all
|
||||
|
|
104
README.md
104
README.md
|
@ -23,3 +23,107 @@ Goals for the project
|
|||
* High Quality
|
||||
* Well Documented
|
||||
* Well Tested
|
||||
|
||||
Currently Available Modules/Systems
|
||||
------------------------------------
|
||||
|
||||
### [ec_date](https://github.com/erlware/erlware_commons/blob/master/src/ec_date.erl)
|
||||
|
||||
This module formats erlang dates in the form {{Year, Month, Day},
|
||||
{Hour, Minute, Second}} to printable strings, using (almost)
|
||||
equivalent formatting rules as http://uk.php.net/date, US vs European
|
||||
dates are disambiguated in the same way as
|
||||
http://uk.php.net/manual/en/function.strtotime.php That is, Dates in
|
||||
the m/d/y or d-m-y formats are disambiguated by looking at the
|
||||
separator between the various components: if the separator is a slash
|
||||
(/), then the American m/d/y is assumed; whereas if the separator is a
|
||||
dash (-) or a dot (.), then the European d-m-y format is assumed. To
|
||||
avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD)
|
||||
dates.
|
||||
|
||||
erlang has no concept of timezone so the following formats are not
|
||||
implemented: B e I O P T Z formats c and r will also differ slightly
|
||||
|
||||
### [ec_file](https://github.com/erlware/erlware_commons/blob/master/src/ec_file.erl)
|
||||
|
||||
A set of commonly defined helper functions for files that are not
|
||||
included in stdlib.
|
||||
|
||||
### [ec_plists](https://github.com/erlware/erlware_commons/blob/master/src/ec_plists.erl)
|
||||
|
||||
plists is a drop-in replacement for module <a
|
||||
href="http://www.erlang.org/doc/man/lists.html">lists</a>, making most
|
||||
list operations parallel. It can operate on each element in parallel,
|
||||
for IO-bound operations, on sublists in parallel, for taking advantage
|
||||
of multi-core machines with CPU-bound operations, and across erlang
|
||||
nodes, for parallizing inside a cluster. It handles errors and node
|
||||
failures. It can be configured, tuned, and tweaked to get optimal
|
||||
performance while minimizing overhead.
|
||||
|
||||
Almost all the functions are identical to equivalent functions in
|
||||
lists, returning exactly the same result, and having both a form with
|
||||
an identical syntax that operates on each element in parallel and a
|
||||
form which takes an optional "malt", a specification for how to
|
||||
parallize the operation.
|
||||
|
||||
fold is the one exception, parallel fold is different from linear
|
||||
fold. This module also include a simple mapreduce implementation, and
|
||||
the function runmany. All the other functions are implemented with
|
||||
runmany, which is as a generalization of parallel list operations.
|
||||
|
||||
### [ec_semver](https://github.com/erlware/erlware_commons/blob/master/src/ec_semver.erl)
|
||||
|
||||
A complete parser for the [semver](http://semver.org/)
|
||||
standard. Including a complete set of conforming comparison functions.
|
||||
|
||||
### [ec_lists](https://github.com/ericbmerritt/erlware_commons/blob/master/src/ec_lists.erl)
|
||||
|
||||
A set of additional list manipulation functions designed to supliment
|
||||
the `lists` module in stdlib.
|
||||
|
||||
### [ec_talk](https://github.com/erlware/erlware_commons/blob/master/src/ec_talk.erl)
|
||||
|
||||
A set of simple utility functions to falicitate command line
|
||||
communication with a user.
|
||||
|
||||
Signatures
|
||||
-----------
|
||||
|
||||
Other languages, have built in support for **Interface** or
|
||||
**signature** functionality. Java has Interfaces, SML has
|
||||
Signatures. Erlang, though, doesn't currently support this model, at
|
||||
least not directly. There are a few ways you can approximate it. We
|
||||
have defined a mechnism called *signatures* and several modules that
|
||||
to serve as examples and provide a good set of *dictionary*
|
||||
signatures. More information about signatures can be found at
|
||||
[signature](https://github.com/erlware/erlware_commons/blob/master/doc/signatures.md).
|
||||
|
||||
|
||||
### [ec_dictionary](https://github.com/erlware/erlware_commons/blob/master/src/ec_dictionary.erl)
|
||||
|
||||
A signature that supports association of keys to values. A map cannot
|
||||
contain duplicate keys; each key can map to at most one value.
|
||||
|
||||
### [ec_dict](https://github.com/erlware/erlware_commons/blob/master/src/ec_dict.erl)
|
||||
|
||||
This provides an implementation of the ec_dictionary signature using
|
||||
erlang's dicts as a base. The function documentation for ec_dictionary
|
||||
applies here as well.
|
||||
|
||||
### [ec_gb_trees](https://github.com/ericbmerritt/erlware_commons/blob/master/src/ec_gb_trees.erl)
|
||||
|
||||
This provides an implementation of the ec_dictionary signature using
|
||||
erlang's gb_trees as a base. The function documentation for
|
||||
ec_dictionary applies here as well.
|
||||
|
||||
### [ec_orddict](https://github.com/ericbmerritt/erlware_commons/blob/master/src/ec_orddict.erl)
|
||||
|
||||
This provides an implementation of the ec_dictionary signature using
|
||||
erlang's orddict as a base. The function documentation for
|
||||
ec_dictionary applies here as well.
|
||||
|
||||
### [ec_rbdict](https://github.com/ericbmerritt/erlware_commons/blob/master/src/ec_rbdict.erl)
|
||||
|
||||
This provides an implementation of the ec_dictionary signature using
|
||||
Robert Virding's rbdict module as a base. The function documentation
|
||||
for ec_dictionary applies here as well.
|
||||
|
|
19
rebar.config
19
rebar.config
|
@ -1,12 +1,25 @@
|
|||
%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*-
|
||||
|
||||
%% These are all only compile time dependencies
|
||||
%% Dependencies ================================================================
|
||||
{deps, [{neotoma, "",
|
||||
{git, "https://github.com/seancribbs/neotoma.git", {tag, "1.5"}}},
|
||||
{proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}}]}.
|
||||
{git, "https://github.com/seancribbs/neotoma.git", {branch, master}}},
|
||||
{proper, "", {git, "https://github.com/manopapad/proper.git", {branch, master}}},
|
||||
{rebar_vsn_plugin, ".*", {git, "https://github.com/erlware/rebar_vsn_plugin.git",
|
||||
{branch, "master"}}}]}.
|
||||
|
||||
{erl_first_files, ["ec_dictionary"]}.
|
||||
|
||||
%% Compiler Options ============================================================
|
||||
{erl_opts,
|
||||
[debug_info,
|
||||
warnings_as_errors]}.
|
||||
|
||||
%% EUnit =======================================================================
|
||||
{eunit_opts, [verbose,
|
||||
{report, {eunit_surefire, [{dir, "."}]}}]}.
|
||||
|
||||
{cover_enabled, true}.
|
||||
{cover_print_enabled, true}.
|
||||
|
||||
%% Rebar Plugins ==============================================================
|
||||
{plugins, [rebar_vsn_plugin]}.
|
||||
|
|
107
src/ec_compile.erl
Normal file
107
src/ec_compile.erl
Normal file
|
@ -0,0 +1,107 @@
|
|||
%%%-------------------------------------------------------------------
|
||||
%%% @author Eric Merritt <>
|
||||
%%% @copyright (C) 2011, Erlware, LLC.
|
||||
%%% @doc
|
||||
%%% These are various utility functions to help with compiling and
|
||||
%%% decompiling erlang source. They are mostly useful to the
|
||||
%%% language/parse transform implementor.
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(ec_compile).
|
||||
|
||||
-export([beam_to_erl_source/2,
|
||||
erl_source_to_core_ast/1,
|
||||
erl_source_to_erl_ast/1,
|
||||
erl_source_to_asm/1,
|
||||
erl_string_to_core_ast/1,
|
||||
erl_string_to_erl_ast/1,
|
||||
erl_string_to_asm/1]).
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
|
||||
%% @doc decompile a beam file that has been compiled with +debug_info
|
||||
%% into a erlang source file
|
||||
%%
|
||||
%% @param BeamFName the name of the beamfile
|
||||
%% @param ErlFName the name of the erlang file where the generated
|
||||
%% source file will be output. This should *not* be the same as the
|
||||
%% source file that created the beamfile unless you want to overwrite
|
||||
%% it.
|
||||
-spec beam_to_erl_source(string(), string()) -> ok | term().
|
||||
beam_to_erl_source(BeamFName, ErlFName) ->
|
||||
case beam_lib:chunks(BeamFName, [abstract_code]) of
|
||||
{ok, {_, [{abstract_code, {raw_abstract_v1,Forms}}]}} ->
|
||||
Src =
|
||||
erl_prettypr:format(erl_syntax:form_list(tl(Forms))),
|
||||
{ok, Fd} = file:open(ErlFName, [write]),
|
||||
io:fwrite(Fd, "~s~n", [Src]),
|
||||
file:close(Fd);
|
||||
Error ->
|
||||
Error
|
||||
end.
|
||||
|
||||
%% @doc compile an erlang source file into a Core Erlang AST
|
||||
%%
|
||||
%% @param Path - The path to the erlang source file
|
||||
-spec erl_source_to_core_ast(file:filename()) -> CoreAst::term().
|
||||
erl_source_to_core_ast(Path) ->
|
||||
{ok, Contents} = file:read_file(Path),
|
||||
erl_string_to_core_ast(binary_to_list(Contents)).
|
||||
|
||||
%% @doc compile an erlang source file into an Erlang AST
|
||||
%%
|
||||
%% @param Path - The path to the erlang source file
|
||||
-spec erl_source_to_erl_ast(file:filename()) -> ErlangAst::term().
|
||||
erl_source_to_erl_ast(Path) ->
|
||||
{ok, Contents} = file:read_file(Path),
|
||||
erl_string_to_erl_ast(binary_to_list(Contents)).
|
||||
|
||||
%% @doc compile an erlang source file into erlang terms that represent
|
||||
%% the relevant ASM
|
||||
%%
|
||||
%% @param Path - The path to the erlang source file
|
||||
-spec erl_source_to_asm(file:filename()) -> ErlangAsm::term().
|
||||
erl_source_to_asm(Path) ->
|
||||
{ok, Contents} = file:read_file(Path),
|
||||
erl_string_to_asm(binary_to_list(Contents)).
|
||||
|
||||
%% @doc compile a string representing an erlang expression into an
|
||||
%% Erlang AST
|
||||
%%
|
||||
%% @param StringExpr - The path to the erlang source file
|
||||
-spec erl_string_to_erl_ast(string()) -> ErlangAst::term().
|
||||
erl_string_to_erl_ast(StringExpr) ->
|
||||
Forms0 =
|
||||
lists:foldl(fun(<<>>, Acc) ->
|
||||
Acc;
|
||||
(<<"\n\n">>, Acc) ->
|
||||
Acc;
|
||||
(El, Acc) ->
|
||||
{ok, Tokens, _} =
|
||||
erl_scan:string(binary_to_list(El)
|
||||
++ "."),
|
||||
[Tokens | Acc]
|
||||
end, [], re:split(StringExpr, "\\.\n")),
|
||||
%% No need to reverse. This will rereverse for us
|
||||
lists:foldl(fun(Form, Forms) ->
|
||||
{ok, ErlAST} = erl_parse:parse_form(Form),
|
||||
[ErlAST | Forms]
|
||||
end, [], Forms0).
|
||||
|
||||
%% @doc compile a string representing an erlang expression into a
|
||||
%% Core Erlang AST
|
||||
%%
|
||||
%% @param StringExpr - The path to the erlang source file
|
||||
-spec erl_string_to_core_ast(string()) -> CoreAst::term().
|
||||
erl_string_to_core_ast(StringExpr) ->
|
||||
compile:forms(erl_string_to_erl_ast(StringExpr), [to_core]).
|
||||
|
||||
%% @doc compile a string representing an erlang expression into a term
|
||||
%% that represents the ASM
|
||||
%%
|
||||
%% @param StringExpr - The path to the erlang source file
|
||||
-spec erl_string_to_asm(string()) -> ErlangAsm::term().
|
||||
erl_string_to_asm(StringExpr) ->
|
||||
compile:forms(erl_string_to_erl_ast(StringExpr), ['S']).
|
|
@ -7,10 +7,12 @@
|
|||
-module(ec_file).
|
||||
|
||||
-export([
|
||||
exists/1,
|
||||
copy/2,
|
||||
copy/3,
|
||||
insecure_mkdtemp/0,
|
||||
mkdir_path/1,
|
||||
mkdir_p/1,
|
||||
find/2,
|
||||
is_symlink/1,
|
||||
remove/1,
|
||||
|
@ -35,12 +37,21 @@
|
|||
%% Types
|
||||
%%============================================================================
|
||||
-type option() :: recursive.
|
||||
-type void() :: ok.
|
||||
|
||||
%%%===================================================================
|
||||
%%% API
|
||||
%%%===================================================================
|
||||
-spec exists(file:filename()) -> boolean().
|
||||
exists(Filename) ->
|
||||
case file:read_file_info(Filename) of
|
||||
{ok, _} ->
|
||||
true;
|
||||
{error, _Reason} ->
|
||||
false
|
||||
end.
|
||||
|
||||
%% @doc copy an entire directory to another location.
|
||||
-spec copy(file:name(), file:name(), Options::[option()]) -> void().
|
||||
-spec copy(file:name(), file:name(), Options::[option()]) -> ok | {error, Reason::term()}.
|
||||
copy(From, To, []) ->
|
||||
copy(From, To);
|
||||
copy(From, To, [recursive] = Options) ->
|
||||
|
@ -229,7 +240,7 @@ tmp() ->
|
|||
end.
|
||||
|
||||
%% Copy the subfiles of the From directory to the to directory.
|
||||
-spec copy_subfiles(file:name(), file:name(), [option()]) -> void().
|
||||
-spec copy_subfiles(file:name(), file:name(), [option()]) -> {error, Reason::term()} | ok.
|
||||
copy_subfiles(From, To, Options) ->
|
||||
Fun =
|
||||
fun(ChildFrom) ->
|
||||
|
@ -313,6 +324,16 @@ setup_base_and_target() ->
|
|||
ok = file:write_file(NoName, DummyContents),
|
||||
{BaseDir, SourceDir, {Name1, Name2, Name3, NoName}}.
|
||||
|
||||
exists_test() ->
|
||||
BaseDir = insecure_mkdtemp(),
|
||||
SourceDir = filename:join([BaseDir, "source1"]),
|
||||
NoName = filename:join([SourceDir, "noname"]),
|
||||
ok = file:make_dir(SourceDir),
|
||||
Name1 = filename:join([SourceDir, "fileone"]),
|
||||
ok = file:write_file(Name1, <<"Testn">>),
|
||||
?assertMatch(true, exists(Name1)),
|
||||
?assertMatch(false, exists(NoName)).
|
||||
|
||||
find_test() ->
|
||||
%% Create a directory in /tmp for the test. Clean everything afterwards
|
||||
{BaseDir, _SourceDir, {Name1, Name2, Name3, _NoName}} = setup_base_and_target(),
|
||||
|
|
1158
src/ec_plists.erl
1158
src/ec_plists.erl
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,4 @@
|
|||
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2011, Erlware LLC
|
||||
%%% @doc
|
||||
|
@ -8,6 +9,7 @@
|
|||
-module(ec_semver).
|
||||
|
||||
-export([parse/1,
|
||||
format/1,
|
||||
eql/2,
|
||||
gt/2,
|
||||
gte/2,
|
||||
|
@ -27,15 +29,20 @@
|
|||
%%% Public Types
|
||||
%%%===================================================================
|
||||
|
||||
-type major_minor_patch() ::
|
||||
non_neg_integer()
|
||||
| {non_neg_integer(), non_neg_integer()}
|
||||
| {non_neg_integer(), non_neg_integer(), non_neg_integer()}.
|
||||
-type version_element() :: non_neg_integer() | binary().
|
||||
|
||||
-type alpha_part() :: integer() | binary().
|
||||
-type major_minor_patch_minpatch() ::
|
||||
version_element()
|
||||
| {version_element(), version_element()}
|
||||
| {version_element(), version_element(), version_element()}
|
||||
| {version_element(), version_element(),
|
||||
version_element(), version_element()}.
|
||||
|
||||
-type semver() :: {major_minor_patch(), {PreReleaseVersion::[alpha_part()],
|
||||
BuildVersion::[alpha_part()]}}.
|
||||
-type alpha_part() :: integer() | binary() | string().
|
||||
-type alpha_info() :: {PreRelease::[alpha_part()],
|
||||
BuildVersion::[alpha_part()]}.
|
||||
|
||||
-type semver() :: {major_minor_patch_minpatch(), alpha_info()}.
|
||||
|
||||
-type version_string() :: string() | binary().
|
||||
|
||||
|
@ -48,12 +55,58 @@
|
|||
%% @doc parse a string or binary into a valid semver representation
|
||||
-spec parse(any_version()) -> semver().
|
||||
parse(Version) when erlang:is_list(Version) ->
|
||||
ec_semver_parser:parse(Version);
|
||||
case ec_semver_parser:parse(Version) of
|
||||
{fail, _} ->
|
||||
{erlang:iolist_to_binary(Version), {[],[]}};
|
||||
Good ->
|
||||
Good
|
||||
end;
|
||||
parse(Version) when erlang:is_binary(Version) ->
|
||||
ec_semver_parser:parse(Version);
|
||||
case ec_semver_parser:parse(Version) of
|
||||
{fail, _} ->
|
||||
{Version, {[],[]}};
|
||||
Good ->
|
||||
Good
|
||||
end;
|
||||
parse(Version) ->
|
||||
Version.
|
||||
|
||||
-spec format(semver()) -> iolist().
|
||||
format({Maj, {AlphaPart, BuildPart}})
|
||||
when erlang:is_integer(Maj);
|
||||
erlang:is_binary(Maj) ->
|
||||
[format_version_part(Maj),
|
||||
format_vsn_rest(<<"-">>, AlphaPart),
|
||||
format_vsn_rest(<<"+">>, BuildPart)];
|
||||
format({{Maj, Min}, {AlphaPart, BuildPart}}) ->
|
||||
[format_version_part(Maj), ".",
|
||||
format_version_part(Min),
|
||||
format_vsn_rest(<<"-">>, AlphaPart),
|
||||
format_vsn_rest(<<"+">>, BuildPart)];
|
||||
format({{Maj, Min, Patch}, {AlphaPart, BuildPart}}) ->
|
||||
[format_version_part(Maj), ".",
|
||||
format_version_part(Min), ".",
|
||||
format_version_part(Patch),
|
||||
format_vsn_rest(<<"-">>, AlphaPart),
|
||||
format_vsn_rest(<<"+">>, BuildPart)];
|
||||
format({{Maj, Min, Patch, MinPatch}, {AlphaPart, BuildPart}}) ->
|
||||
[format_version_part(Maj), ".",
|
||||
format_version_part(Min), ".",
|
||||
format_version_part(Patch), ".",
|
||||
format_version_part(MinPatch),
|
||||
format_vsn_rest(<<"-">>, AlphaPart),
|
||||
format_vsn_rest(<<"+">>, BuildPart)].
|
||||
|
||||
-spec format_version_part(integer() | binary()) -> iolist().
|
||||
format_version_part(Vsn)
|
||||
when erlang:is_integer(Vsn) ->
|
||||
erlang:integer_to_list(Vsn);
|
||||
format_version_part(Vsn)
|
||||
when erlang:is_binary(Vsn) ->
|
||||
Vsn.
|
||||
|
||||
|
||||
|
||||
%% @doc test for quality between semver versions
|
||||
-spec eql(any_version(), any_version()) -> boolean().
|
||||
eql(VsnA, VsnB) ->
|
||||
|
@ -141,8 +194,8 @@ between(Vsn1, Vsn2, VsnMatch) ->
|
|||
%% revisions and "~> 2.6.5" is pessimistic about future minor
|
||||
%% revisions.
|
||||
%%
|
||||
%% "~> 2.6" matches cookbooks >= 2.6.0 AND < 3.0.0
|
||||
%% "~> 2.6.5" matches cookbooks >= 2.6.5 AND < 2.7.0
|
||||
%% "~> 2.6" matches cookbooks >= 2.6.0 AND < 3.0.0
|
||||
%% "~> 2.6.5" matches cookbooks >= 2.6.5 AND < 2.7.0
|
||||
pes(VsnA, VsnB) ->
|
||||
internal_pes(parse(VsnA), parse(VsnB)).
|
||||
|
||||
|
@ -152,17 +205,20 @@ pes(VsnA, VsnB) ->
|
|||
%% @doc helper function for the peg grammer to parse the iolist into a semver
|
||||
-spec internal_parse_version(iolist()) -> semver().
|
||||
internal_parse_version([MMP, AlphaPart, BuildPart, _]) ->
|
||||
{parse_major_minor_patch(MMP), {parse_alpha_part(AlphaPart),
|
||||
{parse_major_minor_patch_minpatch(MMP), {parse_alpha_part(AlphaPart),
|
||||
parse_alpha_part(BuildPart)}}.
|
||||
|
||||
%% @doc helper function for the peg grammer to parse the iolist into a major_minor_patch
|
||||
-spec parse_major_minor_patch(iolist()) -> major_minor_patch().
|
||||
parse_major_minor_patch([MajVsn, [], []]) ->
|
||||
-spec parse_major_minor_patch_minpatch(iolist()) -> major_minor_patch_minpatch().
|
||||
parse_major_minor_patch_minpatch([MajVsn, [], [], []]) ->
|
||||
MajVsn;
|
||||
parse_major_minor_patch([MajVsn, [<<".">>, MinVsn], []]) ->
|
||||
parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn], [], []]) ->
|
||||
{MajVsn, MinVsn};
|
||||
parse_major_minor_patch([MajVsn, [<<".">>, MinVsn], [<<".">>, PatchVsn]]) ->
|
||||
{MajVsn, MinVsn, PatchVsn}.
|
||||
parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn], [<<".">>, PatchVsn], []]) ->
|
||||
{MajVsn, MinVsn, PatchVsn};
|
||||
parse_major_minor_patch_minpatch([MajVsn, [<<".">>, MinVsn],
|
||||
[<<".">>, PatchVsn], [<<".">>, MinPatch]]) ->
|
||||
{MajVsn, MinVsn, PatchVsn, MinPatch}.
|
||||
|
||||
%% @doc helper function for the peg grammer to parse the iolist into an alpha part
|
||||
-spec parse_alpha_part(iolist()) -> [alpha_part()].
|
||||
|
@ -189,32 +245,59 @@ format_alpha_part([<<".">>, AlphaPart]) ->
|
|||
%%%===================================================================
|
||||
%%% Internal Functions
|
||||
%%%===================================================================
|
||||
-spec to_list(integer() | binary() | string()) -> string() | binary().
|
||||
to_list(Detail) when erlang:is_integer(Detail) ->
|
||||
erlang:integer_to_list(Detail);
|
||||
to_list(Detail) when erlang:is_list(Detail); erlang:is_binary(Detail) ->
|
||||
Detail.
|
||||
|
||||
-spec format_vsn_rest(binary() | string(), [integer() | binary()]) -> iolist().
|
||||
format_vsn_rest(_TypeMark, []) ->
|
||||
[];
|
||||
format_vsn_rest(TypeMark, [Head | Rest]) ->
|
||||
[TypeMark, Head |
|
||||
[[".", to_list(Detail)] || Detail <- Rest]].
|
||||
|
||||
%% @doc normalize the semver so they can be compared
|
||||
-spec normalize(semver()) -> semver().
|
||||
normalize({Vsn, Rest})
|
||||
when erlang:is_integer(Vsn) ->
|
||||
{{Vsn, 0, 0}, Rest};
|
||||
when erlang:is_binary(Vsn);
|
||||
erlang:is_integer(Vsn) ->
|
||||
{{Vsn, 0, 0, 0}, Rest};
|
||||
normalize({{Maj, Min}, Rest}) ->
|
||||
{{Maj, Min, 0}, Rest};
|
||||
normalize(Other) ->
|
||||
{{Maj, Min, 0, 0}, Rest};
|
||||
normalize({{Maj, Min, Patch}, Rest}) ->
|
||||
{{Maj, Min, Patch, 0}, Rest};
|
||||
normalize(Other = {{_, _, _, _}, {_,_}}) ->
|
||||
Other.
|
||||
|
||||
%% @doc to do the pessimistic compare we need a parsed semver. This is
|
||||
%% the internal implementation of the of the pessimistic run. The
|
||||
%% external just ensures that versions are parsed.
|
||||
internal_pes(VsnA, {{LM, LMI}, _}) ->
|
||||
-spec internal_pes(semver(), semver()) -> boolean().
|
||||
internal_pes(VsnA, {{LM, LMI}, _})
|
||||
when erlang:is_integer(LM),
|
||||
erlang:is_integer(LMI) ->
|
||||
gte(VsnA, {{LM, LMI, 0}, {[], []}}) andalso
|
||||
lt(VsnA, {{LM + 1, 0, 0}, {[], []}});
|
||||
internal_pes(VsnA, {{LM, LMI, LP}, _}) ->
|
||||
lt(VsnA, {{LM + 1, 0, 0, 0}, {[], []}});
|
||||
internal_pes(VsnA, {{LM, LMI, LP}, _})
|
||||
when erlang:is_integer(LM),
|
||||
erlang:is_integer(LMI),
|
||||
erlang:is_integer(LP) ->
|
||||
gte(VsnA, {{LM, LMI, LP}, {[], []}})
|
||||
andalso
|
||||
lt(VsnA, {{LM, LMI + 1, 0}, {[], []}});
|
||||
lt(VsnA, {{LM, LMI + 1, 0, 0}, {[], []}});
|
||||
internal_pes(VsnA, {{LM, LMI, LP, LMP}, _})
|
||||
when erlang:is_integer(LM),
|
||||
erlang:is_integer(LMI),
|
||||
erlang:is_integer(LP),
|
||||
erlang:is_integer(LMP) ->
|
||||
gte(VsnA, {{LM, LMI, LP, LMP}, {[], []}})
|
||||
andalso
|
||||
lt(VsnA, {{LM, LMI, LP + 1, 0}, {[], []}});
|
||||
internal_pes(Vsn, LVsn) ->
|
||||
gte(Vsn, LVsn).
|
||||
|
||||
|
||||
|
||||
|
||||
%%%===================================================================
|
||||
%%% Test Functions
|
||||
%%%===================================================================
|
||||
|
@ -231,25 +314,43 @@ eql_test() ->
|
|||
"1.0.0")),
|
||||
?assertMatch(true, eql("1.0.0",
|
||||
"1")),
|
||||
?assertMatch(true, eql("1.0.0.0",
|
||||
"1")),
|
||||
?assertMatch(true, eql("1.0+alpha.1",
|
||||
"1.0.0+alpha.1")),
|
||||
?assertMatch(true, eql("1.0-alpha.1+build.1",
|
||||
"1.0.0-alpha.1+build.1")),
|
||||
?assertMatch(true, eql("1.0-alpha.1+build.1",
|
||||
"1.0.0.0-alpha.1+build.1")),
|
||||
?assertMatch(true, eql("aa", "aa")),
|
||||
?assertMatch(true, eql("AA.BB", "AA.BB")),
|
||||
?assertMatch(true, eql("BBB-super", "BBB-super")),
|
||||
?assertMatch(true, not eql("1.0.0",
|
||||
"1.0.1")),
|
||||
?assertMatch(true, not eql("1.0.0-alpha",
|
||||
"1.0.1+alpha")),
|
||||
?assertMatch(true, not eql("1.0.0+build.1",
|
||||
"1.0.1+build.2")).
|
||||
|
||||
"1.0.1+build.2")),
|
||||
?assertMatch(true, not eql("1.0.0.0+build.1",
|
||||
"1.0.0.1+build.2")),
|
||||
?assertMatch(true, not eql("FFF", "BBB")),
|
||||
?assertMatch(true, not eql("1", "1BBBB")).
|
||||
|
||||
gt_test() ->
|
||||
?assertMatch(true, gt("1.0.0-alpha.1",
|
||||
"1.0.0-alpha")),
|
||||
?assertMatch(true, gt("1.0.0.1-alpha.1",
|
||||
"1.0.0.1-alpha")),
|
||||
?assertMatch(true, gt("1.0.0.4-alpha.1",
|
||||
"1.0.0.2-alpha")),
|
||||
?assertMatch(true, gt("1.0.0.0-alpha.1",
|
||||
"1.0.0-alpha")),
|
||||
?assertMatch(true, gt("1.0.0-beta.2",
|
||||
"1.0.0-alpha.1")),
|
||||
?assertMatch(true, gt("1.0.0-beta.11",
|
||||
"1.0.0-beta.2")),
|
||||
?assertMatch(true, gt("1.0.0-beta.11",
|
||||
"1.0.0.0-beta.2")),
|
||||
?assertMatch(true, gt("1.0.0-rc.1", "1.0.0-beta.11")),
|
||||
?assertMatch(true, gt("1.0.0-rc.1+build.1", "1.0.0-rc.1")),
|
||||
?assertMatch(true, gt("1.0.0", "1.0.0-rc.1+build.1")),
|
||||
|
@ -257,10 +358,16 @@ gt_test() ->
|
|||
?assertMatch(true, gt("1.3.7+build", "1.0.0+0.3.7")),
|
||||
?assertMatch(true, gt("1.3.7+build.2.b8f12d7",
|
||||
"1.3.7+build")),
|
||||
?assertMatch(true, gt("1.3.7+build.2.b8f12d7",
|
||||
"1.3.7.0+build")),
|
||||
?assertMatch(true, gt("1.3.7+build.11.e0f985a",
|
||||
"1.3.7+build.2.b8f12d7")),
|
||||
?assertMatch(true, gt("aa.cc",
|
||||
"aa.bb")),
|
||||
?assertMatch(true, not gt("1.0.0-alpha",
|
||||
"1.0.0-alpha.1")),
|
||||
?assertMatch(true, not gt("1.0.0-alpha",
|
||||
"1.0.0.0-alpha.1")),
|
||||
?assertMatch(true, not gt("1.0.0-alpha.1",
|
||||
"1.0.0-beta.2")),
|
||||
?assertMatch(true, not gt("1.0.0-beta.2",
|
||||
|
@ -283,6 +390,10 @@ gt_test() ->
|
|||
"1.0.0-alpha")),
|
||||
?assertMatch(true, not gt("1",
|
||||
"1.0.0")),
|
||||
?assertMatch(true, not gt("aa.bb",
|
||||
"aa.bb")),
|
||||
?assertMatch(true, not gt("aa.cc",
|
||||
"aa.dd")),
|
||||
?assertMatch(true, not gt("1.0",
|
||||
"1.0.0")),
|
||||
?assertMatch(true, not gt("1.0.0",
|
||||
|
@ -295,12 +406,16 @@ gt_test() ->
|
|||
lt_test() ->
|
||||
?assertMatch(true, lt("1.0.0-alpha",
|
||||
"1.0.0-alpha.1")),
|
||||
?assertMatch(true, lt("1.0.0-alpha",
|
||||
"1.0.0.0-alpha.1")),
|
||||
?assertMatch(true, lt("1.0.0-alpha.1",
|
||||
"1.0.0-beta.2")),
|
||||
?assertMatch(true, lt("1.0.0-beta.2",
|
||||
"1.0.0-beta.11")),
|
||||
?assertMatch(true, lt("1.0.0-beta.11",
|
||||
"1.0.0-rc.1")),
|
||||
?assertMatch(true, lt("1.0.0.1-beta.11",
|
||||
"1.0.0.1-rc.1")),
|
||||
?assertMatch(true, lt("1.0.0-rc.1",
|
||||
"1.0.0-rc.1+build.1")),
|
||||
?assertMatch(true, lt("1.0.0-rc.1+build.1",
|
||||
|
@ -317,12 +432,17 @@ lt_test() ->
|
|||
"1.0.0-alpha")),
|
||||
?assertMatch(true, not lt("1",
|
||||
"1.0.0")),
|
||||
?assertMatch(true, lt("1",
|
||||
"1.0.0.1")),
|
||||
?assertMatch(true, lt("AA.DD",
|
||||
"AA.EE")),
|
||||
?assertMatch(true, not lt("1.0",
|
||||
"1.0.0")),
|
||||
?assertMatch(true, not lt("1.0.0",
|
||||
?assertMatch(true, not lt("1.0.0.0",
|
||||
"1")),
|
||||
?assertMatch(true, not lt("1.0+alpha.1",
|
||||
"1.0.0+alpha.1")),
|
||||
?assertMatch(true, not lt("AA.DD", "AA.CC")),
|
||||
?assertMatch(true, not lt("1.0-alpha.1+build.1",
|
||||
"1.0.0-alpha.1+build.1")),
|
||||
?assertMatch(true, not lt("1.0.0-alpha.1",
|
||||
|
@ -341,7 +461,6 @@ lt_test() ->
|
|||
?assertMatch(true, not lt("1.3.7+build.11.e0f985a",
|
||||
"1.3.7+build.2.b8f12d7")).
|
||||
|
||||
|
||||
gte_test() ->
|
||||
?assertMatch(true, gte("1.0.0-alpha",
|
||||
"1.0.0-alpha")),
|
||||
|
@ -355,18 +474,25 @@ gte_test() ->
|
|||
?assertMatch(true, gte("1.0.0",
|
||||
"1")),
|
||||
|
||||
?assertMatch(true, gte("1.0.0.0",
|
||||
"1")),
|
||||
|
||||
?assertMatch(true, gte("1.0+alpha.1",
|
||||
"1.0.0+alpha.1")),
|
||||
|
||||
?assertMatch(true, gte("1.0-alpha.1+build.1",
|
||||
"1.0.0-alpha.1+build.1")),
|
||||
|
||||
?assertMatch(true, gte("1.0.0-alpha.1+build.1",
|
||||
"1.0.0.0-alpha.1+build.1")),
|
||||
?assertMatch(true, gte("1.0.0-alpha.1",
|
||||
"1.0.0-alpha")),
|
||||
?assertMatch(true, gte("1.0.0-beta.2",
|
||||
"1.0.0-alpha.1")),
|
||||
?assertMatch(true, gte("1.0.0-beta.11",
|
||||
"1.0.0-beta.2")),
|
||||
?assertMatch(true, gte("aa.bb", "aa.bb")),
|
||||
?assertMatch(true, gte("dd", "aa")),
|
||||
?assertMatch(true, gte("1.0.0-rc.1", "1.0.0-beta.11")),
|
||||
?assertMatch(true, gte("1.0.0-rc.1+build.1", "1.0.0-rc.1")),
|
||||
?assertMatch(true, gte("1.0.0", "1.0.0-rc.1+build.1")),
|
||||
|
@ -378,6 +504,7 @@ gte_test() ->
|
|||
"1.3.7+build.2.b8f12d7")),
|
||||
?assertMatch(true, not gte("1.0.0-alpha",
|
||||
"1.0.0-alpha.1")),
|
||||
?assertMatch(true, not gte("CC", "DD")),
|
||||
?assertMatch(true, not gte("1.0.0-alpha.1",
|
||||
"1.0.0-beta.2")),
|
||||
?assertMatch(true, not gte("1.0.0-beta.2",
|
||||
|
@ -429,25 +556,29 @@ lte_test() ->
|
|||
"1")),
|
||||
?assertMatch(true, lte("1.0+alpha.1",
|
||||
"1.0.0+alpha.1")),
|
||||
?assertMatch(true, lte("1.0.0.0+alpha.1",
|
||||
"1.0.0+alpha.1")),
|
||||
?assertMatch(true, lte("1.0-alpha.1+build.1",
|
||||
"1.0.0-alpha.1+build.1")),
|
||||
?assertMatch(true, not lt("1.0.0-alpha.1",
|
||||
?assertMatch(true, lte("aa","cc")),
|
||||
?assertMatch(true, lte("cc","cc")),
|
||||
?assertMatch(true, not lte("1.0.0-alpha.1",
|
||||
"1.0.0-alpha")),
|
||||
?assertMatch(true, not lt("1.0.0-beta.2",
|
||||
?assertMatch(true, not lte("cc", "aa")),
|
||||
?assertMatch(true, not lte("1.0.0-beta.2",
|
||||
"1.0.0-alpha.1")),
|
||||
?assertMatch(true, not lt("1.0.0-beta.11",
|
||||
?assertMatch(true, not lte("1.0.0-beta.11",
|
||||
"1.0.0-beta.2")),
|
||||
?assertMatch(true, not lt("1.0.0-rc.1", "1.0.0-beta.11")),
|
||||
?assertMatch(true, not lt("1.0.0-rc.1+build.1", "1.0.0-rc.1")),
|
||||
?assertMatch(true, not lt("1.0.0", "1.0.0-rc.1+build.1")),
|
||||
?assertMatch(true, not lt("1.0.0+0.3.7", "1.0.0")),
|
||||
?assertMatch(true, not lt("1.3.7+build", "1.0.0+0.3.7")),
|
||||
?assertMatch(true, not lt("1.3.7+build.2.b8f12d7",
|
||||
?assertMatch(true, not lte("1.0.0-rc.1", "1.0.0-beta.11")),
|
||||
?assertMatch(true, not lte("1.0.0-rc.1+build.1", "1.0.0-rc.1")),
|
||||
?assertMatch(true, not lte("1.0.0", "1.0.0-rc.1+build.1")),
|
||||
?assertMatch(true, not lte("1.0.0+0.3.7", "1.0.0")),
|
||||
?assertMatch(true, not lte("1.3.7+build", "1.0.0+0.3.7")),
|
||||
?assertMatch(true, not lte("1.3.7+build.2.b8f12d7",
|
||||
"1.3.7+build")),
|
||||
?assertMatch(true, not lt("1.3.7+build.11.e0f985a",
|
||||
?assertMatch(true, not lte("1.3.7+build.11.e0f985a",
|
||||
"1.3.7+build.2.b8f12d7")).
|
||||
|
||||
|
||||
between_test() ->
|
||||
?assertMatch(true, between("1.0.0-alpha",
|
||||
"1.0.0-alpha.3",
|
||||
|
@ -464,6 +595,10 @@ between_test() ->
|
|||
?assertMatch(true, between("1.0.0-rc.1",
|
||||
"1.0.0-rc.1+build.3",
|
||||
"1.0.0-rc.1+build.1")),
|
||||
|
||||
?assertMatch(true, between("1.0.0.0-rc.1",
|
||||
"1.0.0-rc.1+build.3",
|
||||
"1.0.0-rc.1+build.1")),
|
||||
?assertMatch(true, between("1.0.0-rc.1+build.1",
|
||||
"1.0.0",
|
||||
"1.0.0-rc.33")),
|
||||
|
@ -488,6 +623,10 @@ between_test() ->
|
|||
?assertMatch(true, between("1.0",
|
||||
"1.0.0",
|
||||
"1.0.0")),
|
||||
|
||||
?assertMatch(true, between("1.0",
|
||||
"1.0.0.0",
|
||||
"1.0.0.0")),
|
||||
?assertMatch(true, between("1.0.0",
|
||||
"1",
|
||||
"1")),
|
||||
|
@ -497,6 +636,9 @@ between_test() ->
|
|||
?assertMatch(true, between("1.0-alpha.1+build.1",
|
||||
"1.0.0-alpha.1+build.1",
|
||||
"1.0.0-alpha.1+build.1")),
|
||||
?assertMatch(true, between("aaa",
|
||||
"ddd",
|
||||
"cc")),
|
||||
?assertMatch(true, not between("1.0.0-alpha.1",
|
||||
"1.0.0-alpha.22",
|
||||
"1.0.0")),
|
||||
|
@ -506,13 +648,16 @@ between_test() ->
|
|||
?assertMatch(true, not between("1.0.0-beta.1",
|
||||
"1.0.0-beta.11",
|
||||
"1.0.0-alpha")),
|
||||
?assertMatch(true, not between("1.0.0-beta.11", "1.0.0-rc.1", "1.0.0-rc.22")).
|
||||
?assertMatch(true, not between("1.0.0-beta.11", "1.0.0-rc.1",
|
||||
"1.0.0-rc.22")),
|
||||
?assertMatch(true, not between("aaa", "ddd", "zzz")).
|
||||
|
||||
pes_test() ->
|
||||
?assertMatch(true, pes("2.6.0", "2.6")),
|
||||
?assertMatch(true, pes("2.7", "2.6")),
|
||||
?assertMatch(true, pes("2.8", "2.6")),
|
||||
?assertMatch(true, pes("2.9", "2.6")),
|
||||
?assertMatch(true, pes("A.B", "A.A")),
|
||||
?assertMatch(true, not pes("3.0.0", "2.6")),
|
||||
?assertMatch(true, not pes("2.5", "2.6")),
|
||||
?assertMatch(true, pes("2.6.5", "2.6.5")),
|
||||
|
@ -520,7 +665,29 @@ pes_test() ->
|
|||
?assertMatch(true, pes("2.6.7", "2.6.5")),
|
||||
?assertMatch(true, pes("2.6.8", "2.6.5")),
|
||||
?assertMatch(true, pes("2.6.9", "2.6.5")),
|
||||
?assertMatch(true, pes("2.6.0.9", "2.6.0.5")),
|
||||
?assertMatch(true, not pes("2.7", "2.6.5")),
|
||||
?assertMatch(true, not pes("2.1.7", "2.1.6.5")),
|
||||
?assertMatch(true, not pes("A.A", "A.B")),
|
||||
?assertMatch(true, not pes("2.5", "2.6.5")).
|
||||
|
||||
version_format_test() ->
|
||||
?assertEqual(["1", [], []], format({1, {[],[]}})),
|
||||
?assertEqual(["1", ".", "2", ".", "34", [], []], format({{1,2,34},{[],[]}})),
|
||||
?assertEqual(<<"a">>, erlang:iolist_to_binary(format({<<"a">>, {[],[]}}))),
|
||||
?assertEqual(<<"a.b">>, erlang:iolist_to_binary(format({{<<"a">>,<<"b">>}, {[],[]}}))),
|
||||
?assertEqual(<<"1">>, erlang:iolist_to_binary(format({1, {[],[]}}))),
|
||||
?assertEqual(<<"1.2">>, erlang:iolist_to_binary(format({{1,2}, {[],[]}}))),
|
||||
?assertEqual(<<"1.2.2">>, erlang:iolist_to_binary(format({{1,2,2}, {[],[]}}))),
|
||||
?assertEqual(<<"1.99.2">>, erlang:iolist_to_binary(format({{1,99,2}, {[],[]}}))),
|
||||
?assertEqual(<<"1.99.2-alpha">>, erlang:iolist_to_binary(format({{1,99,2}, {[<<"alpha">>],[]}}))),
|
||||
?assertEqual(<<"1.99.2-alpha.1">>, erlang:iolist_to_binary(format({{1,99,2}, {[<<"alpha">>,1], []}}))),
|
||||
?assertEqual(<<"1.99.2+build.1.a36">>,
|
||||
erlang:iolist_to_binary(format({{1,99,2}, {[], [<<"build">>, 1, <<"a36">>]}}))),
|
||||
?assertEqual(<<"1.99.2.44+build.1.a36">>,
|
||||
erlang:iolist_to_binary(format({{1,99,2,44}, {[], [<<"build">>, 1, <<"a36">>]}}))),
|
||||
?assertEqual(<<"1.99.2-alpha.1+build.1.a36">>,
|
||||
erlang:iolist_to_binary(format({{1,99,2}, {[<<"alpha">>, 1], [<<"build">>, 1, <<"a36">>]}}))),
|
||||
?assertEqual(<<"1">>, erlang:iolist_to_binary(format({1, {[],[]}}))).
|
||||
|
||||
-endif.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
semver <- major_minor_patch ("-" alpha_part ("." alpha_part)*)? ("+" alpha_part ("." alpha_part)*)? !.
|
||||
semver <- major_minor_patch_min_patch ("-" alpha_part ("." alpha_part)*)? ("+" alpha_part ("." alpha_part)*)? !.
|
||||
` ec_semver:internal_parse_version(Node) ` ;
|
||||
|
||||
major_minor_patch <- version_part ("." version_part)? ("." version_part)? ;
|
||||
major_minor_patch_min_patch <- version_part ("." version_part)? ("." version_part)? ("." version_part)? ;
|
||||
|
||||
version_part <- [0-9]+ `erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node)))` ;
|
||||
version_part <- numeric_part / alpha_part ;
|
||||
|
||||
alpha_part <- [A-Za-z0-9-]+ ;
|
||||
numeric_part <- [0-9]+ `erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node)))` ;
|
||||
alpha_part <- [A-Za-z0-9]+ `erlang:iolist_to_binary(Node)` ;
|
||||
|
||||
%% This only exists to get around a bug in erlang where if
|
||||
%% warnings_as_errors is specified `nowarn` directives are ignored
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%% -*- mode: Erlang; fill-column: 75; comment-column: 50; -*-
|
||||
{application, erlware_commons,
|
||||
[{description, "Additional standard library for Erlang"},
|
||||
{vsn, "0.8.0"},
|
||||
{vsn, "semver"},
|
||||
{modules, []},
|
||||
{registered, []},
|
||||
{applications, [kernel, stdlib]}]}.
|
||||
|
|
75
test/ec_plists_tests.erl
Normal file
75
test/ec_plists_tests.erl
Normal file
|
@ -0,0 +1,75 @@
|
|||
%%% @copyright Erlware, LLC.
|
||||
-module(ec_plists_tests).
|
||||
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
%%%===================================================================
|
||||
%%% Tests
|
||||
%%%===================================================================
|
||||
|
||||
map_good_test() ->
|
||||
Results = ec_plists:map(fun(_) ->
|
||||
ok
|
||||
end,
|
||||
lists:seq(1, 5)),
|
||||
?assertMatch([ok, ok, ok, ok, ok],
|
||||
Results).
|
||||
|
||||
ftmap_good_test() ->
|
||||
Results = ec_plists:ftmap(fun(_) ->
|
||||
ok
|
||||
end,
|
||||
lists:seq(1, 3)),
|
||||
?assertMatch([{value, ok}, {value, ok}, {value, ok}],
|
||||
Results).
|
||||
|
||||
filter_good_test() ->
|
||||
Results = ec_plists:filter(fun(X) ->
|
||||
X == show
|
||||
end,
|
||||
[show, show, remove]),
|
||||
?assertMatch([show, show],
|
||||
Results).
|
||||
|
||||
map_timeout_test() ->
|
||||
?assertExit(timeout,
|
||||
ec_plists:map(fun(T) ->
|
||||
timer:sleep(T),
|
||||
T
|
||||
end,
|
||||
[1, 100], {timeout, 10})).
|
||||
|
||||
ftmap_timeout_test() ->
|
||||
?assertExit(timeout,
|
||||
ec_plists:ftmap(fun(X) ->
|
||||
timer:sleep(X),
|
||||
true
|
||||
end,
|
||||
[100, 1], {timeout, 10})).
|
||||
|
||||
filter_timeout_test() ->
|
||||
?assertExit(timeout,
|
||||
ec_plists:filter(fun(T) ->
|
||||
timer:sleep(T),
|
||||
T == 1
|
||||
end,
|
||||
[1, 100], {timeout, 10})).
|
||||
|
||||
map_bad_test() ->
|
||||
?assertExit({{nocatch,test_exception}, _},
|
||||
ec_plists:map(fun(_) ->
|
||||
erlang:throw(test_exception)
|
||||
end,
|
||||
lists:seq(1, 5))).
|
||||
|
||||
|
||||
ftmap_bad_test() ->
|
||||
Results =
|
||||
ec_plists:ftmap(fun(2) ->
|
||||
erlang:throw(test_exception);
|
||||
(N) ->
|
||||
N
|
||||
end,
|
||||
lists:seq(1, 5)),
|
||||
?assertMatch([{value, 1}, {error,{throw,test_exception}}, {value, 3},
|
||||
{value, 4}, {value, 5}] , Results).
|
Loading…
Add table
Add a link
Reference in a new issue