Skip to content

Commit 4f4dddf

Browse files
committed
port 03 base operator tests to elixir
1 parent 52275dd commit 4f4dddf

2 files changed

Lines changed: 348 additions & 0 deletions

File tree

test/elixir/test/config/suite.elixir

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,33 @@
789789
"explain with bookmarks",
790790
"sort with all docs"
791791
],
792+
"OperatorTest": [
793+
"all",
794+
"all non array",
795+
"elem match",
796+
"all match",
797+
"empty all match",
798+
"in operator array",
799+
"nin operator array",
800+
"regex",
801+
"exists false",
802+
"eq null does not include missing",
803+
"ne includes null but not missing",
804+
"lte includes null but not missing",
805+
"lte at z except null excludes null and missing",
806+
"range gte null includes null but not missing",
807+
"exists false returns missing but not null",
808+
"beginsWith",
809+
"beginsWith invalid prefix"
810+
],
811+
"OperatorJSONTests": [
812+
"lt includes null but not missing",
813+
"lte includes null but not missing",
814+
"lte respects unicode collation",
815+
"gte respects unicode collation",
816+
"keymap match"
817+
],
818+
"OperatorAllDocsTests": ["range id eq"],
792819
"IgnoreDesignDocsForAllDocsIndexTests": [
793820
"should not return design docs"
794821
],
Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
2+
# use this file except in compliance with the License. You may obtain a copy of
3+
# the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations under
11+
# the License.
12+
13+
defmodule OperatorTest do
14+
use CouchTestCase
15+
16+
@db_name "operator"
17+
18+
setup do
19+
UserDocs.setup(@db_name)
20+
end
21+
22+
test "all" do
23+
q = %{"manager" => true, "favorites" => %{"$all" => ["Lisp", "Python"]}}
24+
{:ok, docs} = MangoDatabase.find(@db_name, q)
25+
26+
assert length(docs) == 3
27+
user_ids = Enum.map(docs, fn doc -> doc["user_id"] end)
28+
assert user_ids == [2, 12, 9]
29+
end
30+
31+
test "all non array" do
32+
q = %{"manager" => true, "location" => %{"$all" => ["Ohai"]}}
33+
{:ok, docs} = MangoDatabase.find(@db_name, q)
34+
35+
assert Enum.empty?(docs)
36+
end
37+
38+
test "elem match" do
39+
emdocs = [
40+
%{"user_id" => "a", "bang" => [%{"foo" => 1, "bar" => 2}]},
41+
%{"user_id" => "b", "bang" => [%{"foo" => 2, "bam" => true}]},
42+
]
43+
MangoDatabase.save_docs(@db_name, emdocs)
44+
45+
q = %{
46+
"_id" => %{"$gt" => nil},
47+
"bang" => %{"$elemMatch" => %{"foo": %{"$gte": 1}, "bam": true}}
48+
}
49+
{:ok, docs} = MangoDatabase.find(@db_name, q)
50+
51+
assert length(docs) == 1
52+
assert Enum.at(docs, 0)["user_id"] == "b"
53+
end
54+
55+
test "all match" do
56+
amdocs = [
57+
%{"user_id" => "a", "bang" => [%{"foo" => 1, "bar" => 2}, %{"foo" => 3, "bar" => 4}]},
58+
%{"user_id" => "b", "bang" => [%{"foo" => 1, "bar" => 2}, %{"foo" => 4, "bar" => 4}]},
59+
]
60+
MangoDatabase.save_docs(@db_name, amdocs)
61+
62+
q = %{
63+
"bang" => %{"$allMatch" => %{"foo" => %{"$mod" => [2, 1]}, "bar" => %{"$mod" => [2, 0]}}}
64+
}
65+
{:ok, docs} = MangoDatabase.find(@db_name, q)
66+
67+
assert length(docs) == 1
68+
assert Enum.at(docs, 0)["user_id"] == "a"
69+
end
70+
71+
test "empty all match" do
72+
amdocs = [
73+
%{"bad_doc" => "a", "emptybang" => []},
74+
]
75+
MangoDatabase.save_docs(@db_name, amdocs)
76+
77+
q = %{
78+
"bang" => %{"emptybang" => %{"$allMatch" => %{"foo" => %{"$eq" => 2}}}}
79+
}
80+
{:ok, docs} = MangoDatabase.find(@db_name, q)
81+
82+
assert Enum.empty?(docs)
83+
end
84+
85+
test "in operator array" do
86+
q = %{
87+
"manager" => true, "favorites" => %{"$in" => ["Ruby", "Python"]}
88+
}
89+
{:ok, docs} = MangoDatabase.find(@db_name, q)
90+
91+
assert length(docs) == 6
92+
user_ids = Enum.sort(Enum.map(docs, fn doc -> doc["user_id"] end))
93+
assert user_ids == [2, 6, 7, 9, 11, 12]
94+
end
95+
96+
test "nin operator array" do
97+
q = %{
98+
"manager" => true, "favorites" => %{"$nin" => ["Erlang", "Python"]}
99+
}
100+
{:ok, docs} = MangoDatabase.find(@db_name, q)
101+
102+
assert length(docs) == 4
103+
for doc <- docs do
104+
if is_list(doc["favorites"]) do
105+
refute "Erlang" in doc["favorites"]
106+
refute "Python" in doc["favorites"]
107+
end
108+
end
109+
end
110+
111+
test "regex" do
112+
q = %{
113+
"age" => %{"$gt" => 40}, "location.state" => %{"$regex" => "(?i)new.*"}
114+
}
115+
{:ok, docs} = MangoDatabase.find(@db_name, q)
116+
117+
assert length(docs) == 2
118+
user_ids = Enum.sort(Enum.map(docs, fn doc -> doc["user_id"] end))
119+
assert user_ids == [2, 10]
120+
end
121+
122+
test "exists false" do
123+
q = %{
124+
"age" => %{"$gt" => 0}, "twitter" => %{"$exists" => false}
125+
}
126+
{:ok, docs} = MangoDatabase.find(@db_name, q)
127+
128+
assert length(docs) == 10
129+
user_ids = Enum.sort(Enum.map(docs, fn doc -> doc["user_id"] end))
130+
assert user_ids == [2, 3, 5, 6, 7, 8, 10, 11, 12, 14]
131+
132+
for doc <- docs do
133+
refute "twitter" in doc
134+
end
135+
end
136+
137+
test "eq null does not include missing" do
138+
q = %{"age" => %{"$gt" => 0}, "twitter" => nil}
139+
{:ok, docs} = MangoDatabase.find(@db_name, q)
140+
141+
assert length(docs) == 1
142+
assert Enum.at(docs, 0)["user_id"] == 9
143+
assert Enum.at(docs, 0)["twitter"] == nil
144+
end
145+
146+
test "ne includes null but not missing" do
147+
q = %{"twitter" => %{"$ne" => "notamatch"}}
148+
{:ok, docs} = MangoDatabase.find(@db_name, q)
149+
user_ids = Enum.sort(Enum.map(docs, fn doc -> doc["user_id"] end))
150+
151+
assert length(docs) == 5
152+
assert user_ids == [0, 1, 4, 9, 13]
153+
154+
for doc <- docs do
155+
assert Map.has_key?(doc, "twitter")
156+
end
157+
end
158+
159+
test "lte includes null but not missing" do
160+
q = %{"twitter" => %{"$lte" => nil}}
161+
{:ok, docs} = MangoDatabase.find(@db_name, q)
162+
163+
assert length(docs) == 1
164+
assert Enum.at(docs, 0)["user_id"] == 9
165+
assert Enum.at(docs, 0)["twitter"] == nil
166+
end
167+
168+
test "lte at z except null excludes null and missing" do
169+
q = %{
170+
"twitter" => %{
171+
"$and" => [%{"$lte" => "@z"}, %{"$ne" => nil}]
172+
}
173+
}
174+
{:ok, docs} = MangoDatabase.find(@db_name, q)
175+
user_ids = Enum.sort(Enum.map(docs, fn doc -> doc["user_id"] end))
176+
177+
assert length(docs) == 4
178+
assert user_ids == [0, 1, 4, 13]
179+
for doc <- docs do
180+
refute doc["twitter"] == nil
181+
end
182+
end
183+
184+
test "range gte null includes null but not missing" do
185+
q = %{"twitter" => %{"$gte" => nil}}
186+
{:ok, docs} = MangoDatabase.find(@db_name, q)
187+
188+
assert length(docs) == 5
189+
for doc <- docs do
190+
assert Map.has_key?(doc, "twitter")
191+
end
192+
end
193+
194+
test "exists false returns missing but not null" do
195+
q = %{"twitter" => %{"$exists" => false}}
196+
{:ok, docs} = MangoDatabase.find(@db_name, q)
197+
198+
assert length(docs) == 10
199+
for doc <- docs do
200+
refute Map.has_key?(doc, "twitter")
201+
end
202+
end
203+
204+
test "beginsWith" do
205+
MangoDatabase.save_docs(@db_name, [
206+
%{"user_id" => 99, "location" => %{"state" => ":Bar"}}
207+
])
208+
209+
cases = [
210+
%{prefix: "New", user_ids: [2, 10]},
211+
# test characters that require escaping
212+
%{prefix: "New ", user_ids: [2, 10]},
213+
%{prefix: ":", user_ids: [99]},
214+
%{prefix: "Foo", user_ids: []},
215+
%{prefix: "\"Foo", user_ids: []},
216+
%{prefix: " New", user_ids: []}
217+
]
218+
219+
for case <- cases do
220+
selector = %{"location.state" => %{"$beginsWith" => case.prefix}}
221+
{:ok, docs} = MangoDatabase.find(@db_name, selector)
222+
user_ids = Enum.sort(Enum.map(docs, fn doc -> doc["user_id"] end))
223+
224+
assert length(docs) == length(case.user_ids)
225+
assert case.user_ids == user_ids
226+
end
227+
end
228+
229+
# non-string prefixes should return an error
230+
test "beginsWith invalid prefix" do
231+
cases = [123, true, [], %{}]
232+
233+
for prefix <- cases do
234+
q = %{"location.state" => %{"$beginsWith" => prefix}}
235+
{:error, response} = MangoDatabase.find(@db_name, q)
236+
assert response.status_code == 400
237+
end
238+
end
239+
end
240+
241+
defmodule OperatorJSONTests do
242+
use CouchTestCase
243+
244+
@db_name "operator"
245+
246+
setup do
247+
UserDocs.setup(@db_name)
248+
end
249+
250+
# START: text indexes do not support range queries across type boundaries so only
251+
# test this for JSON indexes
252+
test "lt includes null but not missing" do
253+
q = %{"twitter" => %{"$lt" => 1}}
254+
{:ok, docs} = MangoDatabase.find(@db_name, q)
255+
256+
assert length(docs) == 1
257+
assert Enum.at(docs, 0)["user_id"] == 9
258+
assert Enum.at(docs, 0)["twitter"] == nil
259+
end
260+
261+
test "lte includes null but not missing" do
262+
q = %{"twitter" => %{"$lte" => 1}}
263+
{:ok, docs} = MangoDatabase.find(@db_name, q)
264+
265+
assert length(docs) == 1
266+
assert Enum.at(docs, 0)["user_id"] == 9
267+
assert Enum.at(docs, 0)["twitter"] == nil
268+
end
269+
270+
test "lte respects unicode collation" do
271+
q = %{"ordered" => %{"$lte" => "a"}}
272+
{:ok, docs} = MangoDatabase.find(@db_name, q)
273+
274+
assert length(docs) == 6
275+
user_ids = Enum.sort(Enum.map(docs, fn doc -> doc["user_id"] end))
276+
assert user_ids == [7, 8, 9, 10, 11, 12]
277+
end
278+
279+
test "gte respects unicode collation" do
280+
q = %{"ordered" => %{"$gte" => "a"}}
281+
{:ok, docs} = MangoDatabase.find(@db_name, q)
282+
283+
assert length(docs) == 3
284+
user_ids = Enum.sort(Enum.map(docs, fn doc -> doc["user_id"] end))
285+
assert user_ids == [12, 13, 14]
286+
end
287+
288+
# $keyMapMatch operator is only supported for JSON indexes
289+
test "keymap match" do
290+
amdocs = [
291+
%{"foo" => %{"aa" => "bar", "bb" => "bang"}},
292+
%{"foo" => %{"cc" => "bar", "bb" => "bang"}},
293+
]
294+
295+
MangoDatabase.save_docs(@db_name, amdocs)
296+
297+
q = %{"foo" => %{"$keyMapMatch" => %{"$eq" => "aa"}}}
298+
{:ok, docs} = MangoDatabase.find(@db_name, q)
299+
300+
assert length(docs) == 1
301+
end
302+
end
303+
304+
defmodule OperatorAllDocsTests do
305+
use CouchTestCase
306+
307+
@db_name "operator"
308+
309+
setup do
310+
UserDocs.setup(@db_name, "special")
311+
end
312+
313+
test "range id eq" do
314+
doc_id = "8e1c90c0-ac18-4832-8081-40d14325bde0"
315+
q = %{"_id" => doc_id}
316+
{:ok, explain} = MangoDatabase.find(@db_name, q, return_raw: true, explain: true)
317+
318+
assert explain["mrargs"]["end_key"] == doc_id
319+
assert explain["mrargs"]["start_key"] == doc_id
320+
end
321+
end

0 commit comments

Comments
 (0)