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__)

Reply via email to