You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2020/04/06 22:02:03 UTC

[couchdb] 05/05: Start running chttpd eunit tests

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

vatamane pushed a commit to branch fix-api-corner-cases-and-make-chttpd-pass
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 9d5d3445f8e5e047612b1446f5fd2247ce553275
Author: Nick Vatamaniuc <va...@apache.org>
AuthorDate: Mon Apr 6 17:53:40 2020 -0400

    Start running chttpd eunit tests
    
    Enable running all chttpd tests. Some fixes needed for this to happen are:
    
     * Some tests were not valid (checking shard maps, etc) and were deleted
    
     * Some tests were disabled either because functionality is not implemented yet
       or simply to minimize the diff between 3.x and this branch for when we have
       to rebase
    
     * Some applications used for index querying had to be started explicitly
    
     * Mock updated to use new version of modules instead of old ones
---
 Makefile                                           |  2 +-
 src/chttpd/src/chttpd_test_util.erl                |  2 +-
 src/chttpd/src/chttpd_view.erl                     | 10 ++---
 .../eunit/chttpd_db_bulk_get_multipart_test.erl    | 31 +++++++-------
 src/chttpd/test/eunit/chttpd_db_bulk_get_test.erl  | 30 ++++++++------
 src/chttpd/test/eunit/chttpd_db_test.erl           | 38 ++++-------------
 src/chttpd/test/eunit/chttpd_dbs_info_test.erl     | 13 +++---
 .../test/eunit/chttpd_open_revs_error_test.erl     |  2 +-
 src/chttpd/test/eunit/chttpd_purge_tests.erl       |  2 +-
 src/chttpd/test/eunit/chttpd_security_tests.erl    | 47 +++++++++-------------
 src/chttpd/test/eunit/chttpd_view_test.erl         |  4 +-
 src/couch/src/couch_db.erl                         |  2 +
 12 files changed, 78 insertions(+), 105 deletions(-)

diff --git a/Makefile b/Makefile
index cc33c61..592093e 100644
--- a/Makefile
+++ b/Makefile
@@ -160,7 +160,7 @@ endif
 
 .PHONY: check-fdb
 check-fdb:
-	make eunit apps=couch_eval,couch_expiring_cache,ctrace,couch_jobs,couch_views,fabric,mango
+	make eunit apps=couch_eval,couch_expiring_cache,ctrace,couch_jobs,couch_views,fabric,mango,chttpd
 	make elixir tests=test/elixir/test/basics_test.exs,test/elixir/test/replication_test.exs,test/elixir/test/map_test.exs,test/elixir/test/all_docs_test.exs,test/elixir/test/bulk_docs_test.exs
 	make exunit tests=src/couch_rate/test/exunit/
 	make mango-test
diff --git a/src/chttpd/src/chttpd_test_util.erl b/src/chttpd/src/chttpd_test_util.erl
index a1a08ef..8930a5a 100644
--- a/src/chttpd/src/chttpd_test_util.erl
+++ b/src/chttpd/src/chttpd_test_util.erl
@@ -21,7 +21,7 @@ start_couch() ->
     start_couch(?CONFIG_CHAIN).
 
 start_couch(IniFiles) ->
-    test_util:start_couch(IniFiles, [chttpd]).
+    test_util:start_couch(IniFiles, [couch_js, couch_views, chttpd]).
 
 stop_couch(Ctx) ->
     test_util:stop_couch(Ctx).
