summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoan Touzet <wohali@users.noreply.github.com>2020-07-15 20:23:18 -0400
committerGitHub <noreply@github.com>2020-07-15 20:23:18 -0400
commit86bc5e555be19a298e8382a2dd88d98beb350063 (patch)
tree4a07f123cc879aacc168acc54a8b97e877b73736
parentcd4cd87309284b038c1f68a8973b838cac706891 (diff)
parent44eeee3414cafe8acbbcf028d5e67a00567df38d (diff)
downloadcouchdb-ci-vm-change-3.x.tar.gz
Merge branch '3.x' into ci-vm-change-3.xci-vm-change-3.x
-rw-r--r--src/couch/src/couch_bt_engine_compactor.erl5
-rw-r--r--test/elixir/README.md6
-rw-r--r--test/elixir/lib/couch/db_test.ex1
-rw-r--r--test/elixir/test/view_collation_raw_test.exs159
-rw-r--r--test/elixir/test/view_compaction_test.exs105
-rw-r--r--test/javascript/tests/view_collation_raw.js1
-rw-r--r--test/javascript/tests/view_compaction.js1
7 files changed, 273 insertions, 5 deletions
diff --git a/src/couch/src/couch_bt_engine_compactor.erl b/src/couch/src/couch_bt_engine_compactor.erl
index 4bed49c7c..3e356e2e3 100644
--- a/src/couch/src/couch_bt_engine_compactor.erl
+++ b/src/couch/src/couch_bt_engine_compactor.erl
@@ -628,8 +628,9 @@ commit_compaction_data(#st{header = OldHeader} = St0, Fd) ->
bind_emsort(St, Fd, nil) ->
{ok, Ems} = couch_emsort:open(Fd),
St#st{id_tree=Ems};
-bind_emsort(St, Fd, State) when is_integer(State) ->
- bind_emsort(St, Fd, [{root, State}]);
+bind_emsort(St, Fd, {BB, _} = Root) when is_list(BB) ->
+ % Upgrade clause when we find old compaction files
+ bind_emsort(St, Fd, [{root, Root}]);
bind_emsort(St, Fd, State) ->
{ok, Ems} = couch_emsort:open(Fd, State),
St#st{id_tree=Ems}.
diff --git a/test/elixir/README.md b/test/elixir/README.md
index 0043fcfea..e48dc2990 100644
--- a/test/elixir/README.md
+++ b/test/elixir/README.md
@@ -99,8 +99,8 @@ X means done, - means partially
- [X] Port utf8.js
- [X] Port uuids.js
- [X] Port view_collation.js
- - [ ] Port view_collation_raw.js
- - [ ] Port view_compaction.js
+ - [X] Port view_collation_raw.js
+ - [X] Port view_compaction.js
- [ ] Port view_conflicts.js
- [ ] Port view_errors.js
- [ ] Port view_include_docs.js
@@ -110,7 +110,7 @@ X means done, - means partially
- [X] Port view_offsets.js
- [X] Port view_pagination.js
- [ ] Port view_sandboxing.js
- - [ ] Port view_update_seq.js
+ - [X] Port view_update_seq.js
# Using ExUnit to write unit tests
diff --git a/test/elixir/lib/couch/db_test.ex b/test/elixir/lib/couch/db_test.ex
index 23f10937d..652fa6bb6 100644
--- a/test/elixir/lib/couch/db_test.ex
+++ b/test/elixir/lib/couch/db_test.ex
@@ -209,6 +209,7 @@ defmodule Couch.DBTest do
)
assert resp.status_code in [201, 202]
+ resp
end
def query(
diff --git a/test/elixir/test/view_collation_raw_test.exs b/test/elixir/test/view_collation_raw_test.exs
new file mode 100644
index 000000000..ee272d72e
--- /dev/null
+++ b/test/elixir/test/view_collation_raw_test.exs
@@ -0,0 +1,159 @@
+defmodule ViewCollationRawTest do
+ use CouchTestCase
+
+ @moduledoc """
+ Test CouchDB View Raw Collation Behavior
+ This is a port of the view_collation_raw.js suite
+ """
+
+ @values [
+ # Then numbers
+ 1,
+ 2,
+ 3,
+ 4,
+ false,
+ :null,
+ true,
+
+ # Then objects, compared each key value in the list until different.
+ # Larger objects sort after their subset objects
+ {[a: 1]},
+ {[a: 2]},
+ {[b: 1]},
+ {[b: 2]},
+ # Member order does matter for collation
+ {[b: 2, a: 1]},
+ {[b: 2, c: 2]},
+
+ # Then arrays, compared element by element until different.
+ # Longer arrays sort after their prefixes
+ ["a"],
+ ["b"],
+ ["b", "c"],
+ ["b", "c", "a"],
+ ["b", "d"],
+ ["b", "d", "e"],
+
+ # Then text, case sensitive
+ "A",
+ "B",
+ "a",
+ "aa",
+ "b",
+ "ba",
+ "bb"
+ ]
+
+ setup_all do
+ db_name = random_db_name()
+ {:ok, _} = create_db(db_name)
+ on_exit(fn -> delete_db(db_name) end)
+
+ {docs, _} =
+ Enum.flat_map_reduce(@values, 1, fn value, idx ->
+ doc = %{:_id => Integer.to_string(idx), :foo => value}
+ {[doc], idx + 1}
+ end)
+
+ resp = Couch.post("/#{db_name}/_bulk_docs", body: %{:docs => docs})
+ Enum.each(resp.body, &assert(&1["ok"]))
+
+ map_fun = "function(doc) { emit(doc.foo, null); }"
+
+ map_doc = %{
+ :language => "javascript",
+ :views => %{:test => %{:map => map_fun, :options => %{:collation => "raw"}}}
+ }
+
+ resp = Couch.put("/#{db_name}/_design/test", body: map_doc)
+ assert resp.body["ok"]
+
+ {:ok, [db_name: db_name]}
+ end
+
+ test "ascending collation order", context do
+ retry_until(fn ->
+ resp = Couch.get(url(context))
+ pairs = Enum.zip(resp.body["rows"], @values)
+
+ Enum.each(pairs, fn {row, value} ->
+ assert row["key"] == convert(value)
+ end)
+ end)
+ end
+
+ test "raw semantics in key ranges", context do
+ retry_until(fn ->
+ resp =
+ Couch.get(url(context),
+ query: %{"startkey" => :jiffy.encode("Z"), "endkey" => :jiffy.encode("a")}
+ )
+
+ assert length(resp.body["rows"]) == 1
+ assert Enum.at(resp.body["rows"], 0)["key"] == "a"
+ end)
+ end
+
+ test "descending collation order", context do
+ retry_until(fn ->
+ resp = Couch.get(url(context), query: %{"descending" => "true"})
+ pairs = Enum.zip(resp.body["rows"], Enum.reverse(@values))
+
+ Enum.each(pairs, fn {row, value} ->
+ assert row["key"] == convert(value)
+ end)
+ end)
+ end
+
+ test "key query option", context do
+ Enum.each(@values, fn value ->
+ retry_until(fn ->
+ resp = Couch.get(url(context), query: %{:key => :jiffy.encode(value)})
+ assert length(resp.body["rows"]) == 1
+ assert Enum.at(resp.body["rows"], 0)["key"] == convert(value)
+ end)
+ end)
+ end
+
+ test "inclusive_end=true", context do
+ query = %{:endkey => :jiffy.encode("b"), :inclusive_end => true}
+ resp = Couch.get(url(context), query: query)
+ assert Enum.at(resp.body["rows"], -1)["key"] == "b"
+
+ query = Map.put(query, :descending, true)
+ resp = Couch.get(url(context), query: query)
+ assert Enum.at(resp.body["rows"], -1)["key"] == "b"
+ end
+
+ test "inclusive_end=false", context do
+ query = %{:endkey => :jiffy.encode("b"), :inclusive_end => false}
+ resp = Couch.get(url(context), query: query)
+ assert Enum.at(resp.body["rows"], -1)["key"] == "aa"
+
+ query = Map.put(query, :descending, true)
+ resp = Couch.get(url(context), query: query)
+ assert Enum.at(resp.body["rows"], -1)["key"] == "ba"
+
+ query = %{
+ :endkey => :jiffy.encode("b"),
+ :endkey_docid => 10,
+ :inclusive_end => false
+ }
+
+ resp = Couch.get(url(context), query: query)
+ assert Enum.at(resp.body["rows"], -1)["key"] == "aa"
+
+ query = Map.put(query, :endkey_docid, 11)
+ resp = Couch.get(url(context), query: query)
+ assert Enum.at(resp.body["rows"], -1)["key"] == "aa"
+ end
+
+ def url(context) do
+ "/#{context[:db_name]}/_design/test/_view/test"
+ end
+
+ def convert(value) do
+ :jiffy.decode(:jiffy.encode(value), [:return_maps])
+ end
+end
diff --git a/test/elixir/test/view_compaction_test.exs b/test/elixir/test/view_compaction_test.exs
new file mode 100644
index 000000000..d2bf060ba
--- /dev/null
+++ b/test/elixir/test/view_compaction_test.exs
@@ -0,0 +1,105 @@
+defmodule ViewCompactionTest do
+ use CouchTestCase
+
+ @moduledoc """
+ Test CouchDB View Compaction Behavior
+ This is a port of the view_compaction.js suite
+ """
+ @num_docs 1000
+
+ @ddoc %{
+ _id: "_design/foo",
+ language: "javascript",
+ views: %{
+ view1: %{
+ map: "function(doc) { emit(doc._id, doc.value) }"
+ },
+ view2: %{
+ map:
+ "function(doc) { if (typeof(doc.integer) === 'number') {emit(doc._id, doc.integer);} }",
+ reduce: "function(keys, values, rereduce) { return sum(values); }"
+ }
+ }
+ }
+
+ defp bulk_save_for_update(db_name, docs) do
+ resp = bulk_save(db_name, docs)
+ revs = resp.body
+
+ Enum.map(docs, fn m ->
+ rev = Enum.at(revs, String.to_integer(m["_id"]))["rev"]
+
+ m
+ |> Map.put("_rev", rev)
+ |> Map.update!("integer", &(&1 + 1))
+ end)
+ end
+
+ @tag :with_db
+ test "view compaction", context do
+ db_name = context[:db_name]
+ create_doc(db_name, @ddoc)
+
+ docs = make_docs(0..(@num_docs - 1))
+ docs = bulk_save_for_update(db_name, docs)
+
+ resp = view(db_name, "foo/view1")
+ assert length(resp.body["rows"]) == @num_docs
+
+ resp = view(db_name, "foo/view2")
+ assert length(resp.body["rows"]) == 1
+
+ resp = Couch.get("/#{db_name}/_design/foo/_info")
+ assert resp.body["view_index"]["update_seq"] == @num_docs + 1
+
+ docs = bulk_save_for_update(db_name, docs)
+
+ resp = view(db_name, "foo/view1")
+ assert length(resp.body["rows"]) == @num_docs
+
+ resp = view(db_name, "foo/view2")
+ assert length(resp.body["rows"]) == 1
+
+ resp = Couch.get("/#{db_name}/_design/foo/_info")
+ assert resp.body["view_index"]["update_seq"] == 2 * @num_docs + 1
+
+ bulk_save(db_name, docs)
+ resp = view(db_name, "foo/view1")
+ assert length(resp.body["rows"]) == @num_docs
+
+ resp = view(db_name, "foo/view2")
+ assert length(resp.body["rows"]) == 1
+
+ resp = Couch.get("/#{db_name}/_design/foo/_info")
+ assert resp.body["view_index"]["update_seq"] == 3 * @num_docs + 1
+
+ disk_size_before_compact = resp.body["view_index"]["sizes"]["file"]
+ data_size_before_compact = resp.body["view_index"]["sizes"]["active"]
+
+ assert is_integer(disk_size_before_compact)
+ assert data_size_before_compact < disk_size_before_compact
+
+ resp = Couch.post("/#{db_name}/_compact/foo")
+ assert resp.body["ok"] == true
+
+ retry_until(fn ->
+ resp = Couch.get("/#{db_name}/_design/foo/_info")
+ resp.body["view_index"]["compact_running"] == false
+ end)
+
+ resp = view(db_name, "foo/view1")
+ assert length(resp.body["rows"]) == @num_docs
+
+ resp = view(db_name, "foo/view2")
+ assert length(resp.body["rows"]) == 1
+
+ resp = Couch.get("/#{db_name}/_design/foo/_info")
+ assert resp.body["view_index"]["update_seq"] == 3 * @num_docs + 1
+
+ disk_size_after_compact = resp.body["view_index"]["sizes"]["file"]
+ data_size_after_compact = resp.body["view_index"]["sizes"]["active"]
+ assert disk_size_after_compact < disk_size_before_compact
+ assert is_integer(data_size_after_compact)
+ assert data_size_after_compact < disk_size_after_compact
+ end
+end
diff --git a/test/javascript/tests/view_collation_raw.js b/test/javascript/tests/view_collation_raw.js
index 9b02ff49d..ee990bc4c 100644
--- a/test/javascript/tests/view_collation_raw.js
+++ b/test/javascript/tests/view_collation_raw.js
@@ -10,6 +10,7 @@
// License for the specific language governing permissions and limitations under
// the License.
+couchTests.elixir = true;
couchTests.view_collation_raw = function(debug) {
var db_name = get_random_db_name();
var db = new CouchDB(db_name, {"X-Couch-Full-Commit":"false"});
diff --git a/test/javascript/tests/view_compaction.js b/test/javascript/tests/view_compaction.js
index d1a1e8790..f2af39058 100644
--- a/test/javascript/tests/view_compaction.js
+++ b/test/javascript/tests/view_compaction.js
@@ -10,6 +10,7 @@
// License for the specific language governing permissions and limitations under
// the License.
+couchTests.elixir = true;
couchTests.view_compaction = function(debug) {
if (debug) debugger;