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