You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2019/02/14 17:05:43 UTC

[couchdb] branch shard-split updated: Property tests for mem3_util:get_ring() function

This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a commit to branch shard-split
in repository https://gitbox.apache.org/repos/asf/couchdb.git


The following commit(s) were added to refs/heads/shard-split by this push:
     new 696ed75  Property tests for mem3_util:get_ring() function
696ed75 is described below

commit 696ed754ddb5fe0f765f9a4ba05fd921fdd07265
Author: Nick Vatamaniuc <va...@apache.org>
AuthorDate: Thu Feb 14 12:05:32 2019 -0500

    Property tests for mem3_util:get_ring() function
---
 src/mem3/src/mem3_util.erl             |  8 +++-
 src/mem3/test/mem3_ring_prop_tests.erl | 84 ++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/src/mem3/src/mem3_util.erl b/src/mem3/src/mem3_util.erl
index 8575e66..af30fb0 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 0000000..0fe6efb
--- /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).