diff --git a/src/chttpd/src/chttpd_view.erl b/src/chttpd/src/chttpd_view.erl
index 3ef9c24..c9340fb 100644
--- a/src/chttpd/src/chttpd_view.erl
+++ b/src/chttpd/src/chttpd_view.erl
@@ -136,7 +136,7 @@ check_multi_query_reduce_view_overrides_test_() ->
 t_check_include_docs_throw_validation_error() ->
     ?_test(begin
         Req = #httpd{qs = []},
-        Db = test_util:fake_db([{name, <<"foo">>}]),
+        Db = #{name => <<"foo">>},
         Query = {[{<<"include_docs">>, true}]},
         Throw = {query_parse_error, <<"`include_docs` is invalid for reduce">>},
         ?assertThrow(Throw, multi_query_view(Req, Db, ddoc, <<"v">>, [Query]))
@@ -146,7 +146,7 @@ t_check_include_docs_throw_validation_error() ->
 t_check_user_can_override_individual_query_type() ->
     ?_test(begin
         Req = #httpd{qs = []},
-        Db = test_util:fake_db([{name, <<"foo">>}]),
+        Db = #{name => <<"foo">>},
         Query = {[{<<"include_docs">>, true}, {<<"reduce">>, false}]},
         multi_query_view(Req, Db, ddoc, <<"v">>, [Query]),
         ?assertEqual(1, meck:num_calls(chttpd, start_delayed_json_response, '_'))
@@ -157,7 +157,7 @@ setup_all() ->
     Views = [#mrview{reduce_funs = [{<<"v">>, <<"_count">>}]}],
     meck:expect(couch_mrview_util, ddoc_to_mrst, 2, {ok, #mrst{views = Views}}),
     meck:expect(chttpd, start_delayed_json_response, 4, {ok, resp}),
-    meck:expect(fabric, query_view, 7, {ok, #vacc{}}),
+    meck:expect(couch_views, query, 6, {ok, #vacc{}}),
     meck:expect(chttpd, send_delayed_chunk, 2, {ok, resp}),
     meck:expect(chttpd, end_delayed_json_response, 1, ok).
 
@@ -169,8 +169,8 @@ teardown_all(_) ->
 setup() ->
     meck:reset([
         chttpd,
-        couch_mrview_util,
-        fabric
+        couch_views,
+        couch_mrview_util
     ]).
 
 
diff --git a/src/chttpd/test/eunit/chttpd_db_bulk_get_multipart_test.erl b/src/chttpd/test/eunit/chttpd_db_bulk_get_multipart_test.erl
index 86a8eab..c0095d5 100644
--- a/src/chttpd/test/eunit/chttpd_db_bulk_get_multipart_test.erl
+++ b/src/chttpd/test/eunit/chttpd_db_bulk_get_multipart_test.erl
@@ -39,7 +39,7 @@ setup() ->
         couch_epi,
         couch_httpd,
         couch_stats,
-        fabric,
+        fabric2_db,
         mochireq
     ]),
     spawn_accumulator().
@@ -78,13 +78,13 @@ bulk_get_test_() ->
 
 should_require_docs_field(_) ->
     Req = fake_request({[{}]}),
-    Db  = test_util:fake_db([{name, <<"foo">>}]),
+    Db  = #{name => <<"foo">>},
     ?_assertThrow({bad_request, _}, chttpd_db:db_req(Req, Db)).
 
 
 should_not_accept_specific_query_params(_) ->
     Req = fake_request({[{<<"docs">>, []}]}),
-    Db  = test_util:fake_db([{name, <<"foo">>}]),
+    Db  = #{name => <<"foo">>},
     lists:map(fun (Param) ->
         {Param, ?_assertThrow({bad_request, _}, begin
             BadReq = Req#httpd{qs = [{Param, ""}]},
@@ -95,7 +95,7 @@ should_not_accept_specific_query_params(_) ->
 
 should_return_empty_results_on_no_docs(Pid) ->
     Req = fake_request({[{<<"docs">>, []}]}),
-    Db  = test_util:fake_db([{name, <<"foo">>}]),
+    Db  = #{name => <<"foo">>},
     chttpd_db:db_req(Req, Db),
     Results = get_results_from_response(Pid),
     ?_assertEqual([], Results).
@@ -104,7 +104,7 @@ should_return_empty_results_on_no_docs(Pid) ->
 should_get_doc_with_all_revs(Pid) ->
     DocId = <<"docudoc">>,
     Req = fake_request(DocId),
-    Db  = test_util:fake_db([{name, <<"foo">>}]),
+    Db  = #{name => <<"foo">>},
 
     DocRevA = #doc{id = DocId, body = {[{<<"_rev">>, <<"1-ABC">>}]}},
     DocRevB = #doc{id = DocId, body = {[{<<"_rev">>, <<"1-CDE">>}]}},
@@ -120,7 +120,7 @@ should_validate_doc_with_bad_id(Pid) ->
     DocId = <<"_docudoc">>,
 
     Req = fake_request(DocId),
-    Db  = test_util:fake_db([{name, <<"foo">>}]),
+    Db  = #{name => <<"foo">>},
     chttpd_db:db_req(Req, Db),
 
     Result = get_results_from_response(Pid),
@@ -137,7 +137,7 @@ should_validate_doc_with_bad_rev(Pid) ->
     Rev = <<"revorev">>,
 
     Req = fake_request(DocId, Rev),
-    Db  = test_util:fake_db([{name, <<"foo">>}]),
+    Db  = #{name => <<"foo">>},
     chttpd_db:db_req(Req, Db),
 
     Result = get_results_from_response(Pid),
@@ -154,7 +154,7 @@ should_validate_missing_doc(Pid) ->
     Rev = <<"1-revorev">>,
 
     Req = fake_request(DocId, Rev),
-    Db  = test_util:fake_db([{name, <<"foo">>}]),
+    Db  = #{name => <<"foo">>},
     mock_open_revs([{1,<<"revorev">>}], {ok, []}),
     chttpd_db:db_req(Req, Db),
 
@@ -172,7 +172,7 @@ should_validate_bad_atts_since(Pid) ->
     Rev = <<"1-revorev">>,
 
     Req = fake_request(DocId, Rev, <<"badattsince">>),
-    Db  = test_util:fake_db([{name, <<"foo">>}]),
+    Db  = #{name => <<"foo">>},
     mock_open_revs([{1,<<"revorev">>}], {ok, []}),
     chttpd_db:db_req(Req, Db),
 
@@ -190,14 +190,13 @@ should_include_attachments_when_atts_since_specified(_) ->
     Rev = <<"1-revorev">>,
 
     Req = fake_request(DocId, Rev, [<<"1-abc">>]),
-    Db  = test_util:fake_db([{name, <<"foo">>}]),
+    Db  = #{name => <<"foo">>},
     mock_open_revs([{1,<<"revorev">>}], {ok, []}),
     chttpd_db:db_req(Req, Db),
 
-    ?_assert(meck:called(fabric, open_revs,
-                         ['_', DocId, [{1, <<"revorev">>}],
-                         [{atts_since, [{1, <<"abc">>}]}, attachments,
-                          {user_ctx, undefined}]])).
+    Options = [{atts_since, [{1, <<"abc">>}]}, attachments],
+    ?_assert(meck:called(fabric2_db, open_doc_revs, ['_', DocId,
+        [{1, <<"revorev">>}], Options])).
 
 %% helpers
 
@@ -217,7 +216,7 @@ fake_request(DocId, Rev, AttsSince) ->
 
 
 mock_open_revs(RevsReq0, RevsResp) ->
-    ok = meck:expect(fabric, open_revs,
+    ok = meck:expect(fabric2_db, open_doc_revs,
                      fun(_, _, RevsReq1, _) ->
                          ?assertEqual(RevsReq0, RevsReq1),
                          RevsResp
@@ -259,7 +258,7 @@ mock(couch_stats) ->
     ok = meck:expect(couch_stats, update_gauge, fun(_, _) -> ok end),
     ok;
 mock(fabric) ->
-    ok = meck:new(fabric, [passthrough]),
+    ok = meck:new(fabric2_db, [passthrough]),
     ok;
 mock(config) ->
     ok = meck:new(config, [passthrough]),
diff --git a/src/chttpd/test/eunit/chttpd_db_bulk_get_test.erl b/src/chttpd/test/eunit/chttpd_db_bulk_get_test.erl
index 1a34112..0e47783 100644
--- a/src/chttpd/test/eunit/chttpd_db_bulk_get_test.erl
+++ b/src/chttpd/test/eunit/chttpd_db_bulk_get_test.erl
@@ -99,7 +99,8 @@ should_get_doc_with_all_revs(Pid) ->
     DocRevB = #doc{id = DocId, body = {[{<<"_rev">>, <<"1-CDE">>}]}},
 
     mock_open_revs(all, {ok, [{ok, DocRevA}, {ok, DocRevB}]}),
-    chttpd_db:db_req(Req, test_util:fake_db([{name, <<"foo">>}])),
+    Db = #{name => <<"foo">>},
+    chttpd_db:db_req(Req, Db),
 
     [{Result}] = get_results_from_response(Pid),
     ?assertEqual(DocId, couch_util:get_value(<<"id">>, Result)),
@@ -119,7 +120,8 @@ should_validate_doc_with_bad_id(Pid) ->
     DocId = <<"_docudoc">>,
 
     Req = fake_request(DocId),
-    chttpd_db:db_req(Req, test_util:fake_db([{name, <<"foo">>}])),
+    Db = #{name => <<"foo">>},
+    chttpd_db:db_req(Req, Db),
 
     [{Result}] = get_results_from_response(Pid),
     ?assertEqual(DocId, couch_util:get_value(<<"id">>, Result)),
@@ -142,7 +144,8 @@ should_validate_doc_with_bad_rev(Pid) ->
     Rev = <<"revorev">>,
 
     Req = fake_request(DocId, Rev),
-    chttpd_db:db_req(Req, test_util:fake_db([{name, <<"foo">>}])),
+    Db = #{name => <<"foo">>},
+    chttpd_db:db_req(Req, Db),
 
     [{Result}] = get_results_from_response(Pid),
     ?assertEqual(DocId, couch_util:get_value(<<"id">>, Result)),
@@ -166,7 +169,8 @@ should_validate_missing_doc(Pid) ->
 
     Req = fake_request(DocId, Rev),
     mock_open_revs([{1,<<"revorev">>}], {ok, []}),
-    chttpd_db:db_req(Req, test_util:fake_db([{name, <<"foo">>}])),
+    Db = #{name => <<"foo">>},
+    chttpd_db:db_req(Req, Db),
 
     [{Result}] = get_results_from_response(Pid),
     ?assertEqual(DocId, couch_util:get_value(<<"id">>, Result)),
@@ -190,7 +194,8 @@ should_validate_bad_atts_since(Pid) ->
 
     Req = fake_request(DocId, Rev, <<"badattsince">>),
     mock_open_revs([{1,<<"revorev">>}], {ok, []}),
-    chttpd_db:db_req(Req, test_util:fake_db([{name, <<"foo">>}])),
+    Db = #{name => <<"foo">>},
+    chttpd_db:db_req(Req, Db),
 
     [{Result}] = get_results_from_response(Pid),
     ?assertEqual(DocId, couch_util:get_value(<<"id">>, Result)),
@@ -214,12 +219,13 @@ should_include_attachments_when_atts_since_specified(_) ->
 
     Req = fake_request(DocId, Rev, [<<"1-abc">>]),
     mock_open_revs([{1,<<"revorev">>}], {ok, []}),
-    chttpd_db:db_req(Req, test_util:fake_db([{name, <<"foo">>}])),
+    Db = #{name => <<"foo">>},
+    chttpd_db:db_req(Req, Db),
+
+    Options = [{atts_since, [{1, <<"abc">>}]}, attachments],
+    ?_assert(meck:called(fabric2_db, open_doc_revs, ['_', DocId,
+        [{1, <<"revorev">>}], Options])).
 
-    ?_assert(meck:called(fabric, open_revs,
-                         ['_', DocId, [{1, <<"revorev">>}],
-                          [{atts_since, [{1, <<"abc">>}]}, attachments,
-                           {user_ctx, undefined}]])).
 
 %% helpers
 
@@ -239,7 +245,7 @@ fake_request(DocId, Rev, AttsSince) ->
 
 
 mock_open_revs(RevsReq0, RevsResp) ->
-    ok = meck:expect(fabric, open_revs,
+    ok = meck:expect(fabric2_db, open_doc_revs,
                      fun(_, _, RevsReq1, _) ->
                          ?assertEqual(RevsReq0, RevsReq1),
                          RevsResp
@@ -276,7 +282,7 @@ mock(couch_stats) ->
     ok = meck:expect(couch_stats, update_gauge, fun(_, _) -> ok end),
     ok;
 mock(fabric) ->
-    ok = meck:new(fabric, [passthrough]),
+    ok = meck:new(fabric2_db, [passthrough]),
     ok;
 mock(config) ->
     ok = meck:new(config, [passthrough]),
diff --git a/src/chttpd/test/eunit/chttpd_db_test.erl b/src/chttpd/test/eunit/chttpd_db_test.erl
index 204332d..b1d514a 100644
--- a/src/chttpd/test/eunit/chttpd_db_test.erl
+++ b/src/chttpd/test/eunit/chttpd_db_test.erl
@@ -73,8 +73,7 @@ all_test_() ->
                     fun should_return_update_seq_when_set_on_all_docs/1,
                     fun should_not_return_update_seq_when_unset_on_all_docs/1,
                     fun should_return_correct_id_on_doc_copy/1,
-                    fun should_return_400_for_bad_engine/1,
-                    fun should_not_change_db_proper_after_rewriting_shardmap/1,
+                    fun should_ignore_engine_parameter/1,
                     fun should_succeed_on_all_docs_with_queries_keys/1,
                     fun should_succeed_on_all_docs_with_queries_limit_skip/1,
                     fun should_succeed_on_all_docs_with_multiple_queries/1,
@@ -282,7 +281,7 @@ attachment_doc() ->
     ]}.
 
 
-should_return_400_for_bad_engine(_) ->
+should_ignore_engine_parameter(_) ->
     {timeout, ?TIMEOUT, ?_test(begin
         TmpDb = ?tempdb(),
         Addr = config:get("chttpd", "bind_address", "127.0.0.1"),
@@ -290,30 +289,7 @@ should_return_400_for_bad_engine(_) ->
         BaseUrl = lists:concat(["http://", Addr, ":", Port, "/", ?b2l(TmpDb)]),
         Url = BaseUrl ++ "?engine=cowabunga",
         {ok, Status, _, _} = test_request:put(Url, [?CONTENT_JSON, ?AUTH], "{}"),
-        ?assertEqual(400, Status)
-    end)}.
-
-
-should_not_change_db_proper_after_rewriting_shardmap(_) ->
-    {timeout, ?TIMEOUT, ?_test(begin
-        TmpDb = ?tempdb(),
-        Addr = config:get("chttpd", "bind_address", "127.0.0.1"),
-        Port = mochiweb_socket_server:get(chttpd, port),
-        AdmPort = mochiweb_socket_server:get(couch_httpd, port),
-
-        BaseUrl = lists:concat(["http://", Addr, ":", Port, "/", ?b2l(TmpDb)]),
-        Url = BaseUrl ++ "?partitioned=true&q=1",
-        {ok, 201, _, _} = test_request:put(Url, [?CONTENT_JSON, ?AUTH], "{}"),
-
-        ShardDbName = ?l2b(config:get("mem3", "shards_db", "_dbs")),
-        {ok, ShardDb} = mem3_util:ensure_exists(ShardDbName),
-        {ok, #doc{body = {Props}}} = couch_db:open_doc(
-            ShardDb, TmpDb, [ejson_body]),
-        Shards = mem3_util:build_shards(TmpDb, Props),
-
-        {Prop2} = ?JSON_DECODE(?JSON_ENCODE({Props})),
-        Shards2 = mem3_util:build_shards(TmpDb, Prop2),
-        ?assertEqual(Shards2, Shards)
+        ?assertEqual(201, Status)
     end)}.
 
 
@@ -341,7 +317,7 @@ should_succeed_on_all_docs_with_queries_limit_skip(Url) ->
         {ResultJson} = ?JSON_DECODE(RespBody),
         ResultJsonBody = couch_util:get_value(<<"results">>, ResultJson),
         {InnerJson} = lists:nth(1, ResultJsonBody),
-        ?assertEqual(2, couch_util:get_value(<<"offset">>, InnerJson)),
+        ?assertEqual(null, couch_util:get_value(<<"offset">>, InnerJson)),
         ?assertEqual(5, length(couch_util:get_value(<<"rows">>, InnerJson)))
     end)}.
 
@@ -359,7 +335,7 @@ should_succeed_on_all_docs_with_multiple_queries(Url) ->
         {InnerJson1} = lists:nth(1, ResultJsonBody),
         ?assertEqual(2, length(couch_util:get_value(<<"rows">>, InnerJson1))),
         {InnerJson2} = lists:nth(2, ResultJsonBody),
-        ?assertEqual(2, couch_util:get_value(<<"offset">>, InnerJson2)),
+        ?assertEqual(null, couch_util:get_value(<<"offset">>, InnerJson2)),
         ?assertEqual(5, length(couch_util:get_value(<<"rows">>, InnerJson2)))
     end)}.
 
@@ -389,7 +365,7 @@ should_succeed_on_design_docs_with_queries_limit_skip(Url) ->
         {ResultJson} = ?JSON_DECODE(RespBody),
         ResultJsonBody = couch_util:get_value(<<"results">>, ResultJson),
         {InnerJson} = lists:nth(1, ResultJsonBody),
-        ?assertEqual(2, couch_util:get_value(<<"offset">>, InnerJson)),
+        ?assertEqual(null, couch_util:get_value(<<"offset">>, InnerJson)),
         ?assertEqual(5, length(couch_util:get_value(<<"rows">>, InnerJson)))
     end)}.
 
@@ -407,7 +383,7 @@ should_succeed_on_design_docs_with_multiple_queries(Url) ->
         {InnerJson1} = lists:nth(1, ResultJsonBody),
         ?assertEqual(2, length(couch_util:get_value(<<"rows">>, InnerJson1))),
         {InnerJson2} = lists:nth(2, ResultJsonBody),
-        ?assertEqual(2, couch_util:get_value(<<"offset">>, InnerJson2)),
+        ?assertEqual(null, couch_util:get_value(<<"offset">>, InnerJson2)),
         ?assertEqual(5, length(couch_util:get_value(<<"rows">>, InnerJson2)))
     end)}.
 
diff --git a/src/chttpd/test/eunit/chttpd_dbs_info_test.erl b/src/chttpd/test/eunit/chttpd_dbs_info_test.erl
index 5b61d88..6e11f32 100644
--- a/src/chttpd/test/eunit/chttpd_dbs_info_test.erl
+++ b/src/chttpd/test/eunit/chttpd_dbs_info_test.erl
@@ -57,7 +57,7 @@ dbs_info_test_() ->
                 foreach,
                 fun setup/0, fun teardown/1,
                 [
-                    fun should_return_error_for_get_db_info/1,
+                    fun should_return_for_get_db_info/1,
                     fun should_return_dbs_info_for_single_db/1,
                     fun should_return_dbs_info_for_multiple_dbs/1,
                     fun should_return_error_for_exceeded_keys/1,
@@ -69,15 +69,14 @@ dbs_info_test_() ->
     }.
 
 
-should_return_error_for_get_db_info(Url) ->
+should_return_for_get_db_info(Url) ->
     ?_test(begin
         {ok, Code, _, ResultBody} = test_request:get(Url ++ "/_dbs_info?"
-            ++ "keys=[\"db1\"]", [?CONTENT_JSON, ?AUTH]),
-        {Body} = jiffy:decode(ResultBody),
+            ++ "start_key=\"db1\"&end_key=\"db1\"", [?CONTENT_JSON, ?AUTH]),
+        Body = jiffy:decode(ResultBody, [return_maps]),
         [
-            ?assertEqual(<<"method_not_allowed">>,
-                couch_util:get_value(<<"error">>, Body)),
-            ?assertEqual(405, Code)
+            ?assertEqual(200, Code),
+            ?assertMatch([#{<<"db_name">> := <<"db1">>}], Body)
         ]
     end).
 
diff --git a/src/chttpd/test/eunit/chttpd_open_revs_error_test.erl b/src/chttpd/test/eunit/chttpd_open_revs_error_test.erl
index d53d370..b34d489 100644
--- a/src/chttpd/test/eunit/chttpd_open_revs_error_test.erl
+++ b/src/chttpd/test/eunit/chttpd_open_revs_error_test.erl
@@ -50,7 +50,7 @@ create_doc(Url, Id) ->
 delete_db(Url) ->
     {ok, 200, _, _} = test_request:delete(Url, [?AUTH]).
 
-open_revs_error_test_() ->
+open_revs_error_test_disabled() ->
     {
         "open revs error tests",
         {
diff --git a/src/chttpd/test/eunit/chttpd_purge_tests.erl b/src/chttpd/test/eunit/chttpd_purge_tests.erl
index ab43568..3d16b76 100644
--- a/src/chttpd/test/eunit/chttpd_purge_tests.erl
+++ b/src/chttpd/test/eunit/chttpd_purge_tests.erl
@@ -62,7 +62,7 @@ delete_db(Url) ->
     {ok, 200, _, _} = test_request:delete(Url, [?AUTH]).
 
 
-purge_test_() ->
+purge_test_disabled() ->
     {
         "chttpd db tests",
         {
diff --git a/src/chttpd/test/eunit/chttpd_security_tests.erl b/src/chttpd/test/eunit/chttpd_security_tests.erl
index 0bea9db..9cc70a8 100644
--- a/src/chttpd/test/eunit/chttpd_security_tests.erl
+++ b/src/chttpd/test/eunit/chttpd_security_tests.erl
@@ -38,14 +38,13 @@ setup() ->
     ok = config:set("admins", ?USER, ?b2l(Hashed), Persist),
     UserDb = ?tempdb(),
     TmpDb = ?tempdb(),
-    ok = config:set("chttpd_auth", "authentication_db", ?b2l(UserDb), Persist),
-
     Addr = config:get("chttpd", "bind_address", "127.0.0.1"),
     Port = mochiweb_socket_server:get(chttpd, port),
     BaseUrl = lists:concat(["http://", Addr, ":", Port, "/"]),
-    Url = lists:concat([BaseUrl, ?b2l(TmpDb)]),
     UsersUrl = lists:concat([BaseUrl, ?b2l(UserDb)]),
     create_db(UsersUrl),
+    ok = config:set("chttpd_auth", "authentication_db", ?b2l(UserDb), Persist),
+    Url = lists:concat([BaseUrl, ?b2l(TmpDb)]),
     create_db(Url),
     create_design_doc(Url),
     create_user(UsersUrl,?TEST_MEMBER,?TEST_MEMBER_PASS,[<<?TEST_MEMBER>>]),
@@ -56,8 +55,10 @@ setup() ->
 teardown([Url,UsersUrl]) ->
     delete_db(Url),
     delete_db(UsersUrl),
+    ok = config:delete("chttpd_auth", "authentication_db", _Persist=false),
     ok = config:delete("admins", ?USER, _Persist=false).
 
+
 create_db(Url) ->
     {ok, Status, _, _} = test_request:put(Url, [?CONTENT_JSON, ?AUTH], "{}"),
     ?assert(Status =:= 201 orelse Status =:= 202).
@@ -236,14 +237,12 @@ should_disallow_anonymous_db_view_cleanup([Url,_UsersUrl]) ->
     ?_assertEqual(<<"unauthorized">>, ErrType).
 
 should_allow_admin_purge([Url,_UsersUrl]) ->
-    ?_assertEqual(null,
+    ?_assertEqual(501,
         begin
             IdsRevs = "{}",
-            {ok, _, _, ResultBody} = test_request:post(Url ++ "/_purge",
+            {ok, Code, _, _} = test_request:post(Url ++ "/_purge",
                 [?CONTENT_JSON, ?AUTH], IdsRevs),
-            ResultJson = ?JSON_DECODE(ResultBody),
-            {InnerJson} = ResultJson,
-            couch_util:get_value(<<"purge_seq">>, InnerJson, undefined)
+            Code
         end).
 
 should_disallow_anonymous_purge([Url,_UsersUrl]) ->
@@ -263,13 +262,11 @@ should_disallow_db_member_purge([Url,_UsersUrl]) ->
     ?_assertEqual(<<"unauthorized">>,ErrType).
 
 should_allow_admin_purged_infos_limit([Url,_UsersUrl]) ->
-    ?_assertEqual(true,
+    ?_assertEqual(501,
         begin
-            {ok, _, _, ResultBody} = test_request:put(Url
+            {ok, Code, _, _} = test_request:put(Url
                 ++ "/_purged_infos_limit/", [?CONTENT_JSON, ?AUTH], "2"),
-            ResultJson = ?JSON_DECODE(ResultBody),
-            {InnerJson} = ResultJson,
-            couch_util:get_value(<<"ok">>, InnerJson, undefined)
+            Code
         end).
 
 should_disallow_anonymous_purged_infos_limit([Url,_UsersUrl]) ->
@@ -337,13 +334,11 @@ should_return_error_for_sec_obj_with_incorrect_roles_and_names(
     Body = jiffy:encode({SecurityProperties}),
     {ok, Status, _, RespBody} = test_request:put(SecurityUrl,
         [?CONTENT_JSON, ?AUTH], Body),
-    ResultJson = ?JSON_DECODE(RespBody),
+    ResultJson = couch_util:json_decode(RespBody, [return_maps]),
+    ExpectReason = <<"names must be a JSON list of strings">>,
     [
         ?_assertEqual(500, Status),
-        ?_assertEqual({[
-            {<<"error">>,<<"error">>},
-            {<<"reason">>,<<"no_majority">>}
-        ]}, ResultJson)
+        ?_assertMatch(#{<<"reason">> := ExpectReason}, ResultJson)
     ].
 
 should_return_error_for_sec_obj_with_incorrect_roles([Url,_UsersUrl]) ->
@@ -356,13 +351,11 @@ should_return_error_for_sec_obj_with_incorrect_roles([Url,_UsersUrl]) ->
     Body = jiffy:encode({SecurityProperties}),
     {ok, Status, _, RespBody} = test_request:put(SecurityUrl,
         [?CONTENT_JSON, ?AUTH], Body),
-    ResultJson = ?JSON_DECODE(RespBody),
+    ResultJson = couch_util:json_decode(RespBody, [return_maps]),
+    ExpectReason = <<"roles must be a JSON list of strings">>,
     [
         ?_assertEqual(500, Status),
-        ?_assertEqual({[
-            {<<"error">>,<<"error">>},
-            {<<"reason">>,<<"no_majority">>}
-        ]}, ResultJson)
+        ?_assertMatch(#{<<"reason">> := ExpectReason}, ResultJson)
     ].
 
 should_return_error_for_sec_obj_with_incorrect_names([Url,_UsersUrl]) ->
@@ -375,13 +368,11 @@ should_return_error_for_sec_obj_with_incorrect_names([Url,_UsersUrl]) ->
     Body = jiffy:encode({SecurityProperties}),
     {ok, Status, _, RespBody} = test_request:put(SecurityUrl,
         [?CONTENT_JSON, ?AUTH], Body),
-    ResultJson = ?JSON_DECODE(RespBody),
+    ResultJson = couch_util:json_decode(RespBody, [return_maps]),
+    ExpectReason = <<"names must be a JSON list of strings">>,
     [
         ?_assertEqual(500, Status),
-        ?_assertEqual({[
-            {<<"error">>,<<"error">>},
-            {<<"reason">>,<<"no_majority">>}
-        ]}, ResultJson)
+        ?_assertMatch(#{<<"reason">> := ExpectReason}, ResultJson)
     ].
 
 should_return_error_for_sec_obj_in_user_db([_,_UsersUrl]) ->
diff --git a/src/chttpd/test/eunit/chttpd_view_test.erl b/src/chttpd/test/eunit/chttpd_view_test.erl
index 4c224bb..1744f97 100644
--- a/src/chttpd/test/eunit/chttpd_view_test.erl
+++ b/src/chttpd/test/eunit/chttpd_view_test.erl
@@ -99,7 +99,7 @@ should_succeed_on_view_with_queries_limit_skip(Url) ->
         {ResultJson} = ?JSON_DECODE(RespBody),
         ResultJsonBody = couch_util:get_value(<<"results">>, ResultJson),
         {InnerJson} = lists:nth(1, ResultJsonBody),
-        ?assertEqual(2, couch_util:get_value(<<"offset">>, InnerJson)),
+        ?assertEqual(null, couch_util:get_value(<<"offset">>, InnerJson)),
         ?assertEqual(5, length(couch_util:get_value(<<"rows">>, InnerJson)))
     end)}.
 
@@ -119,6 +119,6 @@ should_succeed_on_view_with_multiple_queries(Url) ->
         {InnerJson1} = lists:nth(1, ResultJsonBody),
         ?assertEqual(2, length(couch_util:get_value(<<"rows">>, InnerJson1))),
         {InnerJson2} = lists:nth(2, ResultJsonBody),
-        ?assertEqual(2, couch_util:get_value(<<"offset">>, InnerJson2)),
+        ?assertEqual(null, couch_util:get_value(<<"offset">>, InnerJson2)),
         ?assertEqual(5, length(couch_util:get_value(<<"rows">>, InnerJson2)))
     end)}.
diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl
index e1d726d..8a7b218 100644
--- a/src/couch/src/couch_db.erl
+++ b/src/couch/src/couch_db.erl
@@ -212,6 +212,8 @@ is_db(_) ->
 is_system_db(#db{options = Options}) ->
     lists:member(sys_db, Options).
 
+is_clustered(#{}) ->
+    true;
 is_clustered(#db{main_pid = nil}) ->
     true;
 is_clustered(#db{}) ->