summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorBrad Anderson <brad@cloudant.com>2010-08-18 16:16:09 -0400
committerAdam Kocoloski <adam@cloudant.com>2010-08-18 17:19:37 -0400
commit6d18638d747374cb0e90e9bcbefbc71d959254fd (patch)
tree51ee2c2fd1020550e56febb03c740582af04dfce /test
parent1fda1aa8f69d5870c5711b0068971c7d4594e6cc (diff)
clear out root folder a bit, moving couch bits into apps/couch or rel/
Diffstat (limited to 'test')
-rw-r--r--test/bench/bench_marks.js103
-rwxr-xr-xtest/bench/benchbulk.sh69
-rwxr-xr-xtest/bench/run.tpl28
-rwxr-xr-xtest/etap/001-load.t68
-rw-r--r--test/etap/002-icu-driver.t33
-rwxr-xr-xtest/etap/010-file-basics.t107
-rwxr-xr-xtest/etap/011-file-headers.t145
-rwxr-xr-xtest/etap/020-btree-basics.t205
-rwxr-xr-xtest/etap/021-btree-reductions.t141
-rwxr-xr-xtest/etap/030-doc-from-json.t239
-rwxr-xr-xtest/etap/031-doc-to-json.t200
-rwxr-xr-xtest/etap/040-util.t80
-rw-r--r--test/etap/041-uuid-gen-seq.ini19
-rw-r--r--test/etap/041-uuid-gen-utc.ini19
-rwxr-xr-xtest/etap/041-uuid-gen.t118
-rwxr-xr-xtest/etap/050-stream.t87
-rwxr-xr-xtest/etap/060-kt-merging.t140
-rwxr-xr-xtest/etap/061-kt-missing-leaves.t65
-rwxr-xr-xtest/etap/062-kt-remove-leaves.t69
-rwxr-xr-xtest/etap/063-kt-get-leaves.t98
-rwxr-xr-xtest/etap/064-kt-counting.t46
-rwxr-xr-xtest/etap/065-kt-stemming.t42
-rwxr-xr-xtest/etap/070-couch-db.t75
-rwxr-xr-xtest/etap/080-config-get-set.t128
-rw-r--r--test/etap/081-config-override.1.ini22
-rw-r--r--test/etap/081-config-override.2.ini22
-rwxr-xr-xtest/etap/081-config-override.t212
-rwxr-xr-xtest/etap/082-config-register.t94
-rwxr-xr-xtest/etap/083-config-no-files.t55
-rwxr-xr-xtest/etap/090-task-status.t209
-rwxr-xr-xtest/etap/100-ref-counter.t114
-rwxr-xr-xtest/etap/110-replication-httpc.t134
-rwxr-xr-xtest/etap/111-replication-changes-feed.t254
-rwxr-xr-xtest/etap/112-replication-missing-revs.t195
-rwxr-xr-xtest/etap/113-replication-attachment-comp.t273
-rwxr-xr-xtest/etap/120-stats-collect.t150
-rw-r--r--test/etap/121-stats-aggregates.cfg19
-rw-r--r--test/etap/121-stats-aggregates.ini20
-rwxr-xr-xtest/etap/121-stats-aggregates.t171
-rwxr-xr-xtest/etap/130-attachments-md5.t252
-rwxr-xr-xtest/etap/140-attachment-comp.t711
-rwxr-xr-xtest/etap/150-invalid-view-seq.t192
-rwxr-xr-xtest/etap/160-vhosts.t131
-rw-r--r--test/etap/run.tpl27
-rw-r--r--test/etap/test_util.erl.in35
-rw-r--r--test/javascript/cli_runner.js52
-rw-r--r--test/javascript/couch_http.js62
-rw-r--r--test/javascript/run.tpl30
-rw-r--r--test/view_server/query_server_spec.rb824
-rwxr-xr-xtest/view_server/run_native_process.es59
50 files changed, 0 insertions, 6643 deletions
diff --git a/test/bench/bench_marks.js b/test/bench/bench_marks.js
deleted file mode 100644
index 4025adbb..00000000
--- a/test/bench/bench_marks.js
+++ /dev/null
@@ -1,103 +0,0 @@
-// 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.
-
-var NUM_DOCS = 2000;
-var NUM_BATCHES = 20;
-
-var init = function() {
- var db = new CouchDB("bench_mark_db", {"X-Couch-Full-Commit": "false"});
- db.deleteDb();
- db.createDb();
- return db;
-};
-
-var timeit = function(func) {
- var startTime = (new Date()).getTime();
- func();
- return ((new Date()).getTime() - startTime) / 1000;
-};
-
-var report = function(name, rate) {
- rate = Math.round(parseFloat(rate) * 100) / 100;
- console.log("" + name + ": " + rate + " docs/second");
-};
-
-var makeDocs = function(n) {
- docs = [];
- for (var i=0; i < n; i++) {
- docs.push({"foo":"bar"});
- };
- return docs;
-};
-
-var couchTests = {};
-
-couchTests.single_doc_insert = function() {
- var db = init();
- var len = timeit(function() {
- for(var i = 0; i < NUM_DOCS; i++) {
- db.save({"foo": "bar"});
- }
- });
- report("Single doc inserts", NUM_DOCS/len);
-};
-
-couchTests.batch_ok_doc_insert = function() {
- var db = init();
- var len = timeit(function() {
- for(var i = 0; i < NUM_DOCS; i++) {
- db.save({"foo":"bar"}, {"batch":"ok"});
- }
- });
- report("Single doc inserts with batch=ok", NUM_DOCS/len);
-};
-
-couchTests.bulk_doc_100 = function() {
- var db = init();
- var len = timeit(function() {
- for(var i = 0; i < NUM_BATCHES; i++) {
- db.bulkSave(makeDocs(100));
- }
- });
- report("Bulk docs - 100", (NUM_BATCHES*100)/len);
-};
-
-couchTests.bulk_doc_1000 = function() {
- var db = init();
- var len = timeit(function() {
- for(var i = 0; i < NUM_BATCHES; i++) {
- db.bulkSave(makeDocs(1000));
- }
- });
- report("Bulk docs - 1000", (NUM_BATCHES*1000)/len);
-};
-
-
-couchTests.bulk_doc_5000 = function() {
- var db = init();
- var len = timeit(function() {
- for(var i = 0; i < NUM_BATCHES; i++) {
- db.bulkSave(makeDocs(5000));
- }
- });
- report("Bulk docs - 5000", (NUM_BATCHES*5000)/len);
-};
-
-couchTests.bulk_doc_10000 = function() {
- var db = init();
- var len = timeit(function() {
- for(var i = 0; i < NUM_BATCHES; i++) {
- db.bulkSave(makeDocs(10000));
- }
- });
- report("Bulk docs - 10000", (NUM_BATCHES*10000)/len);
-};
diff --git a/test/bench/benchbulk.sh b/test/bench/benchbulk.sh
deleted file mode 100755
index 22804c64..00000000
--- a/test/bench/benchbulk.sh
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/sh -e
-# 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.
-#
-
-# usage: time benchbulk.sh
-# it takes about 30 seconds to run on my old MacBook with bulksize 1000
-
-BULKSIZE=100
-DOCSIZE=10
-INSERTS=10
-ROUNDS=10
-DBURL="http://127.0.0.1:5984/benchbulk"
-POSTURL="$DBURL/_bulk_docs"
-
-function make_bulk_docs() {
- ROW=0
- SIZE=$(($1-1))
- START=$2
- BODYSIZE=$3
-
- BODY=$(printf "%0${BODYSIZE}d")
-
- echo '{"docs":['
- while [ $ROW -lt $SIZE ]; do
- printf '{"_id":"%020d", "body":"'$BODY'"},' $(($ROW + $START))
- let ROW=ROW+1
- done
- printf '{"_id":"%020d", "body":"'$BODY'"}' $(($ROW + $START))
- echo ']}'
-}
-
-echo "Making $INSERTS bulk inserts of $BULKSIZE docs each"
-
-echo "Attempt to delete db at $DBURL"
-curl -X DELETE $DBURL -w\\n
-
-echo "Attempt to create db at $DBURL"
-curl -X PUT $DBURL -w\\n
-
-echo "Running $ROUNDS rounds of $INSERTS concurrent inserts to $POSTURL"
-RUN=0
-while [ $RUN -lt $ROUNDS ]; do
-
- POSTS=0
- while [ $POSTS -lt $INSERTS ]; do
- STARTKEY=$[ POSTS * BULKSIZE + RUN * BULKSIZE * INSERTS ]
- echo "startkey $STARTKEY bulksize $BULKSIZE"
- DOCS=$(make_bulk_docs $BULKSIZE $STARTKEY $DOCSIZE)
- # echo $DOCS
- echo $DOCS | curl -T - -X POST $POSTURL -w%{http_code}\ %{time_total}\ sec\\n >/dev/null 2>&1 &
- let POSTS=POSTS+1
- done
-
- echo "waiting"
- wait
- let RUN=RUN+1
-done
-
-curl $DBURL -w\\n
diff --git a/test/bench/run.tpl b/test/bench/run.tpl
deleted file mode 100755
index 9307863f..00000000
--- a/test/bench/run.tpl
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/sh -e
-
-# 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.
-
-SRC_DIR=%abs_top_srcdir%
-SCRIPT_DIR=$SRC_DIR/share/www/script
-JS_TEST_DIR=$SRC_DIR/test/javascript
-JS_BENCH_DIR=$SRC_DIR/test/bench
-
-COUCHJS=%abs_top_builddir%/src/couchdb/priv/couchjs
-
-cat $SCRIPT_DIR/json2.js \
- $SCRIPT_DIR/couch.js \
- $JS_TEST_DIR/couch_http.js \
- $JS_BENCH_DIR/bench_marks.js \
- $JS_TEST_DIR/cli_runner.js \
- | $COUCHJS -
-
diff --git a/test/etap/001-load.t b/test/etap/001-load.t
deleted file mode 100755
index 6f49e1ba..00000000
--- a/test/etap/001-load.t
+++ /dev/null
@@ -1,68 +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.
-
-% Test that we can load each module.
-
-main(_) ->
- test_util:init_code_path(),
- etap:plan(37),
- Modules = [
- couch_btree,
- couch_config,
- couch_config_writer,
- couch_db,
- couch_db_update_notifier,
- couch_db_update_notifier_sup,
- couch_db_updater,
- couch_doc,
- couch_event_sup,
- couch_external_manager,
- couch_external_server,
- couch_file,
- couch_httpd,
- couch_httpd_db,
- couch_httpd_external,
- couch_httpd_misc_handlers,
- couch_httpd_show,
- couch_httpd_stats_handlers,
- couch_httpd_view,
- couch_key_tree,
- couch_log,
- couch_os_process,
- couch_query_servers,
- couch_ref_counter,
- couch_rep,
- couch_rep_sup,
- couch_server,
- couch_server_sup,
- couch_stats_aggregator,
- couch_stats_collector,
- couch_stream,
- couch_task_status,
- couch_util,
- couch_view,
- couch_view_compactor,
- couch_view_group,
- couch_view_updater
- ],
-
- lists:foreach(
- fun(Module) ->
- etap_can:loaded_ok(
- Module,
- lists:concat(["Loaded: ", Module])
- )
- end, Modules),
- etap:end_tests().
diff --git a/test/etap/002-icu-driver.t b/test/etap/002-icu-driver.t
deleted file mode 100644
index d70f3303..00000000
--- a/test/etap/002-icu-driver.t
+++ /dev/null
@@ -1,33 +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.
-
-
-main(_) ->
- test_util:init_code_path(),
- etap:plan(3),
- etap:is(
- couch_util:start_driver("src/couchdb/priv/.libs"),
- ok,
- "Started couch_icu_driver."
- ),
- etap:is(
- couch_util:collate(<<"foo">>, <<"bar">>),
- 1,
- "Can collate stuff"
- ),
- etap:is(
- couch_util:collate(<<"A">>, <<"aa">>),
- -1,
- "Collate's non-ascii style."
- ),
- etap:end_tests().
diff --git a/test/etap/010-file-basics.t b/test/etap/010-file-basics.t
deleted file mode 100755
index a3599f1a..00000000
--- a/test/etap/010-file-basics.t
+++ /dev/null
@@ -1,107 +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.
-
-filename() -> test_util:build_file("test/etap/temp.010").
-
-main(_) ->
- test_util:init_code_path(),
- etap:plan(19),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail()
- end,
- ok.
-
-test() ->
- etap:is({error, enoent}, couch_file:open("not a real file"),
- "Opening a non-existant file should return an enoent error."),
-
- etap:fun_is(
- fun({ok, _}) -> true; (_) -> false end,
- couch_file:open(filename() ++ ".1", [create, invalid_option]),
- "Invalid flags to open are ignored."
- ),
-
- {ok, Fd} = couch_file:open(filename() ++ ".0", [create, overwrite]),
- etap:ok(is_pid(Fd),
- "Returned file descriptor is a Pid"),
-
- etap:is({ok, 0}, couch_file:bytes(Fd),
- "Newly created files have 0 bytes."),
-
- etap:is({ok, 0}, couch_file:append_term(Fd, foo),
- "Appending a term returns the previous end of file position."),
-
- {ok, Size} = couch_file:bytes(Fd),
- etap:is_greater(Size, 0,
- "Writing a term increased the file size."),
-
- etap:is({ok, Size}, couch_file:append_binary(Fd, <<"fancy!">>),
- "Appending a binary returns the current file size."),
-
- etap:is({ok, foo}, couch_file:pread_term(Fd, 0),
- "Reading the first term returns what we wrote: foo"),
-
- etap:is({ok, <<"fancy!">>}, couch_file:pread_binary(Fd, Size),
- "Reading back the binary returns what we wrote: <<\"fancy\">>."),
-
- etap:is({ok, <<131, 100, 0, 3, 102, 111, 111>>},
- couch_file:pread_binary(Fd, 0),
- "Reading a binary at a term position returns the term as binary."
- ),
-
- {ok, BinPos} = couch_file:append_binary(Fd, <<131,100,0,3,102,111,111>>),
- etap:is({ok, foo}, couch_file:pread_term(Fd, BinPos),
- "Reading a term from a written binary term representation succeeds."),
-
- BigBin = list_to_binary(lists:duplicate(100000, 0)),
- {ok, BigBinPos} = couch_file:append_binary(Fd, BigBin),
- etap:is({ok, BigBin}, couch_file:pread_binary(Fd, BigBinPos),
- "Reading a large term from a written representation succeeds."),
-
- ok = couch_file:write_header(Fd, hello),
- etap:is({ok, hello}, couch_file:read_header(Fd),
- "Reading a header succeeds."),
-
- {ok, BigBinPos2} = couch_file:append_binary(Fd, BigBin),
- etap:is({ok, BigBin}, couch_file:pread_binary(Fd, BigBinPos2),
- "Reading a large term from a written representation succeeds 2."),
-
- % append_binary == append_iolist?
- % Possible bug in pread_iolist or iolist() -> append_binary
- {ok, IOLPos} = couch_file:append_binary(Fd, ["foo", $m, <<"bam">>]),
- etap:is({ok, [<<"foombam">>]}, couch_file:pread_iolist(Fd, IOLPos),
- "Reading an results in a binary form of the written iolist()"),
-
- % XXX: How does on test fsync?
- etap:is(ok, couch_file:sync(Fd),
- "Syncing does not cause an error."),
-
- etap:is(ok, couch_file:truncate(Fd, Size),
- "Truncating a file succeeds."),
-
- %etap:is(eof, (catch couch_file:pread_binary(Fd, Size)),
- % "Reading data that was truncated fails.")
- etap:skip(fun() -> ok end,
- "No idea how to test reading beyond EOF"),
-
- etap:is({ok, foo}, couch_file:pread_term(Fd, 0),
- "Truncating does not affect data located before the truncation mark."),
-
- etap:is(ok, couch_file:close(Fd),
- "Files close properly."),
- ok.
diff --git a/test/etap/011-file-headers.t b/test/etap/011-file-headers.t
deleted file mode 100755
index 4705f629..00000000
--- a/test/etap/011-file-headers.t
+++ /dev/null
@@ -1,145 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-%%! -pa ./src/couchdb -sasl errlog_type error -boot start_sasl -noshell
-
-% 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.
-
-filename() -> test_util:build_file("test/etap/temp.011").
-sizeblock() -> 4096. % Need to keep this in sync with couch_file.erl
-
-main(_) ->
- test_util:init_code_path(),
- {S1, S2, S3} = now(),
- random:seed(S1, S2, S3),
-
- etap:plan(17),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail()
- end,
- ok.
-
-test() ->
- {ok, Fd} = couch_file:open(filename(), [create,overwrite]),
-
- etap:is({ok, 0}, couch_file:bytes(Fd),
- "File should be initialized to contain zero bytes."),
-
- etap:is(ok, couch_file:write_header(Fd, {<<"some_data">>, 32}),
- "Writing a header succeeds."),
-
- {ok, Size1} = couch_file:bytes(Fd),
- etap:is_greater(Size1, 0,
- "Writing a header allocates space in the file."),
-
- etap:is({ok, {<<"some_data">>, 32}}, couch_file:read_header(Fd),
- "Reading the header returns what we wrote."),
-
- etap:is(ok, couch_file:write_header(Fd, [foo, <<"more">>]),
- "Writing a second header succeeds."),
-
- {ok, Size2} = couch_file:bytes(Fd),
- etap:is_greater(Size2, Size1,
- "Writing a second header allocates more space."),
-
- etap:is({ok, [foo, <<"more">>]}, couch_file:read_header(Fd),
- "Reading the second header does not return the first header."),
-
- % Delete the second header.
- ok = couch_file:truncate(Fd, Size1),
-
- etap:is({ok, {<<"some_data">>, 32}}, couch_file:read_header(Fd),
- "Reading the header after a truncation returns a previous header."),
-
- couch_file:write_header(Fd, [foo, <<"more">>]),
- etap:is({ok, Size2}, couch_file:bytes(Fd),
- "Rewriting the same second header returns the same second size."),
-
- ok = couch_file:close(Fd),
-
- % Now for the fun stuff. Try corrupting the second header and see
- % if we recover properly.
-
- % Destroy the 0x1 byte that marks a header
- check_header_recovery(fun(CouchFd, RawFd, Expect, HeaderPos) ->
- etap:isnt(Expect, couch_file:read_header(CouchFd),
- "Should return a different header before corruption."),
- file:pwrite(RawFd, HeaderPos, <<0>>),
- etap:is(Expect, couch_file:read_header(CouchFd),
- "Corrupting the byte marker should read the previous header.")
- end),
-
- % Corrupt the size.
- check_header_recovery(fun(CouchFd, RawFd, Expect, HeaderPos) ->
- etap:isnt(Expect, couch_file:read_header(CouchFd),
- "Should return a different header before corruption."),
- % +1 for 0x1 byte marker
- file:pwrite(RawFd, HeaderPos+1, <<10/integer>>),
- etap:is(Expect, couch_file:read_header(CouchFd),
- "Corrupting the size should read the previous header.")
- end),
-
- % Corrupt the MD5 signature
- check_header_recovery(fun(CouchFd, RawFd, Expect, HeaderPos) ->
- etap:isnt(Expect, couch_file:read_header(CouchFd),
- "Should return a different header before corruption."),
- % +5 = +1 for 0x1 byte and +4 for term size.
- file:pwrite(RawFd, HeaderPos+5, <<"F01034F88D320B22">>),
- etap:is(Expect, couch_file:read_header(CouchFd),
- "Corrupting the MD5 signature should read the previous header.")
- end),
-
- % Corrupt the data
- check_header_recovery(fun(CouchFd, RawFd, Expect, HeaderPos) ->
- etap:isnt(Expect, couch_file:read_header(CouchFd),
- "Should return a different header before corruption."),
- % +21 = +1 for 0x1 byte, +4 for term size and +16 for MD5 sig
- file:pwrite(RawFd, HeaderPos+21, <<"some data goes here!">>),
- etap:is(Expect, couch_file:read_header(CouchFd),
- "Corrupting the header data should read the previous header.")
- end),
-
- ok.
-
-check_header_recovery(CheckFun) ->
- {ok, Fd} = couch_file:open(filename(), [create,overwrite]),
- {ok, RawFd} = file:open(filename(), [read, write, raw, binary]),
-
- {ok, _} = write_random_data(Fd),
- ExpectHeader = {some_atom, <<"a binary">>, 756},
- ok = couch_file:write_header(Fd, ExpectHeader),
-
- {ok, HeaderPos} = write_random_data(Fd),
- ok = couch_file:write_header(Fd, {2342, <<"corruption! greed!">>}),
-
- CheckFun(Fd, RawFd, {ok, ExpectHeader}, HeaderPos),
-
- ok = file:close(RawFd),
- ok = couch_file:close(Fd),
- ok.
-
-write_random_data(Fd) ->
- write_random_data(Fd, 100 + random:uniform(1000)).
-
-write_random_data(Fd, 0) ->
- {ok, Bytes} = couch_file:bytes(Fd),
- {ok, (1 + Bytes div sizeblock()) * sizeblock()};
-write_random_data(Fd, N) ->
- Choices = [foo, bar, <<"bizzingle">>, "bank", ["rough", stuff]],
- Term = lists:nth(random:uniform(4) + 1, Choices),
- {ok, _} = couch_file:append_term(Fd, Term),
- write_random_data(Fd, N-1).
-
diff --git a/test/etap/020-btree-basics.t b/test/etap/020-btree-basics.t
deleted file mode 100755
index 18c4a836..00000000
--- a/test/etap/020-btree-basics.t
+++ /dev/null
@@ -1,205 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-%%! -pa ./src/couchdb -sasl errlog_type error -boot start_sasl -noshell
-
-% 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.
-
-filename() -> test_util:build_file("test/etap/temp.020").
-rows() -> 250.
-
--record(btree, {fd, root, extract_kv, assemble_kv, less, reduce}).
-
-main(_) ->
- test_util:init_code_path(),
- etap:plan(48),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail()
- end,
- ok.
-
-%% @todo Determine if this number should be greater to see if the btree was
-%% broken into multiple nodes. AKA "How do we appropiately detect if multiple
-%% nodes were created."
-test()->
- Sorted = [{Seq, random:uniform()} || Seq <- lists:seq(1, rows())],
- etap:ok(test_kvs(Sorted), "Testing sorted keys"),
- etap:ok(test_kvs(lists:reverse(Sorted)), "Testing reversed sorted keys"),
- etap:ok(test_kvs(shuffle(Sorted)), "Testing shuffled keys."),
- ok.
-
-test_kvs(KeyValues) ->
- ReduceFun = fun
- (reduce, KVs) ->
- length(KVs);
- (rereduce, Reds) ->
- lists:sum(Reds)
- end,
-
- Keys = [K || {K, _} <- KeyValues],
-
- {ok, Fd} = couch_file:open(filename(), [create,overwrite]),
- {ok, Btree} = couch_btree:open(nil, Fd),
- etap:ok(is_record(Btree, btree), "Created btree is really a btree record"),
- etap:is(Btree#btree.fd, Fd, "Btree#btree.fd is set correctly."),
- etap:is(Btree#btree.root, nil, "Btree#btree.root is set correctly."),
-
- Btree1 = couch_btree:set_options(Btree, [{reduce, ReduceFun}]),
- etap:is(Btree1#btree.reduce, ReduceFun, "Reduce function was set"),
- {ok, _, EmptyRes} = couch_btree:foldl(Btree1, fun(_, X) -> {ok, X+1} end, 0),
- etap:is(EmptyRes, 0, "Folding over an empty btree"),
-
- {ok, Btree2} = couch_btree:add_remove(Btree1, KeyValues, []),
- etap:ok(test_btree(Btree2, KeyValues),
- "Adding all keys at once returns a complete btree."),
-
- etap:fun_is(
- fun
- ({ok, {kp_node, _}}) -> true;
- (_) -> false
- end,
- couch_file:pread_term(Fd, element(1, Btree2#btree.root)),
- "Btree root pointer is a kp_node."
- ),
-
- {ok, Btree3} = couch_btree:add_remove(Btree2, [], Keys),
- etap:ok(test_btree(Btree3, []),
- "Removing all keys at once returns an empty btree."),
-
- Btree4 = lists:foldl(fun(KV, BtAcc) ->
- {ok, BtAcc2} = couch_btree:add_remove(BtAcc, [KV], []),
- BtAcc2
- end, Btree3, KeyValues),
- etap:ok(test_btree(Btree4, KeyValues),
- "Adding all keys one at a time returns a complete btree."),
-
- Btree5 = lists:foldl(fun({K, _}, BtAcc) ->
- {ok, BtAcc2} = couch_btree:add_remove(BtAcc, [], [K]),
- BtAcc2
- end, Btree4, KeyValues),
- etap:ok(test_btree(Btree5, []),
- "Removing all keys one at a time returns an empty btree."),
-
- KeyValuesRev = lists:reverse(KeyValues),
- Btree6 = lists:foldl(fun(KV, BtAcc) ->
- {ok, BtAcc2} = couch_btree:add_remove(BtAcc, [KV], []),
- BtAcc2
- end, Btree5, KeyValuesRev),
- etap:ok(test_btree(Btree6, KeyValues),
- "Adding all keys in reverse order returns a complete btree."),
-
- {_, Rem2Keys0, Rem2Keys1} = lists:foldl(fun(X, {Count, Left, Right}) ->
- case Count rem 2 == 0 of
- true-> {Count+1, [X | Left], Right};
- false -> {Count+1, Left, [X | Right]}
- end
- end, {0, [], []}, KeyValues),
-
- etap:ok(test_add_remove(Btree6, Rem2Keys0, Rem2Keys1),
- "Add/Remove every other key."),
-
- etap:ok(test_add_remove(Btree6, Rem2Keys1, Rem2Keys0),
- "Add/Remove opposite every other key."),
-
- {ok, Btree7} = couch_btree:add_remove(Btree6, [], [K||{K,_}<-Rem2Keys1]),
- {ok, Btree8} = couch_btree:add_remove(Btree7, [], [K||{K,_}<-Rem2Keys0]),
- etap:ok(test_btree(Btree8, []),
- "Removing both halves of every other key returns an empty btree."),
-
- %% Third chunk (close out)
- etap:is(couch_file:close(Fd), ok, "closing out"),
- true.
-
-test_btree(Btree, KeyValues) ->
- ok = test_key_access(Btree, KeyValues),
- ok = test_lookup_access(Btree, KeyValues),
- ok = test_final_reductions(Btree, KeyValues),
- true.
-
-test_add_remove(Btree, OutKeyValues, RemainingKeyValues) ->
- Btree2 = lists:foldl(fun({K, _}, BtAcc) ->
- {ok, BtAcc2} = couch_btree:add_remove(BtAcc, [], [K]),
- BtAcc2
- end, Btree, OutKeyValues),
- true = test_btree(Btree2, RemainingKeyValues),
-
- Btree3 = lists:foldl(fun(KV, BtAcc) ->
- {ok, BtAcc2} = couch_btree:add_remove(BtAcc, [KV], []),
- BtAcc2
- end, Btree2, OutKeyValues),
- true = test_btree(Btree3, OutKeyValues ++ RemainingKeyValues).
-
-test_key_access(Btree, List) ->
- FoldFun = fun(Element, {[HAcc|TAcc], Count}) ->
- case Element == HAcc of
- true -> {ok, {TAcc, Count + 1}};
- _ -> {ok, {TAcc, Count + 1}}
- end
- end,
- Length = length(List),
- Sorted = lists:sort(List),
- {ok, _, {[], Length}} = couch_btree:foldl(Btree, FoldFun, {Sorted, 0}),
- {ok, _, {[], Length}} = couch_btree:fold(Btree, FoldFun, {Sorted, 0}, [{dir, rev}]),
- ok.
-
-test_lookup_access(Btree, KeyValues) ->
- FoldFun = fun({Key, Value}, {Key, Value}) -> {stop, true} end,
- lists:foreach(fun({Key, Value}) ->
- [{ok, {Key, Value}}] = couch_btree:lookup(Btree, [Key]),
- {ok, _, true} = couch_btree:foldl(Btree, FoldFun, {Key, Value}, [{start_key, Key}])
- end, KeyValues).
-
-test_final_reductions(Btree, KeyValues) ->
- KVLen = length(KeyValues),
- FoldLFun = fun(_X, LeadingReds, Acc) ->
- CountToStart = KVLen div 3 + Acc,
- CountToStart = couch_btree:final_reduce(Btree, LeadingReds),
- {ok, Acc+1}
- end,
- FoldRFun = fun(_X, LeadingReds, Acc) ->
- CountToEnd = KVLen - KVLen div 3 + Acc,
- CountToEnd = couch_btree:final_reduce(Btree, LeadingReds),
- {ok, Acc+1}
- end,
- {LStartKey, _} = case KVLen of
- 0 -> {nil, nil};
- _ -> lists:nth(KVLen div 3 + 1, lists:sort(KeyValues))
- end,
- {RStartKey, _} = case KVLen of
- 0 -> {nil, nil};
- _ -> lists:nth(KVLen div 3, lists:sort(KeyValues))
- end,
- {ok, _, FoldLRed} = couch_btree:foldl(Btree, FoldLFun, 0, [{start_key, LStartKey}]),
- {ok, _, FoldRRed} = couch_btree:fold(Btree, FoldRFun, 0, [{dir, rev}, {start_key, RStartKey}]),
- KVLen = FoldLRed + FoldRRed,
- ok.
-
-shuffle(List) ->
- randomize(round(math:log(length(List)) + 0.5), List).
-
-randomize(1, List) ->
- randomize(List);
-randomize(T, List) ->
- lists:foldl(fun(_E, Acc) ->
- randomize(Acc)
- end, randomize(List), lists:seq(1, (T - 1))).
-
-randomize(List) ->
- D = lists:map(fun(A) ->
- {random:uniform(), A}
- end, List),
- {_, D1} = lists:unzip(lists:keysort(1, D)),
- D1.
diff --git a/test/etap/021-btree-reductions.t b/test/etap/021-btree-reductions.t
deleted file mode 100755
index 3e19c767..00000000
--- a/test/etap/021-btree-reductions.t
+++ /dev/null
@@ -1,141 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-%%! -pa ./src/couchdb -sasl errlog_type error -boot start_sasl -noshell
-
-% 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.
-
-filename() -> "./test/etap/temp.021".
-rows() -> 1000.
-
-main(_) ->
- test_util:init_code_path(),
- etap:plan(8),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail()
- end,
- ok.
-
-test()->
- ReduceFun = fun
- (reduce, KVs) -> length(KVs);
- (rereduce, Reds) -> lists:sum(Reds)
- end,
-
- {ok, Fd} = couch_file:open(filename(), [create,overwrite]),
- {ok, Btree} = couch_btree:open(nil, Fd, [{reduce, ReduceFun}]),
-
- % Create a list, of {"even", Value} or {"odd", Value} pairs.
- {_, EvenOddKVs} = lists:foldl(fun(Idx, {Key, Acc}) ->
- case Key of
- "even" -> {"odd", [{{Key, Idx}, 1} | Acc]};
- _ -> {"even", [{{Key, Idx}, 1} | Acc]}
- end
- end, {"odd", []}, lists:seq(1, rows())),
-
- {ok, Btree2} = couch_btree:add_remove(Btree, EvenOddKVs, []),
-
- GroupFun = fun({K1, _}, {K2, _}) -> K1 == K2 end,
- FoldFun = fun(GroupedKey, Unreduced, Acc) ->
- {ok, [{GroupedKey, couch_btree:final_reduce(Btree2, Unreduced)} | Acc]}
- end,
-
- {SK1, EK1} = {{"even", -1}, {"even", foo}},
- {SK2, EK2} = {{"odd", -1}, {"odd", foo}},
-
- etap:fun_is(
- fun
- ({ok, [{{"odd", _}, 500}, {{"even", _}, 500}]}) ->
- true;
- (_) ->
- false
- end,
- couch_btree:fold_reduce(Btree2, FoldFun, [], [{key_group_fun, GroupFun}]),
- "Reduction works with no specified direction, startkey, or endkey."
- ),
-
- etap:fun_is(
- fun
- ({ok, [{{"odd", _}, 500}, {{"even", _}, 500}]}) ->
- true;
- (_) ->
- false
- end,
- couch_btree:fold_reduce(Btree2, FoldFun, [], [{key_group_fun, GroupFun}, {dir, fwd}]),
- "Reducing forward works with no startkey or endkey."
- ),
-
- etap:fun_is(
- fun
- ({ok, [{{"even", _}, 500}, {{"odd", _}, 500}]}) ->
- true;
- (_) ->
- false
- end,
- couch_btree:fold_reduce(Btree2, FoldFun, [], [{key_group_fun, GroupFun}, {dir, rev}]),
- "Reducing backwards works with no startkey or endkey."
- ),
-
- etap:fun_is(
- fun
- ({ok, [{{"odd", _}, 500}, {{"even", _}, 500}]}) ->
- true;
- (_) ->
- false
- end,
- couch_btree:fold_reduce(Btree2, FoldFun, [], [{dir, fwd}, {key_group_fun, GroupFun}, {start_key, SK1}, {end_key, EK2}]),
- "Reducing works over the entire range with startkey and endkey set."
- ),
-
- etap:fun_is(
- fun
- ({ok, [{{"even", _}, 500}]}) -> true;
- (_) -> false
- end,
- couch_btree:fold_reduce(Btree2, FoldFun, [], [{dir, fwd}, {key_group_fun, GroupFun}, {start_key, SK1}, {end_key, EK1}]),
- "Reducing foward over first half works with a startkey and endkey."
- ),
-
- etap:fun_is(
- fun
- ({ok, [{{"odd", _}, 500}]}) -> true;
- (_) -> false
- end,
- couch_btree:fold_reduce(Btree2, FoldFun, [], [{dir, fwd}, {key_group_fun, GroupFun}, {start_key, SK2}, {end_key, EK2}]),
- "Reducing foward over second half works with second startkey and endkey"
- ),
-
- etap:fun_is(
- fun
- ({ok, [{{"odd", _}, 500}]}) -> true;
- (_) -> false
- end,
- couch_btree:fold_reduce(Btree2, FoldFun, [], [{dir, rev}, {key_group_fun, GroupFun}, {start_key, EK2}, {end_key, SK2}]),
- "Reducing in reverse works after swapping the startkey and endkey."
- ),
-
- etap:fun_is(
- fun
- ({ok, [{{"even", _}, 500}, {{"odd", _}, 500}]}) ->
- true;
- (_) ->
- false
- end,
- couch_btree:fold_reduce(Btree2, FoldFun, [], [{dir, rev}, {key_group_fun, GroupFun}, {start_key, EK2}, {end_key, SK1}]),
- "Reducing in reverse results in reversed accumulator."
- ),
-
- couch_file:close(Fd).
diff --git a/test/etap/030-doc-from-json.t b/test/etap/030-doc-from-json.t
deleted file mode 100755
index c4ef649a..00000000
--- a/test/etap/030-doc-from-json.t
+++ /dev/null
@@ -1,239 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-%%! -pa ./src/couchdb -pa ./src/mochiweb -sasl errlog_type false -noshell
-
-% 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={[]},
- atts=[], deleted=false, meta=[]}).
--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),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail()
- end,
- 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.
-
-test_from_json_success() ->
- Cases = [
- {
- {[]},
- #doc{},
- "Return an empty document for an empty JSON object."
- },
- {
- {[{<<"_id">>, <<"zing!">>}]},
- #doc{id= <<"zing!">>},
- "Parses document ids."
- },
- {
- {[{<<"_id">>, <<"_design/foo">>}]},
- #doc{id= <<"_design/foo">>},
- "_design/document ids."
- },
- {
- {[{<<"_id">>, <<"_local/bam">>}]},
- #doc{id= <<"_local/bam">>},
- "_local/document ids."
- },
- {
- {[{<<"_rev">>, <<"4-230234">>}]},
- #doc{revs={4, [<<"230234">>]}},
- "_rev stored in revs."
- },
- {
- {[{<<"soap">>, 35}]},
- #doc{body={[{<<"soap">>, 35}]}},
- "Non underscore prefixed fields stored in body."
- },
- {
- {[{<<"_attachments">>, {[
- {<<"my_attachment.fu">>, {[
- {<<"stub">>, true},
- {<<"content_type">>, <<"application/awesome">>},
- {<<"length">>, 45}
- ]}},
- {<<"noahs_private_key.gpg">>, {[
- {<<"data">>, <<"SSBoYXZlIGEgcGV0IGZpc2gh">>},
- {<<"content_type">>, <<"application/pgp-signature">>}
- ]}}
- ]}}]},
- #doc{atts=[
- #att{
- name = <<"my_attachment.fu">>,
- data = stub,
- type = <<"application/awesome">>,
- att_len = 45,
- disk_len = 45,
- revpos = nil
- },
- #att{
- name = <<"noahs_private_key.gpg">>,
- data = <<"I have a pet fish!">>,
- type = <<"application/pgp-signature">>,
- att_len = 18,
- disk_len = 18,
- revpos = 0
- }
- ]},
- "Attachments are parsed correctly."
- },
- {
- {[{<<"_deleted">>, true}]},
- #doc{deleted=true},
- "_deleted controls the deleted field."
- },
- {
- {[{<<"_deleted">>, false}]},
- #doc{},
- "{\"_deleted\": false} is ok."
- },
- {
- {[
- {<<"_revisions">>, {[
- {<<"start">>, 4},
- {<<"ids">>, [<<"foo1">>, <<"phi3">>, <<"omega">>]}
- ]}},
- {<<"_rev">>, <<"6-something">>}
- ]},
- #doc{revs={4, [<<"foo1">>, <<"phi3">>, <<"omega">>]}},
- "_revisions attribute are preferred to _rev."
- },
- {
- {[{<<"_revs_info">>, dropping}]},
- #doc{},
- "Drops _revs_info."
- },
- {
- {[{<<"_local_seq">>, dropping}]},
- #doc{},
- "Drops _local_seq."
- },
- {
- {[{<<"_conflicts">>, dropping}]},
- #doc{},
- "Drops _conflicts."
- },
- {
- {[{<<"_deleted_conflicts">>, dropping}]},
- #doc{},
- "Drops _deleted_conflicts."
- }
- ],
-
- lists:foreach(fun({EJson, Expect, Mesg}) ->
- etap:is(couch_doc:from_json_obj(EJson), Expect, Mesg)
- end, Cases),
- ok.
-
-test_from_json_errors() ->
- Cases = [
- {
- [],
- {bad_request, "Document must be a JSON object"},
- "arrays are invalid"
- },
- {
- 4,
- {bad_request, "Document must be a JSON object"},
- "integers are invalid"
- },
- {
- true,
- {bad_request, "Document must be a JSON object"},
- "literals are invalid"
- },
- {
- {[{<<"_id">>, {[{<<"foo">>, 5}]}}]},
- {bad_request, <<"Document id must be a string">>},
- "Document id must be a string."
- },
- {
- {[{<<"_id">>, <<"_random">>}]},
- {bad_request,
- <<"Only reserved document ids may start with underscore.">>},
- "Disallow arbitrary underscore prefixed docids."
- },
- {
- {[{<<"_rev">>, 5}]},
- {bad_request, <<"Invalid rev format">>},
- "_rev must be a string"
- },
- {
- {[{<<"_rev">>, "foobar"}]},
- {bad_request, <<"Invalid rev format">>},
- "_rev must be %d-%s"
- },
- {
- {[{<<"_rev">>, "foo-bar"}]},
- "Error if _rev's integer expection is broken."
- },
- {
- {[{<<"_revisions">>, {[{<<"start">>, true}]}}]},
- {doc_validation, "_revisions.start isn't an integer."},
- "_revisions.start must be an integer."
- },
- {
- {[{<<"_revisions">>, {[
- {<<"start">>, 0},
- {<<"ids">>, 5}
- ]}}]},
- {doc_validation, "_revisions.ids isn't a array."},
- "_revions.ids must be a list."
- },
- {
- {[{<<"_revisions">>, {[
- {<<"start">>, 0},
- {<<"ids">>, [5]}
- ]}}]},
- {doc_validation, "RevId isn't a string"},
- "Revision ids must be strings."
- },
- {
- {[{<<"_something">>, 5}]},
- {doc_validation, <<"Bad special document member: _something">>},
- "Underscore prefix fields are reserved."
- }
- ],
-
- lists:foreach(fun
- ({EJson, Expect, Mesg}) ->
- Error = (catch couch_doc:from_json_obj(EJson)),
- etap:is(Error, Expect, Mesg);
- ({EJson, Mesg}) ->
- try
- couch_doc:from_json_obj(EJson),
- etap:ok(false, "Conversion failed to raise an exception.")
- catch
- _:_ -> etap:ok(true, Mesg)
- end
- end, Cases),
- ok.
diff --git a/test/etap/031-doc-to-json.t b/test/etap/031-doc-to-json.t
deleted file mode 100755
index 605a6d00..00000000
--- a/test/etap/031-doc-to-json.t
+++ /dev/null
@@ -1,200 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang -*-
-%%! -pa ./src/couchdb -pa ./src/mochiweb -sasl errlog_type false -noshell
-
-% 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={[]},
- atts=[], deleted=false, meta=[]}).
--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),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail()
- end,
- ok.
-
-test() ->
- couch_config:start_link([default_config()]),
- couch_config:set("attachments", "compression_level", "0"),
- ok = test_to_json_success(),
- ok.
-
-test_to_json_success() ->
- Cases = [
- {
- #doc{},
- {[{<<"_id">>, <<"">>}]},
- "Empty docs are {\"_id\": \"\"}"
- },
- {
- #doc{id= <<"foo">>},
- {[{<<"_id">>, <<"foo">>}]},
- "_id is added."
- },
- {
- #doc{revs={5, ["foo"]}},
- {[{<<"_id">>, <<>>}, {<<"_rev">>, <<"5-foo">>}]},
- "_rev is added."
- },
- {
- [revs],
- #doc{revs={5, [<<"first">>, <<"second">>]}},
- {[
- {<<"_id">>, <<>>},
- {<<"_rev">>, <<"5-first">>},
- {<<"_revisions">>, {[
- {<<"start">>, 5},
- {<<"ids">>, [<<"first">>, <<"second">>]}
- ]}}
- ]},
- "_revisions include with revs option"
- },
- {
- #doc{body={[{<<"foo">>, <<"bar">>}]}},
- {[{<<"_id">>, <<>>}, {<<"foo">>, <<"bar">>}]},
- "Arbitrary fields are added."
- },
- {
- #doc{deleted=true, body={[{<<"foo">>, <<"bar">>}]}},
- {[{<<"_id">>, <<>>}, {<<"foo">>, <<"bar">>}, {<<"_deleted">>, true}]},
- "Deleted docs no longer drop body members."
- },
- {
- #doc{meta=[
- {revs_info, 4, [{<<"fin">>, deleted}, {<<"zim">>, missing}]}
- ]},
- {[
- {<<"_id">>, <<>>},
- {<<"_revs_info">>, [
- {[{<<"rev">>, <<"4-fin">>}, {<<"status">>, <<"deleted">>}]},
- {[{<<"rev">>, <<"3-zim">>}, {<<"status">>, <<"missing">>}]}
- ]}
- ]},
- "_revs_info field is added correctly."
- },
- {
- #doc{meta=[{local_seq, 5}]},
- {[{<<"_id">>, <<>>}, {<<"_local_seq">>, 5}]},
- "_local_seq is added as an integer."
- },
- {
- #doc{meta=[{conflicts, [{3, <<"yep">>}, {1, <<"snow">>}]}]},
- {[
- {<<"_id">>, <<>>},
- {<<"_conflicts">>, [<<"3-yep">>, <<"1-snow">>]}
- ]},
- "_conflicts is added as an array of strings."
- },
- {
- #doc{meta=[{deleted_conflicts, [{10923, <<"big_cowboy_hat">>}]}]},
- {[
- {<<"_id">>, <<>>},
- {<<"_deleted_conflicts">>, [<<"10923-big_cowboy_hat">>]}
- ]},
- "_deleted_conflicsts is added as an array of strings."
- },
- {
- #doc{atts=[
- #att{
- 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">>,
- data = <<"{\"so\": \"there!\"}">>,
- revpos = 1,
- att_len = 16,
- disk_len = 16
- }
- ]},
- {[
- {<<"_id">>, <<>>},
- {<<"_attachments">>, {[
- {<<"big.xml">>, {[
- {<<"content_type">>, <<"xml/sucks">>},
- {<<"revpos">>, 1},
- {<<"length">>, 400},
- {<<"stub">>, true}
- ]}},
- {<<"fast.json">>, {[
- {<<"content_type">>, <<"json/ftw">>},
- {<<"revpos">>, 1},
- {<<"length">>, 16},
- {<<"stub">>, true}
- ]}}
- ]}}
- ]},
- "Attachments attached as stubs only include a length."
- },
- {
- [attachments],
- #doc{atts=[
- #att{
- name = <<"stuff.txt">>,
- type = <<"text/plain">>,
- data = fun() -> <<"diet pepsi">> end,
- revpos = 1,
- att_len = 10,
- disk_len = 10
- },
- #att{
- name = <<"food.now">>,
- type = <<"application/food">>,
- revpos = 1,
- data = <<"sammich">>
- }
- ]},
- {[
- {<<"_id">>, <<>>},
- {<<"_attachments">>, {[
- {<<"stuff.txt">>, {[
- {<<"content_type">>, <<"text/plain">>},
- {<<"revpos">>, 1},
- {<<"data">>, <<"ZGlldCBwZXBzaQ==">>}
- ]}},
- {<<"food.now">>, {[
- {<<"content_type">>, <<"application/food">>},
- {<<"revpos">>, 1},
- {<<"data">>, <<"c2FtbWljaA==">>}
- ]}}
- ]}}
- ]},
- "Attachments included inline with attachments option."
- }
- ],
-
- lists:foreach(fun
- ({Doc, EJson, Mesg}) ->
- etap:is(couch_doc:to_json_obj(Doc, []), EJson, Mesg);
- ({Options, Doc, EJson, Mesg}) ->
- etap:is(couch_doc:to_json_obj(Doc, Options), EJson, Mesg)
- end, Cases),
- ok.
-
diff --git a/test/etap/040-util.t b/test/etap/040-util.t
deleted file mode 100755
index 8f80db87..00000000
--- a/test/etap/040-util.t
+++ /dev/null
@@ -1,80 +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(),
- application:start(crypto),
-
- etap:plan(14),
- 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() ->
- % to_existing_atom
- etap:is(true, couch_util:to_existing_atom(true), "An atom is an atom."),
- etap:is(foo, couch_util:to_existing_atom(<<"foo">>),
- "A binary foo is the atom foo."),
- etap:is(foobarbaz, couch_util:to_existing_atom("foobarbaz"),
- "A list of atoms is one munged atom."),
-
- % implode
- etap:is([1, 38, 2, 38, 3], couch_util:implode([1,2,3],"&"),
- "use & as separator in list."),
-
- % trim
- Strings = [" foo", "foo ", "\tfoo", " foo ", "foo\t", "foo\n", "\nfoo"],
- etap:ok(lists:all(fun(S) -> couch_util:trim(S) == "foo" end, Strings),
- "everything here trimmed should be foo."),
-
- % abs_pathname
- {ok, Cwd} = file:get_cwd(),
- etap:is(Cwd ++ "/foo", couch_util:abs_pathname("./foo"),
- "foo is in this directory."),
-
- % should_flush
- etap:ok(not couch_util:should_flush(),
- "Not using enough memory to flush."),
- AcquireMem = fun() ->
- IntsToAGazillion = lists:seq(1, 200000),
- LotsOfData = lists:map(
- fun(Int) -> {Int, <<"foobar">>} end,
- lists:seq(1, 500000)),
- etap:ok(couch_util:should_flush(),
- "Allocation 200K tuples puts us above the memory threshold.")
- end,
- AcquireMem(),
-
- etap:ok(not couch_util:should_flush(),
- "Checking to flush invokes GC."),
-
- % verify
- etap:is(true, couch_util:verify("It4Vooya", "It4Vooya"),
- "String comparison."),
- etap:is(false, couch_util:verify("It4VooyaX", "It4Vooya"),
- "String comparison (unequal lengths)."),
- etap:is(true, couch_util:verify(<<"ahBase3r">>, <<"ahBase3r">>),
- "Binary comparison."),
- etap:is(false, couch_util:verify(<<"ahBase3rX">>, <<"ahBase3r">>),
- "Binary comparison (unequal lengths)."),
- etap:is(false, couch_util:verify(nil, <<"ahBase3r">>),
- "Binary comparison with atom."),
-
- ok.
diff --git a/test/etap/041-uuid-gen-seq.ini b/test/etap/041-uuid-gen-seq.ini
deleted file mode 100644
index 94cebc6f..00000000
--- a/test/etap/041-uuid-gen-seq.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-; Licensed to the Apache Software Foundation (ASF) under one
-; or more contributor license agreements. See the NOTICE file
-; distributed with this work for additional information
-; regarding copyright ownership. The ASF licenses this file
-; to you 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.
-
-[uuids]
-algorithm = sequential
diff --git a/test/etap/041-uuid-gen-utc.ini b/test/etap/041-uuid-gen-utc.ini
deleted file mode 100644
index c2b83831..00000000
--- a/test/etap/041-uuid-gen-utc.ini
+++ /dev/null
@@ -1,19 +0,0 @@
-; Licensed to the Apache Software Foundation (ASF) under one
-; or more contributor license agreements. See the NOTICE file
-; distributed with this work for additional information
-; regarding copyright ownership. The ASF licenses this file
-; to you 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.
-
-[uuids]
-algorithm = utc_random
diff --git a/test/etap/041-uuid-gen.t b/test/etap/041-uuid-gen.t
deleted file mode 100755
index 1e6aa9ee..00000000
--- a/test/etap/041-uuid-gen.t
+++ /dev/null
@@ -1,118 +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").
-
-seq_alg_config() ->
- test_util:source_file("test/etap/041-uuid-gen-seq.ini").
-
-utc_alg_config() ->
- test_util:source_file("test/etap/041-uuid-gen-utc.ini").
-
-% Run tests and wait for the gen_servers to shutdown
-run_test(IniFiles, Test) ->
- {ok, Pid} = couch_config:start_link(IniFiles),
- erlang:monitor(process, Pid),
- couch_uuids:start(),
- Test(),
- couch_uuids:stop(),
- couch_config:stop(),
- receive
- {'DOWN', _, _, Pid, _} -> ok;
- _Other -> etap:diag("OTHER: ~p~n", [_Other])
- after
- 1000 -> throw({timeout_error, config_stop})
- end.
-
-main(_) ->
- test_util:init_code_path(),
- application:start(crypto),
- 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() ->
-
- TestUnique = fun() ->
- etap:is(
- test_unique(10000, couch_uuids:new()),
- true,
- "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),
-
- TestMonotonic = fun () ->
- etap:is(
- couch_uuids:new() < couch_uuids:new(),
- true,
- "should produce monotonically increasing ids"
- )
- end,
- run_test([default_config(), seq_alg_config()], TestMonotonic),
- run_test([default_config(), 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
- % approximately Total / (Range/2 + RangeMin) samples.
- %
- % In our case this works out to be 8194. (0xFFF000 / 0x7FF)
- % These tests just fudge the limits for a good generator at 25%
- % in either direction. Technically it should be possible to generate
- % bounds that will show if your random number generator is not
- % sufficiently random but I hated statistics in school.
- TestRollOver = fun() ->
- 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:is(
- N >= 5000 andalso N =< 11000,
- true,
- "should roll over every so often."
- )
- end,
- run_test([default_config(), seq_alg_config()], TestRollOver).
-
-test_unique(0, _) ->
- true;
-test_unique(N, UUID) ->
- case couch_uuids:new() of
- UUID ->
- etap:diag("N: ~p~n", [N]),
- false;
- Else -> test_unique(N-1, Else)
- end.
-
-get_prefix(UUID) ->
- element(1, lists:split(26, binary_to_list(UUID))).
-
-gen_until_pref_change(_, Count) when Count > 8251 ->
- Count;
-gen_until_pref_change(Prefix, N) ->
- case get_prefix(couch_uuids:new()) of
- Prefix -> gen_until_pref_change(Prefix, N+1);
- _ -> N
- end.
diff --git a/test/etap/050-stream.t b/test/etap/050-stream.t
deleted file mode 100755
index 545dd524..00000000
--- a/test/etap/050-stream.t
+++ /dev/null
@@ -1,87 +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(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.
-
-read_all(Fd, PosList) ->
- Data = couch_stream:foldl(Fd, PosList, fun(Bin, Acc) -> [Bin, Acc] end, []),
- iolist_to_binary(Data).
-
-test() ->
- {ok, Fd} = couch_file:open("test/etap/temp.050", [create,overwrite]),
- {ok, Stream} = couch_stream:open(Fd),
-
- etap:is(ok, couch_stream:write(Stream, <<"food">>),
- "Writing to streams works."),
-
- etap:is(ok, couch_stream:write(Stream, <<"foob">>),
- "Consecutive writing to streams works."),
-
- etap:is(ok, couch_stream:write(Stream, <<>>),
- "Writing an empty binary does nothing."),
-
- {Ptrs, Length, _, _, _} = couch_stream:close(Stream),
- etap:is(Ptrs, [0], "Close returns the file pointers."),
- etap:is(Length, 8, "Close also returns the number of bytes written."),
- etap:is(<<"foodfoob">>, read_all(Fd, Ptrs), "Returned pointers are valid."),
-
- % Remeber where we expect the pointer to be.
- {ok, ExpPtr} = couch_file:bytes(Fd),
- {ok, Stream2} = couch_stream:open(Fd),
- OneBits = <<1:(8*10)>>,
- etap:is(ok, couch_stream:write(Stream2, OneBits),
- "Successfully wrote 80 1 bits."),
-
- ZeroBits = <<0:(8*10)>>,
- etap:is(ok, couch_stream:write(Stream2, ZeroBits),
- "Successfully wrote 80 0 bits."),
-
- {Ptrs2, Length2, _, _, _} = couch_stream:close(Stream2),
- etap:is(Ptrs2, [ExpPtr], "Closing stream returns the file pointers."),
- etap:is(Length2, 20, "Length written is 160 bytes."),
-
- AllBits = iolist_to_binary([OneBits,ZeroBits]),
- etap:is(AllBits, read_all(Fd, Ptrs2), "Returned pointers are valid."),
-
- % Stream more the 4K chunk size.
- {ok, ExpPtr2} = couch_file:bytes(Fd),
- {ok, Stream3} = couch_stream:open(Fd),
- Acc2 = lists:foldl(fun(_, Acc) ->
- Data = <<"a1b2c">>,
- couch_stream:write(Stream3, Data),
- [Data | Acc]
- end, [], lists:seq(1, 1024)),
- {Ptrs3, Length3, _, _, _} = couch_stream:close(Stream3),
-
- % 4095 because of 5 * 4096 rem 5 (last write before exceeding threshold)
- % + 5 puts us over the threshold
- % + 4 bytes for the term_to_binary adding a length header
- % + 1 byte every 4K for tail append headers
- SecondPtr = ExpPtr2 + 4095 + 5 + 4 + 1,
- etap:is(Ptrs3, [ExpPtr2, SecondPtr], "Pointers every 4K bytes."),
- etap:is(Length3, 5120, "Wrote the expected 5K bytes."),
-
- couch_file:close(Fd),
- ok.
diff --git a/test/etap/060-kt-merging.t b/test/etap/060-kt-merging.t
deleted file mode 100755
index d6b13d6d..00000000
--- a/test/etap/060-kt-merging.t
+++ /dev/null
@@ -1,140 +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(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() ->
- EmptyTree = [],
- One = [{0, {"1","foo",[]}}],
- TwoSibs = [{0, {"1","foo",[]}},
- {0, {"2","foo",[]}}],
- OneChild = [{0, {"1","foo",[{"1a", "bar", []}]}}],
- TwoChild = [{0, {"1","foo", [{"1a", "bar", [{"1aa", "bar", []}]}]}}],
- TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []},
- {"1b", "bar", []}]}}],
- TwoChildSibs2 = [{0, {"1","foo", [{"1a", "bar", []},
- {"1b", "bar", [{"1bb", "boo", []}]}]}}],
- Stemmed1b = [{1, {"1a", "bar", []}}],
- Stemmed1a = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}],
- Stemmed1aa = [{2, {"1aa", "bar", []}}],
- Stemmed1bb = [{2, {"1bb", "boo", []}}],
-
- etap:is(
- {EmptyTree, no_conflicts},
- couch_key_tree:merge(EmptyTree, EmptyTree),
- "Merging two empty trees yields an empty tree."
- ),
-
- etap:is(
- {One, no_conflicts},
- couch_key_tree:merge(EmptyTree, One),
- "The empty tree is the identity for merge."
- ),
-
- etap:is(
- {One, no_conflicts},
- couch_key_tree:merge(One, EmptyTree),
- "Merging is commutative."
- ),
-
- etap:is(
- {TwoSibs, no_conflicts},
- couch_key_tree:merge(One, TwoSibs),
- "Merging a prefix of a tree with the tree yields the tree."
- ),
-
- etap:is(
- {One, no_conflicts},
- couch_key_tree:merge(One, One),
- "Merging is reflexive."
- ),
-
- etap:is(
- {TwoChild, no_conflicts},
- couch_key_tree:merge(TwoChild, TwoChild),
- "Merging two children is still reflexive."
- ),
-
- etap:is(
- {TwoChildSibs, no_conflicts},
- couch_key_tree:merge(TwoChildSibs, TwoChildSibs),
- "Merging a tree to itself is itself."),
-
- etap:is(
- {TwoChildSibs, no_conflicts},
- couch_key_tree:merge(TwoChildSibs, Stemmed1b),
- "Merging a tree with a stem."
- ),
-
- etap:is(
- {TwoChildSibs, no_conflicts},
- couch_key_tree:merge(Stemmed1b, TwoChildSibs),
- "Merging in the opposite direction."
- ),
-
- etap:is(
- {TwoChildSibs2, no_conflicts},
- couch_key_tree:merge(TwoChildSibs2, Stemmed1bb),
- "Merging a stem at a deeper level."
- ),
-
- etap:is(
- {TwoChildSibs2, no_conflicts},
- couch_key_tree:merge(Stemmed1bb, TwoChildSibs2),
- "Merging a deeper level in opposite order."
- ),
-
- etap:is(
- {TwoChild, no_conflicts},
- couch_key_tree:merge(TwoChild, Stemmed1aa),
- "Merging a single tree with a deeper stem."
- ),
-
- etap:is(
- {TwoChild, no_conflicts},
- couch_key_tree:merge(TwoChild, Stemmed1a),
- "Merging a larger stem."
- ),
-
- etap:is(
- {Stemmed1a, no_conflicts},
- couch_key_tree:merge(Stemmed1a, Stemmed1aa),
- "More merging."
- ),
-
- Expect1 = OneChild ++ Stemmed1aa,
- etap:is(
- {Expect1, conflicts},
- couch_key_tree:merge(OneChild, Stemmed1aa),
- "Merging should create conflicts."
- ),
-
- etap:is(
- {TwoChild, no_conflicts},
- couch_key_tree:merge(Expect1, TwoChild),
- "Merge should have no conflicts."
- ),
-
- ok.
diff --git a/test/etap/061-kt-missing-leaves.t b/test/etap/061-kt-missing-leaves.t
deleted file mode 100755
index d60b4db8..00000000
--- a/test/etap/061-kt-missing-leaves.t
+++ /dev/null
@@ -1,65 +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() ->
- TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []}, {"1b", "bar", []}]}}],
- Stemmed1 = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}],
- Stemmed2 = [{2, {"1aa", "bar", []}}],
-
- etap:is(
- [],
- couch_key_tree:find_missing(TwoChildSibs, [{0,"1"}, {1,"1a"}]),
- "Look for missing keys."
- ),
-
- etap:is(
- [{0, "10"}, {100, "x"}],
- couch_key_tree:find_missing(
- TwoChildSibs,
- [{0,"1"}, {0, "10"}, {1,"1a"}, {100, "x"}]
- ),
- "Look for missing keys."
- ),
-
- etap:is(
- [{0, "1"}, {100, "x"}],
- couch_key_tree:find_missing(
- Stemmed1,
- [{0,"1"}, {1,"1a"}, {100, "x"}]
- ),
- "Look for missing keys."
- ),
- etap:is(
- [{0, "1"}, {1,"1a"}, {100, "x"}],
- couch_key_tree:find_missing(
- Stemmed2,
- [{0,"1"}, {1,"1a"}, {100, "x"}]
- ),
- "Look for missing keys."
- ),
-
- ok.
diff --git a/test/etap/062-kt-remove-leaves.t b/test/etap/062-kt-remove-leaves.t
deleted file mode 100755
index 745a00be..00000000
--- a/test/etap/062-kt-remove-leaves.t
+++ /dev/null
@@ -1,69 +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(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() ->
- OneChild = [{0, {"1","foo",[{"1a", "bar", []}]}}],
- TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []}, {"1b", "bar", []}]}}],
- Stemmed = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}],
-
- etap:is(
- {TwoChildSibs, []},
- couch_key_tree:remove_leafs(TwoChildSibs, []),
- "Removing no leaves has no effect on the tree."
- ),
-
- etap:is(
- {TwoChildSibs, []},
- couch_key_tree:remove_leafs(TwoChildSibs, [{0, "1"}]),
- "Removing a non-existant branch has no effect."
- ),
-
- etap:is(
- {OneChild, [{1, "1b"}]},
- couch_key_tree:remove_leafs(TwoChildSibs, [{1, "1b"}]),
- "Removing a leaf removes the leaf."
- ),
-
- etap:is(
- {[], [{1, "1b"},{1, "1a"}]},
- couch_key_tree:remove_leafs(TwoChildSibs, [{1, "1a"}, {1, "1b"}]),
- "Removing all leaves returns an empty tree."
- ),
-
- etap:is(
- {Stemmed, []},
- couch_key_tree:remove_leafs(Stemmed, [{1, "1a"}]),
- "Removing a non-existant node has no effect."
- ),
-
- etap:is(
- {[], [{2, "1aa"}]},
- couch_key_tree:remove_leafs(Stemmed, [{2, "1aa"}]),
- "Removing the last leaf returns an empty tree."
- ),
-
- ok.
diff --git a/test/etap/063-kt-get-leaves.t b/test/etap/063-kt-get-leaves.t
deleted file mode 100755
index 6d4e8007..00000000
--- a/test/etap/063-kt-get-leaves.t
+++ /dev/null
@@ -1,98 +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(11),
- 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() ->
- TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []}, {"1b", "bar", []}]}}],
- Stemmed = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}],
-
- etap:is(
- {[{"foo", {0, ["1"]}}],[]},
- couch_key_tree:get(TwoChildSibs, [{0, "1"}]),
- "extract a subtree."
- ),
-
- etap:is(
- {[{"bar", {1, ["1a", "1"]}}],[]},
- couch_key_tree:get(TwoChildSibs, [{1, "1a"}]),
- "extract a subtree."
- ),
-
- etap:is(
- {[],[{0,"x"}]},
- couch_key_tree:get_key_leafs(TwoChildSibs, [{0, "x"}]),
- "gather up the leaves."
- ),
-
- etap:is(
- {[{"bar", {1, ["1a","1"]}}],[]},
- couch_key_tree:get_key_leafs(TwoChildSibs, [{1, "1a"}]),
- "gather up the leaves."
- ),
-
- etap:is(
- {[{"bar", {1, ["1a","1"]}},{"bar",{1, ["1b","1"]}}],[]},
- couch_key_tree:get_key_leafs(TwoChildSibs, [{0, "1"}]),
- "gather up the leaves."
- ),
-
- etap:is(
- {[{0,[{"1", "foo"}]}],[]},
- couch_key_tree:get_full_key_paths(TwoChildSibs, [{0, "1"}]),
- "retrieve full key paths."
- ),
-
- etap:is(
- {[{1,[{"1a", "bar"},{"1", "foo"}]}],[]},
- couch_key_tree:get_full_key_paths(TwoChildSibs, [{1, "1a"}]),
- "retrieve full key paths."
- ),
-
- etap:is(
- [{2, [{"1aa", "bar"},{"1a", "bar"}]}],
- couch_key_tree:get_all_leafs_full(Stemmed),
- "retrieve all leaves."
- ),
-
- etap:is(
- [{1, [{"1a", "bar"},{"1", "foo"}]}, {1, [{"1b", "bar"},{"1", "foo"}]}],
- couch_key_tree:get_all_leafs_full(TwoChildSibs),
- "retrieve all the leaves."
- ),
-
- etap:is(
- [{"bar", {2, ["1aa","1a"]}}],
- couch_key_tree:get_all_leafs(Stemmed),
- "retrieve all leaves."
- ),
-
- etap:is(
- [{"bar", {1, ["1a", "1"]}}, {"bar", {1, ["1b","1"]}}],
- couch_key_tree:get_all_leafs(TwoChildSibs),
- "retrieve all the leaves."
- ),
-
- ok.
diff --git a/test/etap/064-kt-counting.t b/test/etap/064-kt-counting.t
deleted file mode 100755
index f182d287..00000000
--- a/test/etap/064-kt-counting.t
+++ /dev/null
@@ -1,46 +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() ->
- EmptyTree = [],
- One = [{0, {"1","foo",[]}}],
- TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []}, {"1b", "bar", []}]}}],
- Stemmed = [{2, {"1bb", "boo", []}}],
-
- etap:is(0, couch_key_tree:count_leafs(EmptyTree),
- "Empty trees have no leaves."),
-
- etap:is(1, couch_key_tree:count_leafs(One),
- "Single node trees have a single leaf."),
-
- etap:is(2, couch_key_tree:count_leafs(TwoChildSibs),
- "Two children siblings counted as two leaves."),
-
- etap:is(1, couch_key_tree:count_leafs(Stemmed),
- "Stemming does not affect leaf counting."),
-
- ok.
diff --git a/test/etap/065-kt-stemming.t b/test/etap/065-kt-stemming.t
deleted file mode 100755
index 6e781c1d..00000000
--- a/test/etap/065-kt-stemming.t
+++ /dev/null
@@ -1,42 +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(3),
- 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() ->
- TwoChild = [{0, {"1","foo", [{"1a", "bar", [{"1aa", "bar", []}]}]}}],
- Stemmed1 = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}],
- Stemmed2 = [{2, {"1aa", "bar", []}}],
-
- etap:is(TwoChild, couch_key_tree:stem(TwoChild, 3),
- "Stemming more levels than what exists does nothing."),
-
- etap:is(Stemmed1, couch_key_tree:stem(TwoChild, 2),
- "Stemming with a depth of two returns the deepest two nodes."),
-
- etap:is(Stemmed2, couch_key_tree:stem(TwoChild, 1),
- "Stemming to a depth of one returns the deepest node."),
-
- ok.
diff --git a/test/etap/070-couch-db.t b/test/etap/070-couch-db.t
deleted file mode 100755
index 4b14aba6..00000000
--- a/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/test/etap/080-config-get-set.t b/test/etap/080-config-get-set.t
deleted file mode 100755
index a4a8577a..00000000
--- a/test/etap/080-config-get-set.t
+++ /dev/null
@@ -1,128 +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").
-
-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() ->
- % start couch_config with default
- couch_config:start_link([default_config()]),
-
-
- % Check that we can get values
-
-
- etap:fun_is(
- fun(List) -> length(List) > 0 end,
- couch_config:all(),
- "Data was loaded from the INI file."
- ),
-
- etap:fun_is(
- fun(List) -> length(List) > 0 end,
- couch_config:get("daemons"),
- "There are settings in the [daemons] section of the INI file."
- ),
-
- etap:is(
- couch_config:get("httpd_design_handlers", "_view"),
- "{couch_httpd_view, handle_view_req}",
- "The {httpd_design_handlers, view} is the expected default."
- ),
-
- etap:is(
- couch_config:get("httpd", "foo", "bar"),
- "bar",
- "Returns the default when key doesn't exist in config."
- ),
-
- etap:is(
- couch_config:get("httpd", "foo"),
- undefined,
- "The default default is the atom 'undefined'."
- ),
-
- etap:is(
- couch_config:get("httpd", "port", "bar"),
- "5984",
- "Only returns the default when the config setting does not exist."
- ),
-
-
- % Check that setting values works.
-
-
- ok = couch_config:set("log", "level", "severe", false),
-
- etap:is(
- couch_config:get("log", "level"),
- "severe",
- "Non persisted changes take effect."
- ),
-
- etap:is(
- couch_config:get("new_section", "bizzle"),
- undefined,
- "Section 'new_section' does not exist."
- ),
-
- ok = couch_config:set("new_section", "bizzle", "bang", false),
-
- etap:is(
- couch_config:get("new_section", "bizzle"),
- "bang",
- "New section 'new_section' was created for a new key/value pair."
- ),
-
-
- % Check that deleting works
-
-
- ok = couch_config:delete("new_section", "bizzle", false),
- etap:is(
- couch_config:get("new_section", "bizzle"),
- undefined,
- "Deleting sets the value to \"\""
- ),
-
-
- % Check ge/set/delete binary strings
-
- ok = couch_config:set(<<"foo">>, <<"bar">>, <<"baz">>, false),
- etap:is(
- couch_config:get(<<"foo">>, <<"bar">>),
- <<"baz">>,
- "Can get and set with binary section and key values."
- ),
- ok = couch_config:delete(<<"foo">>, <<"bar">>, false),
- etap:is(
- couch_config:get(<<"foo">>, <<"bar">>),
- undefined,
- "Deleting with binary section/key pairs sets the value to \"\""
- ),
-
- ok.
diff --git a/test/etap/081-config-override.1.ini b/test/etap/081-config-override.1.ini
deleted file mode 100644
index 55451dad..00000000
--- a/test/etap/081-config-override.1.ini
+++ /dev/null
@@ -1,22 +0,0 @@
-; Licensed to the Apache Software Foundation (ASF) under one
-; or more contributor license agreements. See the NOTICE file
-; distributed with this work for additional information
-; regarding copyright ownership. The ASF licenses this file
-; to you 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.
-
-[couchdb]
-max_dbs_open=10
-
-[httpd]
-port=4895
diff --git a/test/etap/081-config-override.2.ini b/test/etap/081-config-override.2.ini
deleted file mode 100644
index 5f46357f..00000000
--- a/test/etap/081-config-override.2.ini
+++ /dev/null
@@ -1,22 +0,0 @@
-; Licensed to the Apache Software Foundation (ASF) under one
-; or more contributor license agreements. See the NOTICE file
-; distributed with this work for additional information
-; regarding copyright ownership. The ASF licenses this file
-; to you 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.
-
-[httpd]
-port = 80
-
-[fizbang]
-unicode = normalized
diff --git a/test/etap/081-config-override.t b/test/etap/081-config-override.t
deleted file mode 100755
index 01f8b4c2..00000000
--- a/test/etap/081-config-override.t
+++ /dev/null
@@ -1,212 +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").
-
-local_config_1() ->
- test_util:source_file("test/etap/081-config-override.1.ini").
-
-local_config_2() ->
- test_util:source_file("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) ->
- {ok, Pid} = couch_config:start_link(IniFiles),
- erlang:monitor(process, Pid),
- Tests(),
- couch_config:stop(),
- receive
- {'DOWN', _, _, Pid, _} -> ok;
- _Other -> etap:diag("OTHER: ~p~n", [_Other])
- after
- 1000 -> throw({timeout_error, config_stop})
- end.
-
-main(_) ->
- test_util:init_code_path(),
- etap:plan(17),
-
- 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() ->
-
- CheckStartStop = fun() -> ok end,
- run_tests([default_config()], CheckStartStop),
-
- CheckDefaults = fun() ->
- etap:is(
- couch_config:get("couchdb", "max_dbs_open"),
- "100",
- "{couchdb, max_dbs_open} is 100 by defualt."
- ),
-
- etap:is(
- couch_config:get("httpd","port"),
- "5984",
- "{httpd, port} is 5984 by default"
- ),
-
- etap:is(
- couch_config:get("fizbang", "unicode"),
- undefined,
- "{fizbang, unicode} is undefined by default"
- )
- end,
-
- run_tests([default_config()], CheckDefaults),
-
-
- % Check that subsequent files override values appropriately
-
- CheckOverride = fun() ->
- etap:is(
- couch_config:get("couchdb", "max_dbs_open"),
- "10",
- "{couchdb, max_dbs_open} was overriden with the value 10"
- ),
-
- etap:is(
- couch_config:get("httpd", "port"),
- "4895",
- "{httpd, port} was overriden with the value 4895"
- )
- end,
-
- run_tests([default_config(), local_config_1()], CheckOverride),
-
-
- % Check that overrides can create new sections
-
- CheckOverride2 = fun() ->
- etap:is(
- couch_config:get("httpd", "port"),
- "80",
- "{httpd, port} is overriden with the value 80"
- ),
-
- etap:is(
- couch_config:get("fizbang", "unicode"),
- "normalized",
- "{fizbang, unicode} was created by override INI file"
- )
- end,
-
- run_tests([default_config(), local_config_2()], CheckOverride2),
-
-
- % Check that values can be overriden multiple times
-
- CheckOverride3 = fun() ->
- etap:is(
- couch_config:get("httpd", "port"),
- "80",
- "{httpd, port} value was taken from the last specified INI file."
- )
- end,
-
- run_tests(
- [default_config(), local_config_1(), local_config_2()],
- CheckOverride3
- ),
-
- % Check persistence to last file.
-
- % Empty the file in case it exists.
- {ok, Fd} = file:open(local_config_write(), write),
- ok = file:truncate(Fd),
- ok = file:close(Fd),
-
- % Open and write a value
- CheckCanWrite = fun() ->
- etap:is(
- couch_config:get("httpd", "port"),
- "5984",
- "{httpd, port} is still 5984 by default"
- ),
-
- etap:is(
- couch_config:set("httpd", "port", "8080"),
- ok,
- "Writing {httpd, port} is kosher."
- ),
-
- etap:is(
- couch_config:get("httpd", "port"),
- "8080",
- "{httpd, port} was updated to 8080 successfully."
- ),
-
- etap:is(
- couch_config:delete("httpd", "bind_address"),
- ok,
- "Deleting {httpd, bind_address} succeeds"
- ),
-
- etap:is(
- couch_config:get("httpd", "bind_address"),
- undefined,
- "{httpd, bind_address} was actually deleted."
- )
- end,
-
- run_tests([default_config(), local_config_write()], CheckCanWrite),
-
- % Open and check where we don't expect persistence.
-
- CheckDidntWrite = fun() ->
- etap:is(
- couch_config:get("httpd", "port"),
- "5984",
- "{httpd, port} was not persisted to the primary INI file."
- ),
-
- etap:is(
- couch_config:get("httpd", "bind_address"),
- "127.0.0.1",
- "{httpd, bind_address} was not deleted form the primary INI file."
- )
- end,
-
- run_tests([default_config()], CheckDidntWrite),
-
- % Open and check we have only the persistence we expect.
- CheckDidWrite = fun() ->
- etap:is(
- couch_config:get("httpd", "port"),
- "8080",
- "{httpd, port} is still 8080 after reopening the config."
- ),
-
- etap:is(
- couch_config:get("httpd", "bind_address"),
- undefined,
- "{httpd, bind_address} is still \"\" after reopening."
- )
- end,
-
- run_tests([local_config_write()], CheckDidWrite),
-
- ok.
diff --git a/test/etap/082-config-register.t b/test/etap/082-config-register.t
deleted file mode 100755
index 191ba8f8..00000000
--- a/test/etap/082-config-register.t
+++ /dev/null
@@ -1,94 +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").
-
-main(_) ->
- test_util:init_code_path(),
- etap:plan(5),
- 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_config:start_link([default_config()]),
-
- etap:is(
- couch_config:get("httpd", "port"),
- "5984",
- "{httpd, port} is 5984 by default."
- ),
-
- ok = couch_config:set("httpd", "port", "4895", false),
-
- etap:is(
- couch_config:get("httpd", "port"),
- "4895",
- "{httpd, port} changed to 4895"
- ),
-
- SentinelFunc = fun() ->
- % Ping/Pong to make sure we wait for this
- % process to die
- receive {ping, From} -> From ! pong end
- end,
- SentinelPid = spawn(SentinelFunc),
-
- couch_config:register(
- fun("httpd", "port", Value) ->
- etap:is(Value, "8080", "Registered function got notification.")
- end,
- SentinelPid
- ),
-
- ok = couch_config:set("httpd", "port", "8080", false),
-
- % Implicitly checking that we *don't* call the function
- etap:is(
- couch_config:get("httpd", "bind_address"),
- "127.0.0.1",
- "{httpd, bind_address} is not '0.0.0.0'"
- ),
- ok = couch_config:set("httpd", "bind_address", "0.0.0.0", false),
-
- % Ping-Pong kill process
- SentinelPid ! {ping, self()},
- receive
- _Any -> ok
- after 1000 ->
- throw({timeout_error, registered_pid})
- end,
-
- ok = couch_config:set("httpd", "port", "80", false),
- etap:is(
- couch_config:get("httpd", "port"),
- "80",
- "Implicitly test that the function got de-registered"
- ),
-
- % test passing of Persist flag
- couch_config:register(
- fun("httpd", _, _, Persist) ->
- etap:is(Persist, false)
- end),
- ok = couch_config:set("httpd", "port", "80", false),
-
- ok.
diff --git a/test/etap/083-config-no-files.t b/test/etap/083-config-no-files.t
deleted file mode 100755
index 675feb59..00000000
--- a/test/etap/083-config-no-files.t
+++ /dev/null
@@ -1,55 +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").
-
-main(_) ->
- test_util:init_code_path(),
- etap:plan(3),
- 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_config:start_link([]),
-
- etap:fun_is(
- fun(KVPairs) -> length(KVPairs) == 0 end,
- couch_config:all(),
- "No INI files specified returns 0 key/value pairs."
- ),
-
- ok = couch_config:set("httpd", "port", "80", false),
-
- etap:is(
- couch_config:get("httpd", "port"),
- "80",
- "Created a new non-persisted k/v pair."
- ),
-
- ok = couch_config:set("httpd", "bind_address", "127.0.0.1"),
- etap:is(
- couch_config:get("httpd", "bind_address"),
- "127.0.0.1",
- "Asking for a persistent key/value pair doesn't choke."
- ),
-
- ok.
diff --git a/test/etap/090-task-status.t b/test/etap/090-task-status.t
deleted file mode 100755
index b278de7f..00000000
--- a/test/etap/090-task-status.t
+++ /dev/null
@@ -1,209 +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(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.
-
-check_status(Pid,ListPropLists) ->
- From = list_to_binary(pid_to_list(Pid)),
- Element = lists:foldl(
- fun(PropList,Acc) ->
- case couch_util:get_value(pid,PropList) of
- From ->
- [PropList | Acc];
- _ ->
- []
- end
- end,
- [], ListPropLists
- ),
- couch_util:get_value(status,hd(Element)).
-
-loop() ->
- receive
- {add, From} ->
- Resp = couch_task_status:add_task("type", "task", "init"),
- From ! {ok, self(), Resp},
- loop();
- {update, Status, From} ->
- Resp = couch_task_status:update(Status),
- From ! {ok, self(), Resp},
- loop();
- {update_frequency, Msecs, From} ->
- Resp = couch_task_status:set_update_frequency(Msecs),
- From ! {ok, self(), Resp},
- loop();
- {done, From} ->
- From ! {ok, self(), ok}
- end.
-
-call(Pid, Command) ->
- Pid ! {Command, self()},
- wait(Pid).
-
-call(Pid, Command, Arg) ->
- Pid ! {Command, Arg, self()},
- wait(Pid).
-
-wait(Pid) ->
- receive
- {ok, Pid, Msg} -> Msg
- after 1000 ->
- throw(timeout_error)
- end.
-
-test() ->
- {ok, TaskStatusPid} = couch_task_status:start_link(),
-
- TaskUpdater = fun() -> loop() end,
- % create three updaters
- Pid1 = spawn(TaskUpdater),
- Pid2 = spawn(TaskUpdater),
- Pid3 = spawn(TaskUpdater),
-
- ok = call(Pid1, add),
- etap:is(
- length(couch_task_status:all()),
- 1,
- "Started a task"
- ),
-
- etap:is(
- call(Pid1, add),
- {add_task_error, already_registered},
- "Unable to register multiple tasks for a single Pid."
- ),
-
- etap:is(
- check_status(Pid1, couch_task_status:all()),
- <<"init">>,
- "Task status was set to 'init'."
- ),
-
- call(Pid1,update,"running"),
- etap:is(
- check_status(Pid1,couch_task_status:all()),
- <<"running">>,
- "Status updated to 'running'."
- ),
-
-
- call(Pid2,add),
- etap:is(
- length(couch_task_status:all()),
- 2,
- "Started a second task."
- ),
-
- etap:is(
- check_status(Pid2, couch_task_status:all()),
- <<"init">>,
- "Second tasks's status was set to 'init'."
- ),
-
- call(Pid2, update, "running"),
- etap:is(
- check_status(Pid2, couch_task_status:all()),
- <<"running">>,
- "Second task's status updated to 'running'."
- ),
-
-
- call(Pid3, add),
- etap:is(
- length(couch_task_status:all()),
- 3,
- "Registered a third task."
- ),
-
- etap:is(
- check_status(Pid3, couch_task_status:all()),
- <<"init">>,
- "Third tasks's status was set to 'init'."
- ),
-
- call(Pid3, update, "running"),
- etap:is(
- check_status(Pid3, couch_task_status:all()),
- <<"running">>,
- "Third task's status updated to 'running'."
- ),
-
-
- call(Pid3, update_frequency, 500),
- call(Pid3, update, "still running"),
- etap:is(
- check_status(Pid3, couch_task_status:all()),
- <<"still running">>,
- "Third task's status updated to 'still running'."
- ),
-
- call(Pid3, update, "skip this update"),
- etap:is(
- check_status(Pid3, couch_task_status:all()),
- <<"still running">>,
- "Status update dropped because of frequency limit."
- ),
-
- call(Pid3, update_frequency, 0),
- call(Pid3, update, "don't skip"),
- etap:is(
- check_status(Pid3, couch_task_status:all()),
- <<"don't skip">>,
- "Status updated after reseting frequency limit."
- ),
-
-
- call(Pid1, done),
- etap:is(
- length(couch_task_status:all()),
- 2,
- "First task finished."
- ),
-
- call(Pid2, done),
- etap:is(
- length(couch_task_status:all()),
- 1,
- "Second task finished."
- ),
-
- call(Pid3, done),
- etap:is(
- length(couch_task_status:all()),
- 0,
- "Third task finished."
- ),
-
- erlang:monitor(process, TaskStatusPid),
- couch_task_status:stop(),
- receive
- {'DOWN', _, _, TaskStatusPid, _} ->
- ok
- after
- 1000 ->
- throw(timeout_error)
- end,
-
- ok.
diff --git a/test/etap/100-ref-counter.t b/test/etap/100-ref-counter.t
deleted file mode 100755
index 8f996d04..00000000
--- a/test/etap/100-ref-counter.t
+++ /dev/null
@@ -1,114 +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(8),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail(Other)
- end,
- ok.
-
-loop() ->
- receive
- close -> ok
- end.
-
-wait() ->
- receive
- {'DOWN', _, _, _, _} -> ok
- after 1000 ->
- throw(timeout_error)
- end.
-
-test() ->
- {ok, RefCtr} = couch_ref_counter:start([]),
-
- etap:is(
- couch_ref_counter:count(RefCtr),
- 1,
- "A ref_counter is initialized with the calling process as a referer."
- ),
-
- ChildPid1 = spawn(fun() -> loop() end),
-
- % This is largely implicit in that nothing else breaks
- % as ok is just returned from gen_server:cast()
- etap:is(
- couch_ref_counter:drop(RefCtr, ChildPid1),
- ok,
- "Dropping an unknown Pid is ignored."
- ),
-
- couch_ref_counter:add(RefCtr, ChildPid1),
- etap:is(
- couch_ref_counter:count(RefCtr),
- 2,
- "Adding a Pid to the ref_counter increases it's count."
- ),
-
- couch_ref_counter:add(RefCtr, ChildPid1),
- etap:is(
- couch_ref_counter:count(RefCtr),
- 2,
- "Readding the same Pid maintains the count but increments it's refs."
- ),
-
- couch_ref_counter:drop(RefCtr, ChildPid1),
- etap:is(
- couch_ref_counter:count(RefCtr),
- 2,
- "Droping the doubly added Pid only removes a ref, not a referer."
- ),
-
- couch_ref_counter:drop(RefCtr, ChildPid1),
- etap:is(
- couch_ref_counter:count(RefCtr),
- 1,
- "Dropping the second ref drops the referer."
- ),
-
- couch_ref_counter:add(RefCtr, ChildPid1),
- etap:is(
- couch_ref_counter:count(RefCtr),
- 2,
- "Sanity checking that the Pid was re-added."
- ),
-
- erlang:monitor(process, ChildPid1),
- ChildPid1 ! close,
- wait(),
-
- CheckFun = fun
- (Iter, nil) ->
- case couch_ref_counter:count(RefCtr) of
- 1 -> Iter;
- _ -> nil
- end;
- (_, Acc) ->
- Acc
- end,
- Result = lists:foldl(CheckFun, nil, lists:seq(1, 10000)),
- etap:isnt(
- Result,
- nil,
- "The referer count was decremented automatically on process exit."
- ),
-
- ok.
diff --git a/test/etap/110-replication-httpc.t b/test/etap/110-replication-httpc.t
deleted file mode 100755
index b534b648..00000000
--- a/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/test/etap/111-replication-changes-feed.t b/test/etap/111-replication-changes-feed.t
deleted file mode 100755
index bca12bc7..00000000
--- a/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/test/etap/112-replication-missing-revs.t b/test/etap/112-replication-missing-revs.t
deleted file mode 100755
index ea8466f6..00000000
--- a/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/test/etap/113-replication-attachment-comp.t b/test/etap/113-replication-attachment-comp.t
deleted file mode 100755
index 30f602ef..00000000
--- a/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/test/etap/120-stats-collect.t b/test/etap/120-stats-collect.t
deleted file mode 100755
index dee88765..00000000
--- a/test/etap/120-stats-collect.t
+++ /dev/null
@@ -1,150 +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(11),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail()
- end,
- ok.
-
-test() ->
- couch_stats_collector:start(),
- ok = test_counters(),
- ok = test_abs_values(),
- ok = test_proc_counting(),
- ok = test_all(),
- ok.
-
-test_counters() ->
- AddCount = fun() -> couch_stats_collector:increment(foo) end,
- RemCount = fun() -> couch_stats_collector:decrement(foo) end,
- repeat(AddCount, 100),
- repeat(RemCount, 25),
- repeat(AddCount, 10),
- repeat(RemCount, 5),
- etap:is(
- couch_stats_collector:get(foo),
- 80,
- "Incrememnt tracks correctly."
- ),
-
- repeat(RemCount, 80),
- etap:is(
- couch_stats_collector:get(foo),
- 0,
- "Decremented to zaro."
- ),
- ok.
-
-test_abs_values() ->
- lists:map(fun(Val) ->
- couch_stats_collector:record(bar, Val)
- end, lists:seq(1, 15)),
- etap:is(
- couch_stats_collector:get(bar),
- lists:seq(1, 15),
- "Absolute values are recorded correctly."
- ),
-
- couch_stats_collector:clear(bar),
- etap:is(
- couch_stats_collector:get(bar),
- nil,
- "Absolute values are cleared correctly."
- ),
- ok.
-
-test_proc_counting() ->
- Self = self(),
- OnePid = spawn(fun() ->
- couch_stats_collector:track_process_count(hoopla),
- Self ! reporting,
- receive sepuku -> ok end
- end),
- R1 = erlang:monitor(process, OnePid),
- receive reporting -> ok end,
- etap:is(
- couch_stats_collector:get(hoopla),
- 1,
- "track_process_count incrememnts the counter."
- ),
-
- TwicePid = spawn(fun() ->
- couch_stats_collector:track_process_count(hoopla),
- couch_stats_collector:track_process_count(hoopla),
- Self ! reporting,
- receive sepuku -> ok end
- end),
- R2 = erlang:monitor(process, TwicePid),
- receive reporting -> ok end,
- etap:is(
- couch_stats_collector:get(hoopla),
- 3,
- "track_process_count allows more than one incrememnt per Pid"
- ),
-
- OnePid ! sepuku,
- receive {'DOWN', R1, _, _, _} -> ok end,
- timer:sleep(250),
- etap:is(
- couch_stats_collector:get(hoopla),
- 2,
- "Process count is decremented when process exits."
- ),
-
- TwicePid ! sepuku,
- receive {'DOWN', R2, _, _, _} -> ok end,
- timer:sleep(250),
- etap:is(
- couch_stats_collector:get(hoopla),
- 0,
- "Process count is decremented for each call to track_process_count."
- ),
- ok.
-
-test_all() ->
- couch_stats_collector:record(bar, 0.0),
- couch_stats_collector:record(bar, 1.0),
- etap:is(
- couch_stats_collector:all(),
- [{foo, 0}, {hoopla, 0}, {bar, [1.0, 0.0]}],
- "all/0 returns all counters and absolute values."
- ),
-
- etap:is(
- couch_stats_collector:all(incremental),
- [{foo, 0}, {hoopla, 0}],
- "all/1 returns only the specified type."
- ),
-
- couch_stats_collector:record(zing, 90),
- etap:is(
- couch_stats_collector:all(absolute),
- [{zing, [90]}, {bar, [1.0, 0.0]}],
- "all/1 returns only the specified type."
- ),
- ok.
-
-repeat(_, 0) ->
- ok;
-repeat(Fun, Count) ->
- Fun(),
- repeat(Fun, Count-1).
diff --git a/test/etap/121-stats-aggregates.cfg b/test/etap/121-stats-aggregates.cfg
deleted file mode 100644
index 30e475da..00000000
--- a/test/etap/121-stats-aggregates.cfg
+++ /dev/null
@@ -1,19 +0,0 @@
-% Licensed to the Apache Software Foundation (ASF) under one
-% or more contributor license agreements. See the NOTICE file
-% distributed with this work for additional information
-% regarding copyright ownership. The ASF licenses this file
-% to you 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.
-
-{testing, stuff, "yay description"}.
-{number, '11', "randomosity"}.
diff --git a/test/etap/121-stats-aggregates.ini b/test/etap/121-stats-aggregates.ini
deleted file mode 100644
index cc5cd218..00000000
--- a/test/etap/121-stats-aggregates.ini
+++ /dev/null
@@ -1,20 +0,0 @@
-; Licensed to the Apache Software Foundation (ASF) under one
-; or more contributor license agreements. See the NOTICE file
-; distributed with this work for additional information
-; regarding copyright ownership. The ASF licenses this file
-; to you 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.
-
-[stats]
-rate = 10000000 ; We call collect_sample in testing
-samples = [0, 1]
diff --git a/test/etap/121-stats-aggregates.t b/test/etap/121-stats-aggregates.t
deleted file mode 100755
index d678aa9d..00000000
--- a/test/etap/121-stats-aggregates.t
+++ /dev/null
@@ -1,171 +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.
-
-ini_file() ->
- test_util:source_file("test/etap/121-stats-aggregates.ini").
-
-cfg_file() ->
- test_util:source_file("test/etap/121-stats-aggregates.cfg").
-
-main(_) ->
- test_util:init_code_path(),
- etap:plan(17),
- case (catch test()) of
- ok ->
- etap:end_tests();
- Other ->
- etap:diag(io_lib:format("Test died abnormally: ~p", [Other])),
- etap:bail()
- end,
- ok.
-
-test() ->
- couch_config:start_link([ini_file()]),
- couch_stats_collector:start(),
- couch_stats_aggregator:start(cfg_file()),
- ok = test_all_empty(),
- ok = test_get_empty(),
- ok = test_count_stats(),
- ok = test_abs_stats(),
- ok.
-
-test_all_empty() ->
- {Aggs} = couch_stats_aggregator:all(),
-
- etap:is(length(Aggs), 2, "There are only two aggregate types in testing."),
- etap:is(
- couch_util:get_value(testing, Aggs),
- {[{stuff, make_agg(<<"yay description">>,
- null, null, null, null, null)}]},
- "{testing, stuff} is empty at start."
- ),
- etap:is(
- couch_util:get_value(number, Aggs),
- {[{'11', make_agg(<<"randomosity">>,
- null, null, null, null, null)}]},
- "{number, '11'} is empty at start."
- ),
- ok.
-
-test_get_empty() ->
- etap:is(
- couch_stats_aggregator:get_json({testing, stuff}),
- make_agg(<<"yay description">>, null, null, null, null, null),
- "Getting {testing, stuff} returns an empty aggregate."
- ),
- etap:is(
- couch_stats_aggregator:get_json({number, '11'}),
- make_agg(<<"randomosity">>, null, null, null, null, null),
- "Getting {number, '11'} returns an empty aggregate."
- ),
- ok.
-
-test_count_stats() ->
- lists:foreach(fun(_) ->
- couch_stats_collector:increment({testing, stuff})
- end, lists:seq(1, 100)),
- couch_stats_aggregator:collect_sample(),
- etap:is(
- couch_stats_aggregator:get_json({testing, stuff}),
- make_agg(<<"yay description">>, 100, 100, null, 100, 100),
- "COUNT: Adding values changes the stats."
- ),
- etap:is(
- couch_stats_aggregator:get_json({testing, stuff}, 1),
- make_agg(<<"yay description">>, 100, 100, null, 100, 100),
- "COUNT: Adding values changes stats for all times."
- ),
-
- timer:sleep(500),
- couch_stats_aggregator:collect_sample(),
- etap:is(
- couch_stats_aggregator:get_json({testing, stuff}),
- make_agg(<<"yay description">>, 100, 50, 70.711, 0, 100),
- "COUNT: Removing values changes stats."
- ),
- etap:is(
- couch_stats_aggregator:get_json({testing, stuff}, 1),
- make_agg(<<"yay description">>, 100, 50, 70.711, 0, 100),
- "COUNT: Removing values changes stats for all times."
- ),
-
- timer:sleep(600),
- couch_stats_aggregator:collect_sample(),
- etap:is(
- couch_stats_aggregator:get_json({testing, stuff}),
- make_agg(<<"yay description">>, 100, 33.333, 57.735, 0, 100),
- "COUNT: Letting time passes doesn't remove data from time 0 aggregates"
- ),
- etap:is(
- couch_stats_aggregator:get_json({testing, stuff}, 1),
- make_agg(<<"yay description">>, 0, 0, 0, 0, 0),
- "COUNT: Letting time pass removes data from other time aggregates."
- ),
- ok.
-
-test_abs_stats() ->
- lists:foreach(fun(X) ->
- couch_stats_collector:record({number, 11}, X)
- end, lists:seq(0, 10)),
- couch_stats_aggregator:collect_sample(),
- etap:is(
- couch_stats_aggregator:get_json({number, 11}),
- make_agg(<<"randomosity">>, 5, 5, null, 5, 5),
- "ABS: Adding values changes the stats."
- ),
- etap:is(
- couch_stats_aggregator:get_json({number, 11}, 1),
- make_agg(<<"randomosity">>, 5, 5, null, 5, 5),
- "ABS: Adding values changes stats for all times."
- ),
-
- timer:sleep(500),
- couch_stats_collector:record({number, 11}, 15),
- couch_stats_aggregator:collect_sample(),
- etap:is(
- couch_stats_aggregator:get_json({number, 11}),
- make_agg(<<"randomosity">>, 20, 10, 7.071, 5, 15),
- "ABS: New values changes stats"
- ),
- etap:is(
- couch_stats_aggregator:get_json({number, 11}, 1),
- make_agg(<<"randomosity">>, 20, 10, 7.071, 5, 15),
- "ABS: Removing values changes stats for all times."
- ),
-
- timer:sleep(600),
- couch_stats_aggregator:collect_sample(),
- etap:is(
- couch_stats_aggregator:get_json({number, 11}),
- make_agg(<<"randomosity">>, 20, 10, 7.071, 5, 15),
- "ABS: Letting time passes doesn't remove data from time 0 aggregates"
- ),
- etap:is(
- couch_stats_aggregator:get_json({number, 11}, 1),
- make_agg(<<"randomosity">>, 15, 15, null, 15, 15),
- "ABS: Letting time pass removes data from other time aggregates."
- ),
- ok.
-
-make_agg(Desc, Sum, Mean, StdDev, Min, Max) ->
- {[
- {description, Desc},
- {current, Sum},
- {sum, Sum},
- {mean, Mean},
- {stddev, StdDev},
- {min, Min},
- {max, Max}
- ]}.
diff --git a/test/etap/130-attachments-md5.t b/test/etap/130-attachments-md5.t
deleted file mode 100755
index 4c40f83a..00000000
--- a/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/test/etap/140-attachment-comp.t b/test/etap/140-attachment-comp.t
deleted file mode 100755
index 98d37abc..00000000
--- a/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/test/etap/150-invalid-view-seq.t b/test/etap/150-invalid-view-seq.t
deleted file mode 100755
index 0664c116..00000000
--- a/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/test/etap/160-vhosts.t b/test/etap/160-vhosts.t
deleted file mode 100755
index 7694010a..00000000
--- a/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.
diff --git a/test/etap/run.tpl b/test/etap/run.tpl
deleted file mode 100644
index faf0f456..00000000
--- a/test/etap/run.tpl
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/sh -e
-
-# 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.
-
-SRCDIR="%abs_top_srcdir%"
-BUILDIR="%abs_top_builddir%"
-
-export ERL_FLAGS="$ERL_FLAGS -pa $BUILDIR/test/etap/"
-
-if test $# -gt 0; then
- while [ $# -gt 0 ]; do
- $1
- shift
- done
-else
- prove $SRCDIR/test/etap/*.t
-fi
diff --git a/test/etap/test_util.erl.in b/test/etap/test_util.erl.in
deleted file mode 100644
index 4c42edb1..00000000
--- a/test/etap/test_util.erl.in
+++ /dev/null
@@ -1,35 +0,0 @@
-% Licensed under the Apache License, Version 2.0 (the "License"); you may not
-% use this file except in compliance with the License. You may obtain a copy of
-% the License at
-%
-% http://www.apache.org/licenses/LICENSE-2.0
-%
-% Unless required by applicable law or agreed to in writing, software
-% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-% License for the specific language governing permissions and limitations under
-% the License.
-
--module(test_util).
-
--export([init_code_path/0]).
--export([source_file/1, build_file/1]).
-
-srcdir() ->
- "@abs_top_srcdir@".
-
-builddir() ->
- "@abs_top_builddir@".
-
-init_code_path() ->
- Paths = ["etap", "couchdb", "erlang-oauth", "ibrowse", "mochiweb"],
- lists:foreach(fun(Name) ->
- code:add_pathz(filename:join([builddir(), "src", Name]))
- end, Paths).
-
-source_file(Name) ->
- filename:join([srcdir(), Name]).
-
-build_file(Name) ->
- filename:join([builddir(), Name]).
-
diff --git a/test/javascript/cli_runner.js b/test/javascript/cli_runner.js
deleted file mode 100644
index cdbe2e73..00000000
--- a/test/javascript/cli_runner.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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.
-
-var console = {
- log: function(arg) {
- var msg = (arg.toString()).replace(/\n/g, "\n ");
- print("# " + msg);
- }
-};
-
-function T(arg1, arg2) {
- if(!arg1) {
- throw((arg2 ? arg2 : arg1).toString());
- }
-}
-
-function runTestConsole(num, name, func) {
- try {
- func();
- print("ok " + num + " " + name);
- } catch(e) {
- msg = e.toString();
- msg = msg.replace(/\n/g, "\n ");
- print("not ok " + num + " " + name + " " + msg);
- }
-}
-
-function runAllTestsConsole() {
- var numTests = 0;
- for(var t in couchTests) { numTests += 1; }
- print("1.." + numTests);
- var testId = 0;
- for(var t in couchTests) {
- testId += 1;
- runTestConsole(testId, t, couchTests[t]);
- }
-};
-
-try {
- runAllTestsConsole();
-} catch (e) {
- p("# " + e.toString());
-}
diff --git a/test/javascript/couch_http.js b/test/javascript/couch_http.js
deleted file mode 100644
index 5f4716d2..00000000
--- a/test/javascript/couch_http.js
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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.
-
-(function() {
- CouchHTTP.prototype.base_url = "http://127.0.0.1:5984"
-
- if(typeof(CouchHTTP) != "undefined") {
- CouchHTTP.prototype.open = function(method, url, async) {
- if(!/^\s*http:\/\//.test(url)) {
- if(/^[^\/]/.test(url)) {
- url = this.base_url + "/" + url;
- } else {
- url = this.base_url + url;
- }
- }
-
- return this._open(method, url, async);
- };
-
- CouchHTTP.prototype.setRequestHeader = function(name, value) {
- // Drop content-length headers because cURL will set it for us
- // based on body length
- if(name.toLowerCase().replace(/^\s+|\s+$/g, '') != "content-length") {
- this._setRequestHeader(name, value);
- }
- }
-
- CouchHTTP.prototype.send = function(body) {
- this._send(body || "");
- var headers = {};
- this._headers.forEach(function(hdr) {
- var pair = hdr.split(":");
- var name = pair.shift();
- headers[name] = pair.join(":").replace(/^\s+|\s+$/g, "");
- });
- this.headers = headers;
- };
-
- CouchHTTP.prototype.getResponseHeader = function(name) {
- for(var hdr in this.headers) {
- if(hdr.toLowerCase() == name.toLowerCase()) {
- return this.headers[hdr];
- }
- }
- return null;
- };
- }
-})();
-
-CouchDB.urlPrefix = "";
-CouchDB.newXhr = function() {
- return new CouchHTTP();
-};
diff --git a/test/javascript/run.tpl b/test/javascript/run.tpl
deleted file mode 100644
index c5abe6e7..00000000
--- a/test/javascript/run.tpl
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh -e
-
-# 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.
-
-SRC_DIR=%abs_top_srcdir%
-SCRIPT_DIR=$SRC_DIR/share/www/script
-JS_TEST_DIR=$SRC_DIR/test/javascript
-
-COUCHJS=%abs_top_builddir%/src/couchdb/priv/couchjs
-
-cat $SCRIPT_DIR/json2.js \
- $SCRIPT_DIR/sha1.js \
- $SCRIPT_DIR/oauth.js \
- $SCRIPT_DIR/couch.js \
- $SCRIPT_DIR/couch_test_runner.js \
- $SCRIPT_DIR/couch_tests.js \
- $SCRIPT_DIR/test/*.js \
- $JS_TEST_DIR/couch_http.js \
- $JS_TEST_DIR/cli_runner.js \
- | $COUCHJS -
diff --git a/test/view_server/query_server_spec.rb b/test/view_server/query_server_spec.rb
deleted file mode 100644
index de1df5c1..00000000
--- a/test/view_server/query_server_spec.rb
+++ /dev/null
@@ -1,824 +0,0 @@
-# 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.
-
-# to run (requires ruby and rspec):
-# spec test/view_server/query_server_spec.rb -f specdoc --color
-#
-# environment options:
-# QS_TRACE=true
-# shows full output from the query server
-# QS_LANG=lang
-# run tests on the query server (for now, one of: js, erlang)
-#
-
-COUCH_ROOT = "#{File.dirname(__FILE__)}/../.." unless defined?(COUCH_ROOT)
-LANGUAGE = ENV["QS_LANG"] || "js"
-
-puts "Running query server specs for #{LANGUAGE} query server"
-
-require 'spec'
-require 'json'
-
-class OSProcessRunner
- def self.run
- trace = ENV["QS_TRACE"] || false
- puts "launching #{run_command}" if trace
- if block_given?
- IO.popen(run_command, "r+") do |io|
- qs = QueryServerRunner.new(io, trace)
- yield qs
- end
- else
- io = IO.popen(run_command, "r+")
- QueryServerRunner.new(io, trace)
- end
- end
- def initialize io, trace = false
- @qsio = io
- @trace = trace
- end
- def close
- @qsio.close
- end
- def reset!
- run(["reset"])
- end
- def add_fun(fun)
- run(["add_fun", fun])
- end
- def teach_ddoc(ddoc)
- run(["ddoc", "new", ddoc_id(ddoc), ddoc])
- end
- def ddoc_run(ddoc, fun_path, args)
- run(["ddoc", ddoc_id(ddoc), fun_path, args])
- end
- def ddoc_id(ddoc)
- d_id = ddoc["_id"]
- raise 'ddoc must have _id' unless d_id
- d_id
- end
- def get_chunks
- resp = jsgets
- raise "not a chunk" unless resp.first == "chunks"
- return resp[1]
- end
- def run json
- rrun json
- jsgets
- end
- def rrun json
- line = json.to_json
- puts "run: #{line}" if @trace
- @qsio.puts line
- end
- def rgets
- resp = @qsio.gets
- puts "got: #{resp}" if @trace
- resp
- end
- def jsgets
- resp = rgets
- # err = @qserr.gets
- # puts "err: #{err}" if err
- if resp
- begin
- rj = JSON.parse("[#{resp.chomp}]")[0]
- rescue JSON::ParserError
- puts "JSON ERROR (dump under trace mode)"
- # puts resp.chomp
- while resp = rgets
- # puts resp.chomp
- end
- end
- if rj.respond_to?(:[]) && rj.is_a?(Array)
- if rj[0] == "log"
- log = rj[1]
- puts "log: #{log}" if @trace
- rj = jsgets
- end
- end
- rj
- else
- raise "no response"
- end
- end
-end
-
-class QueryServerRunner < OSProcessRunner
-
- COMMANDS = {
- "js" => "#{COUCH_ROOT}/bin/couchjs_dev #{COUCH_ROOT}/share/server/main.js",
- "erlang" => "#{COUCH_ROOT}/test/view_server/run_native_process.es"
- }
-
- def self.run_command
- COMMANDS[LANGUAGE]
- end
-end
-
-class ExternalRunner < OSProcessRunner
- def self.run_command
- "#{COUCH_ROOT}/src/couchdb/couchjs #{COUCH_ROOT}/share/server/echo.js"
- end
-end
-
-# we could organize this into a design document per language.
-# that would make testing future languages really easy.
-
-functions = {
- "emit-twice" => {
- "js" => %{function(doc){emit("foo",doc.a); emit("bar",doc.a)}},
- "erlang" => <<-ERLANG
- fun({Doc}) ->
- A = couch_util:get_value(<<"a">>, Doc, null),
- Emit(<<"foo">>, A),
- Emit(<<"bar">>, A)
- end.
- ERLANG
- },
- "emit-once" => {
- "js" => <<-JS,
- function(doc){
- emit("baz",doc.a)
- }
- JS
- "erlang" => <<-ERLANG
- fun({Doc}) ->
- A = couch_util:get_value(<<"a">>, Doc, null),
- Emit(<<"baz">>, A)
- end.
- ERLANG
- },
- "reduce-values-length" => {
- "js" => %{function(keys, values, rereduce) { return values.length; }},
- "erlang" => %{fun(Keys, Values, ReReduce) -> length(Values) end.}
- },
- "reduce-values-sum" => {
- "js" => %{function(keys, values, rereduce) { return sum(values); }},
- "erlang" => %{fun(Keys, Values, ReReduce) -> lists:sum(Values) end.}
- },
- "validate-forbidden" => {
- "js" => <<-JS,
- function(newDoc, oldDoc, userCtx) {
- if(newDoc.bad)
- throw({forbidden:"bad doc"}); "foo bar";
- }
- JS
- "erlang" => <<-ERLANG
- fun({NewDoc}, _OldDoc, _UserCtx) ->
- case couch_util:get_value(<<"bad">>, NewDoc) of
- undefined -> 1;
- _ -> {[{forbidden, <<"bad doc">>}]}
- end
- end.
- ERLANG
- },
- "show-simple" => {
- "js" => <<-JS,
- function(doc, req) {
- log("ok");
- return [doc.title, doc.body].join(' - ');
- }
- JS
- "erlang" => <<-ERLANG
- fun({Doc}, Req) ->
- Title = couch_util:get_value(<<"title">>, Doc),
- Body = couch_util:get_value(<<"body">>, Doc),
- Resp = <<Title/binary, " - ", Body/binary>>,
- {[{<<"body">>, Resp}]}
- end.
- ERLANG
- },
- "show-headers" => {
- "js" => <<-JS,
- function(doc, req) {
- var resp = {"code":200, "headers":{"X-Plankton":"Rusty"}};
- resp.body = [doc.title, doc.body].join(' - ');
- return resp;
- }
- JS
- "erlang" => <<-ERLANG
- fun({Doc}, Req) ->
- Title = couch_util:get_value(<<"title">>, Doc),
- Body = couch_util:get_value(<<"body">>, Doc),
- Resp = <<Title/binary, " - ", Body/binary>>,
- {[
- {<<"code">>, 200},
- {<<"headers">>, {[{<<"X-Plankton">>, <<"Rusty">>}]}},
- {<<"body">>, Resp}
- ]}
- end.
- ERLANG
- },
- "show-sends" => {
- "js" => <<-JS,
- function(head, req) {
- start({headers:{"Content-Type" : "text/plain"}});
- send("first chunk");
- send('second "chunk"');
- return "tail";
- };
- JS
- "erlang" => <<-ERLANG
- fun(Head, Req) ->
- Resp = {[
- {<<"headers">>, {[{<<"Content-Type">>, <<"text/plain">>}]}}
- ]},
- Start(Resp),
- Send(<<"first chunk">>),
- Send(<<"second \\\"chunk\\\"">>),
- <<"tail">>
- end.
- ERLANG
- },
- "show-while-get-rows" => {
- "js" => <<-JS,
- function(head, req) {
- send("first chunk");
- send(req.q);
- var row;
- log("about to getRow " + typeof(getRow));
- while(row = getRow()) {
- send(row.key);
- };
- return "tail";
- };
- JS
- "erlang" => <<-ERLANG,
- fun(Head, {Req}) ->
- Send(<<"first chunk">>),
- Send(couch_util:get_value(<<"q">>, Req)),
- Fun = fun({Row}, _) ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {ok, nil}
- end,
- {ok, _} = FoldRows(Fun, nil),
- <<"tail">>
- end.
- ERLANG
- },
- "show-while-get-rows-multi-send" => {
- "js" => <<-JS,
- function(head, req) {
- send("bacon");
- var row;
- log("about to getRow " + typeof(getRow));
- while(row = getRow()) {
- send(row.key);
- send("eggs");
- };
- return "tail";
- };
- JS
- "erlang" => <<-ERLANG,
- fun(Head, Req) ->
- Send(<<"bacon">>),
- Fun = fun({Row}, _) ->
- Send(couch_util:get_value(<<"key">>, Row)),
- Send(<<"eggs">>),
- {ok, nil}
- end,
- FoldRows(Fun, nil),
- <<"tail">>
- end.
- ERLANG
- },
- "list-simple" => {
- "js" => <<-JS,
- function(head, req) {
- send("first chunk");
- send(req.q);
- var row;
- while(row = getRow()) {
- send(row.key);
- };
- return "early";
- };
- JS
- "erlang" => <<-ERLANG,
- fun(Head, {Req}) ->
- Send(<<"first chunk">>),
- Send(couch_util:get_value(<<"q">>, Req)),
- Fun = fun({Row}, _) ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {ok, nil}
- end,
- FoldRows(Fun, nil),
- <<"early">>
- end.
- ERLANG
- },
- "list-chunky" => {
- "js" => <<-JS,
- function(head, req) {
- send("first chunk");
- send(req.q);
- var row, i=0;
- while(row = getRow()) {
- send(row.key);
- i += 1;
- if (i > 2) {
- return('early tail');
- }
- };
- };
- JS
- "erlang" => <<-ERLANG,
- fun(Head, {Req}) ->
- Send(<<"first chunk">>),
- Send(couch_util:get_value(<<"q">>, Req)),
- Fun = fun
- ({Row}, Count) when Count < 2 ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {ok, Count+1};
- ({Row}, Count) when Count == 2 ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {stop, <<"early tail">>}
- end,
- {ok, Tail} = FoldRows(Fun, 0),
- Tail
- end.
- ERLANG
- },
- "list-old-style" => {
- "js" => <<-JS,
- function(head, req, foo, bar) {
- return "stuff";
- }
- JS
- "erlang" => <<-ERLANG,
- fun(Head, Req, Foo, Bar) ->
- <<"stuff">>
- end.
- ERLANG
- },
- "list-capped" => {
- "js" => <<-JS,
- function(head, req) {
- send("bacon")
- var row, i = 0;
- while(row = getRow()) {
- send(row.key);
- i += 1;
- if (i > 2) {
- return('early');
- }
- };
- }
- JS
- "erlang" => <<-ERLANG,
- fun(Head, Req) ->
- Send(<<"bacon">>),
- Fun = fun
- ({Row}, Count) when Count < 2 ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {ok, Count+1};
- ({Row}, Count) when Count == 2 ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {stop, <<"early">>}
- end,
- {ok, Tail} = FoldRows(Fun, 0),
- Tail
- end.
- ERLANG
- },
- "list-raw" => {
- "js" => <<-JS,
- function(head, req) {
- // log(this.toSource());
- // log(typeof send);
- send("first chunk");
- send(req.q);
- var row;
- while(row = getRow()) {
- send(row.key);
- };
- return "tail";
- };
- JS
- "erlang" => <<-ERLANG,
- fun(Head, {Req}) ->
- Send(<<"first chunk">>),
- Send(couch_util:get_value(<<"q">>, Req)),
- Fun = fun({Row}, _) ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {ok, nil}
- end,
- FoldRows(Fun, nil),
- <<"tail">>
- end.
- ERLANG
- },
- "filter-basic" => {
- "js" => <<-JS,
- function(doc, req) {
- if (doc.good) {
- return true;
- }
- }
- JS
- "erlang" => <<-ERLANG,
- fun({Doc}, Req) ->
- couch_util:get_value(<<"good">>, Doc)
- end.
- ERLANG
- },
- "update-basic" => {
- "js" => <<-JS,
- function(doc, req) {
- doc.world = "hello";
- var resp = [doc, "hello doc"];
- return resp;
- }
- JS
- "erlang" => <<-ERLANG,
- fun({Doc}, Req) ->
- Doc2 = [{<<"world">>, <<"hello">>}|Doc],
- [{Doc2}, {[{<<"body">>, <<"hello doc">>}]}]
- end.
- ERLANG
- },
- "error" => {
- "js" => <<-JS,
- function() {
- throw(["error","error_key","testing"]);
- }
- JS
- "erlang" => <<-ERLANG
- fun(A, B) ->
- throw([<<"error">>,<<"error_key">>,<<"testing">>])
- end.
- ERLANG
- },
- "fatal" => {
- "js" => <<-JS,
- function() {
- throw(["fatal","error_key","testing"]);
- }
- JS
- "erlang" => <<-ERLANG
- fun(A, B) ->
- throw([<<"fatal">>,<<"error_key">>,<<"testing">>])
- end.
- ERLANG
- }
-}
-
-def make_ddoc(fun_path, fun_str)
- doc = {"_id"=>"foo"}
- d = doc
- while p = fun_path.shift
- l = p
- if !fun_path.empty?
- d[p] = {}
- d = d[p]
- end
- end
- d[l] = fun_str
- doc
-end
-
-describe "query server normal case" do
- before(:all) do
- `cd #{COUCH_ROOT} && make`
- @qs = QueryServerRunner.run
- end
- after(:all) do
- @qs.close
- end
- it "should reset" do
- @qs.run(["reset"]).should == true
- end
- it "should not erase ddocs on reset" do
- @fun = functions["show-simple"][LANGUAGE]
- @ddoc = make_ddoc(["shows","simple"], @fun)
- @qs.teach_ddoc(@ddoc)
- @qs.run(["reset"]).should == true
- @qs.ddoc_run(@ddoc,
- ["shows","simple"],
- [{:title => "Best ever", :body => "Doc body"}, {}]).should ==
- ["resp", {"body" => "Best ever - Doc body"}]
- end
-
- it "should run map funs" do
- @qs.reset!
- @qs.run(["add_fun", functions["emit-twice"][LANGUAGE]]).should == true
- @qs.run(["add_fun", functions["emit-once"][LANGUAGE]]).should == true
- rows = @qs.run(["map_doc", {:a => "b"}])
- rows[0][0].should == ["foo", "b"]
- rows[0][1].should == ["bar", "b"]
- rows[1][0].should == ["baz", "b"]
- end
- describe "reduce" do
- before(:all) do
- @fun = functions["reduce-values-length"][LANGUAGE]
- @qs.reset!
- end
- it "should reduce" do
- kvs = (0...10).collect{|i|[i,i*2]}
- @qs.run(["reduce", [@fun], kvs]).should == [true, [10]]
- end
- end
- describe "rereduce" do
- before(:all) do
- @fun = functions["reduce-values-sum"][LANGUAGE]
- @qs.reset!
- end
- it "should rereduce" do
- vs = (0...10).collect{|i|i}
- @qs.run(["rereduce", [@fun], vs]).should == [true, [45]]
- end
- end
-
- describe "design docs" do
- before(:all) do
- @ddoc = {
- "_id" => "foo"
- }
- @qs.reset!
- end
- it "should learn design docs" do
- @qs.teach_ddoc(@ddoc).should == true
- end
- end
-
- # it "should validate"
- describe "validation" do
- before(:all) do
- @fun = functions["validate-forbidden"][LANGUAGE]
- @ddoc = make_ddoc(["validate_doc_update"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should allow good updates" do
- @qs.ddoc_run(@ddoc,
- ["validate_doc_update"],
- [{"good" => true}, {}, {}]).should == 1
- end
- it "should reject invalid updates" do
- @qs.ddoc_run(@ddoc,
- ["validate_doc_update"],
- [{"bad" => true}, {}, {}]).should == {"forbidden"=>"bad doc"}
- end
- end
-
- describe "show" do
- before(:all) do
- @fun = functions["show-simple"][LANGUAGE]
- @ddoc = make_ddoc(["shows","simple"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should show" do
- @qs.ddoc_run(@ddoc,
- ["shows","simple"],
- [{:title => "Best ever", :body => "Doc body"}, {}]).should ==
- ["resp", {"body" => "Best ever - Doc body"}]
- end
- end
-
- describe "show with headers" do
- before(:all) do
- # TODO we can make real ddocs up there.
- @fun = functions["show-headers"][LANGUAGE]
- @ddoc = make_ddoc(["shows","headers"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should show headers" do
- @qs.ddoc_run(
- @ddoc,
- ["shows","headers"],
- [{:title => "Best ever", :body => "Doc body"}, {}]
- ).
- should == ["resp", {"code"=>200,"headers" => {"X-Plankton"=>"Rusty"}, "body" => "Best ever - Doc body"}]
- end
- end
-
- describe "recoverable error" do
- before(:all) do
- @fun = functions["error"][LANGUAGE]
- @ddoc = make_ddoc(["shows","error"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should not exit" do
- @qs.ddoc_run(@ddoc, ["shows","error"],
- [{"foo"=>"bar"}, {"q" => "ok"}]).
- should == ["error", "error_key", "testing"]
- # still running
- @qs.run(["reset"]).should == true
- end
- end
-
- describe "changes filter" do
- before(:all) do
- @fun = functions["filter-basic"][LANGUAGE]
- @ddoc = make_ddoc(["filters","basic"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should only return true for good docs" do
- @qs.ddoc_run(@ddoc,
- ["filters","basic"],
- [[{"key"=>"bam", "good" => true}, {"foo" => "bar"}, {"good" => true}], {"req" => "foo"}]
- ).
- should == [true, [true, false, true]]
- end
- end
-
- describe "update" do
- before(:all) do
- # in another patch we can remove this duplication
- # by setting up the design doc for each language ahead of time.
- @fun = functions["update-basic"][LANGUAGE]
- @ddoc = make_ddoc(["updates","basic"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should return a doc and a resp body" do
- up, doc, resp = @qs.ddoc_run(@ddoc,
- ["updates","basic"],
- [{"foo" => "gnarly"}, {"method" => "POST"}]
- )
- up.should == "up"
- doc.should == {"foo" => "gnarly", "world" => "hello"}
- resp["body"].should == "hello doc"
- end
- end
-
-# end
-# LIST TESTS
-# __END__
-
- describe "ddoc list" do
- before(:all) do
- @ddoc = {
- "_id" => "foo",
- "lists" => {
- "simple" => functions["list-simple"][LANGUAGE],
- "headers" => functions["show-sends"][LANGUAGE],
- "rows" => functions["show-while-get-rows"][LANGUAGE],
- "buffer-chunks" => functions["show-while-get-rows-multi-send"][LANGUAGE],
- "chunky" => functions["list-chunky"][LANGUAGE]
- }
- }
- @qs.teach_ddoc(@ddoc)
- end
-
- describe "example list" do
- it "should run normal" do
- @qs.ddoc_run(@ddoc,
- ["lists","simple"],
- [{"foo"=>"bar"}, {"q" => "ok"}]
- ).should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
- @qs.run(["list_row", {"key"=>"baz"}]).should == ["chunks", ["baz"]]
- @qs.run(["list_row", {"key"=>"bam"}]).should == ["chunks", ["bam"]]
- @qs.run(["list_row", {"key"=>"foom"}]).should == ["chunks", ["foom"]]
- @qs.run(["list_row", {"key"=>"fooz"}]).should == ["chunks", ["fooz"]]
- @qs.run(["list_row", {"key"=>"foox"}]).should == ["chunks", ["foox"]]
- @qs.run(["list_end"]).should == ["end" , ["early"]]
- end
- end
-
- describe "headers" do
- it "should do headers proper" do
- @qs.ddoc_run(@ddoc, ["lists","headers"],
- [{"total_rows"=>1000}, {"q" => "ok"}]
- ).should == ["start", ["first chunk", 'second "chunk"'],
- {"headers"=>{"Content-Type"=>"text/plain"}}]
- @qs.rrun(["list_end"])
- @qs.jsgets.should == ["end", ["tail"]]
- end
- end
-
- describe "with rows" do
- it "should list em" do
- @qs.ddoc_run(@ddoc, ["lists","rows"],
- [{"foo"=>"bar"}, {"q" => "ok"}]).
- should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
- @qs.rrun(["list_row", {"key"=>"baz"}])
- @qs.get_chunks.should == ["baz"]
- @qs.rrun(["list_row", {"key"=>"bam"}])
- @qs.get_chunks.should == ["bam"]
- @qs.rrun(["list_end"])
- @qs.jsgets.should == ["end", ["tail"]]
- end
- it "should work with zero rows" do
- @qs.ddoc_run(@ddoc, ["lists","rows"],
- [{"foo"=>"bar"}, {"q" => "ok"}]).
- should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
- @qs.rrun(["list_end"])
- @qs.jsgets.should == ["end", ["tail"]]
- end
- end
-
- describe "should buffer multiple chunks sent for a single row." do
- it "should should buffer em" do
- @qs.ddoc_run(@ddoc, ["lists","buffer-chunks"],
- [{"foo"=>"bar"}, {"q" => "ok"}]).
- should == ["start", ["bacon"], {"headers"=>{}}]
- @qs.rrun(["list_row", {"key"=>"baz"}])
- @qs.get_chunks.should == ["baz", "eggs"]
- @qs.rrun(["list_row", {"key"=>"bam"}])
- @qs.get_chunks.should == ["bam", "eggs"]
- @qs.rrun(["list_end"])
- @qs.jsgets.should == ["end", ["tail"]]
- end
- end
- it "should end after 2" do
- @qs.ddoc_run(@ddoc, ["lists","chunky"],
- [{"foo"=>"bar"}, {"q" => "ok"}]).
- should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
-
- @qs.run(["list_row", {"key"=>"baz"}]).
- should == ["chunks", ["baz"]]
-
- @qs.run(["list_row", {"key"=>"bam"}]).
- should == ["chunks", ["bam"]]
-
- @qs.run(["list_row", {"key"=>"foom"}]).
- should == ["end", ["foom", "early tail"]]
- # here's where js has to discard quit properly
- @qs.run(["reset"]).
- should == true
- end
- end
- end
-
-
-
-def should_have_exited qs
- begin
- qs.run(["reset"])
- "raise before this (except Erlang)".should == true
- rescue RuntimeError => e
- e.message.should == "no response"
- rescue Errno::EPIPE
- true.should == true
- end
-end
-
-describe "query server that exits" do
- before(:each) do
- @qs = QueryServerRunner.run
- @ddoc = {
- "_id" => "foo",
- "lists" => {
- "capped" => functions["list-capped"][LANGUAGE],
- "raw" => functions["list-raw"][LANGUAGE]
- },
- "shows" => {
- "fatal" => functions["fatal"][LANGUAGE]
- }
- }
- @qs.teach_ddoc(@ddoc)
- end
- after(:each) do
- @qs.close
- end
-
- describe "only goes to 2 list" do
- it "should exit if erlang sends too many rows" do
- @qs.ddoc_run(@ddoc, ["lists","capped"],
- [{"foo"=>"bar"}, {"q" => "ok"}]).
- should == ["start", ["bacon"], {"headers"=>{}}]
- @qs.run(["list_row", {"key"=>"baz"}]).should == ["chunks", ["baz"]]
- @qs.run(["list_row", {"key"=>"foom"}]).should == ["chunks", ["foom"]]
- @qs.run(["list_row", {"key"=>"fooz"}]).should == ["end", ["fooz", "early"]]
- e = @qs.run(["list_row", {"key"=>"foox"}])
- e[0].should == "error"
- e[1].should == "unknown_command"
- should_have_exited @qs
- end
- end
-
- describe "raw list" do
- it "should exit if it gets a non-row in the middle" do
- @qs.ddoc_run(@ddoc, ["lists","raw"],
- [{"foo"=>"bar"}, {"q" => "ok"}]).
- should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
- e = @qs.run(["reset"])
- e[0].should == "error"
- e[1].should == "list_error"
- should_have_exited @qs
- end
- end
-
- describe "fatal error" do
- it "should exit" do
- @qs.ddoc_run(@ddoc, ["shows","fatal"],
- [{"foo"=>"bar"}, {"q" => "ok"}]).
- should == ["error", "error_key", "testing"]
- should_have_exited @qs
- end
- end
-end
-
-describe "thank you for using the tests" do
- it "for more info run with QS_TRACE=true or see query_server_spec.rb file header" do
- end
-end \ No newline at end of file
diff --git a/test/view_server/run_native_process.es b/test/view_server/run_native_process.es
deleted file mode 100755
index fcf16d75..00000000
--- a/test/view_server/run_native_process.es
+++ /dev/null
@@ -1,59 +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.
-
-read() ->
- case io:get_line('') of
- eof -> stop;
- Data -> couch_util:json_decode(Data)
- end.
-
-send(Data) when is_binary(Data) ->
- send(binary_to_list(Data));
-send(Data) when is_list(Data) ->
- io:format(Data ++ "\n", []).
-
-write(Data) ->
- % log("~p", [Data]),
- case (catch couch_util:json_encode(Data)) of
- % when testing, this is what prints your errors
- {json_encode, Error} -> write({[{<<"error">>, Error}]});
- Json -> send(Json)
- end.
-
-% log(Mesg) ->
-% log(Mesg, []).
-% log(Mesg, Params) ->
-% io:format(standard_error, Mesg, Params).
-% jlog(Mesg) ->
-% write([<<"log">>, list_to_binary(io_lib:format("~p",[Mesg]))]).
-
-loop(Pid) ->
- case read() of
- stop -> ok;
- Json ->
- case (catch couch_native_process:prompt(Pid, Json)) of
- {error, Reason} ->
- ok = write([error, Reason, Reason]);
- Resp ->
- ok = write(Resp),
- loop(Pid)
- end
- end.
-
-main([]) ->
- code:add_pathz("src/couchdb"),
- code:add_pathz("src/mochiweb"),
- {ok, Pid} = couch_native_process:start_link(),
- loop(Pid).
-