1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
defmodule PartitionViewUpdateTest do
use CouchTestCase
import PartitionHelpers
@moduledoc """
Test Partition view update functionality
"""
@tag :with_partitioned_db
test "view updates properly remove old keys", context do
db_name = context[:db_name]
create_partition_docs(db_name, "foo", "bar")
create_partition_ddoc(db_name)
check_key = fn key, num_rows ->
url = "/#{db_name}/_partition/foo/_design/mrtest/_view/some"
resp = Couch.get(url, query: [key: key])
assert resp.status_code == 200
assert length(resp.body["rows"]) == num_rows
end
check_key.(2, 1)
resp = Couch.get("/#{db_name}/foo:2")
doc = Map.put(resp.body, "value", 4)
resp = Couch.put("/#{db_name}/foo:2", query: [w: 3], body: doc)
assert resp.status_code >= 201 and resp.status_code <= 202
check_key.(4, 2)
check_key.(2, 0)
end
@tag :skip_on_jenkins
@tag :with_partitioned_db
test "query with update=false works", context do
db_name = context[:db_name]
create_partition_docs(db_name)
create_partition_ddoc(db_name)
url = "/#{db_name}/_partition/foo/_design/mrtest/_view/some"
resp =
Couch.get(
url,
query: %{
update: "true",
limit: 3
}
)
assert resp.status_code == 200
ids = get_ids(resp)
assert ids == ["foo:2", "foo:4", "foo:6"]
# Avoid race conditions by attempting to get a full response
# from every shard before we do our update:false test
for _ <- 1..12 do
resp = Couch.get(url)
assert resp.status_code == 200
end
Couch.put("/#{db_name}/foo:1", body: %{some: "field"})
retry_until(fn ->
resp =
Couch.get(
url,
query: %{
update: "false",
limit: 3
}
)
assert resp.status_code == 200
ids = get_ids(resp)
assert ids == ["foo:2", "foo:4", "foo:6"]
end)
end
@tag :with_partitioned_db
test "purge removes view rows", context do
db_name = context[:db_name]
create_partition_docs(db_name)
create_partition_ddoc(db_name)
url = "/#{db_name}/_partition/foo/_design/mrtest/_view/some"
resp = Couch.get(url)
assert resp.status_code == 200
%{body: body} = resp
assert length(body["rows"]) == 50
resp = Couch.get("/#{db_name}/foo:2")
assert resp.status_code == 200
%{body: body} = resp
rev = body["_rev"]
body = %{"foo:2" => [rev]}
resp = Couch.post("/#{db_name}/_purge", query: [w: 3], body: body)
assert resp.status_code == 201
resp = Couch.get(url)
assert resp.status_code == 200
%{body: body} = resp
assert length(body["rows"]) == 49
end
@tag :with_partitioned_db
test "purged conflict changes view rows", context do
db_name = context[:db_name]
create_partition_docs(db_name)
create_partition_ddoc(db_name)
url = "/#{db_name}/_partition/foo/_design/mrtest/_view/some"
resp = Couch.get(url)
assert resp.status_code == 200
%{body: body} = resp
assert length(body["rows"]) == 50
# Create a conflict on foo:2. Since the 4096
# value is deeper than the conflict we can assert
# that's in the view before the purge and assert
# that 8192 is in the view after the purge.
resp = Couch.get("/#{db_name}/foo:2")
assert resp.status_code == 200
%{body: body} = resp
rev1 = body["_rev"]
doc = %{_id: "foo:2", _rev: rev1, value: 4096, some: "field"}
resp = Couch.post("/#{db_name}", query: [w: 3], body: doc)
assert resp.status_code == 201
%{body: body} = resp
rev2 = body["rev"]
query = [w: 3, new_edits: false]
conflict_rev = "1-4a75b4efa0804859b3dfd327cbc1c2f9"
doc = %{_id: "foo:2", _rev: conflict_rev, value: 8192, some: "field"}
resp = Couch.put("/#{db_name}/foo:2", query: query, body: doc)
assert resp.status_code == 201
# Check that our expected row exists
resp = Couch.get(url, query: [key: 4096])
assert resp.status_code == 200
%{body: body} = resp
[row] = body["rows"]
assert row["id"] == "foo:2"
# Remove the current row to be replaced with
# a row from the conflict
body = %{"foo:2" => [rev2]}
resp = Couch.post("/#{db_name}/_purge", query: [w: 3], body: body)
assert resp.status_code == 201
resp = Couch.get(url, query: [key: 8192])
assert resp.status_code == 200
%{body: body} = resp
[row] = body["rows"]
assert row["id"] == "foo:2"
end
end
|