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
161
162
163
164
165
166
167
168
|
defmodule PurgeTest do
use CouchTestCase
@moduletag :purge
@tag :with_db
test "purge documents", context do
db_name = context[:db_name]
design_doc = %{
_id: "_design/test",
language: "javascript",
views: %{
all_docs_twice: %{
map: "function(doc) { emit(doc.integer, null); emit(doc.integer, null) }"
},
single_doc: %{
map: "function(doc) { if (doc._id == \"1\") { emit(1, null) }}"
}
}
}
{:ok, _} = create_doc(db_name, design_doc)
num_docs = 10
bulk_save(db_name, make_docs(1..(num_docs + 1)))
test_all_docs_twice(db_name, num_docs, 1)
info = info(db_name)
doc1 = open_doc(db_name, 1)
doc2 = open_doc(db_name, 2)
resp =
Couch.post("/#{db_name}/_purge",
body: %{"1": [doc1["_rev"]], "2": [doc2["_rev"]]}
)
assert resp.status_code == 201
result = resp.body
assert Enum.at(result["purged"]["1"], 0) == doc1["_rev"]
assert Enum.at(result["purged"]["2"], 0) == doc2["_rev"]
open_doc(db_name, 1, 404)
open_doc(db_name, 2, 404)
purged_info = info(db_name)
assert purged_info["purge_seq"] != info["purge_seq"]
test_all_docs_twice(db_name, num_docs, 0, 2)
# purge sequences are preserved after compaction (COUCHDB-1021)
resp = Couch.post("/#{db_name}/_compact")
assert resp.status_code == 202
retry_until(fn ->
info(db_name)["compact_running"] == false
end)
compacted_info = info(db_name)
assert compacted_info["purge_seq"] == purged_info["purge_seq"]
# purge documents twice in a row without loading views
# (causes full view rebuilds)
doc3 = open_doc(db_name, 3)
doc4 = open_doc(db_name, 4)
resp =
Couch.post("/#{db_name}/_purge",
body: %{"3": [doc3["_rev"]]}
)
assert resp.status_code == 201
resp =
Couch.post("/#{db_name}/_purge",
body: %{"4": [doc4["_rev"]]}
)
assert resp.status_code == 201
test_all_docs_twice(db_name, num_docs, 0, 4)
end
@tag :with_db
test "COUCHDB-1065", context do
db_name_a = context[:db_name]
db_name_b = random_db_name()
{:ok, _} = create_db(db_name_b)
{:ok, doc_a_resp} = create_doc(db_name_a, %{_id: "test", a: 1})
{:ok, doc_b_resp} = create_doc(db_name_b, %{_id: "test", a: 2})
replicate(db_name_a, db_name_b)
open_rev(db_name_b, "test", doc_a_resp.body["rev"], 200)
open_rev(db_name_b, "test", doc_b_resp.body["rev"], 200)
resp =
Couch.post("/#{db_name_b}/_purge",
body: %{test: [doc_a_resp.body["rev"]]}
)
assert resp.status_code == 201
open_rev(db_name_b, "test", doc_a_resp.body["rev"], 404)
resp =
Couch.post("/#{db_name_b}/_purge",
body: %{test: [doc_b_resp.body["rev"]]}
)
assert resp.status_code == 201
open_rev(db_name_b, "test", doc_b_resp.body["rev"], 404)
resp =
Couch.post("/#{db_name_b}/_purge",
body: %{test: [doc_a_resp.body["rev"], doc_b_resp.body["rev"]]}
)
assert resp.status_code == 201
delete_db(db_name_b)
end
def replicate(src, tgt, options \\ []) do
defaults = [headers: [], body: %{}, timeout: 30_000]
options = defaults |> Keyword.merge(options) |> Enum.into(%{})
%{body: body} = options
body = [source: src, target: tgt] |> Enum.into(body)
options = Map.put(options, :body, body)
resp = Couch.post("/_replicate", Enum.to_list(options))
assert HTTPotion.Response.success?(resp), "#{inspect(resp)}"
resp.body
end
defp open_doc(db_name, id, expect \\ 200) do
resp = Couch.get("/#{db_name}/#{id}")
assert resp.status_code == expect
resp.body
end
defp open_rev(db_name, id, rev, expect) do
resp = Couch.get("/#{db_name}/#{id}?rev=#{rev}")
assert resp.status_code == expect
resp.body
end
defp test_all_docs_twice(db_name, num_docs, sigle_doc_expect, offset \\ 0) do
resp = Couch.get("/#{db_name}/_design/test/_view/all_docs_twice")
assert resp.status_code == 200
rows = resp.body["rows"]
for x <- 0..(num_docs - offset) do
assert Map.get(Enum.at(rows, 2 * x), "key") == x + offset + 1
assert Map.get(Enum.at(rows, 2 * x + 1), "key") == x + offset + 1
end
resp = Couch.get("/#{db_name}/_design/test/_view/single_doc")
assert resp.body["total_rows"] == sigle_doc_expect
end
end
|