Created
June 11, 2011 22:58
-
-
Save ferd/1021062 to your computer and use it in GitHub Desktop.
Demo PropEr suite for rabbitMQ paths
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(paths). | |
-include_lib("proper/include/proper.hrl"). | |
%% Just to see a bunch of results without gen_symbolics | |
%prop_test_output() -> | |
% numtests(2, ?FORALL(X, expanded_paths(), | |
% collect(fun print/1, | |
% X, | |
% true))). | |
% | |
%print(X) -> | |
% io:format("~p~n", [X]). | |
%% Checks that the patterns for paths (a.#.*.c) match or do not | |
%% match a given expanded path. | |
prop_expands() -> | |
?FORALL(Paths, expanded_paths(), | |
lists:all(fun(X) -> X end, %% checks if all true | |
[equals(?YOUR_FUN(Pattern, Expanded), Expected) || | |
{Pattern, Expanded, Expected} <- Paths])). | |
%%% GENERATORS | |
%% Gives a list of paths that were expanded, some of them to fail on purpose, | |
%% some of them not to. | |
expanded_paths() -> | |
?LET(P, path(), | |
begin | |
B = list_to_binary(P), | |
?LET({{Expanded1, IsRight1},{Expanded2, IsRight2}}, | |
{wrong(P), right(P)}, | |
[{B, list_to_binary(Expanded1), IsRight1}, | |
{B, list_to_binary(Expanded2), IsRight2}]) | |
end). | |
%% Tries to make a pattern wrong. Will not always suceed because a pattern | |
%% like "#" can be anything at all. | |
%% | |
%% Returns {Str, ShouldMatchOriginal}. | |
wrong(Path) -> | |
?LET(P, Path, wrong(P, true, [])). | |
%% Will expand the patterns according to the rules so they should always match | |
%% | |
%% Returns {Str, ShouldMatchOriginal}. | |
right(Path) -> | |
?LET(P, Path, {right1(P), true}). | |
%% Here's why some patterns will always succeed even if we try to make them | |
%% wrong. In a given strign S, we could add segments, but some subpatterns | |
%% would have a chance to fix the problem we created. See a.*.#, which means | |
%% 'at least two segments' but still matches (albeit wrongly) a.b if we drop | |
%% a section of the text, replace it by one, or add two of them. It can | |
%% technically be done, but we would need a strong lookahead for that. | |
%% This is especially the case of .#., which we will have to simply ignore. | |
%% | |
%% Returns {Str, ShouldMatchOriginal}. | |
wrong([], Bool, Acc) -> | |
{lists:reverse(Acc), Bool}; | |
wrong("*.#." ++ Rest, Bool, Acc) -> %% the # messes stuff up, can't invalidate | |
wrong(Rest, Bool, Acc); | |
wrong("*.#", Bool, Acc) -> %% same as above, end of string | |
{lists:reverse(Acc), Bool}; | |
wrong("*." ++ Rest, _Bool, Acc) -> | |
wrong(Rest, false, Acc); | |
wrong(".*", _Bool, Acc) -> | |
{lists:reverse(Acc), false}; | |
wrong(".#." ++ Rest, Bool, Acc) -> %% can't make this one wrong | |
wrong(Rest, Bool, Acc); | |
wrong("#." ++ Rest, Bool, Acc) -> %% same, start of string | |
wrong(Rest, Bool, Acc); | |
wrong(".#", Bool, Acc) -> %% same as above, end of string | |
{lists:reverse(Acc), Bool}; | |
wrong([Char|Rest], Bool, Acc) when Char =/= $*, Char =/= $# -> | |
wrong(Rest, Bool, [Char|Acc]). | |
%% Returns an expanded string according to the rules | |
right1([]) -> []; | |
right1("*" ++ Rest) -> | |
?LET(S, segment(), S++right1(Rest)); | |
right1("#" ++ Rest) -> | |
?LET(X, | |
union([ | |
"", | |
?LET(S, segment(), S), | |
?LET({A,B}, {segment(), segment()}, A++[$.]++B), | |
?LET({A,B,C}, {segment(), segment(), segment()}, A++[$.]++B++[$.]++C) | |
]), | |
X ++ right1(Rest)); | |
right1([Char|Rest]) -> | |
[Char|right1(Rest)]. | |
%% Building a basic pattern/path string | |
path() -> | |
?LET(Base, ?LAZY(weighted_union([{3,a()}, {1,b()}])), | |
?LET({H,T}, {union(["*.","#.",""]), union([".*",".#",""])}, | |
H ++ Base ++ T)). | |
a() -> | |
?LET({X,Y}, {segment(), ?LAZY(union([b(), markers()]))}, | |
X ++ [$.] ++ Y). | |
b() -> | |
?LET({X,Y}, {segment(), ?LAZY(union([b(), c()]))}, | |
X ++ [$.] ++ Y). | |
c() -> | |
segment(). | |
segment() -> | |
?SUCHTHAT( | |
X, | |
list(union([choose($a,$z), choose($A,$Z), choose($0,$9)])), | |
length(X) =/= 0 | |
). | |
markers() -> | |
?LET(S, ?LAZY(union([[$#, $., c()], [$*, $., b()]])), lists:flatten(S)). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment