This is an automated email from the ASF dual-hosted git repository. jiahuili430 pushed a commit to branch add-retry-until-for-search_test.exs in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 798ce0306e6c6d81f8e004fa505f1110a00add44 Author: Jiahui Li <[email protected]> AuthorDate: Sat Apr 11 15:12:27 2026 -0500 Add `retry_until()` to fix flaky elixir search tests When running Elixir search tests in Clouseau GitHub Actions CI, some tests got `(KeyError) key :status_code not found in: %HTTPotion.ErrorResponse{message: "req_timedout"}`. Adding `retry_until()` to mitigate this. --- test/elixir/test/search_test.exs | 134 +++++++++++++++++++++++++-------------- 1 file changed, 85 insertions(+), 49 deletions(-) diff --git a/test/elixir/test/search_test.exs b/test/elixir/test/search_test.exs index edf6858cf..061ee8da1 100644 --- a/test/elixir/test/search_test.exs +++ b/test/elixir/test/search_test.exs @@ -9,19 +9,18 @@ defmodule SearchTest do """ def create_search_docs(db_name) do - resp = Couch.post("/#{db_name}/_bulk_docs", - headers: ["Content-Type": "application/json"], - body: %{:docs => [ - %{"item" => "apple", "place" => "kitchen", "state" => "new", "price" => 0.99}, - %{"item" => "banana", "place" => "kitchen", "state" => "new", "price" => 1.49}, - %{"item" => "carrot", "place" => "kitchen", "state" => "old", "price" => 0.75}, - %{"item" => "date", "place" => "lobby", "state" => "unknown", "price" => 1.25}, - ]} - ) - assert resp.status_code in [201, 202], - "Cannot create search docs. " <> - "Expected one of [201, 202], got: #{resp.status_code}, body: #{inspect resp.body}" - + resp = Couch.post("/#{db_name}/_bulk_docs", + headers: ["Content-Type": "application/json"], + body: %{:docs => [ + %{"item" => "apple", "place" => "kitchen", "state" => "new", "price" => 0.99}, + %{"item" => "banana", "place" => "kitchen", "state" => "new", "price" => 1.49}, + %{"item" => "carrot", "place" => "kitchen", "state" => "old", "price" => 0.75}, + %{"item" => "date", "place" => "lobby", "state" => "unknown", "price" => 1.25}, + ]} + ) + assert resp.status_code in [201, 202], + "Cannot create search docs. " <> + "Expected one of [201, 202], got: #{resp.status_code}, body: #{inspect resp.body}" end def create_ddoc(db_name, opts \\ %{}) do @@ -74,8 +73,11 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.get(url, query: %{q: "*:*", include_docs: true}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.get(url, query: %{q: "*:*", include_docs: true}) + assert_on_status(resp, 200, "Fail to do search.") + end) + ids = get_items(resp) assert Enum.sort(ids) == Enum.sort(["apple", "banana", "carrot", "date"]) end @@ -87,8 +89,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.get(url, query: %{q: "*:*", drilldown: :jiffy.encode(["place", "kitchen"]), include_docs: true}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.get(url, query: %{q: "*:*", drilldown: :jiffy.encode(["place", "kitchen"]), include_docs: true}) + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == Enum.sort(["apple", "banana", "carrot"]) @@ -101,8 +105,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.get(url, query: %{q: "*:*", drilldown: :jiffy.encode(["state", "new", "unknown"]), include_docs: true}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.get(url, query: %{q: "*:*", drilldown: :jiffy.encode(["state", "new", "unknown"]), include_docs: true}) + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == Enum.sort(["apple", "banana", "date"]) @@ -115,8 +121,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.get(url, query: %{q: "*:*", drilldown: :jiffy.encode([["state", "old"], ["item", "apple"]]), include_docs: true}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.get(url, query: %{q: "*:*", drilldown: :jiffy.encode([["state", "old"], ["item", "apple"]]), include_docs: true}) + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == [] @@ -129,8 +137,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits?q=*:*&drilldown=[\"state\",\"old\"]&drilldown=[\"item\",\"apple\"]&include_docs=true" - resp = Couch.get(url) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.get(url) + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == [] @@ -144,8 +154,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.post(url, body: %{q: "*:*", include_docs: true}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.post(url, body: %{q: "*:*", include_docs: true}) + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == Enum.sort(["apple", "banana", "carrot", "date"]) @@ -158,8 +170,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.post(url, body: %{query: "*:*", drilldown: ["place", "kitchen"], include_docs: true}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.post(url, body: %{query: "*:*", drilldown: ["place", "kitchen"], include_docs: true}) + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == Enum.sort(["apple", "banana", "carrot"]) @@ -172,8 +186,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.post(url, body: %{query: "*:*", drilldown: ["state", "new", "unknown"], include_docs: true}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.post(url, body: %{query: "*:*", drilldown: ["state", "new", "unknown"], include_docs: true}) + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == Enum.sort(["apple", "banana", "date"]) @@ -186,8 +202,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.post(url, body: %{q: "*:*", drilldown: [["state", "old"], ["item", "apple"]], include_docs: true}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.post(url, body: %{q: "*:*", drilldown: [["state", "old"], ["item", "apple"]], include_docs: true}) + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == [] @@ -200,8 +218,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.post(url, body: %{q: "*:*", drilldown: [["place", "kitchen"], ["state", "new"], ["item", "apple"]], include_docs: true}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.post(url, body: %{q: "*:*", drilldown: [["place", "kitchen"], ["state", "new"], ["item", "apple"]], include_docs: true}) + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == ["apple"] @@ -214,8 +234,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.post(url, body: %{q: "*:*", drilldown: [["state", "old", "new"], ["item", "apple"]], include_docs: true}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.post(url, body: %{q: "*:*", drilldown: [["state", "old", "new"], ["item", "apple"]], include_docs: true}) + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == ["apple"] @@ -228,8 +250,10 @@ defmodule SearchTest do create_ddoc(db_name) url = "/#{db_name}/_design/inventory/_search/fruits" - resp = Couch.post(url, body: "{\"include_docs\": true, \"q\": \"*:*\", \"drilldown\": [\"state\", \"old\"], \"drilldown\": [\"item\", \"apple\"]}") - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.post(url, body: "{\"include_docs\": true, \"q\": \"*:*\", \"drilldown\": [\"state\", \"old\"], \"drilldown\": [\"item\", \"apple\"]}") + assert_on_status(resp, 200, "Fail to do search.") + end) ids = get_items(resp) assert Enum.sort(ids) == ["apple"] @@ -242,8 +266,10 @@ defmodule SearchTest do create_ddoc(db_name) create_invalid_ddoc(db_name) - resp = Couch.post("/#{db_name}/_search_cleanup") - assert_on_status(resp, [201, 202], "Fail to do a _search_cleanup.") + retry_until(fn -> + resp = Couch.post("/#{db_name}/_search_cleanup") + assert_on_status(resp, [201, 202], "Fail to do a _search_cleanup.") + end) end @tag :with_db @@ -254,8 +280,10 @@ defmodule SearchTest do url = "/#{db_name}/_design/inventory/_search/fruits" counts = ["place"] - resp = Couch.get(url, query: %{q: "*:*", limit: 0, counts: :jiffy.encode(counts)}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.get(url, query: %{q: "*:*", limit: 0, counts: :jiffy.encode(counts)}) + assert_on_status(resp, 200, "Fail to do search.") + end) %{:body => %{"counts" => counts}} = resp assert counts == %{"place" => %{"kitchen" => 3, "lobby" => 1}} @@ -269,8 +297,10 @@ defmodule SearchTest do url = "/#{db_name}/_design/inventory/_search/fruits" counts = ["place"] - resp = Couch.get(url, query: %{q: "item:tomato", limit: 0, counts: :jiffy.encode(counts)}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.get(url, query: %{q: "item:tomato", limit: 0, counts: :jiffy.encode(counts)}) + assert_on_status(resp, 200, "Fail to do search.") + end) %{:body => %{"counts" => counts}} = resp assert counts == %{"place" => %{}} @@ -284,8 +314,10 @@ defmodule SearchTest do url = "/#{db_name}/_design/inventory/_search/fruits" ranges = %{"price" => %{"cheap" => "[0 TO 0.99]", "expensive" => "[1.00 TO Infinity]"}} - resp = Couch.get(url, query: %{q: "*:*", limit: 0, ranges: :jiffy.encode(ranges)}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.get(url, query: %{q: "*:*", limit: 0, ranges: :jiffy.encode(ranges)}) + assert_on_status(resp, 200, "Fail to do search.") + end) %{:body => %{"ranges" => ranges}} = resp assert ranges == %{"price" => %{"cheap" => 2, "expensive" => 2}} @@ -299,8 +331,10 @@ defmodule SearchTest do url = "/#{db_name}/_design/inventory/_search/fruits" ranges = %{"price" => %{}} - resp = Couch.get(url, query: %{q: "*:*", limit: 0, ranges: :jiffy.encode(ranges)}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.get(url, query: %{q: "*:*", limit: 0, ranges: :jiffy.encode(ranges)}) + assert_on_status(resp, 200, "Fail to do search.") + end) %{:body => %{"ranges" => ranges}} = resp assert ranges == %{"price" => %{}} @@ -314,8 +348,10 @@ defmodule SearchTest do url = "/#{db_name}/_design/inventory/_search/fruits" ranges = %{"price" => %{}} - resp = Couch.get(url, query: %{q: "*:*", group_field: "state"}) - assert_on_status(resp, 200, "Fail to do search.") + retry_until(fn -> + resp = Couch.get(url, query: %{q: "*:*", group_field: "state"}) + assert_on_status(resp, 200, "Fail to do search.") + end) %{:body => %{"groups" => groups}} = resp assert length(groups) == 3
