You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2019/07/02 18:02:55 UTC

[couchdb] branch prototype/fdb-all-dbs-all-docs-qs-params created (now d7fef90)

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

davisp pushed a change to branch prototype/fdb-all-dbs-all-docs-qs-params
in repository https://gitbox.apache.org/repos/asf/couchdb.git.


      at d7fef90  Implement _all_dbs/_all_docs API parameters

This branch includes the following new commits:

     new 3a14e29  Remove tests for deprecated features.
     new d7fef90  Implement _all_dbs/_all_docs API parameters

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[couchdb] 02/02: Implement _all_dbs/_all_docs API parameters

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch prototype/fdb-all-dbs-all-docs-qs-params
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit d7fef90b110c2c62de1ef3d413296adcc1ba7736
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Wed Jun 19 11:58:47 2019 -0500

    Implement _all_dbs/_all_docs API parameters
    
    This adds the mapping of CouchDB start/end keys and so on to the similar
    yet slightly different concepts in FoundationDB. The handlers for
    `_all_dbs` and `_all_docs` have been udpated to use this new logic.
---
 src/chttpd/src/chttpd_misc.erl |  70 +++++++++------
 src/fabric/src/fabric2_db.erl  | 123 ++++++++++++++++++++++++++-
 src/fabric/src/fabric2_fdb.erl | 188 +++++++++++++++--------------------------
 3 files changed, 232 insertions(+), 149 deletions(-)

diff --git a/src/chttpd/src/chttpd_misc.erl b/src/chttpd/src/chttpd_misc.erl
index b244e84..796ce71 100644
--- a/src/chttpd/src/chttpd_misc.erl
+++ b/src/chttpd/src/chttpd_misc.erl
@@ -108,39 +108,57 @@ maybe_add_csp_headers(Headers, _) ->
     Headers.
 
 handle_all_dbs_req(#httpd{method='GET'}=Req) ->
-    % TODO: Support args and options properly, transform
-    % this back into a fold call similar to the old
-    % version.
-    %% Args = couch_mrview_http:parse_params(Req, undefined),
+    #mrargs{
+        start_key = StartKey,
+        end_key = EndKey,
+        direction = Dir,
+        limit = Limit,
+        skip = Skip
+    } = couch_mrview_http:parse_params(Req, undefined),
+
+    Options = [
+        {start_key, StartKey},
+        {end_key, EndKey},
+        {dir, Dir},
+        {limit, Limit},
+        {skip, Skip}
+    ],
+
     % Eventually the Etag for this request will be derived
     % from the \xFFmetadataVersion key in fdb
     Etag = <<"foo">>,
-    %% Options = [{user_ctx, Req#httpd.user_ctx}],
+
     {ok, Resp} = chttpd:etag_respond(Req, Etag, fun() ->
-        AllDbs = fabric2_db:list_dbs(),
-        chttpd:send_json(Req, AllDbs)
-    end);
+        {ok, Resp} = chttpd:start_delayed_json_response(Req, 200, [{"ETag",Etag}]),
+        Callback = fun all_dbs_callback/2,
+        Acc = #vacc{req=Req,resp=Resp},
+        fabric2_db:list_dbs(Callback, Acc, Options)
+    end),
+    case is_record(Resp, vacc) of
+        true -> {ok, Resp#vacc.resp};
+        _ -> {ok, Resp}
+    end;
 handle_all_dbs_req(Req) ->
     send_method_not_allowed(Req, "GET,HEAD").
 
-%% all_dbs_callback({meta, _Meta}, #vacc{resp=Resp0}=Acc) ->
-%%     {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, "["),
-%%     {ok, Acc#vacc{resp=Resp1}};
-%% all_dbs_callback({row, Row}, #vacc{resp=Resp0}=Acc) ->
-%%     Prepend = couch_mrview_http:prepend_val(Acc),
-%%     case couch_util:get_value(id, Row) of <<"_design", _/binary>> ->
-%%         {ok, Acc};
-%%     DbName ->
-%%         {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, [Prepend, ?JSON_ENCODE(DbName)]),
-%%         {ok, Acc#vacc{prepend=",", resp=Resp1}}
-%%     end;
-%% all_dbs_callback(complete, #vacc{resp=Resp0}=Acc) ->
-%%     {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, "]"),
-%%     {ok, Resp2} = chttpd:end_delayed_json_response(Resp1),
-%%     {ok, Acc#vacc{resp=Resp2}};
-%% all_dbs_callback({error, Reason}, #vacc{resp=Resp0}=Acc) ->
-%%     {ok, Resp1} = chttpd:send_delayed_error(Resp0, Reason),
-%%     {ok, Acc#vacc{resp=Resp1}}.
+all_dbs_callback({meta, _Meta}, #vacc{resp=Resp0}=Acc) ->
+    {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, "["),
+    {ok, Acc#vacc{resp=Resp1}};
+all_dbs_callback({row, Row}, #vacc{resp=Resp0}=Acc) ->
+    Prepend = couch_mrview_http:prepend_val(Acc),
+    case couch_util:get_value(id, Row) of <<"_design", _/binary>> ->
+        {ok, Acc};
+    DbName ->
+        {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, [Prepend, ?JSON_ENCODE(DbName)]),
+        {ok, Acc#vacc{prepend=",", resp=Resp1}}
+    end;
+all_dbs_callback(complete, #vacc{resp=Resp0}=Acc) ->
+    {ok, Resp1} = chttpd:send_delayed_chunk(Resp0, "]"),
+    {ok, Resp2} = chttpd:end_delayed_json_response(Resp1),
+    {ok, Acc#vacc{resp=Resp2}};
+all_dbs_callback({error, Reason}, #vacc{resp=Resp0}=Acc) ->
+    {ok, Resp1} = chttpd:send_delayed_error(Resp0, Reason),
+    {ok, Acc#vacc{resp=Resp1}}.
 
 handle_dbs_info_req(#httpd{method='POST'}=Req) ->
     chttpd:validate_ctype(Req, "application/json"),
diff --git a/src/fabric/src/fabric2_db.erl b/src/fabric/src/fabric2_db.erl
index 80028a6..7ec1173 100644
--- a/src/fabric/src/fabric2_db.erl
+++ b/src/fabric/src/fabric2_db.erl
@@ -20,6 +20,7 @@
 
     list_dbs/0,
     list_dbs/1,
+    list_dbs/3,
 
     is_admin/1,
     check_is_admin/1,
@@ -194,8 +195,40 @@ list_dbs() ->
 
 
 list_dbs(Options) ->
+    Skip = case fabric2_util:get_value(skip, Options, 0) of
+        N when is_integer(N), N >= 0 -> N
+    end,
+    Callback = fun
+        (DbName, {0, Acc}) -> {0, [DbName | Acc]};
+        (_DbName, {S, Acc}) -> {S - 1, Acc}
+    end,
     fabric2_fdb:transactional(fun(Tx) ->
-        fabric2_fdb:list_dbs(Tx, Options)
+        {_, DbNames} = fabric2_fdb:list_dbs(Tx, Callback, {Skip, []}, Options),
+        lists:reverse(DbNames)
+    end).
+
+
+list_dbs(UserFun, UserAcc0, Options) ->
+    Skip = case fabric2_util:get_value(skip, Options, 0) of
+        N when is_integer(N), N >= 0 -> N
+    end,
+    FoldFun = fun
+        (DbName, {0, Acc}) -> maybe_stop(UserFun({row, [{id, DbName}]}, Acc));
+        (_DbName, {S, Acc}) -> {S - 1, Acc}
+    end,
+    fabric2_fdb:transactional(fun(Tx) ->
+        try
+            UserAcc1 = maybe_stop(UserFun({meta, []}, UserAcc0)),
+            UserAcc2 = fabric2_fdb:list_dbs(
+                    Tx,
+                    FoldFun,
+                    {Skip, UserAcc1},
+                    Options
+                ),
+            {ok, maybe_stop(UserFun(complete, UserAcc2))}
+        catch throw:{stop, FinalUserAcc} ->
+            {ok, FinalUserAcc}
+        end
     end).
 
 
@@ -615,9 +648,35 @@ fold_docs(Db, UserFun, UserAcc) ->
     fold_docs(Db, UserFun, UserAcc, []).
 
 
-fold_docs(Db, UserFun, UserAcc, Options) ->
+fold_docs(Db, UserFun, UserAcc0, Options) ->
     fabric2_fdb:transactional(Db, fun(TxDb) ->
-        fabric2_fdb:fold_docs(TxDb, UserFun, UserAcc, Options)
+        try
+            #{
+                db_prefix := DbPrefix
+            } = TxDb,
+
+            Prefix = erlfdb_tuple:pack({?DB_ALL_DOCS}, DbPrefix),
+            DocCount = get_doc_count(TxDb),
+
+            UserAcc1 = maybe_stop(UserFun({meta, [
+                {total, DocCount},
+                {offset, null}
+            ]}, UserAcc0)),
+
+            UserAcc2 = fabric2_fdb:fold_range(TxDb, Prefix, fun({K, V}, Acc) ->
+                {DocId} = erlfdb_tuple:unpack(K, Prefix),
+                RevId = erlfdb_tuple:unpack(V),
+                maybe_stop(UserFun({row, [
+                    {id, DocId},
+                    {key, DocId},
+                    {value, couch_doc:rev_to_str(RevId)}
+                ]}, Acc))
+            end, UserAcc1, Options),
+
+            {ok, maybe_stop(UserFun(complete, UserAcc2))}
+        catch throw:{stop, FinalUserAcc} ->
+            {ok, FinalUserAcc}
+        end
     end).
 
 
@@ -627,7 +686,39 @@ fold_changes(Db, SinceSeq, UserFun, UserAcc) ->
 
 fold_changes(Db, SinceSeq, UserFun, UserAcc, Options) ->
     fabric2_fdb:transactional(Db, fun(TxDb) ->
-        fabric2_fdb:fold_changes(TxDb, SinceSeq, UserFun, UserAcc, Options)
+        try
+            #{
+                db_prefix := DbPrefix
+            } = TxDb,
+
+            Prefix = erlfdb_tuple:pack({?DB_CHANGES}, DbPrefix),
+
+            StartKey = get_since_seq(SinceSeq),
+            EndKey = case fabric2_util:get_value(dir, Options, fwd) of
+                rev -> fabric2_util:seq_zero_vs();
+                _ -> fabric2_util:seq_max_vs()
+            end,
+            FoldOpts = [
+                {start_key, StartKey},
+                {end_key, EndKey}
+            ] ++ Options,
+
+            {ok, fabric2_fdb:fold_range(TxDb, Prefix, fun({K, V}, Acc) ->
+                {SeqVS} = erlfdb_tuple:unpack(K, Prefix),
+                {DocId, Deleted, RevId} = erlfdb_tuple:unpack(V),
+
+                Change = #{
+                    id => DocId,
+                    sequence => fabric2_fdb:vs_to_seq(SeqVS),
+                    rev_id => RevId,
+                    deleted => Deleted
+                },
+
+                maybe_stop(UserFun(Change, Acc))
+            end, UserAcc, FoldOpts)}
+        catch throw:{stop, FinalUserAcc} ->
+            {ok, FinalUserAcc}
+        end
     end).
 
 
@@ -1289,6 +1380,25 @@ check_duplicate_attachments(#doc{atts = Atts}) ->
     end, ordsets:new(), Atts).
 
 
+get_since_seq(Seq) when Seq == <<>>; Seq == <<"0">>; Seq == 0->
+    fabric2_util:seq_zero_vs();
+
+get_since_seq(Seq) when Seq == now; Seq == <<"now">> ->
+    fabric2_util:seq_max_vs();
+
+get_since_seq(Seq) when is_binary(Seq), size(Seq) == 24 ->
+    Seq1 = fabric2_util:from_hex(Seq),
+    Seq2 = <<51:8, Seq1/binary>>,
+    {SeqVS} = erlfdb_tuple:unpack(Seq2),
+    fabric2_fdb:next_vs(SeqVS);
+
+get_since_seq(List) when is_list(List) ->
+    get_since_seq(list_to_binary(List));
+
+get_since_seq(Seq) ->
+    erlang:error({invalid_since_seq, Seq}).
+
+
 get_leaf_path(Pos, Rev, [{Pos, [{Rev, _RevInfo} | LeafPath]} | _]) ->
     LeafPath;
 get_leaf_path(Pos, Rev, [_WrongLeaf | RestLeafs]) ->
@@ -1353,3 +1463,8 @@ rev(Rev) when is_list(Rev); is_binary(Rev) ->
 rev({Seq, Hash} = Rev) when is_integer(Seq), is_binary(Hash) ->
     Rev.
 
+
+maybe_stop({ok, Acc}) ->
+    Acc;
+maybe_stop({stop, Acc}) ->
+    throw({stop, Acc}).
diff --git a/src/fabric/src/fabric2_fdb.erl b/src/fabric/src/fabric2_fdb.erl
index 4b01826..5a4d9f9 100644
--- a/src/fabric/src/fabric2_fdb.erl
+++ b/src/fabric/src/fabric2_fdb.erl
@@ -24,7 +24,7 @@
     delete/1,
     exists/1,
 
-    list_dbs/2,
+    list_dbs/4,
 
     get_info/1,
     get_config/1,
@@ -50,11 +50,12 @@
     read_attachment/3,
     write_attachment/3,
 
-    fold_docs/4,
-    fold_changes/5,
     get_last_change/1,
 
+    fold_range/5,
+
     vs_to_seq/1,
+    next_vs/1,
 
     debug_cluster/0,
     debug_cluster/2
@@ -254,16 +255,15 @@ exists(#{name := DbName} = Db) when is_binary(DbName) ->
     end.
 
 
-list_dbs(Tx, _Options) ->
+list_dbs(Tx, Callback, AccIn, Options) ->
     Root = erlfdb_directory:root(),
     CouchDB = erlfdb_directory:create_or_open(Tx, Root, [<<"couchdb">>]),
     LayerPrefix = erlfdb_directory:get_name(CouchDB),
-    {Start, End} = erlfdb_tuple:range({?ALL_DBS}, LayerPrefix),
-    Future = erlfdb:get_range(Tx, Start, End),
-    lists:map(fun({K, _V}) ->
-        {?ALL_DBS, DbName} = erlfdb_tuple:unpack(K, LayerPrefix),
-        DbName
-    end, erlfdb:wait(Future)).
+    Prefix = erlfdb_tuple:pack({?ALL_DBS}, LayerPrefix),
+    fold_range({tx, Tx}, Prefix, fun({K, _V}, Acc) ->
+        {DbName} = erlfdb_tuple:unpack(K, Prefix),
+        Callback(DbName, Acc)
+    end, AccIn, Options).
 
 
 get_info(#{} = Db) ->
@@ -640,84 +640,6 @@ write_attachment(#{} = Db, DocId, Data) when is_binary(Data) ->
     {ok, AttId}.
 
 
-fold_docs(#{} = Db, UserFun, UserAcc0, Options) ->
-    #{
-        tx := Tx,
-        db_prefix := DbPrefix
-    } = ensure_current(Db),
-
-    {Reverse, Start, End} = get_dir_and_bounds(DbPrefix, Options),
-
-    DocCountKey = erlfdb_tuple:pack({?DB_STATS, <<"doc_count">>}, DbPrefix),
-    DocCountBin = erlfdb:wait(erlfdb:get(Tx, DocCountKey)),
-
-    try
-        UserAcc1 = maybe_stop(UserFun({meta, [
-            {total, ?bin2uint(DocCountBin)},
-            {offset, null}
-        ]}, UserAcc0)),
-
-        UserAcc2 = erlfdb:fold_range(Tx, Start, End, fun({K, V}, UserAccIn) ->
-            {?DB_ALL_DOCS, DocId} = erlfdb_tuple:unpack(K, DbPrefix),
-            RevId = erlfdb_tuple:unpack(V),
-            maybe_stop(UserFun({row, [
-                {id, DocId},
-                {key, DocId},
-                {value, couch_doc:rev_to_str(RevId)}
-            ]}, UserAccIn))
-        end, UserAcc1, [{reverse, Reverse}] ++ Options),
-
-        {ok, maybe_stop(UserFun(complete, UserAcc2))}
-    catch throw:{stop, FinalUserAcc} ->
-        {ok, FinalUserAcc}
-    end.
-
-
-fold_changes(#{} = Db, SinceSeq0, UserFun, UserAcc0, Options) ->
-    #{
-        tx := Tx,
-        db_prefix := DbPrefix
-    } = ensure_current(Db),
-
-    SinceSeq1 = get_since_seq(SinceSeq0),
-
-    Reverse = case fabric2_util:get_value(dir, Options, fwd) of
-        fwd -> false;
-        rev -> true
-    end,
-
-    {Start0, End0} = case Reverse of
-        false -> {SinceSeq1, fabric2_util:seq_max_vs()};
-        true -> {fabric2_util:seq_zero_vs(), SinceSeq1}
-    end,
-
-    Start1 = erlfdb_tuple:pack({?DB_CHANGES, Start0}, DbPrefix),
-    End1 = erlfdb_tuple:pack({?DB_CHANGES, End0}, DbPrefix),
-
-    {Start, End} = case Reverse of
-        false -> {erlfdb_key:first_greater_than(Start1), End1};
-        true -> {Start1, erlfdb_key:first_greater_than(End1)}
-    end,
-
-    try
-        {ok, erlfdb:fold_range(Tx, Start, End, fun({K, V}, UserAccIn) ->
-            {?DB_CHANGES, SeqVS} = erlfdb_tuple:unpack(K, DbPrefix),
-            {DocId, Deleted, RevId} = erlfdb_tuple:unpack(V),
-
-            Change = #{
-                id => DocId,
-                sequence => vs_to_seq(SeqVS),
-                rev_id => RevId,
-                deleted => Deleted
-            },
-
-            maybe_stop(UserFun(Change, UserAccIn))
-        end, UserAcc0, [{reverse, Reverse}] ++ Options)}
-    catch throw:{stop, FinalUserAcc} ->
-        {ok, FinalUserAcc}
-    end.
-
-
 get_last_change(#{} = Db) ->
     #{
         tx := Tx,
@@ -735,10 +657,15 @@ get_last_change(#{} = Db) ->
     end.
 
 
-maybe_stop({ok, Acc}) ->
-    Acc;
-maybe_stop({stop, Acc}) ->
-    throw({stop, Acc}).
+fold_range(#{} = Db, RangePrefix, Callback, Acc, Options) ->
+    #{
+        tx := Tx
+    } = ensure_current(Db),
+    fold_range({tx, Tx}, RangePrefix, Callback, Acc, Options);
+
+fold_range({tx, Tx}, RangePrefix, Callback, Acc, Options) ->
+    {Start, End, FoldOpts} = get_fold_opts(RangePrefix, Options),
+    erlfdb:fold_range(Tx, Start, End, Callback, Acc, FoldOpts).
 
 
 vs_to_seq(VS) ->
@@ -746,6 +673,21 @@ vs_to_seq(VS) ->
     fabric2_util:to_hex(SeqBin).
 
 
+next_vs({versionstamp, VS, Batch, TxId}) ->
+    {V, B, T} = case TxId =< 65535 of
+        true ->
+            {VS, Batch, TxId + 1};
+        false ->
+            case Batch =< 65535 of
+                true ->
+                    {VS, Batch + 1, 0};
+                false ->
+                    {VS + 1, 0, 0}
+            end
+    end,
+    {versionstamp, V, B, T}.
+
+
 debug_cluster() ->
     debug_cluster(<<>>, <<16#FE, 16#FF, 16#FF>>).
 
@@ -753,7 +695,7 @@ debug_cluster() ->
 debug_cluster(Start, End) ->
     transactional(fun(Tx) ->
         lists:foreach(fun({Key, Val}) ->
-            io:format("~s => ~s~n", [
+            io:format(standard_error, "~s => ~s~n", [
                     string:pad(erlfdb_util:repr(Key), 60),
                     erlfdb_util:repr(Val)
                 ])
@@ -790,7 +732,7 @@ load_validate_doc_funs(#{} = Db) ->
         {end_key, <<"_design0">>}
     ],
 
-    {ok, Infos1} = fold_docs(Db, FoldFun, [], Options),
+    {ok, Infos1} = fabric2_db:fold_docs(Db, FoldFun, [], Options),
 
     Infos2 = lists:map(fun(Info) ->
         #{
@@ -999,11 +941,12 @@ chunkify_attachment(Data) ->
     end.
 
 
-get_dir_and_bounds(DbPrefix, Options) ->
-    Reverse = case fabric2_util:get_value(dir, Options, fwd) of
-        fwd -> false;
-        rev -> true
+get_fold_opts(RangePrefix, Options) ->
+    Reverse = case fabric2_util:get_value(dir, Options) of
+        rev -> true;
+        _ -> false
     end,
+
     StartKey0 = fabric2_util:get_value(start_key, Options),
     EndKeyGt = fabric2_util:get_value(end_key_gt, Options),
     EndKey0 = fabric2_util:get_value(end_key, Options, EndKeyGt),
@@ -1019,17 +962,17 @@ get_dir_and_bounds(DbPrefix, Options) ->
 
     % Set the maximum bounds for the start and endkey
     StartKey2 = case StartKey1 of
-        undefined -> {?DB_ALL_DOCS};
-        SK2 when is_binary(SK2) -> {?DB_ALL_DOCS, SK2}
+        undefined -> <<>>;
+        SK2 -> SK2
     end,
 
     EndKey2 = case EndKey1 of
-        undefined -> {?DB_ALL_DOCS, <<16#FF>>};
-        EK2 when is_binary(EK2) -> {?DB_ALL_DOCS, EK2}
+        undefined -> <<255>>;
+        EK2 -> EK2
     end,
 
-    StartKey3 = erlfdb_tuple:pack(StartKey2, DbPrefix),
-    EndKey3 = erlfdb_tuple:pack(EndKey2, DbPrefix),
+    StartKey3 = erlfdb_tuple:pack({StartKey2}, RangePrefix),
+    EndKey3 = erlfdb_tuple:pack({EndKey2}, RangePrefix),
 
     % FoundationDB ranges are applied as SK <= key < EK
     % By default, CouchDB is SK <= key <= EK with the
@@ -1056,26 +999,33 @@ get_dir_and_bounds(DbPrefix, Options) ->
             EndKey3
     end,
 
-    {Reverse, StartKey4, EndKey4}.
-
+    Limit = case fabric2_util:get_value(limit, Options) of
+        L when is_integer(L), L >= 0 -> [{limit, L}];
+        undefined -> []
+    end,
 
-get_since_seq(Seq) when Seq == <<>>; Seq == <<"0">>; Seq == 0->
-    fabric2_util:seq_zero_vs();
+    TargetBytes = case fabric2_util:get_value(target_bytes, Options) of
+        T when is_integer(T), T >= 0 -> [{target_bytes, T}];
+        undefined -> []
+    end,
 
-get_since_seq(Seq) when Seq == now; Seq == <<"now">> ->
-    fabric2_util:seq_max_vs();
+    StreamingMode = case fabric2_util:get_value(streaming_mode, Options) of
+        undefined -> [];
+        Name when is_atom(Name) -> [{streaming_mode, Name}]
+    end,
 
-get_since_seq(Seq) when is_binary(Seq), size(Seq) == 24 ->
-    Seq1 = fabric2_util:from_hex(Seq),
-    Seq2 = <<51:8, Seq1/binary>>,
-    {SeqVS} = erlfdb_tuple:unpack(Seq2),
-    SeqVS;
+    Snapshot = case fabric2_util:get_value(snapshot, Options) of
+        undefined -> [];
+        B when is_boolean(B) -> [{snapshot, B}]
+    end,
 
-get_since_seq(List) when is_list(List) ->
-    get_since_seq(list_to_binary(List));
+    OutOpts = [{reverse, Reverse}]
+            ++ Limit
+            ++ TargetBytes
+            ++ StreamingMode
+            ++ Snapshot,
 
-get_since_seq(Seq) ->
-    erlang:error({invalid_since_seq, Seq}).
+    {StartKey4, EndKey4, OutOpts}.
 
 
 get_db_handle() ->


[couchdb] 01/02: Remove tests for deprecated features.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

davisp pushed a commit to branch prototype/fdb-all-dbs-all-docs-qs-params
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 3a14e2918efbfd2b1286995a9f39c71cf6ca88f8
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Tue Jun 18 15:32:13 2019 -0500

    Remove tests for deprecated features.
    
    Neither partitioned databases or shard splitting will exist in a
    FoundationDB layer.
---
 test/elixir/test/partition_all_docs_test.exs    | 204 --------
 test/elixir/test/partition_crud_test.exs        | 360 -------------
 test/elixir/test/partition_ddoc_test.exs        | 179 -------
 test/elixir/test/partition_design_docs_test.exs |  16 -
 test/elixir/test/partition_helpers.exs          |  76 ---
 test/elixir/test/partition_mango_test.exs       | 663 ------------------------
 test/elixir/test/partition_size_limit_test.exs  | 305 -----------
 test/elixir/test/partition_size_test.exs        | 361 -------------
 test/elixir/test/partition_view_test.exs        | 374 -------------
 test/elixir/test/partition_view_update_test.exs | 160 ------
 test/elixir/test/reshard_all_docs_test.exs      |  79 ---
 test/elixir/test/reshard_basic_test.exs         | 174 -------
 test/elixir/test/reshard_changes_feed.exs       |  81 ---
 test/elixir/test/reshard_helpers.exs            | 114 ----
 test/elixir/test/test_helper.exs                |   2 -
 15 files changed, 3148 deletions(-)

diff --git a/test/elixir/test/partition_all_docs_test.exs b/test/elixir/test/partition_all_docs_test.exs
deleted file mode 100644
index 816a8d6..0000000
--- a/test/elixir/test/partition_all_docs_test.exs
+++ /dev/null
@@ -1,204 +0,0 @@
-defmodule PartitionAllDocsTest do
-  use CouchTestCase
-  import PartitionHelpers
-
-  @moduledoc """
-  Test Partition functionality for for all_docs
-  """
-
-  setup_all do
-    db_name = random_db_name()
-    {:ok, _} = create_db(db_name, query: %{partitioned: true, q: 1})
-    on_exit(fn -> delete_db(db_name) end)
-
-    create_partition_docs(db_name)
-
-    {:ok, [db_name: db_name]}
-  end
-
-  test "all_docs with partitioned:true returns partitioned fields", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_all_docs"
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert Enum.dedup(partitions) == ["foo"]
-
-    url = "/#{db_name}/_partition/bar/_all_docs"
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert Enum.dedup(partitions) == ["bar"]
-  end
-
-  test "partition all_docs errors with incorrect partition supplied", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/_bar/_all_docs"
-    resp = Couch.get(url)
-    assert resp.status_code == 400
-
-    url = "/#{db_name}/_partition//_all_docs"
-    resp = Couch.get(url)
-    assert resp.status_code == 400
-  end
-
-  test "partitioned _all_docs works with startkey, endkey range", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_all_docs"
-    resp = Couch.get(url, query: %{start_key: "\"foo:12\"", end_key: "\"foo:2\""})
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert Enum.dedup(partitions) == ["foo"]
-  end
-
-  test "partitioned _all_docs works with keys", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_all_docs"
-    resp = Couch.post(url, body: %{keys: ["foo:2", "foo:4", "foo:6"]})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 3
-    assert ids == ["foo:2", "foo:4", "foo:6"]
-  end
-
-  test "partition _all_docs works with limit", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_all_docs"
-    resp = Couch.get(url, query: %{limit: 5})
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert Enum.dedup(partitions) == ["foo"]
-  end
-
-  test "partition _all_docs with descending", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_all_docs"
-    resp = Couch.get(url, query: %{descending: true, limit: 5})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 5
-    assert ids == ["foo:98", "foo:96", "foo:94", "foo:92", "foo:90"]
-
-    resp = Couch.get(url, query: %{descending: false, limit: 5})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 5
-    assert ids == ["foo:10", "foo:100", "foo:12", "foo:14", "foo:16"]
-  end
-
-  test "partition _all_docs with skip", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_all_docs"
-    resp = Couch.get(url, query: %{skip: 5, limit: 5})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 5
-    assert ids == ["foo:18", "foo:2", "foo:20", "foo:22", "foo:24"]
-  end
-
-  test "partition _all_docs with key", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_all_docs"
-    resp = Couch.get(url, query: %{key: "\"foo:22\""})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 1
-    assert ids == ["foo:22"]
-  end
-
-  test "partition all docs can set query limits", context do
-    set_config({"query_server_config", "partition_query_limit", "2000"})
-
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_partition_ddoc(db_name)
-
-    url = "/#{db_name}/_partition/foo/_all_docs"
-
-    resp =
-      Couch.get(
-        url,
-        query: %{
-          limit: 20
-        }
-      )
-
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 20
-
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 50
-
-    resp =
-      Couch.get(
-        url,
-        query: %{
-          limit: 2000
-        }
-      )
-
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 50
-
-    resp =
-      Couch.get(
-        url,
-        query: %{
-          limit: 2001
-        }
-      )
-
-    assert resp.status_code == 400
-    %{:body => %{"reason" => reason}} = resp
-    assert Regex.match?(~r/Limit is too large/, reason)
-
-    resp =
-      Couch.get(
-        url,
-        query: %{
-          limit: 2000,
-          skip: 25
-        }
-      )
-
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 25
-  end
-
-  # This test is timing based so it could be a little flaky.
-  # If that turns out to be the case we should probably just skip it
-  @tag :pending
-  test "partition _all_docs with timeout", context do
-    set_config({"fabric", "partition_view_timeout", "1"})
-
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-
-    retry_until(fn ->
-      url = "/#{db_name}/_partition/foo/_all_docs"
-
-      case Couch.get(url) do
-        %{:body => %{"reason" => reason}} ->
-          Regex.match?(~r/not be processed in a reasonable amount of time./, reason)
-
-        _ ->
-          false
-      end
-    end)
-  end
-end
diff --git a/test/elixir/test/partition_crud_test.exs b/test/elixir/test/partition_crud_test.exs
deleted file mode 100644
index aea8069..0000000
--- a/test/elixir/test/partition_crud_test.exs
+++ /dev/null
@@ -1,360 +0,0 @@
-defmodule PartitionCrudTest do
-  use CouchTestCase
-
-  @tag :with_partitioned_db
-  test "Sets partition in db info", context do
-    db_name = context[:db_name]
-    resp = Couch.get("/#{db_name}")
-    %{body: body} = resp
-    assert body["props"] == %{"partitioned" => true}
-  end
-
-  @tag :with_partitioned_db
-  test "PUT and GET document", context do
-    db_name = context[:db_name]
-    id = "my-partition:doc"
-    url = "/#{db_name}/#{id}"
-
-    resp = Couch.put(url, body: %{partitioned_doc: true})
-    %{body: doc} = resp
-    assert resp.status_code == 201
-    assert doc["id"] == id
-
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-
-    %{body: doc} = resp
-    assert doc["_id"] == id
-  end
-
-  @tag :with_partitioned_db
-  test "PUT fails if a partition key is not supplied", context do
-    db_name = context[:db_name]
-    id = "not-partitioned"
-    url = "/#{db_name}/#{id}"
-
-    resp = Couch.put(url, body: %{partitioned_doc: false})
-    assert resp.status_code == 400
-
-    error = %{
-      "error" => "illegal_docid",
-      "reason" => "Doc id must be of form partition:id"
-    }
-
-    assert Map.get(resp, :body) == error
-  end
-
-  @tag :with_partitioned_db
-  test "PUT fails for partitions with _", context do
-    db_name = context[:db_name]
-    id = "_bad:partitioned"
-    url = "/#{db_name}/#{id}"
-
-    resp = Couch.put(url, body: %{partitioned_doc: false})
-
-    error = %{
-      "error" => "illegal_docid",
-      "reason" => "Only reserved document ids may start with underscore."
-    }
-
-    assert resp.status_code == 400
-    assert Map.get(resp, :body) == error
-  end
-
-  @tag :with_partitioned_db
-  test "PUT fails for bad partitions", context do
-    db_name = context[:db_name]
-    id = "bad:"
-    url = "/#{db_name}/#{id}"
-
-    resp = Couch.put(url, body: %{partitioned_doc: false})
-
-    error = %{
-      "error" => "illegal_docid",
-      "reason" => "Document id must not be empty"
-    }
-
-    assert resp.status_code == 400
-    assert Map.get(resp, :body) == error
-  end
-
-  @tag :with_partitioned_db
-  test "POST and GET document", context do
-    db_name = context[:db_name]
-    id = "my-partition-post:doc"
-    url = "/#{db_name}"
-
-    resp = Couch.post(url, body: %{_id: id, partitioned_doc: true})
-    assert resp.status_code == 201
-
-    resp = Couch.get("#{url}/#{id}")
-    assert resp.status_code == 200
-
-    %{body: doc} = resp
-    assert doc["_id"] == id
-  end
-
-  @tag :with_partitioned_db
-  test "POST and _bulk_get document", context do
-    db_name = context[:db_name]
-    id = "my-partition-post:doc"
-    url = "/#{db_name}"
-
-    resp = Couch.post(url, body: %{_id: id, partitioned_doc: true})
-    assert resp.status_code == 201
-
-    resp = Couch.post("#{url}/_bulk_get", body: %{docs: [%{id: id}]})
-    assert resp.status_code == 200
-
-    %{body: body} = resp
-
-    assert %{
-             "results" => [
-               %{
-                 "docs" => [
-                   %{
-                     "ok" => %{
-                       "_id" => "my-partition-post:doc",
-                       "_rev" => "1-43d86359741cb629c0953a2beb6e9d7a",
-                       "partitioned_doc" => true
-                     }
-                   }
-                 ],
-                 "id" => "my-partition-post:doc"
-               }
-             ]
-           } == body
-  end
-
-  @tag :with_partitioned_db
-  test "_bulk_get bad partitioned document", context do
-    db_name = context[:db_name]
-    id = "my-partition-post"
-    url = "/#{db_name}"
-
-    resp = Couch.post("#{url}/_bulk_get", body: %{docs: [%{id: id}]})
-    assert resp.status_code == 200
-    %{:body => body} = resp
-
-    assert %{
-             "results" => [
-               %{
-                 "docs" => [
-                   %{
-                     "error" => %{
-                       "error" => "illegal_docid",
-                       "id" => "my-partition-post",
-                       "reason" => "Doc id must be of form partition:id",
-                       "rev" => :null
-                     }
-                   }
-                 ],
-                 "id" => "my-partition-post"
-               }
-             ]
-           } == body
-  end
-
-  @tag :with_partitioned_db
-  test "POST fails if a partition key is not supplied", context do
-    db_name = context[:db_name]
-    id = "not-partitioned-post"
-    url = "/#{db_name}"
-
-    resp = Couch.post(url, body: %{_id: id, partitited_doc: false})
-    assert resp.status_code == 400
-  end
-
-  @tag :with_partitioned_db
-  test "_bulk_docs saves docs with partition key", context do
-    db_name = context[:db_name]
-
-    docs = [
-      %{_id: "foo:1"},
-      %{_id: "bar:1"}
-    ]
-
-    url = "/#{db_name}"
-    resp = Couch.post("#{url}/_bulk_docs", body: %{:docs => docs})
-    assert resp.status_code == 201
-
-    resp = Couch.get("#{url}/foo:1")
-    assert resp.status_code == 200
-
-    resp = Couch.get("#{url}/bar:1")
-    assert resp.status_code == 200
-  end
-
-  @tag :with_partitioned_db
-  test "_bulk_docs errors with missing partition key", context do
-    db_name = context[:db_name]
-
-    docs = [
-      %{_id: "foo1"}
-    ]
-
-    error = %{
-      "error" => "illegal_docid",
-      "reason" => "Doc id must be of form partition:id"
-    }
-
-    url = "/#{db_name}"
-    resp = Couch.post("#{url}/_bulk_docs", body: %{:docs => docs})
-    assert resp.status_code == 400
-    assert Map.get(resp, :body) == error
-  end
-
-  @tag :with_partitioned_db
-  test "_bulk_docs errors with bad partition key", context do
-    db_name = context[:db_name]
-
-    docs = [
-      %{_id: "_foo:1"}
-    ]
-
-    error = %{
-      "error" => "illegal_docid",
-      "reason" => "Only reserved document ids may start with underscore."
-    }
-
-    url = "/#{db_name}"
-    resp = Couch.post("#{url}/_bulk_docs", body: %{:docs => docs})
-    assert resp.status_code == 400
-    assert Map.get(resp, :body) == error
-  end
-
-  @tag :with_partitioned_db
-  test "_bulk_docs errors with bad doc key", context do
-    db_name = context[:db_name]
-
-    docs = [
-      %{_id: "foo:"}
-    ]
-
-    error = %{
-      "error" => "illegal_docid",
-      "reason" => "Document id must not be empty"
-    }
-
-    url = "/#{db_name}"
-    resp = Couch.post("#{url}/_bulk_docs", body: %{:docs => docs})
-    assert resp.status_code == 400
-    assert Map.get(resp, :body) == error
-  end
-
-  @tag :with_partitioned_db
-  test "saves attachment with partitioned doc", context do
-    db_name = context[:db_name]
-    id = "foo:doc-with-attachment"
-
-    doc = %{
-      _id: id,
-      _attachments: %{
-        "foo.txt": %{
-          content_type: "text/plain",
-          data: Base.encode64("This is a text document to save")
-        }
-      }
-    }
-
-    resp = Couch.put("/#{db_name}/#{id}", body: doc)
-
-    assert resp.status_code == 201
-
-    resp = Couch.get("/#{db_name}/#{id}")
-    assert resp.status_code == 200
-    body = Map.get(resp, :body)
-    rev = Map.get(body, "_rev")
-
-    assert body["_attachments"] == %{
-             "foo.txt" => %{
-               "content_type" => "text/plain",
-               #  "digest" => "md5-OW2BoZAtMqs1E+fAnLpNBw==",
-               # Temp remove the digest part since the digest value 
-               # seems to be different on travis
-               "digest" => body["_attachments"]["foo.txt"]["digest"],
-               "length" => 31,
-               "revpos" => 1,
-               "stub" => true
-             }
-           }
-
-    resp = Couch.get("/#{db_name}/#{id}/foo.txt")
-    assert Map.get(resp, :body) == "This is a text document to save"
-
-    resp =
-      Couch.put(
-        "/#{db_name}/#{id}/bar.txt?rev=#{rev}",
-        headers: ["Content-Type": "text/plain"],
-        body: "This is another document"
-      )
-
-    assert resp.status_code == 201
-    %{:body => body} = resp
-    assert body["ok"] == true
-    assert body["id"] == id
-  end
-
-  @tag :with_partitioned_db
-  test "can purge partitioned db docs", context do
-    db_name = context[:db_name]
-
-    doc = %{
-      _id: "foo:bar",
-      value: "some value"
-    }
-
-    resp = Couch.post("/#{db_name}", query: [w: 3], body: doc)
-    assert resp.status_code == 201
-    %{body: body} = resp
-    rev = body["rev"]
-
-    resp = Couch.get("/#{db_name}/foo:bar")
-    assert resp.status_code == 200
-
-    body = %{"foo:bar" => [rev]}
-    resp = Couch.post("/#{db_name}/_purge", query: [w: 3], body: body)
-    assert resp.status_code == 201
-
-    resp = Couch.get("/#{db_name}/foo:bar")
-    assert resp.status_code == 404
-    assert resp.body == %{"error" => "not_found", "reason" => "missing"}
-  end
-
-  @tag :with_partitioned_db
-  test "purge rejects unpartitioned docid", context do
-    db_name = context[:db_name]
-    body = %{"no_partition" => ["1-967a00dff5e02add41819138abb3284d"]}
-    resp = Couch.post("/#{db_name}/_purge", query: [w: 3], body: body)
-    assert resp.status_code == 400
-    %{body: body} = resp
-    assert body["error"] == "illegal_docid"
-  end
-
-  test "create database with bad `partitioned` value", _context do
-    resp = Couch.put("/bad-db?partitioned=tru")
-    assert resp.status_code == 400
-
-    assert Map.get(resp, :body) == %{
-             "error" => "bad_request",
-             "reason" => "Invalid `partitioned` parameter"
-           }
-  end
-
-  test "can create unpartitioned system db", _context do
-    Couch.delete("/_replicator")
-    resp = Couch.put("/_replicator")
-    assert resp.status_code == 201
-    assert resp.body == %{"ok" => true}
-  end
-
-  test "cannot create partitioned system db", _context do
-    Couch.delete("/_replicator")
-
-    resp = Couch.put("/_replicator?partitioned=true")
-    assert resp.status_code == 400
-
-    %{:body => %{"reason" => reason}} = resp
-    assert Regex.match?(~r/Cannot partition a system database/, reason)
-  end
-end
diff --git a/test/elixir/test/partition_ddoc_test.exs b/test/elixir/test/partition_ddoc_test.exs
deleted file mode 100644
index 92ecae2..0000000
--- a/test/elixir/test/partition_ddoc_test.exs
+++ /dev/null
@@ -1,179 +0,0 @@
-defmodule PartitionDDocTest do
-  use CouchTestCase
-
-  @moduledoc """
-  Test partition design doc interactions
-  """
-
-  setup do
-    db_name = random_db_name()
-    {:ok, _} = create_db(db_name, query: %{partitioned: true, q: 1})
-    on_exit(fn -> delete_db(db_name) end)
-
-    {:ok, [db_name: db_name]}
-  end
-
-  test "PUT /dbname/_design/foo", context do
-    db_name = context[:db_name]
-    resp = Couch.put("/#{db_name}/_design/foo", body: %{stuff: "here"})
-    assert resp.status_code == 201
-  end
-
-  test "PUT /dbname/_design/foo to update", context do
-    db_name = context[:db_name]
-    ddoc_id = "_design/foo"
-
-    ddoc = %{
-      _id: ddoc_id,
-      stuff: "here"
-    }
-
-    resp = Couch.put("/#{db_name}/#{ddoc_id}", body: ddoc)
-    assert resp.status_code == 201
-    %{body: body} = resp
-
-    ddoc = Map.put(ddoc, :_rev, body["rev"])
-    ddoc = Map.put(ddoc, :other, "attribute")
-    resp = Couch.put("/#{db_name}/#{ddoc_id}", body: ddoc)
-    assert resp.status_code == 201
-  end
-
-  test "PUT /dbname/_design/foo/readme.txt", context do
-    db_name = context[:db_name]
-    ddoc_id = "_design/foo"
-
-    ddoc = %{
-      _id: ddoc_id,
-      stuff: "here"
-    }
-
-    resp = Couch.put("/#{db_name}/#{ddoc_id}", body: ddoc)
-    assert resp.status_code == 201
-    %{body: body} = resp
-
-    att = "This is a readme.txt"
-
-    opts = [
-      headers: [{:"Content-Type", "text/plain"}],
-      query: [rev: body["rev"]],
-      body: att
-    ]
-
-    resp = Couch.put("/#{db_name}/#{ddoc_id}/readme.txt", opts)
-    assert resp.status_code == 201
-  end
-
-  test "DELETE /dbname/_design/foo", context do
-    db_name = context[:db_name]
-    ddoc_id = "_design/foo"
-
-    ddoc = %{
-      _id: ddoc_id,
-      stuff: "here"
-    }
-
-    resp = Couch.put("/#{db_name}/#{ddoc_id}", body: ddoc)
-    assert resp.status_code == 201
-    %{body: body} = resp
-
-    resp = Couch.delete("/#{db_name}/#{ddoc_id}", query: [rev: body["rev"]])
-    assert resp.status_code == 200
-  end
-
-  test "POST /dbname with design doc", context do
-    db_name = context[:db_name]
-    body = %{_id: "_design/foo", stuff: "here"}
-    resp = Couch.post("/#{db_name}", body: body)
-    assert resp.status_code == 201
-  end
-
-  test "POST /dbname/_bulk_docs with design doc", context do
-    db_name = context[:db_name]
-    body = %{:docs => [%{_id: "_design/foo", stuff: "here"}]}
-    resp = Couch.post("/#{db_name}/_bulk_docs", body: body)
-    assert resp.status_code == 201
-  end
-
-  test "GET /dbname/_design/foo", context do
-    db_name = context[:db_name]
-    resp = Couch.put("/#{db_name}/_design/foo", body: %{stuff: "here"})
-    assert resp.status_code == 201
-
-    resp = Couch.get("/#{db_name}/_design/foo")
-    assert resp.status_code == 200
-  end
-
-  test "GET /dbname/_design/foo?rev=$rev", context do
-    db_name = context[:db_name]
-    resp = Couch.put("/#{db_name}/_design/foo", body: %{stuff: "here"})
-    assert resp.status_code == 201
-    %{body: body} = resp
-
-    resp = Couch.get("/#{db_name}/_design/foo", query: [rev: body["rev"]])
-    assert resp.status_code == 200
-  end
-
-  test "GET /dbname/_bulk_get", context do
-    db_name = context[:db_name]
-    resp = Couch.put("/#{db_name}/_design/foo", body: %{stuff: "here"})
-    assert resp.status_code == 201
-
-    body = %{docs: [%{id: "_design/foo"}]}
-    resp = Couch.post("/#{db_name}/_bulk_get", body: body)
-    assert resp.status_code == 200
-    %{body: body} = resp
-
-    assert length(body["results"]) == 1
-
-    %{"results" => [%{"id" => "_design/foo", "docs" => [%{"ok" => _}]}]} = body
-  end
-
-  test "GET /dbname/_bulk_get with rev", context do
-    db_name = context[:db_name]
-    resp = Couch.put("/#{db_name}/_design/foo", body: %{stuff: "here"})
-    assert resp.status_code == 201
-    %{body: body} = resp
-
-    body = %{docs: [%{id: "_design/foo", rev: body["rev"]}]}
-    resp = Couch.post("/#{db_name}/_bulk_get", body: body)
-    assert resp.status_code == 200
-    %{body: body} = resp
-
-    assert length(body["results"]) == 1
-    %{"results" => [%{"id" => "_design/foo", "docs" => [%{"ok" => _}]}]} = body
-  end
-
-  test "GET /dbname/_all_docs?key=$ddoc_id", context do
-    db_name = context[:db_name]
-    resp = Couch.put("/#{db_name}/_design/foo", body: %{stuff: "here"}, query: [w: 3])
-    assert resp.status_code == 201
-
-    resp = Couch.get("/#{db_name}/_all_docs", query: [key: "\"_design/foo\""])
-    assert resp.status_code == 200
-    %{body: body} = resp
-
-    assert length(body["rows"]) == 1
-    assert %{"rows" => [%{"id" => "_design/foo"}]} = body
-  end
-
-  @tag :skip_on_jenkins
-  test "GET /dbname/_design_docs", context do
-    db_name = context[:db_name]
-
-    retry_until(
-      fn ->
-        resp = Couch.put("/#{db_name}/_design/foo", body: %{stuff: "here"})
-        assert resp.status_code == 201
-
-        resp = Couch.get("/#{db_name}/_design_docs")
-        assert resp.status_code == 200
-        %{body: body} = resp
-
-        assert length(body["rows"]) == 1
-        %{"rows" => [%{"id" => "_design/foo"}]} = body
-      end,
-      500,
-      10_000
-    )
-  end
-end
diff --git a/test/elixir/test/partition_design_docs_test.exs b/test/elixir/test/partition_design_docs_test.exs
deleted file mode 100644
index 4ccd63f..0000000
--- a/test/elixir/test/partition_design_docs_test.exs
+++ /dev/null
@@ -1,16 +0,0 @@
-defmodule PartitionDesignDocsTest do
-  use CouchTestCase
-
-  @moduledoc """
-  Test Partition functionality for partition design docs
-  """
-
-  @tag :with_partitioned_db
-  test "/_partition/:pk/_design/doc 404", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/fakekey/_design/mrtest/_view/some"
-    resp = Couch.get(url)
-    assert resp.status_code == 404
-  end
-end
diff --git a/test/elixir/test/partition_helpers.exs b/test/elixir/test/partition_helpers.exs
deleted file mode 100644
index 6eac2b1..0000000
--- a/test/elixir/test/partition_helpers.exs
+++ /dev/null
@@ -1,76 +0,0 @@
-defmodule PartitionHelpers do
-  use ExUnit.Case
-
-  def create_partition_docs(db_name, pk1 \\ "foo", pk2 \\ "bar") do
-    docs =
-      for i <- 1..100 do
-        id =
-          if rem(i, 2) == 0 do
-            "#{pk1}:#{i}"
-          else
-            "#{pk2}:#{i}"
-          end
-
-        group =
-          if rem(i, 3) == 0 do
-            "one"
-          else
-            "two"
-          end
-
-        %{
-          :_id => id,
-          :value => i,
-          :some => "field",
-          :group => group
-        }
-      end
-
-    resp = Couch.post("/#{db_name}/_bulk_docs", body: %{:w => 3, :docs => docs})
-    assert resp.status_code == 201
-  end
-
-  def create_partition_ddoc(db_name, opts \\ %{}) do
-    map_fn = """
-      function(doc) {
-        if (doc.some) {
-          emit(doc.value, doc.some);
-        }
-      }
-    """
-
-    default_ddoc = %{
-      views: %{
-        some: %{
-          map: map_fn
-        }
-      }
-    }
-
-    ddoc = Enum.into(opts, default_ddoc)
-
-    resp = Couch.put("/#{db_name}/_design/mrtest", body: ddoc)
-    assert resp.status_code == 201
-    assert Map.has_key?(resp.body, "ok") == true
-  end
-
-  def get_ids(resp) do
-    %{:body => %{"rows" => rows}} = resp
-    Enum.map(rows, fn row -> row["id"] end)
-  end
-
-  def get_partitions(resp) do
-    %{:body => %{"rows" => rows}} = resp
-
-    Enum.map(rows, fn row ->
-      [partition, _] = String.split(row["id"], ":")
-      partition
-    end)
-  end
-
-  def assert_correct_partition(partitions, correct_partition) do
-    assert Enum.all?(partitions, fn partition ->
-             partition == correct_partition
-           end)
-  end
-end
diff --git a/test/elixir/test/partition_mango_test.exs b/test/elixir/test/partition_mango_test.exs
deleted file mode 100644
index 3fd38d5..0000000
--- a/test/elixir/test/partition_mango_test.exs
+++ /dev/null
@@ -1,663 +0,0 @@
-defmodule PartitionMangoTest do
-  use CouchTestCase
-  import PartitionHelpers, except: [get_partitions: 1]
-
-  @moduledoc """
-  Test Partition functionality for mango
-  """
-  def create_index(db_name, fields \\ ["some"], opts \\ %{}) do
-    default_index = %{
-      index: %{
-        fields: fields
-      }
-    }
-
-    index = Enum.into(opts, default_index)
-    resp = Couch.post("/#{db_name}/_index", body: index)
-
-    assert resp.status_code == 200
-    assert resp.body["result"] == "created"
-  end
-
-  def get_partitions(resp) do
-    %{:body => %{"docs" => docs}} = resp
-
-    Enum.map(docs, fn doc ->
-      [partition, _] = String.split(doc["_id"], ":")
-      partition
-    end)
-  end
-
-  @tag :with_partitioned_db
-  test "query using _id and partition works", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_index(db_name)
-
-    url = "/#{db_name}/_partition/foo/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            _id: %{
-              "$gt": "foo:"
-            }
-          },
-          limit: 20
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 20
-    assert_correct_partition(partitions, "foo")
-
-    url = "/#{db_name}/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            _id: %{
-              "$lt": "foo:"
-            }
-          },
-          limit: 20
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 20
-    assert_correct_partition(partitions, "bar")
-  end
-
-  @tag :with_partitioned_db
-  test "query using _id works for global and local query", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_index(db_name)
-
-    url = "/#{db_name}/_partition/foo/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            _id: %{
-              "$gt": 0
-            }
-          },
-          limit: 20
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 20
-    assert_correct_partition(partitions, "foo")
-
-    url = "/#{db_name}/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            _id: %{
-              "$gt": 0
-            }
-          },
-          limit: 20
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 20
-    assert_correct_partition(partitions, "bar")
-  end
-
-  @tag :with_partitioned_db
-  test "query with partitioned:true using index and $eq", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_index(db_name)
-
-    url = "/#{db_name}/_partition/foo/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            some: "field"
-          },
-          limit: 20
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 20
-    assert_correct_partition(partitions, "foo")
-
-    url = "/#{db_name}/_partition/bar/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            some: "field"
-          },
-          limit: 20
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 20
-    assert_correct_partition(partitions, "bar")
-  end
-
-  @tag :with_partitioned_db
-  test "partitioned query using _all_docs with $eq", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-
-    url = "/#{db_name}/_partition/foo/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            some: "field"
-          },
-          limit: 20
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 20
-    assert_correct_partition(partitions, "foo")
-
-    url = "/#{db_name}/_partition/bar/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            some: "field"
-          },
-          limit: 20
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 20
-    assert_correct_partition(partitions, "bar")
-  end
-
-  @tag :with_db
-  test "non-partitioned query using _all_docs and $eq", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-
-    url = "/#{db_name}/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            some: "field"
-          },
-          skip: 40,
-          limit: 5
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert partitions == ["bar", "bar", "bar", "bar", "bar"]
-
-    url = "/#{db_name}/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            some: "field"
-          },
-          skip: 50,
-          limit: 5
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert partitions == ["foo", "foo", "foo", "foo", "foo"]
-  end
-
-  @tag :with_partitioned_db
-  test "partitioned query using index and range scan", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name, "foo", "bar42")
-    create_index(db_name, ["value"])
-
-    url = "/#{db_name}/_partition/foo/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            value: %{
-              "$gte": 6,
-              "$lt": 16
-            }
-          }
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert_correct_partition(partitions, "foo")
-
-    url = "/#{db_name}/_partition/bar42/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            value: %{
-              "$gte": 6,
-              "$lt": 16
-            }
-          }
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert_correct_partition(partitions, "bar42")
-  end
-
-  @tag :with_partitioned_db
-  test "partitioned query using _all_docs and range scan", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-
-    url = "/#{db_name}/_partition/foo/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            value: %{
-              "$gte": 6,
-              "$lt": 16
-            }
-          }
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert_correct_partition(partitions, "foo")
-
-    url = "/#{db_name}/_partition/bar/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            value: %{
-              "$gte": 6,
-              "$lt": 16
-            }
-          }
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert_correct_partition(partitions, "bar")
-  end
-
-  @tag :with_partitioned_db
-  test "partitioned query using _all_docs", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name, "foo", "bar42")
-
-    url = "/#{db_name}/_partition/foo/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            value: %{
-              "$gte": 6,
-              "$lt": 16
-            }
-          }
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert_correct_partition(partitions, "foo")
-
-    url = "/#{db_name}/_partition/bar42/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            value: %{
-              "$gte": 6,
-              "$lt": 16
-            }
-          }
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert_correct_partition(partitions, "bar42")
-  end
-
-  @tag :with_partitioned_db
-  test "explain works with partitions", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_index(db_name, ["some"])
-
-    url = "/#{db_name}/_partition/foo/_explain"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            value: %{
-              "$gte": 6,
-              "$lt": 16
-            }
-          }
-        }
-      )
-
-    %{:body => body} = resp
-
-    assert body["index"]["name"] == "_all_docs"
-    assert body["mrargs"]["partition"] == "foo"
-
-    url = "/#{db_name}/_partition/bar/_explain"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            some: "field"
-          }
-        }
-      )
-
-    %{:body => body} = resp
-
-    assert body["index"]["def"] == %{"fields" => [%{"some" => "asc"}]}
-    assert body["mrargs"]["partition"] == "bar"
-  end
-
-  @tag :with_db
-  test "explain works with non partitioned db", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_index(db_name, ["some"])
-
-    url = "/#{db_name}/_explain"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            value: %{
-              "$gte": 6,
-              "$lt": 16
-            }
-          }
-        }
-      )
-
-    %{:body => body} = resp
-
-    assert body["index"]["name"] == "_all_docs"
-    assert body["mrargs"]["partition"] == :null
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            some: "field"
-          }
-        }
-      )
-
-    %{:body => body} = resp
-
-    assert body["index"]["def"] == %{"fields" => [%{"some" => "asc"}]}
-    assert body["mrargs"]["partition"] == :null
-  end
-
-  @tag :with_partitioned_db
-  test "partitioned query using bookmarks", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_index(db_name, ["value"])
-
-    url = "/#{db_name}/_partition/foo/_find"
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            value: %{
-              "$gte": 6,
-              "$lt": 16
-            }
-          },
-          limit: 3
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 3
-    assert_correct_partition(partitions, "foo")
-
-    %{:body => %{"bookmark" => bookmark}} = resp
-
-    resp =
-      Couch.post(
-        url,
-        body: %{
-          selector: %{
-            value: %{
-              "$gte": 6,
-              "$lt": 16
-            }
-          },
-          limit: 3,
-          bookmark: bookmark
-        }
-      )
-
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 2
-    assert_correct_partition(partitions, "foo")
-  end
-
-  @tag :with_partitioned_db
-  test "global query uses global index", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_index(db_name, ["some"], %{partitioned: false})
-
-    url = "/#{db_name}/_explain"
-
-    selector = %{
-      selector: %{
-        some: "field"
-      },
-      limit: 100
-    }
-
-    resp = Couch.post(url, body: selector)
-    assert resp.status_code == 200
-    %{:body => body} = resp
-    assert body["index"]["def"] == %{"fields" => [%{"some" => "asc"}]}
-
-    url = "/#{db_name}/_find"
-    resp = Couch.post(url, body: selector)
-    assert resp.status_code == 200
-
-    partitions = get_partitions(resp)
-    assert length(partitions) == 100
-  end
-
-  @tag :with_partitioned_db
-  test "global query does not use partition index", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_index(db_name, ["some"])
-
-    url = "/#{db_name}/_explain"
-
-    selector = %{
-      selector: %{
-        some: "field"
-      },
-      limit: 100
-    }
-
-    resp = Couch.post(url, body: selector)
-    %{:body => body} = resp
-    assert body["index"]["name"] == "_all_docs"
-
-    url = "/#{db_name}/_find"
-    resp = Couch.post(url, body: selector)
-
-    assert resp.status_code == 200
-
-    partitions = get_partitions(resp)
-    assert length(partitions) == 100
-  end
-
-  @tag :with_partitioned_db
-  test "partitioned query does not use global index", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_index(db_name, ["some"], %{partitioned: false})
-
-    url = "/#{db_name}/_partition/foo/_explain"
-
-    selector = %{
-      selector: %{
-        some: "field"
-      },
-      limit: 50
-    }
-
-    resp = Couch.post(url, body: selector)
-    assert resp.status_code == 200
-    %{:body => body} = resp
-    assert body["index"]["name"] == "_all_docs"
-
-    url = "/#{db_name}/_partition/foo/_find"
-    resp = Couch.post(url, body: selector)
-    assert resp.status_code == 200
-
-    partitions = get_partitions(resp)
-    assert length(partitions) == 50
-    assert_correct_partition(partitions, "foo")
-  end
-
-  @tag :with_partitioned_db
-  test "partitioned _find and _explain with missing partition returns 400", context do
-    db_name = context[:db_name]
-
-    selector = %{
-      selector: %{
-        some: "field"
-      }
-    }
-
-    resp = Couch.get("/#{db_name}/_partition/_find", body: selector)
-    validate_missing_partition(resp)
-
-    resp = Couch.get("/#{db_name}/_partition/_explain", body: selector)
-    validate_missing_partition(resp)
-  end
-
-  defp validate_missing_partition(resp) do
-    assert resp.status_code == 400
-    %{:body => %{"reason" => reason}} = resp
-    assert Regex.match?(~r/Partition must not start/, reason)
-  end
-
-  @tag :with_partitioned_db
-  test "partitioned query sends correct errors for sort errors", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-
-    url = "/#{db_name}/_partition/foo/_find"
-
-    selector = %{
-      selector: %{
-        some: "field"
-      },
-      sort: ["some"],
-      limit: 50
-    }
-
-    resp = Couch.post(url, body: selector)
-    assert resp.status_code == 400
-    %{:body => %{"reason" => reason}} = resp
-    assert Regex.match?(~r/No partitioned index exists for this sort/, reason)
-
-    url = "/#{db_name}/_find"
-    resp = Couch.post(url, body: selector)
-    assert resp.status_code == 400
-    %{:body => %{"reason" => reason}} = resp
-    assert Regex.match?(~r/No global index exists for this sort/, reason)
-  end
-end
diff --git a/test/elixir/test/partition_size_limit_test.exs b/test/elixir/test/partition_size_limit_test.exs
deleted file mode 100644
index b4be648..0000000
--- a/test/elixir/test/partition_size_limit_test.exs
+++ /dev/null
@@ -1,305 +0,0 @@
-defmodule PartitionSizeLimitTest do
-  use CouchTestCase
-
-  @moduledoc """
-  Test Partition size limit functionality
-  """
-
-  @max_size 10_240
-
-  setup do
-    db_name = random_db_name()
-    {:ok, _} = create_db(db_name, query: %{partitioned: true, q: 1})
-    on_exit(fn -> delete_db(db_name) end)
-
-    set_config({"couchdb", "max_partition_size", Integer.to_string(@max_size)})
-
-    {:ok, [db_name: db_name]}
-  end
-
-  defp get_db_info(dbname) do
-    resp = Couch.get("/#{dbname}")
-    assert resp.status_code == 200
-    %{:body => body} = resp
-    body
-  end
-
-  defp get_partition_info(dbname, partition) do
-    resp = Couch.get("/#{dbname}/_partition/#{partition}")
-    assert resp.status_code == 200
-    %{:body => body} = resp
-    body
-  end
-
-  defp open_doc(db_name, docid, status_assert \\ 200) do
-    resp = Couch.get("/#{db_name}/#{docid}")
-    assert resp.status_code == status_assert
-    %{:body => body} = resp
-    body
-  end
-
-  defp save_doc(db_name, doc, status_assert \\ 201) do
-    resp = Couch.post("/#{db_name}", query: [w: 3], body: doc)
-    assert resp.status_code == status_assert
-    %{:body => body} = resp
-    body["rev"]
-  end
-
-  defp delete_doc(db_name, doc, status_assert \\ 200) do
-    url = "/#{db_name}/#{doc["_id"]}"
-    rev = doc["_rev"]
-    resp = Couch.delete(url, query: [w: 3, rev: rev])
-    assert resp.status_code == status_assert
-    %{:body => body} = resp
-    body["rev"]
-  end
-
-  defp fill_partition(db_name, partition \\ "foo") do
-    docs =
-      1..15
-      |> Enum.map(fn i ->
-        id = i |> Integer.to_string() |> String.pad_leading(4, "0")
-        docid = "#{partition}:#{id}"
-        %{_id: docid, value: "0" |> String.pad_leading(1024)}
-      end)
-
-    body = %{:w => 3, :docs => docs}
-    resp = Couch.post("/#{db_name}/_bulk_docs", body: body)
-    assert resp.status_code == 201
-  end
-
-  defp compact(db) do
-    assert Couch.post("/#{db}/_compact").status_code == 202
-
-    retry_until(
-      fn ->
-        Couch.get("/#{db}").body["compact_running"] == false
-      end,
-      200,
-      20_000
-    )
-  end
-
-  test "fill partition manually", context do
-    db_name = context[:db_name]
-    partition = "foo"
-
-    resp =
-      1..1000
-      |> Enum.find_value(0, fn i ->
-        id = i |> Integer.to_string() |> String.pad_leading(4, "0")
-        docid = "#{partition}:#{id}"
-        doc = %{_id: docid, value: "0" |> String.pad_leading(1024)}
-        resp = Couch.post("/#{db_name}", query: [w: 3], body: doc)
-
-        if resp.status_code == 201 do
-          false
-        else
-          resp
-        end
-      end)
-
-    assert resp.status_code == 403
-    %{body: body} = resp
-    assert body["error"] == "partition_overflow"
-
-    info = get_partition_info(db_name, partition)
-    assert info["sizes"]["external"] >= @max_size
-  end
-
-  test "full partitions reject POST /dbname", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-
-    doc = %{_id: "foo:bar", value: "stuff"}
-    resp = Couch.post("/#{db_name}", query: [w: 3], body: doc)
-    assert resp.status_code == 403
-    %{body: body} = resp
-    assert body["error"] == "partition_overflow"
-  end
-
-  test "full partitions reject PUT /dbname/docid", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-
-    doc = %{value: "stuff"}
-    resp = Couch.put("/#{db_name}/foo:bar", query: [w: 3], body: doc)
-    assert resp.status_code == 403
-    %{body: body} = resp
-    assert body["error"] == "partition_overflow"
-  end
-
-  test "full partitions reject POST /dbname/_bulk_docs", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-
-    body = %{w: 3, docs: [%{_id: "foo:bar"}]}
-    resp = Couch.post("/#{db_name}/_bulk_docs", query: [w: 3], body: body)
-    assert resp.status_code == 201
-    %{body: body} = resp
-    doc_resp = Enum.at(body, 0)
-    assert doc_resp["error"] == "partition_overflow"
-  end
-
-  test "full partitions with mixed POST /dbname/_bulk_docs", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-
-    body = %{w: 3, docs: [%{_id: "foo:bar"}, %{_id: "baz:bang"}]}
-    resp = Couch.post("/#{db_name}/_bulk_docs", query: [w: 3], body: body)
-    assert resp.status_code == 201
-    %{body: body} = resp
-
-    doc_resp1 = Enum.at(body, 0)
-    assert doc_resp1["error"] == "partition_overflow"
-
-    doc_resp2 = Enum.at(body, 1)
-    assert doc_resp2["ok"]
-  end
-
-  test "full partitions are still readable", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-    open_doc(db_name, "foo:0001")
-  end
-
-  test "full partitions can accept deletes", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-
-    doc = open_doc(db_name, "foo:0001")
-    delete_doc(db_name, doc)
-  end
-
-  test "full partitions can accept updates that reduce size", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-
-    doc = open_doc(db_name, "foo:0001")
-    save_doc(db_name, %{doc | "value" => ""})
-  end
-
-  test "full partition does not affect other partitions", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-    save_doc(db_name, %{_id: "bar:foo", value: "stuff"})
-  end
-
-  test "full partition does not affect design documents", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-    rev1 = save_doc(db_name, %{_id: "_design/foo", value: "stuff"})
-    save_doc(db_name, %{_id: "_design/foo", _rev: rev1, value: "hi"})
-    doc = open_doc(db_name, "_design/foo")
-    delete_doc(db_name, doc)
-  end
-
-  test "replication into a full partition works", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-    save_doc(db_name, %{_id: "foo:bar", value: "stuff"}, 403)
-
-    doc = %{
-      _id: "foo:bar",
-      _rev: <<"1-23202479633c2b380f79507a776743d5">>,
-      value: "stuff"
-    }
-
-    url = "/#{db_name}/#{doc[:_id]}"
-    query = [new_edits: false, w: 3]
-    resp = Couch.put(url, query: query, body: doc)
-    assert resp.status_code == 201
-  end
-
-  test "compacting a full partition works", context do
-    db_name = context[:db_name]
-    db_info1 = get_db_info(db_name)
-    fill_partition(db_name)
-    compact(db_name)
-    db_info2 = get_db_info(db_name)
-    assert db_info2["sizes"]["file"] != db_info1["sizes"]["file"]
-  end
-
-  test "indexing a full partition works", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-
-    ddoc = %{
-      _id: "_design/foo",
-      views: %{
-        bar: %{
-          map: "function(doc) {emit(doc.group, 1);}"
-        }
-      }
-    }
-
-    save_doc(db_name, ddoc)
-
-    url = "/#{db_name}/_partition/foo/_design/foo/_view/bar"
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    %{body: body} = resp
-
-    assert length(body["rows"]) > 0
-  end
-
-  test "purging docs allows writes", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-
-    info = get_partition_info(db_name, "foo")
-    limit = info["doc_count"] - 1
-
-    query = [
-      start_key: "\"foo:0000\"",
-      end_key: "\"foo:9999\"",
-      limit: limit
-    ]
-
-    resp = Couch.get("/#{db_name}/_all_docs", query: query)
-    assert resp.status_code == 200
-    %{body: body} = resp
-
-    pbody =
-      body["rows"]
-      |> Enum.reduce(%{}, fn row, acc ->
-        Map.put(acc, row["id"], [row["value"]["rev"]])
-      end)
-
-    resp = Couch.post("/#{db_name}/_purge", query: [w: 3], body: pbody)
-    assert resp.status_code == 201
-
-    save_doc(db_name, %{_id: "foo:bar", value: "some value"})
-  end
-
-  test "increasing partition size allows more writes", context do
-    db_name = context[:db_name]
-    fill_partition(db_name)
-
-    # We use set_config_raw so that we're not setting
-    # on_exit handlers that might interfere with the original
-    # config change done in setup of this test
-    new_size = Integer.to_string(@max_size * 1000)
-    set_config_raw("couchdb", "max_partition_size", new_size)
-
-    save_doc(db_name, %{_id: "foo:bar", value: "stuff"})
-  end
-
-  test "decreasing partition size disables more writes", context do
-    db_name = context[:db_name]
-
-    # We use set_config_raw so that we're not setting
-    # on_exit handlers that might interfere with the original
-    # config change done in setup of this test
-    new_size = Integer.to_string(@max_size * 1000)
-    set_config_raw("couchdb", "max_partition_size", new_size)
-
-    fill_partition(db_name)
-    save_doc(db_name, %{_id: "foo:bar", value: "stuff"})
-
-    old_size = Integer.to_string(@max_size)
-    set_config_raw("couchdb", "max_partition_size", old_size)
-
-    save_doc(db_name, %{_id: "foo:baz", value: "stuff"}, 403)
-  end
-end
diff --git a/test/elixir/test/partition_size_test.exs b/test/elixir/test/partition_size_test.exs
deleted file mode 100644
index b292dc4..0000000
--- a/test/elixir/test/partition_size_test.exs
+++ /dev/null
@@ -1,361 +0,0 @@
-defmodule PartitionSizeTest do
-  use CouchTestCase
-
-  @moduledoc """
-  Test Partition size functionality
-  """
-
-  setup do
-    db_name = random_db_name()
-    {:ok, _} = create_db(db_name, query: %{partitioned: true, q: 1})
-    on_exit(fn -> delete_db(db_name) end)
-
-    {:ok, [db_name: db_name]}
-  end
-
-  def get_db_info(dbname) do
-    resp = Couch.get("/#{dbname}")
-    assert resp.status_code == 200
-    %{:body => body} = resp
-    body
-  end
-
-  def get_partition_info(dbname, partition) do
-    resp = Couch.get("/#{dbname}/_partition/#{partition}")
-    assert resp.status_code == 200
-    %{:body => body} = resp
-    body
-  end
-
-  def mk_partition(i) do
-    i |> rem(10) |> Integer.to_string() |> String.pad_leading(3, "0")
-  end
-
-  def mk_docid(i) do
-    id = i |> Integer.to_string() |> String.pad_leading(4, "0")
-    "#{mk_partition(i)}:#{id}"
-  end
-
-  def mk_docs(db_name) do
-    docs =
-      for i <- 1..1000 do
-        group = Integer.to_string(rem(i, 3))
-
-        %{
-          :_id => mk_docid(i),
-          :value => i,
-          :some => "field",
-          :group => group
-        }
-      end
-
-    body = %{:w => 3, :docs => docs}
-
-    retry_until(fn ->
-      resp = Couch.post("/#{db_name}/_bulk_docs", body: body)
-      assert resp.status_code == 201
-    end)
-  end
-
-  def save_doc(db_name, doc) do
-    resp = Couch.post("/#{db_name}", query: [w: 3], body: doc)
-    assert resp.status_code == 201
-    %{:body => body} = resp
-    body["rev"]
-  end
-
-  test "get empty partition", context do
-    db_name = context[:db_name]
-    partition = "non_existent_partition"
-
-    info = get_partition_info(db_name, partition)
-
-    assert info["doc_count"] == 0
-    assert info["doc_del_count"] == 0
-    assert info["partition"] == partition
-    assert info["sizes"]["external"] == 0
-    assert info["sizes"]["active"] == 0
-  end
-
-  test "unknown partition return's zero", context do
-    db_name = context[:db_name]
-    mk_docs(db_name)
-
-    info = get_partition_info(db_name, "unknown")
-    assert info["doc_count"] == 0
-    assert info["doc_del_count"] == 0
-    assert info["sizes"]["external"] == 0
-    assert info["sizes"]["active"] == 0
-  end
-
-  test "simple partition size", context do
-    db_name = context[:db_name]
-    save_doc(db_name, %{_id: "foo:bar", val: 42})
-
-    info = get_partition_info(db_name, "foo")
-    assert info["doc_count"] == 1
-    assert info["doc_del_count"] == 0
-    assert info["sizes"]["external"] > 0
-    assert info["sizes"]["active"] > 0
-  end
-
-  test "adding docs increases partition sizes", context do
-    db_name = context[:db_name]
-    save_doc(db_name, %{_id: "foo:bar", val: 42})
-    pre_info = get_partition_info(db_name, "foo")
-
-    save_doc(db_name, %{_id: "foo:baz", val: 24})
-    post_info = get_partition_info(db_name, "foo")
-
-    assert post_info["doc_count"] == 2
-    assert post_info["doc_del_count"] == 0
-    assert post_info["sizes"]["external"] > pre_info["sizes"]["external"]
-    assert post_info["sizes"]["active"] > pre_info["sizes"]["active"]
-  end
-
-  test "updating docs affects partition sizes", context do
-    db_name = context[:db_name]
-    rev1 = save_doc(db_name, %{_id: "foo:bar", val: ""})
-    info1 = get_partition_info(db_name, "foo")
-
-    rev2 =
-      save_doc(db_name, %{
-        _id: "foo:bar",
-        _rev: rev1,
-        val: "this is a very long string that is so super long its beyond long"
-      })
-
-    info2 = get_partition_info(db_name, "foo")
-
-    save_doc(db_name, %{
-      _id: "foo:bar",
-      _rev: rev2,
-      val: "this string is shorter"
-    })
-
-    info3 = get_partition_info(db_name, "foo")
-
-    assert info3["doc_count"] == 1
-    assert info3["doc_del_count"] == 0
-
-    assert info3["sizes"]["external"] > info1["sizes"]["external"]
-    assert info2["sizes"]["external"] > info3["sizes"]["external"]
-  end
-
-  test "deleting a doc affects partition sizes", context do
-    db_name = context[:db_name]
-    rev1 = save_doc(db_name, %{_id: "foo:bar", val: "some stuff here"})
-    info1 = get_partition_info(db_name, "foo")
-
-    save_doc(db_name, %{_id: "foo:bar", _rev: rev1, _deleted: true})
-    info2 = get_partition_info(db_name, "foo")
-
-    assert info1["doc_count"] == 1
-    assert info1["doc_del_count"] == 0
-
-    assert info2["doc_count"] == 0
-    assert info2["doc_del_count"] == 1
-
-    assert info2["sizes"]["external"] < info1["sizes"]["external"]
-  end
-
-  test "design docs do not affect partition sizes", context do
-    db_name = context[:db_name]
-    mk_docs(db_name)
-
-    pre_infos =
-      0..9
-      |> Enum.map(fn i ->
-        get_partition_info(db_name, mk_partition(i))
-      end)
-
-    0..5
-    |> Enum.map(fn i ->
-      base = i |> Integer.to_string() |> String.pad_leading(5, "0")
-      docid = "_design/#{base}"
-      save_doc(db_name, %{_id: docid, value: "some stuff here"})
-    end)
-
-    post_infos =
-      0..9
-      |> Enum.map(fn i ->
-        get_partition_info(db_name, mk_partition(i))
-      end)
-
-    assert post_infos == pre_infos
-  end
-
-  @tag :skip_on_jenkins
-  test "get all partition sizes", context do
-    db_name = context[:db_name]
-    mk_docs(db_name)
-
-    {esum, asum} =
-      0..9
-      |> Enum.reduce({0, 0}, fn i, {esize, asize} ->
-        partition = mk_partition(i)
-        info = get_partition_info(db_name, partition)
-        assert info["doc_count"] == 100
-        assert info["doc_del_count"] == 0
-        assert info["sizes"]["external"] > 0
-        assert info["sizes"]["active"] > 0
-        {esize + info["sizes"]["external"], asize + info["sizes"]["active"]}
-      end)
-
-    db_info = get_db_info(db_name)
-    assert db_info["sizes"]["external"] >= esum
-    assert db_info["sizes"]["active"] >= asum
-  end
-
-  test "get partition size with attachment", context do
-    db_name = context[:db_name]
-
-    doc = %{
-      _id: "foo:doc-with-attachment",
-      _attachments: %{
-        "foo.txt": %{
-          content_type: "text/plain",
-          data: Base.encode64("This is a text document to save")
-        }
-      }
-    }
-
-    save_doc(db_name, doc)
-
-    db_info = get_db_info(db_name)
-    foo_info = get_partition_info(db_name, "foo")
-
-    assert foo_info["doc_count"] == 1
-    assert foo_info["doc_del_count"] == 0
-    assert foo_info["sizes"]["active"] > 0
-    assert foo_info["sizes"]["external"] > 0
-
-    assert foo_info["sizes"]["active"] <= db_info["sizes"]["active"]
-    assert foo_info["sizes"]["external"] <= db_info["sizes"]["external"]
-  end
-
-  test "attachments don't affect other partitions", context do
-    db_name = context[:db_name]
-    mk_docs(db_name)
-
-    pre_infos =
-      0..9
-      |> Enum.map(fn i ->
-        get_partition_info(db_name, mk_partition(i))
-      end)
-
-    doc = %{
-      _id: "foo:doc-with-attachment",
-      _attachments: %{
-        "foo.txt": %{
-          content_type: "text/plain",
-          data: Base.encode64("This is a text document to save")
-        }
-      }
-    }
-
-    save_doc(db_name, doc)
-
-    att_info = get_partition_info(db_name, "foo")
-    assert att_info["doc_count"] == 1
-    assert att_info["sizes"]["external"] > 0
-
-    post_infos =
-      0..9
-      |> Enum.map(fn i ->
-        get_partition_info(db_name, mk_partition(i))
-      end)
-
-    assert post_infos == pre_infos
-
-    esize =
-      ([att_info] ++ post_infos)
-      |> Enum.reduce(0, fn info, acc ->
-        info["sizes"]["external"] + acc
-      end)
-
-    db_info = get_db_info(db_name)
-    assert esize == db_info["sizes"]["external"]
-  end
-
-  test "partition activity not affect other partition sizes", context do
-    db_name = context[:db_name]
-    mk_docs(db_name)
-
-    partition1 = "000"
-    partition2 = "001"
-
-    info2 = get_partition_info(db_name, partition2)
-
-    doc_id = "#{partition1}:doc-with-attachment"
-
-    doc = %{
-      _id: doc_id,
-      _attachments: %{
-        "foo.txt": %{
-          content_type: "text/plain",
-          data: Base.encode64("This is a text document to save")
-        }
-      }
-    }
-
-    doc_rev = save_doc(db_name, doc)
-
-    info2_attach = get_partition_info(db_name, partition2)
-    assert info2_attach == info2
-
-    doc =
-      Enum.into(
-        %{
-          another: "add another field",
-          _rev: doc_rev
-        },
-        doc
-      )
-
-    doc_rev = save_doc(db_name, doc)
-
-    info2_update = get_partition_info(db_name, partition2)
-    assert info2_update == info2
-
-    resp = Couch.delete("/#{db_name}/#{doc_id}", query: %{rev: doc_rev})
-    assert resp.status_code == 200
-
-    info2_delete = get_partition_info(db_name, partition2)
-    assert info2_delete == info2
-  end
-
-  test "purging docs decreases partition size", context do
-    db_name = context[:db_name]
-    mk_docs(db_name)
-
-    partition = "000"
-
-    query = [
-      start_key: "\"#{partition}:0000\"",
-      end_key: "\"#{partition}:9999\"",
-      limit: 50
-    ]
-
-    resp = Couch.get("/#{db_name}/_all_docs", query: query)
-    assert resp.status_code == 200
-    %{body: body} = resp
-
-    pre_info = get_partition_info(db_name, partition)
-
-    pbody =
-      body["rows"]
-      |> Enum.reduce(%{}, fn row, acc ->
-        Map.put(acc, row["id"], [row["value"]["rev"]])
-      end)
-
-    resp = Couch.post("/#{db_name}/_purge", query: [w: 3], body: pbody)
-    assert resp.status_code == 201
-
-    post_info = get_partition_info(db_name, partition)
-    assert post_info["doc_count"] == pre_info["doc_count"] - 50
-    assert post_info["doc_del_count"] == 0
-    assert post_info["sizes"]["active"] < pre_info["sizes"]["active"]
-    assert post_info["sizes"]["external"] < pre_info["sizes"]["external"]
-  end
-end
diff --git a/test/elixir/test/partition_view_test.exs b/test/elixir/test/partition_view_test.exs
deleted file mode 100644
index 0a55c24..0000000
--- a/test/elixir/test/partition_view_test.exs
+++ /dev/null
@@ -1,374 +0,0 @@
-defmodule ViewPartitionTest do
-  use CouchTestCase
-  import PartitionHelpers
-
-  @moduledoc """
-  Test Partition functionality for views
-  """
-
-  setup_all do
-    db_name = random_db_name()
-    {:ok, _} = create_db(db_name, query: %{partitioned: true, q: 1})
-    on_exit(fn -> delete_db(db_name) end)
-
-    create_partition_docs(db_name)
-
-    map_fun1 = """
-      function(doc) {
-        if (doc.some) {
-          emit(doc.value, doc.some);
-        }
-      }
-    """
-
-    map_fun2 = """
-      function(doc) {
-        if (doc.group) {
-          emit([doc.some, doc.group], 1);
-        }
-      }
-    """
-
-    query = %{:w => 3}
-
-    body = %{
-      :docs => [
-        %{
-          _id: "_design/map",
-          views: %{some: %{map: map_fun1}}
-        },
-        %{
-          _id: "_design/map_some",
-          views: %{some: %{map: map_fun2}}
-        },
-        %{
-          _id: "_design/partitioned_true",
-          views: %{some: %{map: map_fun1}},
-          options: %{partitioned: true}
-        },
-        %{
-          _id: "_design/partitioned_false",
-          views: %{some: %{map: map_fun1}},
-          options: %{partitioned: false}
-        },
-        %{
-          _id: "_design/reduce",
-          views: %{some: %{map: map_fun2, reduce: "_count"}}
-        },
-        %{
-          _id: "_design/include_ddocs",
-          views: %{some: %{map: map_fun1}},
-          options: %{include_design: true}
-        }
-      ]
-    }
-
-    resp = Couch.post("/#{db_name}/_bulk_docs", query: query, body: body)
-    Enum.each(resp.body, &assert(&1["ok"]))
-
-    {:ok, [db_name: db_name]}
-  end
-
-  def get_reduce_result(resp) do
-    %{:body => %{"rows" => rows}} = resp
-    rows
-  end
-
-  test "query with partitioned:true returns partitioned fields", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/partitioned_true/_view/some"
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert Enum.dedup(partitions) == ["foo"]
-
-    url = "/#{db_name}/_partition/bar/_design/partitioned_true/_view/some"
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert Enum.dedup(partitions) == ["bar"]
-  end
-
-  test "default view query returns partitioned fields", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/map/_view/some"
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert Enum.dedup(partitions) == ["foo"]
-
-    url = "/#{db_name}/_partition/bar/_design/map/_view/some"
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert Enum.dedup(partitions) == ["bar"]
-  end
-
-  test "conflicting partitions in path and query string rejected", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/map/_view/some"
-    resp = Couch.get(url, query: %{partition: "bar"})
-    assert resp.status_code == 400
-    %{:body => %{"reason" => reason}} = resp
-    assert Regex.match?(~r/Conflicting value/, reason)
-  end
-
-  test "query will return zero results for wrong inputs", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/map/_view/some"
-    resp = Couch.get(url, query: %{start_key: "\"foo:12\""})
-    assert resp.status_code == 200
-    assert Map.get(resp, :body)["rows"] == []
-  end
-
-  test "partitioned ddoc cannot be used in global query", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_design/map/_view/some"
-    resp = Couch.get(url)
-    %{:body => %{"reason" => reason}} = resp
-    assert resp.status_code == 400
-    assert Regex.match?(~r/mandatory for queries to this view./, reason)
-  end
-
-  test "partitioned query cannot be used with global ddoc", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/partitioned_false/_view/some"
-    resp = Couch.get(url)
-    %{:body => %{"reason" => reason}} = resp
-    assert resp.status_code == 400
-    assert Regex.match?(~r/is not supported in this design doc/, reason)
-  end
-
-  test "view query returns all docs for global query", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_design/partitioned_false/_view/some"
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 100
-  end
-
-  test "partition query errors with incorrect partition supplied", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/_bar/_design/map/_view/some"
-    resp = Couch.get(url)
-    assert resp.status_code == 400
-
-    url = "/#{db_name}/_partition//_design/map/_view/some"
-    resp = Couch.get(url)
-    assert resp.status_code == 400
-  end
-
-  test "partitioned query works with startkey, endkey range", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/map/_view/some"
-    resp = Couch.get(url, query: %{start_key: 12, end_key: 20})
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert Enum.dedup(partitions) == ["foo"]
-  end
-
-  test "partitioned query works with keys", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/map/_view/some"
-    resp = Couch.post(url, body: %{keys: [2, 4, 6]})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 3
-    assert ids == ["foo:2", "foo:4", "foo:6"]
-  end
-
-  test "global query works with keys", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_design/partitioned_false/_view/some"
-    resp = Couch.post(url, body: %{keys: [2, 4, 6]})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 3
-    assert ids == ["foo:2", "foo:4", "foo:6"]
-  end
-
-  test "partition query works with limit", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/map/_view/some"
-    resp = Couch.get(url, query: %{limit: 5})
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 5
-    assert Enum.dedup(partitions) == ["foo"]
-  end
-
-  test "partition query with descending", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/map/_view/some"
-    resp = Couch.get(url, query: %{descending: true, limit: 5})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 5
-    assert ids == ["foo:100", "foo:98", "foo:96", "foo:94", "foo:92"]
-
-    resp = Couch.get(url, query: %{descending: false, limit: 5})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 5
-    assert ids == ["foo:2", "foo:4", "foo:6", "foo:8", "foo:10"]
-  end
-
-  test "partition query with skip", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/map/_view/some"
-    resp = Couch.get(url, query: %{skip: 5, limit: 5})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 5
-    assert ids == ["foo:12", "foo:14", "foo:16", "foo:18", "foo:20"]
-  end
-
-  test "partition query with key", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/map/_view/some"
-    resp = Couch.get(url, query: %{key: 22})
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 1
-    assert ids == ["foo:22"]
-  end
-
-  test "partition query with startkey_docid and endkey_docid", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/map_some/_view/some"
-
-    resp =
-      Couch.get(
-        url,
-        query: %{
-          startkey: "[\"field\",\"one\"]",
-          endkey: "[\"field\",\"one\"]",
-          startkey_docid: "foo:12",
-          endkey_docid: "foo:30"
-        }
-      )
-
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert ids == ["foo:12", "foo:18", "foo:24", "foo:30"]
-  end
-
-  test "query with reduce works", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/reduce/_view/some"
-    resp = Couch.get(url, query: %{reduce: true, group_level: 1})
-    assert resp.status_code == 200
-    results = get_reduce_result(resp)
-    assert results == [%{"key" => ["field"], "value" => 50}]
-
-    resp = Couch.get(url, query: %{reduce: true, group_level: 2})
-    results = get_reduce_result(resp)
-
-    assert results == [
-             %{"key" => ["field", "one"], "value" => 16},
-             %{"key" => ["field", "two"], "value" => 34}
-           ]
-
-    resp = Couch.get(url, query: %{reduce: true, group: true})
-    results = get_reduce_result(resp)
-
-    assert results == [
-             %{"key" => ["field", "one"], "value" => 16},
-             %{"key" => ["field", "two"], "value" => 34}
-           ]
-  end
-
-  test "partition query can set query limits", context do
-    set_config({"query_server_config", "partition_query_limit", "2000"})
-
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_partition_ddoc(db_name)
-
-    url = "/#{db_name}/_partition/foo/_design/mrtest/_view/some"
-
-    resp =
-      Couch.get(
-        url,
-        query: %{
-          limit: 20
-        }
-      )
-
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 20
-
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 50
-
-    resp =
-      Couch.get(
-        url,
-        query: %{
-          limit: 2000
-        }
-      )
-
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 50
-
-    resp =
-      Couch.get(
-        url,
-        query: %{
-          limit: 2001
-        }
-      )
-
-    assert resp.status_code == 400
-    %{:body => %{"reason" => reason}} = resp
-    assert Regex.match?(~r/Limit is too large/, reason)
-
-    resp =
-      Couch.get(
-        url,
-        query: %{
-          limit: 2000,
-          skip: 25
-        }
-      )
-
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert length(ids) == 25
-  end
-
-  test "include_design works correctly", context do
-    db_name = context[:db_name]
-
-    url = "/#{db_name}/_partition/foo/_design/include_ddocs/_view/some"
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    partitions = get_partitions(resp)
-    assert length(partitions) == 50
-    assert Enum.dedup(partitions) == ["foo"]
-  end
-end
diff --git a/test/elixir/test/partition_view_update_test.exs b/test/elixir/test/partition_view_update_test.exs
deleted file mode 100644
index 63c6268..0000000
--- a/test/elixir/test/partition_view_update_test.exs
+++ /dev/null
@@ -1,160 +0,0 @@
-defmodule PartitionViewUpdateTest do
-  use CouchTestCase
-  import PartitionHelpers
-
-  @moduledoc """
-  Test Partition view update functionality
-  """
-  @tag :with_partitioned_db
-  test "view updates properly remove old keys", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name, "foo", "bar")
-    create_partition_ddoc(db_name)
-
-    check_key = fn key, num_rows ->
-      url = "/#{db_name}/_partition/foo/_design/mrtest/_view/some"
-      resp = Couch.get(url, query: [key: key])
-      assert resp.status_code == 200
-      assert length(resp.body["rows"]) == num_rows
-    end
-
-    check_key.(2, 1)
-
-    resp = Couch.get("/#{db_name}/foo:2")
-    doc = Map.put(resp.body, "value", 4)
-    resp = Couch.put("/#{db_name}/foo:2", query: [w: 3], body: doc)
-    assert resp.status_code >= 201 and resp.status_code <= 202
-
-    check_key.(4, 2)
-    check_key.(2, 0)
-  end
-
-  @tag :skip_on_jenkins
-  @tag :with_partitioned_db
-  test "query with update=false works", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_partition_ddoc(db_name)
-
-    url = "/#{db_name}/_partition/foo/_design/mrtest/_view/some"
-
-    resp =
-      Couch.get(
-        url,
-        query: %{
-          update: "true",
-          limit: 3
-        }
-      )
-
-    assert resp.status_code == 200
-    ids = get_ids(resp)
-    assert ids == ["foo:2", "foo:4", "foo:6"]
-
-    # Avoid race conditions by attempting to get a full response
-    # from every shard before we do our update:false test
-    for _ <- 1..12 do
-      resp = Couch.get(url)
-      assert resp.status_code == 200
-    end
-
-    Couch.put("/#{db_name}/foo:1", body: %{some: "field"})
-
-    retry_until(fn ->
-      resp =
-        Couch.get(
-          url,
-          query: %{
-            update: "false",
-            limit: 3
-          }
-        )
-
-      assert resp.status_code == 200
-      ids = get_ids(resp)
-      assert ids == ["foo:2", "foo:4", "foo:6"]
-    end)
-  end
-
-  @tag :with_partitioned_db
-  test "purge removes view rows", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_partition_ddoc(db_name)
-
-    url = "/#{db_name}/_partition/foo/_design/mrtest/_view/some"
-
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    %{body: body} = resp
-    assert length(body["rows"]) == 50
-
-    resp = Couch.get("/#{db_name}/foo:2")
-    assert resp.status_code == 200
-    %{body: body} = resp
-    rev = body["_rev"]
-
-    body = %{"foo:2" => [rev]}
-    resp = Couch.post("/#{db_name}/_purge", query: [w: 3], body: body)
-    assert resp.status_code == 201
-
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    %{body: body} = resp
-    assert length(body["rows"]) == 49
-  end
-
-  @tag :with_partitioned_db
-  test "purged conflict changes view rows", context do
-    db_name = context[:db_name]
-    create_partition_docs(db_name)
-    create_partition_ddoc(db_name)
-
-    url = "/#{db_name}/_partition/foo/_design/mrtest/_view/some"
-
-    resp = Couch.get(url)
-    assert resp.status_code == 200
-    %{body: body} = resp
-    assert length(body["rows"]) == 50
-
-    # Create a conflict on foo:2. Since the 4096
-    # value is deeper than the conflict we can assert
-    # that's in the view before the purge and assert
-    # that 8192 is in the view after the purge.
-    resp = Couch.get("/#{db_name}/foo:2")
-    assert resp.status_code == 200
-    %{body: body} = resp
-    rev1 = body["_rev"]
-
-    doc = %{_id: "foo:2", _rev: rev1, value: 4096, some: "field"}
-    resp = Couch.post("/#{db_name}", query: [w: 3], body: doc)
-    assert resp.status_code == 201
-    %{body: body} = resp
-    rev2 = body["rev"]
-
-    query = [w: 3, new_edits: false]
-    conflict_rev = "1-4a75b4efa0804859b3dfd327cbc1c2f9"
-    doc = %{_id: "foo:2", _rev: conflict_rev, value: 8192, some: "field"}
-    resp = Couch.put("/#{db_name}/foo:2", query: query, body: doc)
-    assert resp.status_code == 201
-
-    # Check that our expected row exists
-    resp = Couch.get(url, query: [key: 4096])
-    assert resp.status_code == 200
-    %{body: body} = resp
-    [row] = body["rows"]
-    assert row["id"] == "foo:2"
-
-    # Remove the current row to be replaced with
-    # a row from the conflict
-    body = %{"foo:2" => [rev2]}
-    resp = Couch.post("/#{db_name}/_purge", query: [w: 3], body: body)
-    assert resp.status_code == 201
-
-    resp = Couch.get(url, query: [key: 8192])
-    assert resp.status_code == 200
-    %{body: body} = resp
-    [row] = body["rows"]
-    assert row["id"] == "foo:2"
-  end
-end
diff --git a/test/elixir/test/reshard_all_docs_test.exs b/test/elixir/test/reshard_all_docs_test.exs
deleted file mode 100644
index 62b6e37..0000000
--- a/test/elixir/test/reshard_all_docs_test.exs
+++ /dev/null
@@ -1,79 +0,0 @@
-defmodule ReshardAllDocsTest do
-  use CouchTestCase
-  import ReshardHelpers
-
-  @moduledoc """
-  Test _all_docs interaction with resharding
-  """
-
-  setup do
-    db = random_db_name()
-    {:ok, _} = create_db(db, query: %{q: 2})
-
-    on_exit(fn ->
-      reset_reshard_state()
-      delete_db(db)
-    end)
-
-    {:ok, [db: db]}
-  end
-
-  test "all_docs after splitting all shards on node1", context do
-    db = context[:db]
-    node1 = get_first_node()
-    docs = add_docs(1..100, db)
-
-    before_split_all_docs = all_docs(db)
-    assert docs == before_split_all_docs
-
-    resp = post_job_node(db, node1)
-    assert resp.status_code == 201
-    jobid = hd(resp.body)["id"]
-    wait_job_completed(jobid)
-
-    assert before_split_all_docs == all_docs(db)
-
-    assert remove_job(jobid).status_code == 200
-  end
-
-  test "all_docs after splitting the same range on all nodes", context do
-    db = context[:db]
-    docs = add_docs(1..100, db)
-
-    before_split_all_docs = all_docs(db)
-    assert docs == before_split_all_docs
-
-    resp = post_job_range(db, "00000000-7fffffff")
-    assert resp.status_code == 201
-
-    resp.body
-    |> Enum.map(fn j -> j["id"] end)
-    |> Enum.each(fn id -> wait_job_completed(id) end)
-
-    assert before_split_all_docs == all_docs(db)
-
-    get_jobs()
-    |> Enum.map(fn j -> j["id"] end)
-    |> Enum.each(fn id -> remove_job(id) end)
-  end
-
-  defp add_docs(range, db) do
-    docs = create_docs(range)
-    w3 = %{:w => 3}
-    resp = Couch.post("/#{db}/_bulk_docs", body: %{docs: docs}, query: w3)
-    assert resp.status_code == 201
-    assert length(resp.body) == length(docs)
-
-    docs
-    |> rev(resp.body)
-    |> Enum.into(%{}, fn %{:_id => id, :_rev => rev} -> {id, rev} end)
-  end
-
-  defp all_docs(db, query \\ %{}) do
-    resp = Couch.get("/#{db}/_all_docs", query: query)
-    assert resp.status_code == 200
-
-    resp.body["rows"]
-    |> Enum.into(%{}, fn %{"id" => id, "value" => v} -> {id, v["rev"]} end)
-  end
-end
diff --git a/test/elixir/test/reshard_basic_test.exs b/test/elixir/test/reshard_basic_test.exs
deleted file mode 100644
index 211dd6b..0000000
--- a/test/elixir/test/reshard_basic_test.exs
+++ /dev/null
@@ -1,174 +0,0 @@
-defmodule ReshardBasicTest do
-  use CouchTestCase
-  import ReshardHelpers
-
-  @moduledoc """
-  Test resharding basic functionality
-  """
-
-  setup_all do
-    db1 = random_db_name()
-    {:ok, _} = create_db(db1, query: %{q: 1})
-    db2 = random_db_name()
-    {:ok, _} = create_db(db2, query: %{q: 2})
-
-    on_exit(fn ->
-      reset_reshard_state()
-      delete_db(db1)
-      delete_db(db2)
-    end)
-
-    {:ok, [db1: db1, db2: db2]}
-  end
-
-  test "basic api querying, no jobs present" do
-    summary = get_summary()
-    assert summary["state"] == "running"
-    assert summary["state_reason"] == :null
-    assert summary["total"] == 0
-    assert summary["completed"] == 0
-    assert summary["failed"] == 0
-    assert summary["stopped"] == 0
-    assert get_state() == %{"state" => "running", "reason" => :null}
-    assert get_jobs() == []
-  end
-
-  test "check validation of invalid parameters", context do
-    db1 = context[:db1]
-    node1 = get_first_node()
-
-    resp = post_job_node(db1, "badnode")
-    assert resp.status_code == 400
-
-    resp = post_job_node("badresharddb", node1)
-    assert resp.status_code == 400
-
-    resp = post_job_db("badresharddb")
-    assert resp.status_code == 400
-
-    resp = post_job_range("badresharddb", "randomgarbage")
-    assert resp.status_code == 400
-
-    resp = get_job("badjobid")
-    assert resp.status_code == 404
-
-    resp = remove_job("badjobid")
-    assert resp.status_code == 404
-  end
-
-  test "toggle global state" do
-    assert get_state() == %{"state" => "running", "reason" => :null}
-    put_state_stopped("xyz")
-    assert get_state() == %{"state" => "stopped", "reason" => "xyz"}
-    put_state_running()
-    assert get_state() == %{"state" => "running", "reason" => :null}
-  end
-
-  test "split q=1 db shards on node1 (1 job)", context do
-    db = context[:db1]
-    node1 = get_first_node()
-
-    resp = post_job_node(db, node1)
-    assert resp.status_code == 201
-
-    body = resp.body
-    assert is_list(body)
-    assert length(body) == 1
-
-    [job] = body
-    id = job["id"]
-    assert is_binary(id)
-    node = job["node"]
-    assert is_binary(node)
-    assert node == node1
-    assert job["ok"] == true
-    shard = job["shard"]
-    assert is_binary(shard)
-
-    resp = get_job(id)
-    assert resp.status_code == 200
-
-    body = resp.body
-    assert body["type"] == "split"
-    assert body["id"] == id
-    assert body["source"] == shard
-    assert is_list(body["history"])
-    assert body["job_state"] in ["new", "running", "completed"]
-    assert is_list(body["target"])
-    assert length(body["target"]) == 2
-
-    wait_job_completed(id)
-
-    resp = get_job(id)
-    assert resp.status_code == 200
-
-    body = resp.body
-    assert body["job_state"] == "completed"
-    assert body["split_state"] == "completed"
-
-    resp = Couch.get("/#{db}/_shards")
-    assert resp.status_code == 200
-    shards = resp.body["shards"]
-    assert node1 not in shards["00000000-ffffffff"]
-    assert shards["00000000-7fffffff"] == [node1]
-    assert shards["80000000-ffffffff"] == [node1]
-
-    summary = get_summary()
-    assert summary["total"] == 1
-    assert summary["completed"] == 1
-
-    resp = remove_job(id)
-    assert resp.status_code == 200
-
-    assert get_jobs() == []
-
-    summary = get_summary()
-    assert summary["total"] == 0
-    assert summary["completed"] == 0
-  end
-
-  test "split q=2 shards on node1 (2 jobs)", context do
-    db = context[:db2]
-    node1 = get_first_node()
-
-    resp = post_job_node(db, node1)
-    assert resp.status_code == 201
-
-    body = resp.body
-    assert is_list(body)
-    assert length(body) == 2
-
-    [job1, job2] = Enum.sort(body)
-    {id1, id2} = {job1["id"], job2["id"]}
-
-    assert get_job(id1).body["id"] == id1
-    assert get_job(id2).body["id"] == id2
-
-    summary = get_summary()
-    assert summary["total"] == 2
-
-    wait_job_completed(id1)
-    wait_job_completed(id2)
-
-    summary = get_summary()
-    assert summary["completed"] == 2
-
-    resp = Couch.get("/#{db}/_shards")
-    assert resp.status_code == 200
-    shards = resp.body["shards"]
-    assert node1 not in shards["00000000-7fffffff"]
-    assert node1 not in shards["80000000-ffffffff"]
-    assert shards["00000000-3fffffff"] == [node1]
-    assert shards["40000000-7fffffff"] == [node1]
-    assert shards["80000000-bfffffff"] == [node1]
-    assert shards["c0000000-ffffffff"] == [node1]
-
-    # deleting the source db should remove the jobs
-    delete_db(db)
-    wait_job_removed(id1)
-    wait_job_removed(id2)
-
-    summary = get_summary()
-    assert summary["total"] == 0
-  end
-end
diff --git a/test/elixir/test/reshard_changes_feed.exs b/test/elixir/test/reshard_changes_feed.exs
deleted file mode 100644
index a4a39fe..0000000
--- a/test/elixir/test/reshard_changes_feed.exs
+++ /dev/null
@@ -1,81 +0,0 @@
-defmodule ReshardChangesFeedTest do
-  use CouchTestCase
-  import ReshardHelpers
-
-  @moduledoc """
-  Test _changes interaction with resharding
-  """
-
-  setup do
-    db = random_db_name()
-    {:ok, _} = create_db(db, query: %{q: 2})
-
-    on_exit(fn ->
-      reset_reshard_state()
-      delete_db(db)
-    end)
-
-    {:ok, [db: db]}
-  end
-
-  test "all_docs after splitting all shards on node1", context do
-    db = context[:db]
-    add_docs(1..3, db)
-
-    all_before = changes(db)
-    first_seq = hd(all_before["results"])["seq"]
-    last_seq = all_before["last_seq"]
-    since_1_before = docset(changes(db, %{:since => first_seq}))
-    since_last_before = docset(changes(db, %{:since => last_seq}))
-
-    resp = post_job_range(db, "00000000-7fffffff")
-    assert resp.status_code == 201
-
-    resp.body
-    |> Enum.map(fn j -> j["id"] end)
-    |> Enum.each(fn id -> wait_job_completed(id) end)
-
-    all_after = changes(db)
-    since_1_after = docset(changes(db, %{:since => first_seq}))
-    since_last_after = docset(changes(db, %{:since => last_seq}))
-
-    assert docset(all_before) == docset(all_after)
-    assert MapSet.subset?(since_1_before, since_1_after)
-    assert MapSet.subset?(since_last_before, since_last_after)
-
-    get_jobs()
-    |> Enum.map(fn j -> j["id"] end)
-    |> Enum.each(fn id -> remove_job(id) end)
-  end
-
-  defp docset(changes) do
-    changes["results"]
-    |> Enum.map(fn %{"id" => id} -> id end)
-    |> MapSet.new()
-  end
-
-  defp changes(db, query \\ %{}) do
-    resp = Couch.get("/#{db}/_changes", query: query)
-    assert resp.status_code == 200
-    resp.body
-  end
-
-  defp add_docs(range, db) do
-    docs = create_docs(range)
-    w3 = %{:w => 3}
-    resp = Couch.post("/#{db}/_bulk_docs", body: %{docs: docs}, query: w3)
-    assert resp.status_code == 201
-    assert length(resp.body) == length(docs)
-
-    docs
-    |> rev(resp.body)
-    |> Enum.into(%{}, fn %{:_id => id, :_rev => rev} -> {id, rev} end)
-  end
-
-  # (Keep for debugging)
-  # defp unpack_seq(seq) when is_binary(seq) do
-  #   [_, opaque] = String.split(seq, "-")
-  #   {:ok, binblob} = Base.url_decode64(opaque, padding: false)
-  #   :erlang.binary_to_term(binblob)
-  # end
-end
diff --git a/test/elixir/test/reshard_helpers.exs b/test/elixir/test/reshard_helpers.exs
deleted file mode 100644
index 52ce301..0000000
--- a/test/elixir/test/reshard_helpers.exs
+++ /dev/null
@@ -1,114 +0,0 @@
-defmodule ReshardHelpers do
-  use CouchTestCase
-
-  def get_summary do
-    resp = Couch.get("/_reshard")
-    assert resp.status_code == 200
-    resp.body
-  end
-
-  def get_state do
-    resp = Couch.get("/_reshard/state")
-    assert resp.status_code == 200
-    resp.body
-  end
-
-  def put_state_running do
-    resp = Couch.put("/_reshard/state", body: %{:state => "running"})
-    assert resp.status_code == 200
-    resp
-  end
-
-  def put_state_stopped(reason \\ "") do
-    body = %{:state => "stopped", :reason => reason}
-    resp = Couch.put("/_reshard/state", body: body)
-    assert resp.status_code == 200
-    resp
-  end
-
-  def get_jobs do
-    resp = Couch.get("/_reshard/jobs")
-    assert resp.status_code == 200
-    resp.body["jobs"]
-  end
-
-  def post_job_db(db) do
-    body = %{:type => :split, :db => db}
-    Couch.post("/_reshard/jobs", body: body)
-  end
-
-  def post_job_node(db, node) do
-    body = %{:type => :split, :db => db, :node => node}
-    Couch.post("/_reshard/jobs", body: body)
-  end
-
-  def post_job_range(db, range) do
-    body = %{:type => :split, :db => db, :range => range}
-    Couch.post("/_reshard/jobs", body: body)
-  end
-
-  def post_job_node_and_range(db, node, range) do
-    body = %{:type => :split, :db => db, :node => node, :range => range}
-    Couch.post("/_reshard/jobs", body: body)
-  end
-
-  def get_job(id) when is_binary(id) do
-    Couch.get("/_reshard/jobs/#{id}")
-  end
-
-  def remove_job(id) when is_binary(id) do
-    Couch.delete("/_reshard/jobs/#{id}")
-  end
-
-  def get_job_state(id) when is_binary(id) do
-    resp = Couch.get("/_reshard/jobs/#{id}/state")
-    assert resp.status_code == 200
-    resp.body["state"]
-  end
-
-  def stop_job(id, reason \\ "") when is_binary(id) do
-    body = %{:state => "stopped", :reason => reason}
-    Couch.post("/_reshard/jobs/#{id}/state", body: body)
-  end
-
-  def resume_job(id) when is_binary(id) do
-    body = %{:state => "running"}
-    Couch.post("/_reshard/jobs/#{id}/state", body: body)
-  end
-
-  def job_ids(jobs) do
-    Enum.map(fn job -> job["id"] end, jobs)
-  end
-
-  def get_first_node do
-    mresp = Couch.get("/_membership")
-    assert mresp.status_code == 200
-    all_nodes = mresp.body["all_nodes"]
-
-    mresp.body["cluster_nodes"]
-    |> Enum.filter(fn n -> n in all_nodes end)
-    |> Enum.sort()
-    |> hd()
-  end
-
-  def wait_job_removed(id) do
-    retry_until(fn -> get_job(id).status_code == 404 end, 200, 10_000)
-  end
-
-  def wait_job_completed(id) do
-    wait_job_state(id, "completed")
-  end
-
-  def wait_job_state(id, state) do
-    retry_until(fn -> get_job_state(id) == state end, 200, 10_000)
-  end
-
-  def reset_reshard_state do
-    get_jobs()
-    |> Enum.map(fn j -> j["id"] end)
-    |> Enum.each(fn id -> remove_job(id) end)
-
-    assert get_jobs() == []
-    put_state_running()
-  end
-end
diff --git a/test/elixir/test/test_helper.exs b/test/elixir/test/test_helper.exs
index ef71bbb..b114f53 100644
--- a/test/elixir/test/test_helper.exs
+++ b/test/elixir/test/test_helper.exs
@@ -12,5 +12,3 @@ ExUnit.configure(
 )
 
 ExUnit.start()
-Code.require_file("partition_helpers.exs", __DIR__)
-Code.require_file("reshard_helpers.exs", __DIR__)