This is an automated email from the ASF dual-hosted git repository.

jan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit ea16a558d3bd5653eb67b2a899ec7ce8161c4eb2
Author: James Coglan <[email protected]>
AuthorDate: Fri Oct 3 14:45:45 2025 +0100

    Port a basic _find test to Elixir along with the user_docs fixture it 
depends on
---
 test/elixir/test/config/suite.elixir          |   3 +
 test/elixir/test/mango/02_basic_find_test.exs |  28 ++
 test/elixir/test/support/mango_database.ex    |  70 +++++
 test/elixir/test/support/user_docs.ex         | 399 ++++++++++++++++++++++++++
 4 files changed, 500 insertions(+)

diff --git a/test/elixir/test/config/suite.elixir 
b/test/elixir/test/config/suite.elixir
index 1cbdfccf3..a9d58e823 100644
--- a/test/elixir/test/config/suite.elixir
+++ b/test/elixir/test/config/suite.elixir
@@ -729,5 +729,8 @@
     "Creating-Updating/Deleting doc with overriden quorum should return 
201-Created/200-OK",
     "Creating/Deleting DB should return 202-Acepted",
     "Creating/Updating/Deleting doc should return 202-Acepted"
+  ],
+  "BasicFindTest": [
+    "simple find"
   ]
 }
