summaryrefslogtreecommitdiff
path: root/apps/couch/test
diff options
context:
space:
mode:
authorBrad Anderson <brad@cloudant.com>2010-08-19 17:51:06 -0400
committerBrad Anderson <brad@cloudant.com>2010-08-19 17:51:06 -0400
commit1ac66234d0e1481b32701503be5f2da28c81fd8b (patch)
treeb8c9b1f71b0c7bf400a75de33e1aba9b927ec0dc /apps/couch/test
parent8920ea6ae399c651ccd51239d7fb7358d9d44f97 (diff)
Cloudant changes to etap tests
Diffstat (limited to 'apps/couch/test')
-rw-r--r--apps/couch/test/etap/002-icu-driver.t2
-rwxr-xr-xapps/couch/test/etap/020-btree-basics.t1
-rwxr-xr-xapps/couch/test/etap/021-btree-reductions.t3
-rwxr-xr-xapps/couch/test/etap/030-doc-from-json.t5
-rwxr-xr-xapps/couch/test/etap/031-doc-to-json.t14
-rwxr-xr-xapps/couch/test/etap/041-uuid-gen.t24
-rwxr-xr-xapps/couch/test/etap/050-stream.t3
-rwxr-xr-xapps/couch/test/etap/070-couch-db.t75
-rw-r--r--apps/couch/test/etap/080-config-get-set.ini8
-rwxr-xr-xapps/couch/test/etap/080-config-get-set.t3
-rw-r--r--apps/couch/test/etap/081-config-default.ini6
-rwxr-xr-xapps/couch/test/etap/081-config-override.t7
-rw-r--r--apps/couch/test/etap/082-config-default.ini6
-rwxr-xr-xapps/couch/test/etap/082-config-register.t3
-rwxr-xr-xapps/couch/test/etap/083-config-no-files.t3
-rwxr-xr-xapps/couch/test/etap/110-replication-httpc.t134
-rwxr-xr-xapps/couch/test/etap/111-replication-changes-feed.t254
-rwxr-xr-xapps/couch/test/etap/112-replication-missing-revs.t195
-rwxr-xr-xapps/couch/test/etap/113-replication-attachment-comp.t273
-rwxr-xr-xapps/couch/test/etap/120-stats-collect.inactive (renamed from apps/couch/test/etap/120-stats-collect.t)0
-rwxr-xr-xapps/couch/test/etap/121-stats-aggregates.inactive (renamed from apps/couch/test/etap/121-stats-aggregates.t)0
-rwxr-xr-xapps/couch/test/etap/130-attachments-md5.t252
-rwxr-xr-xapps/couch/test/etap/140-attachment-comp.t711
-rwxr-xr-xapps/couch/test/etap/150-invalid-view-seq.t192
-rwxr-xr-xapps/couch/test/etap/160-vhosts.t131
25 files changed, 51 insertions, 2254 deletions
diff --git a/apps/couch/test/etap/002-icu-driver.t b/apps/couch/test/etap/002-icu-driver.t
index d70f3303..4167aeeb 100644
--- a/apps/couch/test/etap/002-icu-driver.t
+++ b/apps/couch/test/etap/002-icu-driver.t
@@ -16,7 +16,7 @@ main(_) ->
test_util:init_code_path(),
etap:plan(3),
etap:is(
- couch_util:start_driver("src/couchdb/priv/.libs"),
+ erl_ddll:load(code:priv_dir(couch), "couch_icu_driver"),
ok,
"Started couch_icu_driver."
),
diff --git a/apps/couch/test/etap/020-btree-basics.t b/apps/couch/test/etap/020-btree-basics.t
index 18c4a836..996d240a 100755
--- a/apps/couch/test/etap/020-btree-basics.t
+++ b/apps/couch/test/etap/020-btree-basics.t
@@ -21,6 +21,7 @@ rows() -> 250.
main(_) ->
test_util:init_code_path(),
+ couch_config:start_link([]),
etap:plan(48),
case (catch test()) of
ok ->
diff --git a/apps/couch/test/etap/021-btree-reductions.t b/apps/couch/test/etap/021-btree-reductions.t
index 3e19c767..30ffd530 100755
--- a/apps/couch/test/etap/021-btree-reductions.t
+++ b/apps/couch/test/etap/021-btree-reductions.t
@@ -14,11 +14,12 @@
% License for the specific language governing permissions and limitations under
% the License.
-filename() -> "./test/etap/temp.021".
+filename() -> "./apps/couch/test/etap/temp.021".
rows() -> 1000.
main(_) ->
test_util:init_code_path(),
+ couch_config:start_link([]),
etap:plan(8),
case (catch test()) of
ok ->
diff --git a/apps/couch/test/etap/030-doc-from-json.t b/apps/couch/test/etap/030-doc-from-json.t
index c4ef649a..8dd5fa1e 100755
--- a/apps/couch/test/etap/030-doc-from-json.t
+++ b/apps/couch/test/etap/030-doc-from-json.t
@@ -20,9 +20,6 @@
-record(att, {name, type, att_len, disk_len, md5= <<>>, revpos=0, data,
encoding=identity}).
-default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
-
main(_) ->
test_util:init_code_path(),
etap:plan(26),
@@ -36,8 +33,6 @@ main(_) ->
ok.
test() ->
- couch_config:start_link([default_config()]),
- couch_config:set("attachments", "compression_level", "0"),
ok = test_from_json_success(),
ok = test_from_json_errors(),
ok.
diff --git a/apps/couch/test/etap/031-doc-to-json.t b/apps/couch/test/etap/031-doc-to-json.t
index 605a6d00..6f2ae7a2 100755
--- a/apps/couch/test/etap/031-doc-to-json.t
+++ b/apps/couch/test/etap/031-doc-to-json.t
@@ -20,9 +20,6 @@
-record(att, {name, type, att_len, disk_len, md5= <<>>, revpos=0, data,
encoding=identity}).
-default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
-
main(_) ->
test_util:init_code_path(),
etap:plan(12),
@@ -36,8 +33,6 @@ main(_) ->
ok.
test() ->
- couch_config:start_link([default_config()]),
- couch_config:set("attachments", "compression_level", "0"),
ok = test_to_json_success(),
ok.
@@ -118,16 +113,16 @@ test_to_json_success() ->
{
#doc{atts=[
#att{
- name = <<"big.xml">>,
- type = <<"xml/sucks">>,
+ name = <<"big.xml">>,
+ type = <<"xml/sucks">>,
data = fun() -> ok end,
revpos = 1,
att_len = 400,
disk_len = 400
},
#att{
- name = <<"fast.json">>,
- type = <<"json/ftw">>,
+ name = <<"fast.json">>,
+ type = <<"json/ftw">>,
data = <<"{\"so\": \"there!\"}">>,
revpos = 1,
att_len = 16,
@@ -197,4 +192,3 @@ test_to_json_success() ->
etap:is(couch_doc:to_json_obj(Doc, Options), EJson, Mesg)
end, Cases),
ok.
-
diff --git a/apps/couch/test/etap/041-uuid-gen.t b/apps/couch/test/etap/041-uuid-gen.t
index 1e6aa9ee..84c93a44 100755
--- a/apps/couch/test/etap/041-uuid-gen.t
+++ b/apps/couch/test/etap/041-uuid-gen.t
@@ -13,17 +13,15 @@
% License for the specific language governing permissions and limitations under
% the License.
-default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
-
seq_alg_config() ->
- test_util:source_file("test/etap/041-uuid-gen-seq.ini").
+ filename:join([code:lib_dir(couch, test), "etap/041-uuid-gen-seq.ini"]).
utc_alg_config() ->
- test_util:source_file("test/etap/041-uuid-gen-utc.ini").
+ filename:join([code:lib_dir(couch, test), "etap/041-uuid-gen-utc.ini"]).
% Run tests and wait for the gen_servers to shutdown
run_test(IniFiles, Test) ->
+ couch_config_event:start_link(),
{ok, Pid} = couch_config:start_link(IniFiles),
erlang:monitor(process, Pid),
couch_uuids:start(),
@@ -40,7 +38,7 @@ run_test(IniFiles, Test) ->
main(_) ->
test_util:init_code_path(),
application:start(crypto),
- etap:plan(6),
+ etap:plan(5),
case (catch test()) of
ok ->
@@ -60,9 +58,9 @@ test() ->
"Can generate 10K unique IDs"
)
end,
- run_test([default_config()], TestUnique),
- run_test([default_config(), seq_alg_config()], TestUnique),
- run_test([default_config(), utc_alg_config()], TestUnique),
+ %run_test([default_config()], TestUnique),
+ run_test([seq_alg_config()], TestUnique),
+ run_test([utc_alg_config()], TestUnique),
TestMonotonic = fun () ->
etap:is(
@@ -71,8 +69,8 @@ test() ->
"should produce monotonically increasing ids"
)
end,
- run_test([default_config(), seq_alg_config()], TestMonotonic),
- run_test([default_config(), utc_alg_config()], TestMonotonic),
+ run_test([seq_alg_config()], TestMonotonic),
+ run_test([utc_alg_config()], TestMonotonic),
% Pretty sure that the average of a uniform distribution is the
% midpoint of the range. Thus, to exceed a threshold, we need
@@ -87,14 +85,14 @@ test() ->
UUID = binary_to_list(couch_uuids:new()),
Prefix = element(1, lists:split(26, UUID)),
N = gen_until_pref_change(Prefix,0),
- etap:diag("N is: ~p~n",[N]),
+ etap:diag("N is: ~p~n",[N]),
etap:is(
N >= 5000 andalso N =< 11000,
true,
"should roll over every so often."
)
end,
- run_test([default_config(), seq_alg_config()], TestRollOver).
+ run_test([seq_alg_config()], TestRollOver).
test_unique(0, _) ->
true;
diff --git a/apps/couch/test/etap/050-stream.t b/apps/couch/test/etap/050-stream.t
index 545dd524..03949690 100755
--- a/apps/couch/test/etap/050-stream.t
+++ b/apps/couch/test/etap/050-stream.t
@@ -30,7 +30,8 @@ read_all(Fd, PosList) ->
iolist_to_binary(Data).
test() ->
- {ok, Fd} = couch_file:open("test/etap/temp.050", [create,overwrite]),
+ {ok, Fd} = couch_file:open("apps/couch/test/etap/temp.050",
+ [create,overwrite]),
{ok, Stream} = couch_stream:open(Fd),
etap:is(ok, couch_stream:write(Stream, <<"food">>),
diff --git a/apps/couch/test/etap/070-couch-db.t b/apps/couch/test/etap/070-couch-db.t
deleted file mode 100755
index 4b14aba6..00000000
--- a/apps/couch/test/etap/070-couch-db.t
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
-main(_) ->
- test_util:init_code_path(),
-
- etap:plan(4),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail(Other)
- end,
- ok.
-
-test() ->
-
- couch_server_sup:start_link(
- ["etc/couchdb/default_dev.ini", "etc/couchdb/local_dev.ini"]
- ),
-
- couch_db:create(<<"etap-test-db">>, []),
- {ok, AllDbs} = couch_server:all_databases(),
- etap:ok(lists:member(<<"etap-test-db">>, AllDbs), "Database was created."),
-
- couch_server:delete(<<"etap-test-db">>, []),
- {ok, AllDbs2} = couch_server:all_databases(),
- etap:ok(not lists:member(<<"etap-test-db">>, AllDbs2),
- "Database was deleted."),
-
- gen_server:call(couch_server, {set_max_dbs_open, 3}),
- MkDbName = fun(Int) -> list_to_binary("lru-" ++ integer_to_list(Int)) end,
-
- lists:foreach(fun(Int) ->
- {ok, TestDbs} = couch_server:all_databases(),
- ok = case lists:member(MkDbName(Int), TestDbs) of
- true -> couch_server:delete(MkDbName(Int), []);
- _ -> ok
- end,
- {ok, Db} = couch_db:create(MkDbName(Int), []),
- ok = couch_db:close(Db)
- end, lists:seq(1, 6)),
-
- {ok, AllDbs3} = couch_server:all_databases(),
- NumCreated = lists:foldl(fun(Int, Acc) ->
- true = lists:member(MkDbName(Int), AllDbs3),
- Acc+1
- end, 0, lists:seq(1, 6)),
- etap:is(6, NumCreated, "Created all databases."),
-
- lists:foreach(fun(Int) ->
- ok = couch_server:delete(MkDbName(Int), [])
- end, lists:seq(1, 6)),
-
- {ok, AllDbs4} = couch_server:all_databases(),
- NumDeleted = lists:foldl(fun(Int, Acc) ->
- false = lists:member(MkDbName(Int), AllDbs4),
- Acc+1
- end, 0, lists:seq(1, 6)),
- etap:is(6, NumDeleted, "Deleted all databases."),
-
- ok.
diff --git a/apps/couch/test/etap/080-config-get-set.ini b/apps/couch/test/etap/080-config-get-set.ini
new file mode 100644
index 00000000..e72e08db
--- /dev/null
+++ b/apps/couch/test/etap/080-config-get-set.ini
@@ -0,0 +1,8 @@
+[daemons]
+something=somevalue
+
+[httpd_design_handlers]
+_view = {couch_httpd_view, handle_view_req}
+
+[httpd]
+port = 5984
diff --git a/apps/couch/test/etap/080-config-get-set.t b/apps/couch/test/etap/080-config-get-set.t
index a4a8577a..c457c7f0 100755
--- a/apps/couch/test/etap/080-config-get-set.t
+++ b/apps/couch/test/etap/080-config-get-set.t
@@ -14,7 +14,7 @@
% the License.
default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
+ filename:join([code:lib_dir(couch, test), "etap/080-config-get-set.ini"]).
main(_) ->
test_util:init_code_path(),
@@ -30,6 +30,7 @@ main(_) ->
test() ->
% start couch_config with default
+ couch_config_event:start_link(),
couch_config:start_link([default_config()]),
diff --git a/apps/couch/test/etap/081-config-default.ini b/apps/couch/test/etap/081-config-default.ini
new file mode 100644
index 00000000..abdf79bc
--- /dev/null
+++ b/apps/couch/test/etap/081-config-default.ini
@@ -0,0 +1,6 @@
+[couchdb]
+max_dbs_open=100
+
+[httpd]
+port=5984
+bind_address = 127.0.0.1
diff --git a/apps/couch/test/etap/081-config-override.t b/apps/couch/test/etap/081-config-override.t
index 01f8b4c2..16a6b6f6 100755
--- a/apps/couch/test/etap/081-config-override.t
+++ b/apps/couch/test/etap/081-config-override.t
@@ -14,19 +14,20 @@
% the License.
default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
+ filename:join([code:lib_dir(couch, test),"etap/081-config-default.ini"]).
local_config_1() ->
- test_util:source_file("test/etap/081-config-override.1.ini").
+ filename:join([code:lib_dir(couch, test),"etap/081-config-override.1.ini"]).
local_config_2() ->
- test_util:source_file("test/etap/081-config-override.2.ini").
+ filename:join([code:lib_dir(couch, test),"etap/081-config-override.2.ini"]).
local_config_write() ->
test_util:build_file("test/etap/temp.081").
% Run tests and wait for the config gen_server to shutdown.
run_tests(IniFiles, Tests) ->
+ couch_config_event:start_link(),
{ok, Pid} = couch_config:start_link(IniFiles),
erlang:monitor(process, Pid),
Tests(),
diff --git a/apps/couch/test/etap/082-config-default.ini b/apps/couch/test/etap/082-config-default.ini
new file mode 100644
index 00000000..e46f158f
--- /dev/null
+++ b/apps/couch/test/etap/082-config-default.ini
@@ -0,0 +1,6 @@
+[couchdb]
+max_dbs_open=500
+
+[httpd]
+port=5984
+bind_address = 127.0.0.1
diff --git a/apps/couch/test/etap/082-config-register.t b/apps/couch/test/etap/082-config-register.t
index 191ba8f8..36b48cf8 100755
--- a/apps/couch/test/etap/082-config-register.t
+++ b/apps/couch/test/etap/082-config-register.t
@@ -14,7 +14,7 @@
% the License.
default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
+ filename:join([code:lib_dir(couch, test), "etap/082-config-default.ini"]).
main(_) ->
test_util:init_code_path(),
@@ -29,6 +29,7 @@ main(_) ->
ok.
test() ->
+ couch_config_event:start_link(),
couch_config:start_link([default_config()]),
etap:is(
diff --git a/apps/couch/test/etap/083-config-no-files.t b/apps/couch/test/etap/083-config-no-files.t
index 675feb59..edf8315d 100755
--- a/apps/couch/test/etap/083-config-no-files.t
+++ b/apps/couch/test/etap/083-config-no-files.t
@@ -14,7 +14,7 @@
% the License.
default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
+ "rel/overlay/etc/default.ini".
main(_) ->
test_util:init_code_path(),
@@ -29,6 +29,7 @@ main(_) ->
ok.
test() ->
+ couch_config_event:start_link(),
couch_config:start_link([]),
etap:fun_is(
diff --git a/apps/couch/test/etap/110-replication-httpc.t b/apps/couch/test/etap/110-replication-httpc.t
deleted file mode 100755
index b534b648..00000000
--- a/apps/couch/test/etap/110-replication-httpc.t
+++ /dev/null
@@ -1,134 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
-%% XXX: Figure out how to -include("couch_rep.hrl")
--record(http_db, {
- url,
- auth = [],
- resource = "",
- headers = [
- {"User-Agent", "CouchDB/"++couch:version()},
- {"Accept", "application/json"},
- {"Accept-Encoding", "gzip"}
- ],
- qs = [],
- method = get,
- body = nil,
- options = [
- {response_format,binary},
- {inactivity_timeout, 30000}
- ],
- retries = 10,
- pause = 1,
- conn = nil
-}).
-
-server() -> "http://127.0.0.1:5984/".
-dbname() -> "etap-test-db".
-
-config_files() ->
- lists:map(fun test_util:build_file/1, [
- "etc/couchdb/default_dev.ini",
- "etc/couchdb/local_dev.ini"
- ]).
-
-main(_) ->
- test_util:init_code_path(),
-
- etap:plan(6),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail(Other)
- end,
- ok.
-
-test() ->
- couch_server_sup:start_link(config_files()),
- ibrowse:start(),
- crypto:start(),
-
- couch_server:delete(list_to_binary(dbname()), []),
- {ok, Db} = couch_db:create(list_to_binary(dbname()), []),
-
- test_welcome(),
- test_binary_url(),
- test_put(),
- test_qs(),
- test_db_exists(),
-
- couch_db:close(Db),
- couch_server:delete(list_to_binary(dbname()), []),
- ok.
-
-test_welcome() ->
- WelcomeReq = #http_db{url=server()},
- Expect = {[
- {<<"couchdb">>, <<"Welcome">>},
- {<<"version">>, list_to_binary(couch:version())}
- ]},
- etap:is(
- couch_rep_httpc:request(WelcomeReq),
- Expect,
- "welcome request with url-as-list"
- ).
-
-test_binary_url() ->
- Req = #http_db{url=list_to_binary(server())},
- Expect = {[
- {<<"couchdb">>, <<"Welcome">>},
- {<<"version">>, list_to_binary(couch:version())}
- ]},
- etap:is(
- couch_rep_httpc:request(Req),
- Expect,
- "welcome request with url-as-binary"
- ).
-
-test_put() ->
- Req = #http_db{
- url = server() ++ dbname() ++ "/",
- resource = "test_put",
- body = {[{<<"foo">>, <<"bar">>}]},
- method = put
- },
- {Resp} = couch_rep_httpc:request(Req),
- etap:ok(couch_util:get_value(<<"ok">>, Resp), "ok:true on upload"),
- etap:is(<<"test_put">>, couch_util:get_value(<<"id">>, Resp), "id is correct").
-
-test_qs() ->
- Req = #http_db{
- url = server() ++ dbname() ++ "/",
- resource = "foo",
- qs = [
- {bar, true},
- {baz, 1.03},
- {bif, mochijson2:encode(<<"1-23456">>)}
- ]
- },
- Expect = server() ++ dbname() ++ "/foo?bar=true&baz=1.03&bif=\"1-23456\"",
- etap:is(
- couch_rep_httpc:full_url(Req),
- Expect,
- "query-string proplist encoding ok"
- ).
-
-test_db_exists() ->
- Req1 = #http_db{url=server() ++ dbname() ++ "/"},
- Req2 = #http_db{url=server() ++ dbname() ++ "_foo/"},
- etap:is(couch_rep_httpc:db_exists(Req1), Req1, "db_exists true check").
- % etap:is(couch_rep_httpc:db_exists(Req2), false, "db_exists false check").
diff --git a/apps/couch/test/etap/111-replication-changes-feed.t b/apps/couch/test/etap/111-replication-changes-feed.t
deleted file mode 100755
index bca12bc7..00000000
--- a/apps/couch/test/etap/111-replication-changes-feed.t
+++ /dev/null
@@ -1,254 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
-%% XXX: Figure out how to -include("couch_db.hrl")
--record(doc, {id= <<"">>, revs={0, []}, body={[]},
- attachments=[], deleted=false, meta=[]}).
-
--record(http_db, {
- url,
- auth = [],
- resource = "",
- headers = [
- {"User-Agent", "CouchDB/"++couch:version()},
- {"Accept", "application/json"},
- {"Accept-Encoding", "gzip"}
- ],
- qs = [],
- method = get,
- body = nil,
- options = [
- {response_format,binary},
- {inactivity_timeout, 30000}
- ],
- retries = 10,
- pause = 1,
- conn = nil
-}).
-
-config_files() ->
- lists:map(fun test_util:build_file/1, [
- "etc/couchdb/default_dev.ini",
- "etc/couchdb/local_dev.ini"
- ]).
-
-main(_) ->
- test_util:init_code_path(),
-
- etap:plan(13),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail(Other)
- end,
- ok.
-
-test() ->
- couch_server_sup:start_link(config_files()),
- ibrowse:start(),
- crypto:start(),
-
- couch_server:delete(<<"etap-test-db">>, []),
- {ok, Db1} = couch_db:create(<<"etap-test-db">>, []),
- test_all(local),
- couch_db:close(Db1),
- couch_server:delete(<<"etap-test-db">>, []),
-
- couch_server:delete(<<"etap-test-db">>, []),
- {ok, Db2} = couch_db:create(<<"etap-test-db">>, []),
- test_all(remote),
- test_remote_only(),
- couch_db:close(Db2),
- couch_server:delete(<<"etap-test-db">>, []),
-
- ok.
-
-test_all(Type) ->
- test_unchanged_db(Type),
- test_simple_change(Type),
- test_since_parameter(Type),
- test_continuous_parameter(Type),
- test_conflicts(Type),
- test_deleted_conflicts(Type).
-
-test_remote_only() ->
- test_chunk_reassembly(remote).
-
-test_unchanged_db(Type) ->
- {ok, Pid} = start_changes_feed(Type, 0, false),
- etap:is(
- couch_rep_changes_feed:next(Pid),
- complete,
- io_lib:format(
- "(~p) changes feed for unchanged DB is automatically complete",
- [Type])
- ).
-
-test_simple_change(Type) ->
- Expect = generate_change(),
- {ok, Pid} = start_changes_feed(Type, 0, false),
- etap:is(
- {couch_rep_changes_feed:next(Pid), couch_rep_changes_feed:next(Pid)},
- {[Expect], complete},
- io_lib:format("(~p) change one document, get one row", [Type])
- ).
-
-test_since_parameter(Type) ->
- {ok, Pid} = start_changes_feed(Type, get_update_seq(), false),
- etap:is(
- couch_rep_changes_feed:next(Pid),
- complete,
- io_lib:format(
- "(~p) since query-string parameter allows us to skip changes",
- [Type])
- ).
-
-test_continuous_parameter(Type) ->
- {ok, Pid} = start_changes_feed(Type, get_update_seq(), true),
-
- % make the changes_feed request before the next update
- Self = self(),
- spawn(fun() ->
- Change = couch_rep_changes_feed:next(Pid),
- Self ! {actual, Change}
- end),
-
- Expect = generate_change(),
- etap:is(
- receive {actual, Actual} -> Actual end,
- [Expect],
- io_lib:format(
- "(~p) feed=continuous query-string parameter picks up new changes",
- [Type])
- ),
-
- ok = couch_rep_changes_feed:stop(Pid).
-
-test_conflicts(Type) ->
- Since = get_update_seq(),
- Expect = generate_conflict(),
- {ok, Pid} = start_changes_feed(Type, Since, false),
- etap:is(
- {couch_rep_changes_feed:next(Pid), couch_rep_changes_feed:next(Pid)},
- {[Expect], complete},
- io_lib:format("(~p) conflict revisions show up in feed", [Type])
- ).
-
-test_deleted_conflicts(Type) ->
- Since = get_update_seq(),
- {ExpectProps} = generate_conflict(),
-
- %% delete the conflict revision
- Id = couch_util:get_value(<<"id">>, ExpectProps),
- [Win, {[{<<"rev">>, Lose}]}] = couch_util:get_value(<<"changes">>, ExpectProps),
- Doc = couch_doc:from_json_obj({[
- {<<"_id">>, Id},
- {<<"_rev">>, Lose},
- {<<"_deleted">>, true}
- ]}),
- Db = get_db(),
- {ok, Rev} = couch_db:update_doc(Db, Doc, [full_commit]),
- couch_db:close(Db),
-
- Expect = {[
- {<<"seq">>, get_update_seq()},
- {<<"id">>, Id},
- {<<"changes">>, [Win, {[{<<"rev">>, couch_doc:rev_to_str(Rev)}]}]}
- ]},
-
- {ok, Pid} = start_changes_feed(Type, Since, false),
- etap:is(
- {couch_rep_changes_feed:next(Pid), couch_rep_changes_feed:next(Pid)},
- {[Expect], complete},
- io_lib:format("(~p) deleted conflict revisions show up in feed", [Type])
- ).
-
-test_chunk_reassembly(Type) ->
- Since = get_update_seq(),
- Expect = [generate_change() || _I <- lists:seq(1,30)],
- {ok, Pid} = start_changes_feed(Type, Since, false),
- etap:is(
- get_all_changes(Pid, []),
- Expect,
- io_lib:format("(~p) reassembles chunks split across TCP frames",
- [Type])
- ).
-
-get_all_changes(Pid, Acc) ->
- case couch_rep_changes_feed:next(Pid) of
- complete ->
- lists:flatten(lists:reverse(Acc));
- Else ->
- get_all_changes(Pid, [Else|Acc])
- end.
-
-generate_change() ->
- generate_change(couch_uuids:random()).
-
-generate_change(Id) ->
- generate_change(Id, {[]}).
-
-generate_change(Id, EJson) ->
- Doc = couch_doc:from_json_obj(EJson),
- Db = get_db(),
- {ok, Rev} = couch_db:update_doc(Db, Doc#doc{id = Id}, [full_commit]),
- couch_db:close(Db),
- {[
- {<<"seq">>, get_update_seq()},
- {<<"id">>, Id},
- {<<"changes">>, [{[{<<"rev">>, couch_doc:rev_to_str(Rev)}]}]}
- ]}.
-
-generate_conflict() ->
- Id = couch_uuids:random(),
- Db = get_db(),
- Doc1 = (couch_doc:from_json_obj({[<<"foo">>, <<"bar">>]}))#doc{id = Id},
- Doc2 = (couch_doc:from_json_obj({[<<"foo">>, <<"baz">>]}))#doc{id = Id},
- {ok, Rev1} = couch_db:update_doc(Db, Doc1, [full_commit]),
- {ok, Rev2} = couch_db:update_doc(Db, Doc2, [full_commit, all_or_nothing]),
-
- %% relies on undocumented CouchDB conflict winner algo and revision sorting!
- RevList = [{[{<<"rev">>, couch_doc:rev_to_str(R)}]} || R
- <- lists:sort(fun(A,B) -> B<A end, [Rev1,Rev2])],
- {[
- {<<"seq">>, get_update_seq()},
- {<<"id">>, Id},
- {<<"changes">>, RevList}
- ]}.
-
-get_db() ->
- {ok, Db} = couch_db:open(<<"etap-test-db">>, []),
- Db.
-
-get_dbname(local) ->
- "etap-test-db";
-get_dbname(remote) ->
- "http://127.0.0.1:5984/etap-test-db/".
-
-get_update_seq() ->
- Db = get_db(),
- Seq = couch_db:get_update_seq(Db),
- couch_db:close(Db),
- Seq.
-
-start_changes_feed(local, Since, Continuous) ->
- Props = [{<<"continuous">>, Continuous}],
- couch_rep_changes_feed:start_link(self(), get_db(), Since, Props);
-start_changes_feed(remote, Since, Continuous) ->
- Props = [{<<"continuous">>, Continuous}],
- Db = #http_db{url = get_dbname(remote)},
- couch_rep_changes_feed:start_link(self(), Db, Since, Props).
diff --git a/apps/couch/test/etap/112-replication-missing-revs.t b/apps/couch/test/etap/112-replication-missing-revs.t
deleted file mode 100755
index ea8466f6..00000000
--- a/apps/couch/test/etap/112-replication-missing-revs.t
+++ /dev/null
@@ -1,195 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
-%% XXX: Figure out how to -include("couch_db.hrl")
-
--record(doc, {id= <<"">>, revs={0, []}, body={[]},
- attachments=[], deleted=false, meta=[]}).
-
--record(http_db, {
- url,
- auth = [],
- resource = "",
- headers = [
- {"User-Agent", "CouchDB/"++couch:version()},
- {"Accept", "application/json"},
- {"Accept-Encoding", "gzip"}
- ],
- qs = [],
- method = get,
- body = nil,
- options = [
- {response_format,binary},
- {inactivity_timeout, 30000}
- ],
- retries = 10,
- pause = 1,
- conn = nil
-}).
-
-config_files() ->
- lists:map(fun test_util:build_file/1, [
- "etc/couchdb/default_dev.ini",
- "etc/couchdb/local_dev.ini"
- ]).
-
-main(_) ->
- test_util:init_code_path(),
-
- etap:plan(12),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail(Other)
- end,
- ok.
-
-test() ->
- couch_server_sup:start_link(config_files()),
- ibrowse:start(),
- crypto:start(),
-
- couch_server:delete(<<"etap-test-source">>, []),
- couch_server:delete(<<"etap-test-target">>, []),
-
- Dbs1 = setup(),
- test_all(local, local),
- ok = teardown(Dbs1),
-
- Dbs2 = setup(),
- test_all(local, remote),
- ok = teardown(Dbs2),
-
- Dbs3 = setup(),
- test_all(remote, local),
- ok = teardown(Dbs3),
-
- Dbs4 = setup(),
- test_all(remote, remote),
- ok = teardown(Dbs4),
-
- ok.
-
-test_all(SrcType, TgtType) ->
- test_unchanged_db(SrcType, TgtType),
- test_multiple_changes(SrcType, TgtType),
- test_changes_not_missing(SrcType, TgtType).
-
-test_unchanged_db(SrcType, TgtType) ->
- {ok, Pid1} = start_changes_feed(SrcType, 0, false),
- {ok, Pid2} = start_missing_revs(TgtType, Pid1),
- etap:is(
- couch_rep_missing_revs:next(Pid2),
- complete,
- io_lib:format(
- "(~p, ~p) no missing revs if source is unchanged",
- [SrcType, TgtType])
- ).
-
-test_multiple_changes(SrcType, TgtType) ->
- Expect = {2, [generate_change(), generate_change()]},
- {ok, Pid1} = start_changes_feed(SrcType, 0, false),
- {ok, Pid2} = start_missing_revs(TgtType, Pid1),
- etap:is(
- get_all_missing_revs(Pid2, {0, []}),
- Expect,
- io_lib:format("(~p, ~p) add src docs, get missing tgt revs + high seq",
- [SrcType, TgtType])
- ).
-
-test_changes_not_missing(SrcType, TgtType) ->
- %% put identical changes on source and target
- Id = couch_uuids:random(),
- {Id, _Seq, [Rev]} = Expect = generate_change(Id, {[]}, get_db(source)),
- {Id, _, [Rev]} = generate_change(Id, {[]}, get_db(target)),
-
- %% confirm that this change is not in missing revs feed
- {ok, Pid1} = start_changes_feed(SrcType, 0, false),
- {ok, Pid2} = start_missing_revs(TgtType, Pid1),
- {HighSeq, AllRevs} = get_all_missing_revs(Pid2, {0, []}),
-
- %% etap:none/3 has a bug, so just define it correctly here
- etap:is(
- lists:member(Expect, AllRevs),
- false,
- io_lib:format(
- "(~p, ~p) skip revs that already exist on target",
- [SrcType, TgtType])
- ).
-
-generate_change() ->
- generate_change(couch_uuids:random()).
-
-generate_change(Id) ->
- generate_change(Id, {[]}).
-
-generate_change(Id, EJson) ->
- generate_change(Id, EJson, get_db(source)).
-
-generate_change(Id, EJson, Db) ->
- Doc = couch_doc:from_json_obj(EJson),
- Seq = get_update_seq(),
- {ok, Rev} = couch_db:update_doc(Db, Doc#doc{id = Id}, [full_commit]),
- couch_db:close(Db),
- {Id, Seq+1, [Rev]}.
-
-get_all_missing_revs(Pid, {HighSeq, Revs}) ->
- case couch_rep_missing_revs:next(Pid) of
- complete ->
- {HighSeq, lists:flatten(lists:reverse(Revs))};
- {Seq, More} ->
- get_all_missing_revs(Pid, {Seq, [More|Revs]})
- end.
-
-get_db(source) ->
- {ok, Db} = couch_db:open(<<"etap-test-source">>, []),
- Db;
-get_db(target) ->
- {ok, Db} = couch_db:open(<<"etap-test-target">>, []),
- Db.
-
-get_update_seq() ->
- Db = get_db(source),
- Seq = couch_db:get_update_seq(Db),
- couch_db:close(Db),
- Seq.
-
-setup() ->
- {ok, DbA} = couch_db:create(<<"etap-test-source">>, []),
- {ok, DbB} = couch_db:create(<<"etap-test-target">>, []),
- [DbA, DbB].
-
-teardown([DbA, DbB]) ->
- couch_db:close(DbA),
- couch_db:close(DbB),
- couch_server:delete(<<"etap-test-source">>, []),
- couch_server:delete(<<"etap-test-target">>, []),
- ok.
-
-start_changes_feed(local, Since, Continuous) ->
- Props = [{<<"continuous">>, Continuous}],
- couch_rep_changes_feed:start_link(self(), get_db(source), Since, Props);
-start_changes_feed(remote, Since, Continuous) ->
- Props = [{<<"continuous">>, Continuous}],
- Db = #http_db{url = "http://127.0.0.1:5984/etap-test-source/"},
- couch_rep_changes_feed:start_link(self(), Db, Since, Props).
-
-start_missing_revs(local, Changes) ->
- couch_rep_missing_revs:start_link(self(), get_db(target), Changes, []);
-start_missing_revs(remote, Changes) ->
- Db = #http_db{url = "http://127.0.0.1:5984/etap-test-target/"},
- couch_rep_missing_revs:start_link(self(), Db, Changes, []).
diff --git a/apps/couch/test/etap/113-replication-attachment-comp.t b/apps/couch/test/etap/113-replication-attachment-comp.t
deleted file mode 100755
index 30f602ef..00000000
--- a/apps/couch/test/etap/113-replication-attachment-comp.t
+++ /dev/null
@@ -1,273 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--record(user_ctx, {
- name = null,
- roles = [],
- handler
-}).
-
-default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
-
-test_db_a_name() ->
- <<"couch_test_rep_att_comp_a">>.
-
-test_db_b_name() ->
- <<"couch_test_rep_att_comp_b">>.
-
-main(_) ->
- test_util:init_code_path(),
- etap:plan(30),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail(Other)
- end,
- ok.
-
-test() ->
- couch_server_sup:start_link([default_config()]),
- put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")),
- put(port, couch_config:get("httpd", "port", "5984")),
- application:start(inets),
- ibrowse:start(),
- timer:sleep(1000),
-
- %
- % test pull replication
- %
-
- delete_db(test_db_a_name()),
- delete_db(test_db_b_name()),
- create_db(test_db_a_name()),
- create_db(test_db_b_name()),
-
- % enable compression
- couch_config:set("attachments", "compression_level", "8"),
- couch_config:set("attachments", "compressible_types", "text/*"),
-
- % store doc with text attachment in DB A
- put_text_att(test_db_a_name()),
-
- % disable attachment compression
- couch_config:set("attachments", "compression_level", "0"),
-
- % do pull replication
- do_pull_replication(test_db_a_name(), test_db_b_name()),
-
- % verify that DB B has the attachment stored in compressed form
- check_att_is_compressed(test_db_b_name()),
- check_server_can_decompress_att(test_db_b_name()),
- check_att_stubs(test_db_a_name(), test_db_b_name()),
-
- %
- % test push replication
- %
-
- delete_db(test_db_a_name()),
- delete_db(test_db_b_name()),
- create_db(test_db_a_name()),
- create_db(test_db_b_name()),
-
- % enable compression
- couch_config:set("attachments", "compression_level", "8"),
- couch_config:set("attachments", "compressible_types", "text/*"),
-
- % store doc with text attachment in DB A
- put_text_att(test_db_a_name()),
-
- % disable attachment compression
- couch_config:set("attachments", "compression_level", "0"),
-
- % do push replication
- do_push_replication(test_db_a_name(), test_db_b_name()),
-
- % verify that DB B has the attachment stored in compressed form
- check_att_is_compressed(test_db_b_name()),
- check_server_can_decompress_att(test_db_b_name()),
- check_att_stubs(test_db_a_name(), test_db_b_name()),
-
- timer:sleep(3000), % to avoid mochiweb socket closed exceptions
- delete_db(test_db_a_name()),
- delete_db(test_db_b_name()),
- couch_server_sup:stop(),
- ok.
-
-put_text_att(DbName) ->
- {ok, {{_, Code, _}, _Headers, _Body}} = http:request(
- put,
- {db_url(DbName) ++ "/testdoc1/readme.txt", [],
- "text/plain", test_text_data()},
- [],
- [{sync, true}]),
- etap:is(Code, 201, "Created text attachment"),
- ok.
-
-do_pull_replication(SourceDbName, TargetDbName) ->
- RepObj = {[
- {<<"source">>, list_to_binary(db_url(SourceDbName))},
- {<<"target">>, TargetDbName}
- ]},
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- post,
- {rep_url(), [],
- "application/json", list_to_binary(couch_util:json_encode(RepObj))},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "Pull replication successfully triggered"),
- Json = couch_util:json_decode(Body),
- RepOk = couch_util:get_nested_json_value(Json, [<<"ok">>]),
- etap:is(RepOk, true, "Pull replication completed with success"),
- ok.
-
-do_push_replication(SourceDbName, TargetDbName) ->
- RepObj = {[
- {<<"source">>, SourceDbName},
- {<<"target">>, list_to_binary(db_url(TargetDbName))}
- ]},
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- post,
- {rep_url(), [],
- "application/json", list_to_binary(couch_util:json_encode(RepObj))},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "Push replication successfully triggered"),
- Json = couch_util:json_decode(Body),
- RepOk = couch_util:get_nested_json_value(Json, [<<"ok">>]),
- etap:is(RepOk, true, "Push replication completed with success"),
- ok.
-
-check_att_is_compressed(DbName) ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url(DbName) ++ "/testdoc1/readme.txt",
- [{"Accept-Encoding", "gzip"}]},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code for the attachment request is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, true, "The attachment was received in compressed form"),
- Uncompressed = binary_to_list(zlib:gunzip(list_to_binary(Body))),
- etap:is(
- Uncompressed,
- test_text_data(),
- "The attachment content is valid after decompression at the client side"
- ),
- ok.
-
-check_server_can_decompress_att(DbName) ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url(DbName) ++ "/testdoc1/readme.txt", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code for the attachment request is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(
- Gziped, false, "The attachment was not received in compressed form"
- ),
- etap:is(
- Body,
- test_text_data(),
- "The attachment content is valid after server decompression"
- ),
- ok.
-
-check_att_stubs(SourceDbName, TargetDbName) ->
- {ok, {{_, Code1, _}, _Headers1, Body1}} = http:request(
- get,
- {db_url(SourceDbName) ++ "/testdoc1?att_encoding_info=true", []},
- [],
- [{sync, true}]),
- etap:is(
- Code1,
- 200,
- "HTTP response code is 200 for the source DB doc request"
- ),
- Json1 = couch_util:json_decode(Body1),
- SourceAttStub = couch_util:get_nested_json_value(
- Json1,
- [<<"_attachments">>, <<"readme.txt">>]
- ),
- {ok, {{_, Code2, _}, _Headers2, Body2}} = http:request(
- get,
- {db_url(TargetDbName) ++ "/testdoc1?att_encoding_info=true", []},
- [],
- [{sync, true}]),
- etap:is(
- Code2,
- 200,
- "HTTP response code is 200 for the target DB doc request"
- ),
- Json2 = couch_util:json_decode(Body2),
- TargetAttStub = couch_util:get_nested_json_value(
- Json2,
- [<<"_attachments">>, <<"readme.txt">>]
- ),
- IdenticalStubs = (SourceAttStub =:= TargetAttStub),
- etap:is(IdenticalStubs, true, "Attachment stubs are identical"),
- TargetAttStubLength = couch_util:get_nested_json_value(
- TargetAttStub,
- [<<"length">>]
- ),
- TargetAttStubEnc = couch_util:get_nested_json_value(
- TargetAttStub,
- [<<"encoding">>]
- ),
- etap:is(
- TargetAttStubEnc,
- <<"gzip">>,
- "Attachment stub has encoding property set to gzip"
- ),
- TargetAttStubEncLength = couch_util:get_nested_json_value(
- TargetAttStub,
- [<<"encoded_length">>]
- ),
- EncLengthDefined = is_integer(TargetAttStubEncLength),
- etap:is(
- EncLengthDefined,
- true,
- "Stubs have the encoded_length field properly defined"
- ),
- EncLengthSmaller = (TargetAttStubEncLength < TargetAttStubLength),
- etap:is(
- EncLengthSmaller,
- true,
- "Stubs have the encoded_length field smaller than their length field"
- ),
- ok.
-
-admin_user_ctx() ->
- {user_ctx, #user_ctx{roles=[<<"_admin">>]}}.
-
-create_db(DbName) ->
- {ok, _} = couch_db:create(DbName, [admin_user_ctx()]).
-
-delete_db(DbName) ->
- couch_server:delete(DbName, [admin_user_ctx()]).
-
-db_url(DbName) ->
- "http://" ++ get(addr) ++ ":" ++ get(port) ++ "/" ++
- binary_to_list(DbName).
-
-rep_url() ->
- "http://" ++ get(addr) ++ ":" ++ get(port) ++ "/_replicate".
-
-test_text_data() ->
- {ok, Data} = file:read_file(test_util:source_file("README")),
- binary_to_list(Data).
diff --git a/apps/couch/test/etap/120-stats-collect.t b/apps/couch/test/etap/120-stats-collect.inactive
index dee88765..dee88765 100755
--- a/apps/couch/test/etap/120-stats-collect.t
+++ b/apps/couch/test/etap/120-stats-collect.inactive
diff --git a/apps/couch/test/etap/121-stats-aggregates.t b/apps/couch/test/etap/121-stats-aggregates.inactive
index d678aa9d..d678aa9d 100755
--- a/apps/couch/test/etap/121-stats-aggregates.t
+++ b/apps/couch/test/etap/121-stats-aggregates.inactive
diff --git a/apps/couch/test/etap/130-attachments-md5.t b/apps/couch/test/etap/130-attachments-md5.t
deleted file mode 100755
index 4c40f83a..00000000
--- a/apps/couch/test/etap/130-attachments-md5.t
+++ /dev/null
@@ -1,252 +0,0 @@
-#!/usr/bin/env escript
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
-default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
-
-test_db_name() ->
- <<"etap-test-db">>.
-
-docid() ->
- case get(docid) of
- undefined ->
- put(docid, 1),
- "1";
- Count ->
- put(docid, Count+1),
- integer_to_list(Count+1)
- end.
-
-main(_) ->
- test_util:init_code_path(),
-
- etap:plan(16),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail(Other)
- end,
- ok.
-
-test() ->
- couch_server_sup:start_link([default_config()]),
- Addr = couch_config:get("httpd", "bind_address", any),
- Port = list_to_integer(couch_config:get("httpd", "port", "5984")),
- put(addr, Addr),
- put(port, Port),
- timer:sleep(1000),
-
- couch_server:delete(test_db_name(), []),
- couch_db:create(test_db_name(), []),
-
- test_identity_without_md5(),
- test_chunked_without_md5(),
-
- test_identity_with_valid_md5(),
- test_chunked_with_valid_md5_header(),
- test_chunked_with_valid_md5_trailer(),
-
- test_identity_with_invalid_md5(),
- test_chunked_with_invalid_md5_header(),
- test_chunked_with_invalid_md5_trailer(),
-
- couch_server:delete(test_db_name(), []),
- couch_server_sup:stop(),
- ok.
-
-test_identity_without_md5() ->
- Data = [
- "PUT /", test_db_name(), "/", docid(), "/readme.txt HTTP/1.1\r\n",
- "Content-Type: text/plain\r\n",
- "Content-Length: 34\r\n",
- "\r\n",
- "We all live in a yellow submarine!"],
-
- {Code, Json} = do_request(Data),
- etap:is(Code, 201, "Stored with identity encoding and no MD5"),
- etap:is(get_json(Json, [<<"ok">>]), true, "Body indicates success.").
-
-test_chunked_without_md5() ->
- AttData = <<"We all live in a yellow submarine!">>,
- <<Part1:21/binary, Part2:13/binary>> = AttData,
- Data = [
- "PUT /", test_db_name(), "/", docid(), "/readme.txt HTTP/1.1\r\n",
- "Content-Type: text/plain\r\n",
- "Transfer-Encoding: chunked\r\n",
- "\r\n",
- to_hex(size(Part1)), "\r\n",
- Part1, "\r\n",
- to_hex(size(Part2)), "\r\n",
- Part2, "\r\n"
- "0\r\n"
- "\r\n"],
-
- {Code, Json} = do_request(Data),
- etap:is(Code, 201, "Stored with chunked encoding and no MD5"),
- etap:is(get_json(Json, [<<"ok">>]), true, "Body indicates success.").
-
-test_identity_with_valid_md5() ->
- AttData = "We all live in a yellow submarine!",
- Data = [
- "PUT /", test_db_name(), "/", docid(), "/readme.txt HTTP/1.1\r\n",
- "Content-Type: text/plain\r\n",
- "Content-Length: 34\r\n",
- "Content-MD5: ", base64:encode(couch_util:md5(AttData)), "\r\n",
- "\r\n",
- AttData],
-
- {Code, Json} = do_request(Data),
- etap:is(Code, 201, "Stored with identity encoding and valid MD5"),
- etap:is(get_json(Json, [<<"ok">>]), true, "Body indicates success.").
-
-test_chunked_with_valid_md5_header() ->
- AttData = <<"We all live in a yellow submarine!">>,
- <<Part1:21/binary, Part2:13/binary>> = AttData,
- Data = [
- "PUT /", test_db_name(), "/", docid(), "/readme.txt HTTP/1.1\r\n",
- "Content-Type: text/plain\r\n",
- "Transfer-Encoding: chunked\r\n",
- "Content-MD5: ", base64:encode(couch_util:md5(AttData)), "\r\n",
- "\r\n",
- to_hex(size(Part1)), "\r\n",
- Part1, "\r\n",
- to_hex(size(Part2)), "\r\n",
- Part2, "\r\n",
- "0\r\n",
- "\r\n"],
-
- {Code, Json} = do_request(Data),
- etap:is(Code, 201, "Stored with chunked encoding and valid MD5 header."),
- etap:is(get_json(Json, [<<"ok">>]), true, "Body indicates success.").
-
-test_chunked_with_valid_md5_trailer() ->
- AttData = <<"We all live in a yellow submarine!">>,
- <<Part1:21/binary, Part2:13/binary>> = AttData,
- Data = [
- "PUT /", test_db_name(), "/", docid(), "/readme.txt HTTP/1.1\r\n",
- "Content-Type: text/plain\r\n",
- "Transfer-Encoding: chunked\r\n",
- "Trailer: Content-MD5\r\n",
- "\r\n",
- to_hex(size(Part1)), "\r\n",
- Part1, "\r\n",
- to_hex(size(Part2)), "\r\n",
- Part2, "\r\n",
- "0\r\n",
- "Content-MD5: ", base64:encode(couch_util:md5(AttData)), "\r\n",
- "\r\n"],
-
- {Code, Json} = do_request(Data),
- etap:is(Code, 201, "Stored with chunked encoding and valid MD5 trailer."),
- etap:is(get_json(Json, [<<"ok">>]), true, "Body indicates success.").
-
-test_identity_with_invalid_md5() ->
- Data = [
- "PUT /", test_db_name(), "/", docid(), "/readme.txt HTTP/1.1\r\n",
- "Content-Type: text/plain\r\n",
- "Content-Length: 34\r\n",
- "Content-MD5: ", base64:encode(<<"foobar!">>), "\r\n",
- "\r\n",
- "We all live in a yellow submarine!"],
-
- {Code, Json} = do_request(Data),
- etap:is(Code, 400, "Invalid MD5 header causes an error: identity"),
- etap:is(
- get_json(Json, [<<"error">>]),
- <<"content_md5_mismatch">>,
- "Body indicates reason for failure."
- ).
-
-test_chunked_with_invalid_md5_header() ->
- AttData = <<"We all live in a yellow submarine!">>,
- <<Part1:21/binary, Part2:13/binary>> = AttData,
- Data = [
- "PUT /", test_db_name(), "/", docid(), "/readme.txt HTTP/1.1\r\n",
- "Content-Type: text/plain\r\n",
- "Transfer-Encoding: chunked\r\n",
- "Content-MD5: ", base64:encode(<<"so sneaky...">>), "\r\n",
- "\r\n",
- to_hex(size(Part1)), "\r\n",
- Part1, "\r\n",
- to_hex(size(Part2)), "\r\n",
- Part2, "\r\n",
- "0\r\n",
- "\r\n"],
-
- {Code, Json} = do_request(Data),
- etap:is(Code, 400, "Invalid MD5 header causes an error: chunked"),
- etap:is(
- get_json(Json, [<<"error">>]),
- <<"content_md5_mismatch">>,
- "Body indicates reason for failure."
- ).
-
-test_chunked_with_invalid_md5_trailer() ->
- AttData = <<"We all live in a yellow submarine!">>,
- <<Part1:21/binary, Part2:13/binary>> = AttData,
- Data = [
- "PUT /", test_db_name(), "/", docid(), "/readme.txt HTTP/1.1\r\n",
- "Content-Type: text/plain\r\n",
- "Transfer-Encoding: chunked\r\n",
- "Trailer: Content-MD5\r\n",
- "\r\n",
- to_hex(size(Part1)), "\r\n",
- Part1, "\r\n",
- to_hex(size(Part2)), "\r\n",
- Part2, "\r\n",
- "0\r\n",
- "Content-MD5: ", base64:encode(<<"Kool-Aid Fountain!">>), "\r\n",
- "\r\n"],
-
- {Code, Json} = do_request(Data),
- etap:is(Code, 400, "Invalid MD5 Trailer causes an error"),
- etap:is(
- get_json(Json, [<<"error">>]),
- <<"content_md5_mismatch">>,
- "Body indicates reason for failure."
- ).
-
-
-get_socket() ->
- Options = [binary, {packet, 0}, {active, false}],
- {ok, Sock} = gen_tcp:connect(get(addr), get(port), Options),
- Sock.
-
-do_request(Request) ->
- Sock = get_socket(),
- gen_tcp:send(Sock, list_to_binary(lists:flatten(Request))),
- timer:sleep(1000),
- {ok, R} = gen_tcp:recv(Sock, 0),
- gen_tcp:close(Sock),
- [Header, Body] = re:split(R, "\r\n\r\n", [{return, binary}]),
- {ok, {http_response, _, Code, _}, _} =
- erlang:decode_packet(http, Header, []),
- Json = couch_util:json_decode(Body),
- {Code, Json}.
-
-get_json(Json, Path) ->
- couch_util:get_nested_json_value(Json, Path).
-
-to_hex(Val) ->
- to_hex(Val, []).
-
-to_hex(0, Acc) ->
- Acc;
-to_hex(Val, Acc) ->
- to_hex(Val div 16, [hex_char(Val rem 16) | Acc]).
-
-hex_char(V) when V < 10 -> $0 + V;
-hex_char(V) -> $A + V - 10.
-
diff --git a/apps/couch/test/etap/140-attachment-comp.t b/apps/couch/test/etap/140-attachment-comp.t
deleted file mode 100755
index 98d37abc..00000000
--- a/apps/couch/test/etap/140-attachment-comp.t
+++ /dev/null
@@ -1,711 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
-default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
-
-test_db_name() ->
- <<"couch_test_atts_compression">>.
-
-main(_) ->
- test_util:init_code_path(),
-
- etap:plan(78),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail(Other)
- end,
- ok.
-
-test() ->
- couch_server_sup:start_link([default_config()]),
- put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")),
- put(port, couch_config:get("httpd", "port", "5984")),
- application:start(inets),
- timer:sleep(1000),
- couch_server:delete(test_db_name(), []),
- couch_db:create(test_db_name(), []),
-
- couch_config:set("attachments", "compression_level", "8"),
- couch_config:set("attachments", "compressible_types", "text/*"),
-
- create_1st_text_att(),
- create_1st_png_att(),
- create_2nd_text_att(),
- create_2nd_png_att(),
-
- tests_for_1st_text_att(),
- tests_for_1st_png_att(),
- tests_for_2nd_text_att(),
- tests_for_2nd_png_att(),
-
- create_already_compressed_att(db_url() ++ "/doc_comp_att", "readme.txt"),
- test_already_compressed_att(db_url() ++ "/doc_comp_att", "readme.txt"),
-
- test_create_already_compressed_att_with_invalid_content_encoding(
- db_url() ++ "/doc_att_deflate",
- "readme.txt",
- zlib:compress(test_text_data()),
- "deflate"
- ),
-
- test_create_already_compressed_att_with_invalid_content_encoding(
- db_url() ++ "/doc_att_compress",
- "readme.txt",
- % Note: As of OTP R13B04, it seems there's no LZW compression
- % (i.e. UNIX compress utility implementation) lib in OTP.
- % However there's a simple working Erlang implementation at:
- % http://scienceblogs.com/goodmath/2008/01/simple_lempelziv_compression_i.php
- test_text_data(),
- "compress"
- ),
-
- timer:sleep(3000), % to avoid mochiweb socket closed exceptions
- couch_server:delete(test_db_name(), []),
- couch_server_sup:stop(),
- ok.
-
-db_url() ->
- "http://" ++ get(addr) ++ ":" ++ get(port) ++ "/" ++
- binary_to_list(test_db_name()).
-
-create_1st_text_att() ->
- {ok, {{_, Code, _}, _Headers, _Body}} = http:request(
- put,
- {db_url() ++ "/testdoc1/readme.txt", [],
- "text/plain", test_text_data()},
- [],
- [{sync, true}]),
- etap:is(Code, 201, "Created text attachment using the standalone api"),
- ok.
-
-create_1st_png_att() ->
- {ok, {{_, Code, _}, _Headers, _Body}} = http:request(
- put,
- {db_url() ++ "/testdoc2/icon.png", [],
- "image/png", test_png_data()},
- [],
- [{sync, true}]),
- etap:is(Code, 201, "Created png attachment using the standalone api"),
- ok.
-
-% create a text attachment using the non-standalone attachment api
-create_2nd_text_att() ->
- DocJson = {[
- {<<"_attachments">>, {[
- {<<"readme.txt">>, {[
- {<<"content_type">>, <<"text/plain">>},
- {<<"data">>, base64:encode(test_text_data())}
- ]}
- }]}}
- ]},
- {ok, {{_, Code, _}, _Headers, _Body}} = http:request(
- put,
- {db_url() ++ "/testdoc3", [],
- "application/json", list_to_binary(couch_util:json_encode(DocJson))},
- [],
- [{sync, true}]),
- etap:is(Code, 201, "Created text attachment using the non-standalone api"),
- ok.
-
-% create a png attachment using the non-standalone attachment api
-create_2nd_png_att() ->
- DocJson = {[
- {<<"_attachments">>, {[
- {<<"icon.png">>, {[
- {<<"content_type">>, <<"image/png">>},
- {<<"data">>, base64:encode(test_png_data())}
- ]}
- }]}}
- ]},
- {ok, {{_, Code, _}, _Headers, _Body}} = http:request(
- put,
- {db_url() ++ "/testdoc4", [],
- "application/json", list_to_binary(couch_util:json_encode(DocJson))},
- [],
- [{sync, true}]),
- etap:is(Code, 201, "Created png attachment using the non-standalone api"),
- ok.
-
-create_already_compressed_att(DocUri, AttName) ->
- {ok, {{_, Code, _}, _Headers, _Body}} = http:request(
- put,
- {DocUri ++ "/" ++ AttName, [{"Content-Encoding", "gzip"}],
- "text/plain", zlib:gzip(test_text_data())},
- [],
- [{sync, true}]),
- etap:is(
- Code,
- 201,
- "Created already compressed attachment using the standalone api"
- ),
- ok.
-
-tests_for_1st_text_att() ->
- test_get_1st_text_att_with_accept_encoding_gzip(),
- test_get_1st_text_att_without_accept_encoding_header(),
- test_get_1st_text_att_with_accept_encoding_deflate(),
- test_get_1st_text_att_with_accept_encoding_deflate_only(),
- test_get_doc_with_1st_text_att(),
- test_1st_text_att_stub().
-
-tests_for_1st_png_att() ->
- test_get_1st_png_att_without_accept_encoding_header(),
- test_get_1st_png_att_with_accept_encoding_gzip(),
- test_get_1st_png_att_with_accept_encoding_deflate(),
- test_get_doc_with_1st_png_att(),
- test_1st_png_att_stub().
-
-tests_for_2nd_text_att() ->
- test_get_2nd_text_att_with_accept_encoding_gzip(),
- test_get_2nd_text_att_without_accept_encoding_header(),
- test_get_doc_with_2nd_text_att(),
- test_2nd_text_att_stub().
-
-tests_for_2nd_png_att() ->
- test_get_2nd_png_att_without_accept_encoding_header(),
- test_get_2nd_png_att_with_accept_encoding_gzip(),
- test_get_doc_with_2nd_png_att(),
- test_2nd_png_att_stub().
-
-test_get_1st_text_att_with_accept_encoding_gzip() ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc1/readme.txt", [{"Accept-Encoding", "gzip"}]},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, true, "received body is gziped"),
- Uncompressed = binary_to_list(zlib:gunzip(list_to_binary(Body))),
- etap:is(
- Uncompressed,
- test_text_data(),
- "received data for the 1st text attachment is ok"
- ),
- ok.
-
-test_get_1st_text_att_without_accept_encoding_header() ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc1/readme.txt", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, false, "received body is not gziped"),
- etap:is(
- Body,
- test_text_data(),
- "received data for the 1st text attachment is ok"
- ),
- ok.
-
-test_get_1st_text_att_with_accept_encoding_deflate() ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc1/readme.txt", [{"Accept-Encoding", "deflate"}]},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, false, "received body is not gziped"),
- Deflated = lists:member({"content-encoding", "deflate"}, Headers),
- etap:is(Deflated, false, "received body is not deflated"),
- etap:is(
- Body,
- test_text_data(),
- "received data for the 1st text attachment is ok"
- ),
- ok.
-
-test_get_1st_text_att_with_accept_encoding_deflate_only() ->
- {ok, {{_, Code, _}, _Headers, _Body}} = http:request(
- get,
- {db_url() ++ "/testdoc1/readme.txt",
- [{"Accept-Encoding", "deflate, *;q=0"}]},
- [],
- [{sync, true}]),
- etap:is(
- Code,
- 406,
- "HTTP response code is 406 for an unsupported content encoding request"
- ),
- ok.
-
-test_get_1st_png_att_without_accept_encoding_header() ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc2/icon.png", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, false, "received body is not gziped"),
- etap:is(
- Body,
- test_png_data(),
- "received data for the 1st png attachment is ok"
- ),
- ok.
-
-test_get_1st_png_att_with_accept_encoding_gzip() ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc2/icon.png", [{"Accept-Encoding", "gzip"}]},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, false, "received body is not gziped"),
- etap:is(
- Body,
- test_png_data(),
- "received data for the 1st png attachment is ok"
- ),
- ok.
-
-test_get_1st_png_att_with_accept_encoding_deflate() ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc2/icon.png", [{"Accept-Encoding", "deflate"}]},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Deflated = lists:member({"content-encoding", "deflate"}, Headers),
- etap:is(Deflated, false, "received body is not deflated"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, false, "received body is not gziped"),
- etap:is(
- Body,
- test_png_data(),
- "received data for the 1st png attachment is ok"
- ),
- ok.
-
-test_get_doc_with_1st_text_att() ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc1?attachments=true", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Json = couch_util:json_decode(Body),
- TextAttJson = couch_util:get_nested_json_value(
- Json,
- [<<"_attachments">>, <<"readme.txt">>]
- ),
- TextAttType = couch_util:get_nested_json_value(
- TextAttJson,
- [<<"content_type">>]
- ),
- TextAttData = couch_util:get_nested_json_value(
- TextAttJson,
- [<<"data">>]
- ),
- etap:is(
- TextAttType,
- <<"text/plain">>,
- "1st text attachment has type text/plain"
- ),
- %% check the attachment's data is the base64 encoding of the plain text
- %% and not the base64 encoding of the gziped plain text
- etap:is(
- TextAttData,
- base64:encode(test_text_data()),
- "1st text attachment data is properly base64 encoded"
- ),
- ok.
-
-test_1st_text_att_stub() ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc1?att_encoding_info=true", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Json = couch_util:json_decode(Body),
- {TextAttJson} = couch_util:get_nested_json_value(
- Json,
- [<<"_attachments">>, <<"readme.txt">>]
- ),
- TextAttLength = couch_util:get_value(<<"length">>, TextAttJson),
- etap:is(
- TextAttLength,
- length(test_text_data()),
- "1st text attachment stub length matches the uncompressed length"
- ),
- TextAttEncoding = couch_util:get_value(<<"encoding">>, TextAttJson),
- etap:is(
- TextAttEncoding,
- <<"gzip">>,
- "1st text attachment stub has the encoding field set to gzip"
- ),
- TextAttEncLength = couch_util:get_value(<<"encoded_length">>, TextAttJson),
- etap:is(
- TextAttEncLength,
- iolist_size(zlib:gzip(test_text_data())),
- "1st text attachment stub encoded_length matches the compressed length"
- ),
- ok.
-
-test_get_doc_with_1st_png_att() ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc2?attachments=true", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Json = couch_util:json_decode(Body),
- PngAttJson = couch_util:get_nested_json_value(
- Json,
- [<<"_attachments">>, <<"icon.png">>]
- ),
- PngAttType = couch_util:get_nested_json_value(
- PngAttJson,
- [<<"content_type">>]
- ),
- PngAttData = couch_util:get_nested_json_value(
- PngAttJson,
- [<<"data">>]
- ),
- etap:is(PngAttType, <<"image/png">>, "attachment has type image/png"),
- etap:is(
- PngAttData,
- base64:encode(test_png_data()),
- "1st png attachment data is properly base64 encoded"
- ),
- ok.
-
-test_1st_png_att_stub() ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc2?att_encoding_info=true", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Json = couch_util:json_decode(Body),
- {PngAttJson} = couch_util:get_nested_json_value(
- Json,
- [<<"_attachments">>, <<"icon.png">>]
- ),
- PngAttLength = couch_util:get_value(<<"length">>, PngAttJson),
- etap:is(
- PngAttLength,
- length(test_png_data()),
- "1st png attachment stub length matches the uncompressed length"
- ),
- PngEncoding = couch_util:get_value(<<"encoding">>, PngAttJson),
- etap:is(
- PngEncoding,
- undefined,
- "1st png attachment stub doesn't have an encoding field"
- ),
- PngEncLength = couch_util:get_value(<<"encoded_length">>, PngAttJson),
- etap:is(
- PngEncLength,
- undefined,
- "1st png attachment stub doesn't have an encoded_length field"
- ),
- ok.
-
-test_get_2nd_text_att_with_accept_encoding_gzip() ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc3/readme.txt", [{"Accept-Encoding", "gzip"}]},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, true, "received body is gziped"),
- Uncompressed = binary_to_list(zlib:gunzip(list_to_binary(Body))),
- etap:is(
- Uncompressed,
- test_text_data(),
- "received data for the 2nd text attachment is ok"
- ),
- ok.
-
-test_get_2nd_text_att_without_accept_encoding_header() ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc3/readme.txt", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, false, "received body is not gziped"),
- etap:is(
- Body,
- test_text_data(),
- "received data for the 2nd text attachment is ok"
- ),
- ok.
-
-test_get_2nd_png_att_without_accept_encoding_header() ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc4/icon.png", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, false, "received body is not gziped"),
- etap:is(
- Body,
- test_png_data(),
- "received data for the 2nd png attachment is ok"
- ),
- ok.
-
-test_get_2nd_png_att_with_accept_encoding_gzip() ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc4/icon.png", [{"Accept-Encoding", "gzip"}]},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, false, "received body is not gziped"),
- etap:is(
- Body,
- test_png_data(),
- "received data for the 2nd png attachment is ok"
- ),
- ok.
-
-test_get_doc_with_2nd_text_att() ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc3?attachments=true", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Json = couch_util:json_decode(Body),
- TextAttJson = couch_util:get_nested_json_value(
- Json,
- [<<"_attachments">>, <<"readme.txt">>]
- ),
- TextAttType = couch_util:get_nested_json_value(
- TextAttJson,
- [<<"content_type">>]
- ),
- TextAttData = couch_util:get_nested_json_value(
- TextAttJson,
- [<<"data">>]
- ),
- etap:is(TextAttType, <<"text/plain">>, "attachment has type text/plain"),
- %% check the attachment's data is the base64 encoding of the plain text
- %% and not the base64 encoding of the gziped plain text
- etap:is(
- TextAttData,
- base64:encode(test_text_data()),
- "2nd text attachment data is properly base64 encoded"
- ),
- ok.
-
-test_2nd_text_att_stub() ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc3?att_encoding_info=true", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Json = couch_util:json_decode(Body),
- {TextAttJson} = couch_util:get_nested_json_value(
- Json,
- [<<"_attachments">>, <<"readme.txt">>]
- ),
- TextAttLength = couch_util:get_value(<<"length">>, TextAttJson),
- etap:is(
- TextAttLength,
- length(test_text_data()),
- "2nd text attachment stub length matches the uncompressed length"
- ),
- TextAttEncoding = couch_util:get_value(<<"encoding">>, TextAttJson),
- etap:is(
- TextAttEncoding,
- <<"gzip">>,
- "2nd text attachment stub has the encoding field set to gzip"
- ),
- TextAttEncLength = couch_util:get_value(<<"encoded_length">>, TextAttJson),
- etap:is(
- TextAttEncLength,
- iolist_size(zlib:gzip(test_text_data())),
- "2nd text attachment stub encoded_length matches the compressed length"
- ),
- ok.
-
-test_get_doc_with_2nd_png_att() ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc4?attachments=true", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Json = couch_util:json_decode(Body),
- PngAttJson = couch_util:get_nested_json_value(
- Json,
- [<<"_attachments">>, <<"icon.png">>]
- ),
- PngAttType = couch_util:get_nested_json_value(
- PngAttJson,
- [<<"content_type">>]
- ),
- PngAttData = couch_util:get_nested_json_value(
- PngAttJson,
- [<<"data">>]
- ),
- etap:is(PngAttType, <<"image/png">>, "attachment has type image/png"),
- etap:is(
- PngAttData,
- base64:encode(test_png_data()),
- "2nd png attachment data is properly base64 encoded"
- ),
- ok.
-
-test_2nd_png_att_stub() ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {db_url() ++ "/testdoc4?att_encoding_info=true", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Json = couch_util:json_decode(Body),
- {PngAttJson} = couch_util:get_nested_json_value(
- Json,
- [<<"_attachments">>, <<"icon.png">>]
- ),
- PngAttLength = couch_util:get_value(<<"length">>, PngAttJson),
- etap:is(
- PngAttLength,
- length(test_png_data()),
- "2nd png attachment stub length matches the uncompressed length"
- ),
- PngEncoding = couch_util:get_value(<<"encoding">>, PngAttJson),
- etap:is(
- PngEncoding,
- undefined,
- "2nd png attachment stub doesn't have an encoding field"
- ),
- PngEncLength = couch_util:get_value(<<"encoded_length">>, PngAttJson),
- etap:is(
- PngEncLength,
- undefined,
- "2nd png attachment stub doesn't have an encoded_length field"
- ),
- ok.
-
-test_already_compressed_att(DocUri, AttName) ->
- test_get_already_compressed_att_with_accept_gzip(DocUri, AttName),
- test_get_already_compressed_att_without_accept(DocUri, AttName),
- test_get_already_compressed_att_stub(DocUri, AttName).
-
-test_get_already_compressed_att_with_accept_gzip(DocUri, AttName) ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {DocUri ++ "/" ++ AttName, [{"Accept-Encoding", "gzip"}]},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, true, "received body is gziped"),
- etap:is(
- iolist_to_binary(Body),
- iolist_to_binary(zlib:gzip(test_text_data())),
- "received data for the already compressed attachment is ok"
- ),
- ok.
-
-test_get_already_compressed_att_without_accept(DocUri, AttName) ->
- {ok, {{_, Code, _}, Headers, Body}} = http:request(
- get,
- {DocUri ++ "/" ++ AttName, []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Gziped = lists:member({"content-encoding", "gzip"}, Headers),
- etap:is(Gziped, false, "received body is not gziped"),
- etap:is(
- iolist_to_binary(Body),
- iolist_to_binary(test_text_data()),
- "received data for the already compressed attachment is ok"
- ),
- ok.
-
-test_get_already_compressed_att_stub(DocUri, AttName) ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {DocUri ++ "?att_encoding_info=true", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "HTTP response code is 200"),
- Json = couch_util:json_decode(Body),
- {AttJson} = couch_util:get_nested_json_value(
- Json,
- [<<"_attachments">>, iolist_to_binary(AttName)]
- ),
- AttLength = couch_util:get_value(<<"length">>, AttJson),
- etap:is(
- AttLength,
- iolist_size((zlib:gzip(test_text_data()))),
- "Already compressed attachment stub length matches the "
- "compressed length"
- ),
- Encoding = couch_util:get_value(<<"encoding">>, AttJson),
- etap:is(
- Encoding,
- <<"gzip">>,
- "Already compressed attachment stub has the encoding field set to gzip"
- ),
- EncLength = couch_util:get_value(<<"encoded_length">>, AttJson),
- etap:is(
- EncLength,
- AttLength,
- "Already compressed attachment stub encoded_length matches the "
- "length field value"
- ),
- ok.
-
-test_create_already_compressed_att_with_invalid_content_encoding(
- DocUri, AttName, AttData, Encoding) ->
- {ok, {{_, Code, _}, _Headers, _Body}} = http:request(
- put,
- {DocUri ++ "/" ++ AttName, [{"Content-Encoding", Encoding}],
- "text/plain", AttData},
- [],
- [{sync, true}]),
- etap:is(
- Code,
- 415,
- "Couldn't create an already compressed attachment using the "
- "unsupported encoding '" ++ Encoding ++ "'"
- ),
- ok.
-
-test_png_data() ->
- {ok, Data} = file:read_file(
- test_util:source_file("share/www/image/logo.png")
- ),
- binary_to_list(Data).
-
-test_text_data() ->
- {ok, Data} = file:read_file(
- test_util:source_file("README")
- ),
- binary_to_list(Data).
diff --git a/apps/couch/test/etap/150-invalid-view-seq.t b/apps/couch/test/etap/150-invalid-view-seq.t
deleted file mode 100755
index 0664c116..00000000
--- a/apps/couch/test/etap/150-invalid-view-seq.t
+++ /dev/null
@@ -1,192 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--record(user_ctx, {
- name = null,
- roles = [],
- handler
-}).
-
-default_config() ->
- test_util:build_file("etc/couchdb/default_dev.ini").
-
-test_db_name() ->
- <<"couch_test_invalid_view_seq">>.
-
-main(_) ->
- test_util:init_code_path(),
-
- etap:plan(10),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail(Other)
- end,
- ok.
-
-%% NOTE: since during the test we stop the server,
-%% a huge and ugly but harmless stack trace is sent to stderr
-%%
-test() ->
- couch_server_sup:start_link([default_config()]),
- timer:sleep(1000),
- delete_db(),
- create_db(),
-
- create_docs(),
- create_design_doc(),
-
- % make DB file backup
- backup_db_file(),
-
- put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")),
- put(port, couch_config:get("httpd", "port", "5984")),
- application:start(inets),
-
- create_new_doc(),
- query_view_before_restore_backup(),
-
- % restore DB file backup after querying view
- restore_backup_db_file(),
-
- query_view_after_restore_backup(),
-
- delete_db(),
- couch_server_sup:stop(),
- ok.
-
-admin_user_ctx() ->
- {user_ctx, #user_ctx{roles=[<<"_admin">>]}}.
-
-create_db() ->
- {ok, _} = couch_db:create(test_db_name(), [admin_user_ctx()]).
-
-delete_db() ->
- couch_server:delete(test_db_name(), [admin_user_ctx()]).
-
-create_docs() ->
- {ok, Db} = couch_db:open(test_db_name(), [admin_user_ctx()]),
- Doc1 = couch_doc:from_json_obj({[
- {<<"_id">>, <<"doc1">>},
- {<<"value">>, 1}
-
- ]}),
- Doc2 = couch_doc:from_json_obj({[
- {<<"_id">>, <<"doc2">>},
- {<<"value">>, 2}
-
- ]}),
- Doc3 = couch_doc:from_json_obj({[
- {<<"_id">>, <<"doc3">>},
- {<<"value">>, 3}
-
- ]}),
- {ok, _} = couch_db:update_docs(Db, [Doc1, Doc2, Doc3]),
- couch_db:ensure_full_commit(Db),
- couch_db:close(Db).
-
-create_design_doc() ->
- {ok, Db} = couch_db:open(test_db_name(), [admin_user_ctx()]),
- DDoc = couch_doc:from_json_obj({[
- {<<"_id">>, <<"_design/foo">>},
- {<<"language">>, <<"javascript">>},
- {<<"views">>, {[
- {<<"bar">>, {[
- {<<"map">>, <<"function(doc) { emit(doc.value, 1); }">>}
- ]}}
- ]}}
- ]}),
- {ok, _} = couch_db:update_docs(Db, [DDoc]),
- couch_db:ensure_full_commit(Db),
- couch_db:close(Db).
-
-backup_db_file() ->
- DbFile = test_util:build_file("tmp/lib/" ++
- binary_to_list(test_db_name()) ++ ".couch"),
- {ok, _} = file:copy(DbFile, DbFile ++ ".backup"),
- ok.
-
-create_new_doc() ->
- {ok, Db} = couch_db:open(test_db_name(), [admin_user_ctx()]),
- Doc666 = couch_doc:from_json_obj({[
- {<<"_id">>, <<"doc666">>},
- {<<"value">>, 999}
-
- ]}),
- {ok, _} = couch_db:update_docs(Db, [Doc666]),
- couch_db:ensure_full_commit(Db),
- couch_db:close(Db).
-
-db_url() ->
- "http://" ++ get(addr) ++ ":" ++ get(port) ++ "/" ++
- binary_to_list(test_db_name()).
-
-query_view_before_restore_backup() ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {db_url() ++ "/_design/foo/_view/bar", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "Got view response before restoring backup."),
- ViewJson = couch_util:json_decode(Body),
- Rows = couch_util:get_nested_json_value(ViewJson, [<<"rows">>]),
- HasDoc1 = has_doc("doc1", Rows),
- HasDoc2 = has_doc("doc2", Rows),
- HasDoc3 = has_doc("doc3", Rows),
- HasDoc666 = has_doc("doc666", Rows),
- etap:is(HasDoc1, true, "Before backup restore, view has doc1"),
- etap:is(HasDoc2, true, "Before backup restore, view has doc2"),
- etap:is(HasDoc3, true, "Before backup restore, view has doc3"),
- etap:is(HasDoc666, true, "Before backup restore, view has doc666"),
- ok.
-
-has_doc(DocId1, Rows) ->
- DocId = iolist_to_binary(DocId1),
- lists:any(
- fun({R}) -> lists:member({<<"id">>, DocId}, R) end,
- Rows
- ).
-
-restore_backup_db_file() ->
- couch_server_sup:stop(),
- timer:sleep(3000),
- DbFile = test_util:build_file("tmp/lib/" ++
- binary_to_list(test_db_name()) ++ ".couch"),
- ok = file:delete(DbFile),
- ok = file:rename(DbFile ++ ".backup", DbFile),
- couch_server_sup:start_link([default_config()]),
- timer:sleep(1000),
- ok.
-
-query_view_after_restore_backup() ->
- {ok, {{_, Code, _}, _Headers, Body}} = http:request(
- get,
- {db_url() ++ "/_design/foo/_view/bar", []},
- [],
- [{sync, true}]),
- etap:is(Code, 200, "Got view response after restoring backup."),
- ViewJson = couch_util:json_decode(Body),
- Rows = couch_util:get_nested_json_value(ViewJson, [<<"rows">>]),
- HasDoc1 = has_doc("doc1", Rows),
- HasDoc2 = has_doc("doc2", Rows),
- HasDoc3 = has_doc("doc3", Rows),
- HasDoc666 = has_doc("doc666", Rows),
- etap:is(HasDoc1, true, "After backup restore, view has doc1"),
- etap:is(HasDoc2, true, "After backup restore, view has doc2"),
- etap:is(HasDoc3, true, "After backup restore, view has doc3"),
- etap:is(HasDoc666, false, "After backup restore, view does not have doc666"),
- ok.
diff --git a/apps/couch/test/etap/160-vhosts.t b/apps/couch/test/etap/160-vhosts.t
deleted file mode 100755
index 7694010a..00000000
--- a/apps/couch/test/etap/160-vhosts.t
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
-%% XXX: Figure out how to -include("couch_rep.hrl")
--record(http_db, {
- url,
- auth = [],
- resource = "",
- headers = [
- {"User-Agent", "CouchDB/"++couch:version()},
- {"Accept", "application/json"},
- {"Accept-Encoding", "gzip"}
- ],
- qs = [],
- method = get,
- body = nil,
- options = [
- {response_format,binary},
- {inactivity_timeout, 30000}
- ],
- retries = 10,
- pause = 1,
- conn = nil
-}).
-
--record(user_ctx, {
- name = null,
- roles = [],
- handler
-}).
-
-server() -> "http://127.0.0.1:5984/".
-dbname() -> "etap-test-db".
-admin_user_ctx() -> {user_ctx, #user_ctx{roles=[<<"_admin">>]}}.
-
-config_files() ->
- lists:map(fun test_util:build_file/1, [
- "etc/couchdb/default_dev.ini",
- "etc/couchdb/local_dev.ini"
- ]).
-
-main(_) ->
- test_util:init_code_path(),
-
- etap:plan(4),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail(Other)
- end,
- ok.
-
-test() ->
- couch_server_sup:start_link(config_files()),
- ibrowse:start(),
- crypto:start(),
-
- couch_server:delete(list_to_binary(dbname()), [admin_user_ctx()]),
- {ok, Db} = couch_db:create(list_to_binary(dbname()), [admin_user_ctx()]),
-
- Doc = couch_doc:from_json_obj({[
- {<<"_id">>, <<"doc1">>},
- {<<"value">>, 666}
- ]}),
- {ok, _} = couch_db:update_docs(Db, [Doc]),
- couch_db:ensure_full_commit(Db),
-
- %% end boilerplate, start test
-
- couch_config:set("vhosts", "example.com", "/etap-test-db", false),
- test_regular_request(),
- test_vhost_request(),
- test_vhost_request_with_qs(),
- test_vhost_request_with_global(),
-
- %% restart boilerplate
- couch_db:close(Db),
- couch_server:delete(list_to_binary(dbname()), []),
- ok.
-
-test_regular_request() ->
- case ibrowse:send_req(server(), [], get, []) of
- {ok, _, _, Body} ->
- {[{<<"couchdb">>, <<"Welcome">>},
- {<<"version">>,_}
- ]} = couch_util:json_decode(Body),
- etap:is(true, true, "should return server info");
- _Else -> false
- end.
-
-test_vhost_request() ->
- case ibrowse:send_req(server(), [], get, [], [{host_header, "example.com"}]) of
- {ok, _, _, Body} ->
- {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]}
- = couch_util:json_decode(Body),
- etap:is(true, true, "should return database info");
- _Else -> false
- end.
-
-test_vhost_request_with_qs() ->
- Url = server() ++ "doc1?revs_info=true",
- case ibrowse:send_req(Url, [], get, [], [{host_header, "example.com"}]) of
- {ok, _, _, Body} ->
- {JsonProps} = couch_util:json_decode(Body),
- HasRevsInfo = proplists:is_defined(<<"_revs_info">>, JsonProps),
- etap:is(HasRevsInfo, true, "should return _revs_info");
- _Else -> false
- end.
-
-test_vhost_request_with_global() ->
- Url2 = server() ++ "_utils/index.html",
- case ibrowse:send_req(Url2, [], get, [], [{host_header, "example.com"}]) of
- {ok, _, _, Body2} ->
- "<!DOCTYPE" ++ _Foo = Body2,
- etap:is(true, true, "should serve /_utils even inside vhosts");
- _Else -> false
- end.