summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@apache.org>2019-02-14 12:05:32 -0500
committerNick Vatamaniuc <vatamane@apache.org>2019-02-15 16:42:43 -0500
commitf3a98a134433a17f014ef8110282b537d0ac96f5 (patch)
tree34aa0ce5cee66ef13356cc1e5a3d2868e46d33d2
parentde3bec42d3f45e0e0316e5a3c558f1dd533a44c0 (diff)
downloadcouchdb-f3a98a134433a17f014ef8110282b537d0ac96f5.tar.gz
Property tests for mem3_util:get_ring() function
-rw-r--r--src/mem3/src/mem3_util.erl8
-rw-r--r--src/mem3/test/mem3_ring_prop_tests.erl84
2 files changed, 91 insertions, 1 deletions
diff --git a/src/mem3/src/mem3_util.erl b/src/mem3/src/mem3_util.erl
index 8575e66b3..af30fb0d2 100644
--- a/src/mem3/src/mem3_util.erl
+++ b/src/mem3/src/mem3_util.erl
@@ -24,6 +24,7 @@
range_overlap/2,
get_ring/1,
get_ring/2,
+ get_ring/3,
get_ring/4,
non_overlapping_shards/1,
non_overlapping_shards/3
@@ -411,10 +412,15 @@ non_overlapping_shards(Shards, Start, End) ->
get_ring(Ranges) ->
get_ring(Ranges, fun sort_ranges_fun/2, 0, ?RING_END).
+
get_ring(Ranges, SortFun) when is_function(SortFun, 2) ->
get_ring(Ranges, SortFun, 0, ?RING_END).
+get_ring(Ranges, Start, End) when is_integer(Start), is_integer(End),
+ Start >= 0, End >= 0, Start =< End ->
+ get_ring(Ranges, fun sort_ranges_fun/2, Start, End).
+
% Build a ring out of a list of possibly overlapping ranges. If a ring cannot
% be built then [] is returned. Start and End supply a custom range such that
% only intervals in that range will be considered. SortFun is a custom sorting
@@ -423,7 +429,7 @@ get_ring(Ranges, SortFun) when is_function(SortFun, 2) ->
% shortest ranges first (and thus have more total shards) or longer or any
% other scheme.
%
-get_ring([], _SortFun, _Begin, _End) ->
+get_ring([], _SortFun, _Start, _End) ->
[];
get_ring(Ranges, SortFun, Start, End) when is_function(SortFun, 2),
is_integer(Start), is_integer(End),
diff --git a/src/mem3/test/mem3_ring_prop_tests.erl b/src/mem3/test/mem3_ring_prop_tests.erl
new file mode 100644
index 000000000..0fe6efb1f
--- /dev/null
+++ b/src/mem3/test/mem3_ring_prop_tests.erl
@@ -0,0 +1,84 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(mem3_ring_prop_tests).
+
+
+-include_lib("triq/include/triq.hrl").
+-triq(eunit).
+
+-compile(export_all).
+
+
+% Properties
+
+prop_get_ring_with_connected_intervals() ->
+ ?FORALL({Start, End}, oneof(ranges()),
+ ?FORALL(Intervals, g_connected_intervals(Start, End),
+ mem3_util:get_ring(Intervals, Start, End) =/= []
+ )
+ ).
+
+
+prop_get_ring_with_disconnected_intervals() ->
+ ?FORALL({Start, End}, oneof(ranges()),
+ ?FORALL(Intervals, g_disconnected_intervals(Start, End),
+ mem3_util:get_ring(Intervals, Start, End) =:= []
+ )
+ ).
+
+
+% Generators
+
+ranges() ->
+ [{0,1}, {1, 10}, {0, 2 bsl 31 - 1}, {2 bsl 31 - 10, 2 bsl 31 - 1}].
+
+
+g_connected_intervals(Begin, End) ->
+ ?SIZED(Size, g_connected_intervals(Begin, End, 10 * Size)).
+
+
+g_connected_intervals(Begin, End, Split) when Begin =< End ->
+ ?LET(N, choose(0, Split),
+ begin
+ if
+ N == 0 ->
+ [{Begin, End}];
+ N > 0 ->
+ Ns = lists:seq(1, N - 1),
+ Bs = lists:usort([rand_range(Begin, End) || _ <- Ns]),
+ Es = [B - 1 || B <- Bs],
+ lists:zip([Begin] ++ Bs, Es ++ [End])
+ end
+ end).
+
+
+g_non_trivial_connected_intervals(Begin, End, Split) ->
+ ?SUCHTHAT(Connected, g_connected_intervals(Begin, End, Split),
+ length(Connected) > 1).
+
+
+g_disconnected_intervals(Begin, End) ->
+ ?SIZED(Size, g_disconnected_intervals(Begin, End, Size)).
+
+
+g_disconnected_intervals(Begin, End, Split) when Begin =< End ->
+ ?LET(Connected, g_non_trivial_connected_intervals(Begin, End, Split),
+ begin
+ I = triq_rnd:uniform(length(Connected)) - 1,
+ {Before, [_ | After]} = lists:split(I, Connected),
+ Before ++ After
+ end).
+
+
+rand_range(B, E) ->
+ B + triq_rnd:uniform(E - B).