diff --git a/test/elixir/test/mango/02_basic_find_test.exs 
b/test/elixir/test/mango/02_basic_find_test.exs
new file mode 100644
index 000000000..e6ae1ad64
--- /dev/null
+++ b/test/elixir/test/mango/02_basic_find_test.exs
@@ -0,0 +1,28 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+defmodule BasicFindTest do
+  use CouchTestCase
+
+  @db_name "basic-find"
+
+  setup do
+    UserDocs.setup(@db_name)
+  end
+
+  test "simple find" do
+    docs = MangoDatabase.find(@db_name, %{"age" => %{"$lt" => 35}})
+    user_ids = Enum.map(docs, fn doc -> doc["user_id"] end)
+
+    assert user_ids == [9, 1, 7]
+  end
+end
diff --git a/test/elixir/test/support/mango_database.ex 
b/test/elixir/test/support/mango_database.ex
new file mode 100644
index 000000000..80dcd338c
--- /dev/null
+++ b/test/elixir/test/support/mango_database.ex
@@ -0,0 +1,70 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+defmodule MangoDatabase do
+  def recreate(db, opts \\ []) do
+    resp = Couch.get("/#{db}")
+    if resp.status_code == 200 do
+      docs = resp.body["doc_count"] + resp.body["doc_del_count"]
+      if docs > 0 do
+        delete(db)
+        create(db, opts)
+      end
+    else
+      create(db, opts)
+    end
+  end
+
+  defp create(db, opts) do
+    partitioned = Keyword.get(opts, :partitioned, false)
+    Couch.put("/#{db}?partitioned=#{partitioned}")
+  end
+
+  defp delete(db) do
+    Couch.delete("/#{db}")
+  end
+
+  # TODO: make this use batches if necessary
+  def save_docs(db, docs) do
+    resp = Couch.post("/#{db}/_bulk_docs", body: %{"docs" => docs})
+  end
+
+  def create_index(db, fields, name) do
+    resp = Couch.post("/#{db}/_index", body: %{
+      "index" => %{"fields" => fields},
+      "name" => name,
+      "ddoc" => name,
+      "type" => "json",
+      "w" => 3
+    })
+  end
+
+  def create_text_index(db) do
+    # TODO
+  end
+
+  # TODO: port more options from src/mango/test/mango.py `def find(...)`
+  def find(db, selector, opts \\ []) do
+    defaults = [use_index: nil, skip: 0, limit: 25, r: 1, conflicts: false]
+    options = Keyword.merge(defaults, opts)
+
+    resp = Couch.post("/#{db}/_find", body: %{
+      "selector" => selector,
+      "use_index" => options[:use_index],
+      "skip" => options[:skip],
+      "limit" => options[:limit],
+      "r" => options[:r],
+      "conflicts" => options[:conflicts]
+    })
+    resp.body["docs"]
+  end
+end
diff --git a/test/elixir/test/support/user_docs.ex 
b/test/elixir/test/support/user_docs.ex
new file mode 100644
index 000000000..456fd0b81
--- /dev/null
+++ b/test/elixir/test/support/user_docs.ex
@@ -0,0 +1,399 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+defmodule UserDocs do
+  @moduledoc """
+  Generated with http://www.json-generator.com/
+
+  With this pattern:
+
+  [
+      '{{repeat(20)}}',
+      {
+          _id: '{{guid()}}',
+          user_id: "{{index()}}",
+          name: {
+              first: "{{firstName()}}",
+              last: "{{surname()}}"
+          },
+          age: "{{integer(18,90)}}",
+          location: {
+              state: "{{state()}}",
+              city: "{{city()}}",
+              address: {
+                  street: "{{street()}}",
+                  number: "{{integer(10, 10000)}}"
+              }
+          },
+          company: "{{company()}}",
+          email: "{{email()}}",
+          manager: "{{bool()}}",
+          twitter: function(tags) {
+              if(this.manager)
+                  return;
+              return "@" + this.email.split("@")[0];
+          },
+          favorites: [
+              "{{repeat(2,5)}}",
+              "{{random('C', 'C++', 'Python', 'Ruby', 'Erlang', 'Lisp')}}"
+          ]
+      }
+  ]
+  """
+
+  @partitions 3
+
+  @docs [
+    %{
+      "_id" => "71562648-6acb-42bc-a182-df6b1f005b09",
+      "user_id" => 0,
+      "name" => %{"first" => "Stephanie", "last" => "Kirkland"},
+      "age" => 48,
+      "location" => %{
+        "state" => "Nevada",
+        "city" => "Ronco",
+        "address" => %{"street" => "Evergreen Avenue", "number" => 347},
+      },
+      "company" => "Dreamia",
+      "email" => "[email protected]",
+      "manager" => false,
+      "twitter" => "@stephaniekirkland",
+      "favorites" => ["Ruby", "C", "Python"],
+      "test" => [%{"a" => 1}, %{"b" => 2}],
+    },
+    %{
+      "_id" => "12a2800c-4fe2-45a8-8d78-c084f4e242a9",
+      "user_id" => 1,
+      "name" => %{"first" => "Abbott", "last" => "Watson"},
+      "age" => 31,
+      "location" => %{
+        "state" => "Connecticut",
+        "city" => "Gerber",
+        "address" => %{"street" => "Huntington Street", "number" => 8987},
+      },
+      "company" => "Talkola",
+      "email" => "[email protected]",
+      "manager" => false,
+      "twitter" => "@abbottwatson",
+      "favorites" => ["Ruby", "Python", "C", %{"Versions" => %{"Alpha" => 
"Beta"}}],
+      "test" => [%{"a" => 1, "b" => 2}],
+    },
+    %{
+      "_id" => "48ca0455-8bd0-473f-9ae2-459e42e3edd1",
+      "user_id" => 2,
+      "name" => %{"first" => "Shelly", "last" => "Ewing"},
+      "age" => 42,
+      "location" => %{
+        "state" => "New Mexico",
+        "city" => "Thornport",
+        "address" => %{"street" => "Miller Avenue", "number" => 7100},
+      },
+      "company" => "Zialactic",
+      "email" => "[email protected]",
+      "manager" => true,
+      "favorites" => ["Lisp", "Python", "Erlang"],
+      "test_in" => %{"val1" => 1, "val2" => "val2"},
+    },
+    %{
+      "_id" => "0461444c-e60a-457d-a4bb-b8d811853f21",
+      "user_id" => 3,
+      "name" => %{"first" => "Madelyn", "last" => "Soto"},
+      "age" => 79,
+      "location" => %{
+        "state" => "Utah",
+        "city" => "Albany",
+        "address" => %{"street" => "Stockholm Street", "number" => 710},
+      },
+      "company" => "Tasmania",
+      "email" => "[email protected]",
+      "manager" => true,
+      "favorites" => [["Lisp", "Erlang", "Python"], "Erlang", "C", "Erlang"],
+      "11111" => "number_field",
+      "22222" => %{"33333" => "nested_number_field"},
+    },
+    %{
+      "_id" => "8e1c90c0-ac18-4832-8081-40d14325bde0",
+      "user_id" => 4,
+      "name" => %{"first" => "Nona", "last" => "Horton"},
+      "age" => 61,
+      "location" => %{
+        "state" => "Georgia",
+        "city" => "Corinne",
+        "address" => %{"street" => "Woodhull Street", "number" => 6845},
+      },
+      "company" => "Signidyne",
+      "email" => "[email protected]",
+      "manager" => false,
+      "twitter" => "@nonahorton",
+      "favorites" => ["Lisp", "C", "Ruby", "Ruby"],
+      "name.first" => "name dot first",
+    },
+    %{
+      "_id" => "a33d5457-741a-4dce-a217-3eab28b24e3e",
+      "user_id" => 5,
+      "name" => %{"first" => "Sheri", "last" => "Perkins"},
+      "age" => 73,
+      "location" => %{
+        "state" => "Michigan",
+        "city" => "Nutrioso",
+        "address" => %{"street" => "Bassett Avenue", "number" => 5648},
+      },
+      "company" => "Myopium",
+      "email" => "[email protected]",
+      "manager" => true,
+      "favorites" => ["Lisp", "Lisp"],
+    },
+    %{
+      "_id" => "b31dad3f-ae8b-4f86-8327-dfe8770beb27",
+      "user_id" => 6,
+      "name" => %{"first" => "Tate", "last" => "Guy"},
+      "age" => 47,
+      "location" => %{
+        "state" => "Illinois",
+        "city" => "Helen",
+        "address" => %{"street" => "Schenck Court", "number" => 7392},
+      },
+      "company" => "Prosely",
+      "email" => "[email protected]",
+      "manager" => true,
+      "favorites" => ["C", "Lisp", "Ruby", "C"],
+    },
+    %{
+      "_id" => "659d0430-b1f4-413a-a6b7-9ea1ef071325",
+      "user_id" => 7,
+      "name" => %{"first" => "Jewell", "last" => "Stafford"},
+      "age" => 33,
+      "location" => %{
+        "state" => "Iowa",
+        "city" => "Longbranch",
+        "address" => %{"street" => "Dodworth Street", "number" => 3949},
+      },
+      "company" => "Niquent",
+      "email" => "[email protected]",
+      "manager" => true,
+      "favorites" => ["C", "C", "Ruby", "Ruby", "Erlang"],
+      "exists_field" => "should_exist1",
+      "ordered" => nil,
+    },
+    %{
+      "_id" => "6c0afcf1-e57e-421d-a03d-0c0717ebf843",
+      "user_id" => 8,
+      "name" => %{"first" => "James", "last" => "Mcdaniel"},
+      "age" => 68,
+      "location" => %{
+        "state" => "Maine",
+        "city" => "Craig",
+        "address" => %{"street" => "Greene Avenue", "number" => 8776},
+      },
+      "company" => "Globoil",
+      "email" => "[email protected]",
+      "manager" => true,
+      "favorites" => nil,
+      "exists_field" => "should_exist2",
+      "ordered" => false,
+    },
+    %{
+      "_id" => "954272af-d5ed-4039-a5eb-8ed57e9def01",
+      "user_id" => 9,
+      "name" => %{"first" => "Ramona", "last" => "Floyd"},
+      "age" => 22,
+      "location" => %{
+        "state" => "Missouri",
+        "city" => "Foxworth",
+        "address" => %{"street" => "Lott Place", "number" => 1697},
+      },
+      "company" => "Manglo",
+      "email" => "[email protected]",
+      "manager" => true,
+      "twitter" => nil,
+      "favorites" => ["Lisp", "Erlang", "Python"],
+      "exists_array" => ["should", "exist", "array1"],
+      "complex_field_value" => '+-()%{}[]^~&&*||"\\/? =>!',
+      "ordered" => true,
+    },
+    %{
+      "_id" => "e900001d-bc48-48a6-9b1a-ac9a1f5d1a03",
+      "user_id" => 10,
+      "name" => %{"first" => "Charmaine", "last" => "Mills"},
+      "age" => 43,
+      "location" => %{
+        "state" => "New Hampshire",
+        "city" => "Kiskimere",
+        "address" => %{"street" => "Nostrand Avenue", "number" => 4503},
+      },
+      "company" => "Lyria",
+      "email" => "[email protected]",
+      "manager" => true,
+      "favorites" => ["Erlang", "Erlang"],
+      "exists_array" => ["should", "exist", "array2"],
+      "ordered" => 9,
+    },
+    %{
+      "_id" => "b06aadcf-cd0f-4ca6-9f7e-2c993e48d4c4",
+      "user_id" => 11,
+      "name" => %{"first" => "Mathis", "last" => "Hernandez"},
+      "age" => 75,
+      "location" => %{
+        "state" => "Hawaii",
+        "city" => "Dupuyer",
+        "address" => %{"street" => "Bancroft Place", "number" => 2741},
+      },
+      "company" => "Affluex",
+      "email" => "[email protected]",
+      "manager" => true,
+      "favorites" => ["Ruby", "Lisp", "C", "C++", "C++"],
+      "exists_object" => %{"should" => "object"},
+      "ordered" => 10_000,
+    },
+    %{
+      "_id" => "5b61abc1-a3d3-4092-b9d7-ced90e675536",
+      "user_id" => 12,
+      "name" => %{"first" => "Patti", "last" => "Rosales"},
+      "age" => 71,
+      "location" => %{
+        "state" => "Pennsylvania",
+        "city" => "Juntura",
+        "address" => %{"street" => "Hunterfly Place", "number" => 7683},
+      },
+      "company" => "Oulu",
+      "email" => "[email protected]",
+      "manager" => true,
+      "favorites" => ["C", "Python", "Lisp"],
+      "exists_object" => %{"another" => "object"},
+      "ordered" => "a",
+    },
+    %{
+      "_id" => "b1e70402-8add-4068-af8f-b4f3d0feb049",
+      "user_id" => 13,
+      "name" => %{"first" => "Whitley", "last" => "Harvey"},
+      "age" => 78,
+      "location" => %{
+        "state" => "Minnesota",
+        "city" => "Trail",
+        "address" => %{"street" => "Pleasant Place", "number" => 8766},
+      },
+      "company" => nil,
+      "email" => "[email protected]",
+      "manager" => false,
+      "twitter" => "@whitleyharvey",
+      "favorites" => ["C", "Ruby", "Ruby"],
+      "ordered" => "A",
+    },
+    %{
+      "_id" => "c78c529f-0b07-4947-90a6-d6b7ca81da62",
+      "user_id" => 14,
+      "name" => %{"first" => "Faith", "last" => "Hess"},
+      "age" => 51,
+      "location" => %{
+        "state" => "North Dakota",
+        "city" => "Axis",
+        "address" => %{"street" => "Brightwater Avenue", "number" => 1106},
+      },
+      "foo" => "bar car apple",
+      "company" => "Pharmex",
+      "email" => "[email protected]",
+      "favorites" => ["Erlang", "Python", "Lisp"],
+      "ordered" => "aa",
+    }
+  ]
+
+  @users_docs [
+    %{
+      "_id" => "org.couchdb.user =>demo01",
+      "name" => "demo01",
+      "username" => "demo01",
+      "password" => "apple01",
+      "roles" => ["design"],
+      "order" => 1,
+      "type" => "user",
+    },
+    %{
+      "_id" => "org.couchdb.user =>demo02",
+      "name" => "demo02",
+      "username" => "demo02",
+      "password" => "apple02",
+      "roles" => ["reader"],
+      "order" => 2,
+      "type" => "user",
+    },
+    %{
+      "_id" => "org.couchdb.user =>demo03",
+      "name" => "demo03",
+      "username" => "demo03",
+      "password" => "apple03",
+      "roles" => ["reader", "writer"],
+      "order" => 3,
+      "type" => "user",
+    }
+  ]
+
+  def setup_users(db) do
+    MangoDatabase.recreate(db)
+    MangoDatabase.save_docs(db, @users_docs)
+  end
+
+  def setup(db, index_type \\ "view", partitioned \\ false) do
+    MangoDatabase.recreate(db, [partitioned: partitioned])
+    docs = @docs
+
+    if partitioned do
+      partition_docs = Enum.map(Enum.with_index(docs), fn {doc, index} ->
+        partition = rem(index, @partitions)
+        %{doc | "_id" => "#{partition}:#{doc["_id"]}"}
+      end)
+      MangoDatabase.save_docs(db, partition_docs)
+    else
+      MangoDatabase.save_docs(db, docs)
+    end
+
+    case index_type do
+      "view" -> add_view_indexes(db)
+      "text" -> add_text_indexes(db)
+      "special" -> :ok
+    end
+  end
+
+  def len() do
+    length(@docs)
+  end
+
+  defp add_view_indexes(db) do
+    indexes = [
+      {["user_id"], "user_id"},
+      {["name.last", "name.first"], "name"},
+      {["age"], "age"},
+      {
+        [
+          "location.state",
+          "location.city",
+          "location.address.street",
+          "location.address.number",
+        ],
+        "location",
+      },
+      {["company", "manager"], "company_and_manager"},
+      {["manager"], "manager"},
+      {["favorites"], "favorites"},
+      {["favorites.3"], "favorites_3"},
+      {["twitter"], "twitter"},
+      {["ordered"], "ordered"},
+    ]
+
+    Enum.each(indexes, fn {idx, name} ->
+      MangoDatabase.create_index(db, idx, name)
+    end)
+  end
+
+  defp add_text_indexes(db) do
+    MangoDatabase.create_text_index(db)
+  end
+end

Reply via email to