-
-
Notifications
You must be signed in to change notification settings - Fork 941
/
Copy pathdeletion_test.rb
278 lines (220 loc) · 7.46 KB
/
deletion_test.rb
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
require "test_helper"
class DeletionTest < ActiveSupport::TestCase
include SearchKickHelper
include ActiveJob::TestHelper
setup do
@user = create(:user)
@api_key = create(:api_key, owner: @user)
@gem_file = gem_file("test-0.0.0.gem")
Pusher.new(@api_key, @gem_file).process
@gem_file.rewind
@version = Version.last
@spec_rz = RubygemFs.instance.get("quick/Marshal.4.8/#{@version.full_name}.gemspec.rz")
import_and_refresh
end
teardown do
@gem_file.close
end
should "be indexed" do
@version.indexed = false
assert_predicate Deletion.new(version: @version, user: @user), :invalid?,
"Deletion should only work on indexed gems"
end
should "not be popular" do
GemDownload.increment(
100_001,
rubygem_id: @version.rubygem.id,
version_id: @version.id
)
assert_predicate Deletion.new(version: @version, user: @user), :invalid?,
"Versions with more than 100_000 downloads should not be deletable"
end
should "be forceable even when popular" do
GemDownload.increment(
100_001,
rubygem_id: @version.rubygem.id,
version_id: @version.id
)
assert_predicate Deletion.new(version: @version, user: @user, force: true), :valid?,
"Admins should be allowed to delete popular versions when necessary"
end
should "not be old" do
@version.update(created_at: 31.days.ago)
assert_predicate Deletion.new(version: @version, user: @user), :invalid?,
"Versions older than 30 days should not be deletable"
end
should "be forceable even when old" do
@version.update(created_at: 31.days.ago)
assert_predicate Deletion.new(version: @version, user: @user, force: true), :valid?,
"Admins should be allowed to delete old versions when necessary"
end
context "association" do
subject { Deletion.new(version: @version, user: @user) }
should belong_to(:user).without_validating_presence
end
context "with deleted gem" do
setup do
@gem_name = @version.rubygem.name
GemCachePurger.stubs(:call)
end
context "when delete is called" do
setup do
delete_gem
end
should "unindexes" do
refute_predicate @version, :indexed?
refute_predicate @version.rubygem, :indexed?
end
should "be considered deleted" do
assert_includes Version.yanked, @version
end
should "no longer be latest" do
refute_predicate @version.reload, :latest?
end
should "keep the yanked time" do
assert @version.reload.yanked_at
end
should "set the yanked info checksum" do
refute_nil @version.reload.yanked_info_checksum
end
should "delete the .gem file" do
assert_nil RubygemFs.instance.get("gems/#{@version.full_name}.gem"), "Rubygem still exists!"
end
should "delete the .gemspec.rz file" do
assert_nil RubygemFs.instance.get("quick/Marshal.4.8/#{@version.full_name}.gemspec.rz"), "Gemspec.rz still exists!"
end
should "send gem yanked email" do
perform_enqueued_jobs only: ActionMailer::MailDeliveryJob
email = ActionMailer::Base.deliveries.last
assert_equal "Gem #{@version.to_title} yanked from RubyGems.org", email.subject
assert_equal [@user.email], email.to
end
end
should "call GemCachePurger" do
GemCachePurger.expects(:call).with(@gem_name)
delete_gem
end
end
should "enqueue yank version contents job" do
assert_enqueued_jobs 1, only: YankVersionContentsJob do
delete_gem
end
end
context "when rstuf is enabled" do
setup do
setup_rstuf
end
should "enqueue rstuf removal" do
assert_enqueued_with(job: Rstuf::RemoveJob, args: [{ version: @version }]) do
delete_gem
end
end
teardown do
teardown_rstuf
end
end
should "enque job for updating ES index, spec index and purging cdn" do
assert_enqueued_jobs 1, only: ActionMailer::MailDeliveryJob do
assert_enqueued_jobs 8, only: FastlyPurgeJob do
assert_enqueued_jobs 1, only: Indexer do
assert_enqueued_jobs 1, only: ReindexRubygemJob do
delete_gem
end
end
end
end
perform_enqueued_jobs
response = Searchkick.client.get index: Rubygem.searchkick_index.name,
id: @version.rubygem_id
assert response["_source"]["yanked"]
end
should "record version metadata" do
deletion = Deletion.new(version: @version, user: @user)
assert_nil deletion.rubygem
deletion.valid?
assert_equal deletion.rubygem, @version.rubygem.name
assert_equal @version.id, deletion.version_id
end
context "with restored gem" do
setup do
@gem_name = @version.rubygem.name
GemCachePurger.stubs(:call)
RubygemFs.instance.stubs(:restore).with do |file|
case file
when "gems/#{@version.full_name}.gem"
RubygemFs.instance.store(file, @gem_file.read)
when "quick/Marshal.4.8/#{@version.full_name}.gemspec.rz"
RubygemFs.instance.store(file, @spec_rz)
end
end.returns(true)
end
context "when gem is deleted and restored" do
setup do
@deletion = delete_gem
@deletion.restore!
end
should "index rubygem and version" do
assert_predicate @version.rubygem, :indexed?
assert_predicate @version, :indexed?
end
should "reorder versions" do
assert_predicate @version.reload, :latest?
end
should "remove the yanked time and yanked_info_checksum" do
assert_nil @version.yanked_at
assert_nil @version.yanked_info_checksum
end
should "purge fastly" do
Fastly.expects(:purge).with({ path: "info/#{@version.rubygem.name}", soft: true })
Fastly.expects(:purge).with({ path: "names", soft: true })
Fastly.expects(:purge).with({ path: "versions", soft: true })
Fastly.expects(:purge).with({ path: "gem/#{@version.rubygem.name}", soft: true })
Fastly.expects(:purge).with({ path: "gems/#{@version.full_name}.gem", soft: false }).times(2)
Fastly.expects(:purge).with({ path: "quick/Marshal.4.8/#{@version.full_name}.gemspec.rz", soft: false }).times(2)
perform_enqueued_jobs(only: FastlyPurgeJob)
end
should "remove deletion record" do
assert_predicate @deletion, :destroyed?
end
end
should "call GemCachePurger" do
GemCachePurger.expects(:call).with(@gem_name).times(2)
@deletion = delete_gem
@deletion.restore!
end
should "enqueue store version contents job" do
@deletion = delete_gem
assert_enqueued_jobs 1, only: StoreVersionContentsJob do
@deletion.restore!
end
end
context "with rstuf enabled" do
setup do
setup_rstuf
end
should "enqueue rstuf addition" do
@deletion = delete_gem
assert_enqueued_jobs 1, only: Rstuf::AddJob do
@deletion.restore!
end
end
teardown do
teardown_rstuf
end
end
should "enqueue indexing jobs" do
@deletion = delete_gem
assert_enqueued_jobs 1, only: Indexer do
assert_enqueued_jobs 1, only: UploadVersionsFileJob do
assert_enqueued_with job: UploadInfoFileJob, args: [{ rubygem_name: @gem_name }] do
@deletion.restore!
end
end
end
end
end
private
def delete_gem
Deletion.create!(version: @version, user: @user)
end
end