This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a commit to branch reshard
in repository https://gitbox.apache.org/repos/asf/couchdb.git
The following commit(s) were added to refs/heads/reshard by this push:
new 6465f97 [fixup|tests] Add Elixir integration tests
6465f97 is described below
commit 6465f9755574c7201965f5b643f3f1ae0b9a6065
Author: Nick Vatamaniuc <[email protected]>
AuthorDate: Wed Mar 13 14:11:51 2019 -0400
[fixup|tests] Add Elixir integration tests
Add test helpers as well as integration tests for basic API functions
---
test/elixir/test/reshard_basic_test.exs | 171 ++++++++++++++++++++++++++++++++
test/elixir/test/reshard_helpers.exs | 107 ++++++++++++++++++++
test/elixir/test/test_helper.exs | 1 +
3 files changed, 279 insertions(+)
diff --git a/test/elixir/test/reshard_basic_test.exs
b/test/elixir/test/reshard_basic_test.exs
new file mode 100644
index 0000000..99cdc47
--- /dev/null
+++ b/test/elixir/test/reshard_basic_test.exs
@@ -0,0 +1,171 @@
+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_node1()
+
+ 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 db1 (q=1) shards on node1", context do
+ db1 = context[:db1]
+ node1 = get_node1()
+
+ resp = post_job_node(db1, 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("/#{db1}/_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 db2 (q=2) shards on node1", context do
+ db2 = context[:db2]
+ node1 = get_node1()
+
+ resp = post_job_node(db2, 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("/#{db2}/_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]
+
+ remove_job(id1)
+ remove_job(id2)
+ summary = get_summary()
+ assert summary["total"] == 0
+ end
+end
diff --git a/test/elixir/test/reshard_helpers.exs
b/test/elixir/test/reshard_helpers.exs
new file mode 100644
index 0000000..66a2f7c
--- /dev/null
+++ b/test/elixir/test/reshard_helpers.exs
@@ -0,0 +1,107 @@
+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_node1 do
+ mresp = Couch.get("/_membership")
+ assert mresp.status_code == 200
+ cluster_nodes = mresp.body["cluster_nodes"]
+ [node1 | _] = cluster_nodes
+ node1
+ 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 4df3bf7..ef71bbb 100644
--- a/test/elixir/test/test_helper.exs
+++ b/test/elixir/test/test_helper.exs
@@ -13,3 +13,4 @@ ExUnit.configure(
ExUnit.start()
Code.require_file("partition_helpers.exs", __DIR__)
+Code.require_file("reshard_helpers.exs", __DIR__)