baza.rb 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +3 -3
- data/Gemfile.lock +28 -28
- data/baza.rb.gemspec +3 -3
- data/lib/baza-rb/version.rb +1 -1
- data/lib/baza-rb.rb +24 -20
- metadata +6 -28
- data/.0pdd.yml +0 -8
- data/.gitattributes +0 -7
- data/.github/workflows/actionlint.yml +0 -25
- data/.github/workflows/codecov.yml +0 -25
- data/.github/workflows/copyrights.yml +0 -19
- data/.github/workflows/markdown-lint.yml +0 -23
- data/.github/workflows/pdd.yml +0 -19
- data/.github/workflows/rake.yml +0 -29
- data/.github/workflows/reuse.yml +0 -19
- data/.github/workflows/typos.yml +0 -19
- data/.github/workflows/xcop.yml +0 -19
- data/.github/workflows/yamllint.yml +0 -21
- data/.gitignore +0 -11
- data/.pdd +0 -7
- data/.rubocop.yml +0 -55
- data/.rultor.yml +0 -26
- data/.simplecov +0 -24
- data/.yamllint.yml +0 -7
- data/renovate.json +0 -6
- data/test/test__helper.rb +0 -32
- data/test/test_baza-rb.rb +0 -821
- data/test/test_fake.rb +0 -135
data/test/test_baza-rb.rb
DELETED
@@ -1,821 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
|
4
|
-
# SPDX-License-Identifier: MIT
|
5
|
-
|
6
|
-
require 'factbase'
|
7
|
-
require 'loog'
|
8
|
-
require 'net/http'
|
9
|
-
require 'qbash'
|
10
|
-
require 'online'
|
11
|
-
require 'random-port'
|
12
|
-
require 'securerandom'
|
13
|
-
require 'socket'
|
14
|
-
require 'stringio'
|
15
|
-
require 'uri'
|
16
|
-
require 'wait_for'
|
17
|
-
require 'webrick'
|
18
|
-
require_relative 'test__helper'
|
19
|
-
require_relative '../lib/baza-rb'
|
20
|
-
|
21
|
-
# Test.
|
22
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
23
|
-
# Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
|
24
|
-
# License:: MIT
|
25
|
-
class TestBazaRb < Minitest::Test
|
26
|
-
# The token to use for testing, in Zerocracy.com:
|
27
|
-
TOKEN = 'ZRCY-00000000-0000-0000-0000-000000000000'
|
28
|
-
|
29
|
-
# The host of the production platform:
|
30
|
-
HOST = 'api.zerocracy.com'
|
31
|
-
|
32
|
-
# The HTTPS port to use:
|
33
|
-
PORT = 443
|
34
|
-
|
35
|
-
# Live agent:
|
36
|
-
LIVE = BazaRb.new(HOST, PORT, TOKEN, loog: Loog::VERBOSE)
|
37
|
-
|
38
|
-
def test_live_full_cycle
|
39
|
-
WebMock.enable_net_connect!
|
40
|
-
skip('We are offline') unless we_are_online?
|
41
|
-
fb = Factbase.new
|
42
|
-
fb.insert.foo = 'test-' * 10_000
|
43
|
-
fb.insert
|
44
|
-
n = fake_name
|
45
|
-
LIVE.push(n, fb.export, [])
|
46
|
-
assert(LIVE.name_exists?(n))
|
47
|
-
assert_predicate(LIVE.recent(n), :positive?)
|
48
|
-
id = LIVE.recent(n)
|
49
|
-
assert(
|
50
|
-
wait_for(8 * 60) do
|
51
|
-
sleep(5)
|
52
|
-
LIVE.finished?(id)
|
53
|
-
end
|
54
|
-
)
|
55
|
-
refute_nil(LIVE.pull(id))
|
56
|
-
refute_nil(LIVE.stdout(id))
|
57
|
-
refute_nil(LIVE.exit_code(id))
|
58
|
-
refute_nil(LIVE.verified(id))
|
59
|
-
owner = 'baza.rb testing'
|
60
|
-
refute_nil(LIVE.lock(n, owner))
|
61
|
-
refute_nil(LIVE.unlock(n, owner))
|
62
|
-
end
|
63
|
-
|
64
|
-
def test_live_whoami
|
65
|
-
WebMock.enable_net_connect!
|
66
|
-
skip('We are offline') unless we_are_online?
|
67
|
-
refute_nil(LIVE.whoami)
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_live_balance
|
71
|
-
WebMock.enable_net_connect!
|
72
|
-
skip('We are offline') unless we_are_online?
|
73
|
-
z = LIVE.balance
|
74
|
-
refute_nil(z)
|
75
|
-
assert(z.to_f)
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_live_fee_payment
|
79
|
-
WebMock.enable_net_connect!
|
80
|
-
skip('We are offline') unless we_are_online?
|
81
|
-
refute_nil(LIVE.fee('unknown', 0.007, 'just for fun', 777))
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_live_push_no_compression
|
85
|
-
WebMock.enable_net_connect!
|
86
|
-
skip('We are offline') unless we_are_online?
|
87
|
-
fb = Factbase.new
|
88
|
-
fb.insert.foo = 'test-' * 10_000
|
89
|
-
fb.insert
|
90
|
-
baza = BazaRb.new(HOST, PORT, TOKEN, compress: false)
|
91
|
-
baza.push(fake_name, fb.export, [])
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_live_durable_lock_unlock
|
95
|
-
WebMock.enable_net_connect!
|
96
|
-
skip('We are offline') unless we_are_online?
|
97
|
-
Dir.mktmpdir do |dir|
|
98
|
-
file = File.join(dir, 'before.bin')
|
99
|
-
before = 'hello, Джеф!' * 10
|
100
|
-
File.binwrite(file, before)
|
101
|
-
jname = fake_name
|
102
|
-
refute(LIVE.durable_find(jname, File.basename(file)))
|
103
|
-
id = LIVE.durable_place(jname, file)
|
104
|
-
assert_equal(id, LIVE.durable_find(jname, File.basename(file)))
|
105
|
-
owner = fake_name
|
106
|
-
LIVE.durable_lock(id, owner)
|
107
|
-
LIVE.durable_load(id, file)
|
108
|
-
assert_equal(before, File.binread(file).force_encoding('UTF-8'))
|
109
|
-
after = 'привет, друг!'
|
110
|
-
File.binwrite(file, after)
|
111
|
-
LIVE.durable_save(id, file)
|
112
|
-
LIVE.durable_load(id, file)
|
113
|
-
assert_equal(after, File.binread(file).force_encoding('UTF-8'))
|
114
|
-
LIVE.durable_unlock(id, owner)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def test_live_enter_valve
|
119
|
-
WebMock.enable_net_connect!
|
120
|
-
skip('We are offline') unless we_are_online?
|
121
|
-
r = 'something'
|
122
|
-
n = fake_name
|
123
|
-
badge = fake_name
|
124
|
-
assert_equal(r, LIVE.enter(n, badge, 'no reason', nil) { r })
|
125
|
-
assert_equal(r, LIVE.enter(n, badge, 'no reason', nil) { nil })
|
126
|
-
end
|
127
|
-
|
128
|
-
def test_get_csrf_token
|
129
|
-
WebMock.enable_net_connect!
|
130
|
-
skip('We are offline') unless we_are_online?
|
131
|
-
assert_operator(LIVE.csrf.length, :>, 10)
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_transfer_payment
|
135
|
-
WebMock.disable_net_connect!
|
136
|
-
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
137
|
-
stub_request(:post, 'https://example.org/account/transfer').to_return(
|
138
|
-
status: 302, headers: { 'X-Zerocracy-ReceiptId' => '42' }
|
139
|
-
)
|
140
|
-
id = fake_baza.transfer('jeff', 42.50, 'for fun')
|
141
|
-
assert_equal(42, id)
|
142
|
-
end
|
143
|
-
|
144
|
-
def test_transfer_payment_with_job
|
145
|
-
WebMock.disable_net_connect!
|
146
|
-
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
147
|
-
stub_request(:post, 'https://example.org/account/transfer').to_return(
|
148
|
-
status: 302, headers: { 'X-Zerocracy-ReceiptId' => '42' }
|
149
|
-
)
|
150
|
-
id = fake_baza.transfer('jeff', 42.50, 'for fun', job: 555)
|
151
|
-
assert_equal(42, id)
|
152
|
-
end
|
153
|
-
|
154
|
-
def test_reads_whoami
|
155
|
-
WebMock.disable_net_connect!
|
156
|
-
stub_request(:get, 'https://example.org/whoami').to_return(status: 200, body: 'jeff')
|
157
|
-
assert_equal('jeff', fake_baza.whoami)
|
158
|
-
end
|
159
|
-
|
160
|
-
def test_reads_balance
|
161
|
-
WebMock.disable_net_connect!
|
162
|
-
stub_request(:get, 'https://example.org/account/balance').to_return(status: 200, body: '42.33')
|
163
|
-
assert_in_delta(42.33, fake_baza.balance)
|
164
|
-
end
|
165
|
-
|
166
|
-
def test_checks_whether_job_is_finished
|
167
|
-
WebMock.disable_net_connect!
|
168
|
-
stub_request(:get, 'https://example.org/finished/42').to_return(status: 200, body: 'yes')
|
169
|
-
assert(fake_baza.finished?(42))
|
170
|
-
end
|
171
|
-
|
172
|
-
def test_reads_verification_verdict
|
173
|
-
WebMock.disable_net_connect!
|
174
|
-
stub_request(:get, 'https://example.org/jobs/42/verified.txt').to_return(status: 200, body: 'done')
|
175
|
-
assert(fake_baza.verified(42))
|
176
|
-
end
|
177
|
-
|
178
|
-
def test_unlocks_job_by_name
|
179
|
-
WebMock.disable_net_connect!
|
180
|
-
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
181
|
-
stub_request(:post, %r{https://example.org/unlock/foo}).to_return(status: 302)
|
182
|
-
assert(fake_baza.unlock('foo', 'x'))
|
183
|
-
end
|
184
|
-
|
185
|
-
def test_durable_place
|
186
|
-
WebMock.disable_net_connect!
|
187
|
-
[fake_baza(compress: true), fake_baza(compress: false)].each do |baza|
|
188
|
-
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
189
|
-
stub_request(:post, 'https://example.org/durables/place').to_return(
|
190
|
-
status: 302, headers: { 'X-Zerocracy-DurableId' => '42' }
|
191
|
-
)
|
192
|
-
stub_request(:post, %r{https://example\.org/durables/42/lock})
|
193
|
-
.to_return(status: 302)
|
194
|
-
stub_request(:post, %r{https://example\.org/durables/42/unlock})
|
195
|
-
.to_return(status: 302)
|
196
|
-
stub_request(:put, 'https://example.org/durables/42')
|
197
|
-
.with(headers: { 'X-Zerocracy-Chunk' => '0' })
|
198
|
-
.to_return(status: 200)
|
199
|
-
stub_request(:put, 'https://example.org/durables/42')
|
200
|
-
.with(headers: { 'X-Zerocracy-Chunk' => '1' })
|
201
|
-
.to_return(status: 200)
|
202
|
-
stub_request(:put, 'https://example.org/durables/42')
|
203
|
-
.with(headers: { 'X-Zerocracy-Chunk' => '2' })
|
204
|
-
.to_return(status: 200)
|
205
|
-
Dir.mktmpdir do |dir|
|
206
|
-
file = File.join(dir, 'test.bin')
|
207
|
-
File.binwrite(file, 'hello, world!')
|
208
|
-
assert_equal(42, baza.durable_place('simple', file, chunk_size: 8))
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
def test_simple_push
|
214
|
-
WebMock.disable_net_connect!
|
215
|
-
stub_request(:put, 'https://example.org/push/simple').to_return(
|
216
|
-
status: 200, body: '42'
|
217
|
-
)
|
218
|
-
fake_baza.push('simple', 'hello, world!', [])
|
219
|
-
end
|
220
|
-
|
221
|
-
def test_simple_pop_with_no_job_found
|
222
|
-
WebMock.disable_net_connect!
|
223
|
-
stub_request(:get, 'https://example.org/pop?owner=me').to_return(status: 204)
|
224
|
-
Tempfile.open do |zip|
|
225
|
-
refute(fake_baza.pop('me', zip.path))
|
226
|
-
refute_path_exists(zip.path)
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def test_simple_pop_with_ranges
|
231
|
-
WebMock.disable_net_connect!
|
232
|
-
owner = 'owner888'
|
233
|
-
job = 4242
|
234
|
-
stub_request(:get, 'https://example.org/pop')
|
235
|
-
.with(query: { owner: })
|
236
|
-
.to_return(
|
237
|
-
status: 302,
|
238
|
-
headers: { 'X-Zerocracy-JobId' => job },
|
239
|
-
body: ''
|
240
|
-
)
|
241
|
-
stub_request(:get, 'https://example.org/pop')
|
242
|
-
.with(query: { job: })
|
243
|
-
.to_return(
|
244
|
-
status: 206,
|
245
|
-
headers: { 'Content-Range' => 'bytes 0-0/*', 'Content-Length' => 0 },
|
246
|
-
body: ''
|
247
|
-
)
|
248
|
-
bin = nil
|
249
|
-
Tempfile.open do |zip|
|
250
|
-
File.binwrite(zip.path, 'the archive to return (not a real ZIP for now)')
|
251
|
-
bin = File.binread(zip.path)
|
252
|
-
stub_request(:get, 'https://example.org/pop')
|
253
|
-
.with(query: { job:, owner: })
|
254
|
-
.with(headers: { 'Range' => 'bytes=0-' })
|
255
|
-
.to_return(
|
256
|
-
status: 206,
|
257
|
-
headers: {
|
258
|
-
'Content-Range' => "bytes 0-7/#{bin.size}",
|
259
|
-
'Content-Length' => 8
|
260
|
-
},
|
261
|
-
body: bin[0..7]
|
262
|
-
)
|
263
|
-
stub_request(:get, 'https://example.org/pop')
|
264
|
-
.with(query: { job:, owner: })
|
265
|
-
.with(headers: { 'Range' => 'bytes=8-' })
|
266
|
-
.to_return(
|
267
|
-
status: 206,
|
268
|
-
headers: {
|
269
|
-
'Content-Range' => "bytes 8-#{bin.size - 1}/#{bin.size}",
|
270
|
-
'Content-Length' => bin.size - 8
|
271
|
-
},
|
272
|
-
body: bin[8..]
|
273
|
-
)
|
274
|
-
end
|
275
|
-
Tempfile.open do |zip|
|
276
|
-
assert(fake_baza.pop(owner, zip.path))
|
277
|
-
assert_path_exists(zip.path)
|
278
|
-
assert_equal(bin, File.binread(zip.path))
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
def test_simple_finish
|
283
|
-
WebMock.disable_net_connect!
|
284
|
-
stub_request(:put, 'https://example.org/finish?id=42').to_return(status: 200)
|
285
|
-
Tempfile.open do |zip|
|
286
|
-
fake_baza.finish(42, zip.path)
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
def test_simple_recent_check
|
291
|
-
WebMock.disable_net_connect!
|
292
|
-
stub_request(:get, 'https://example.org/recent/simple.txt')
|
293
|
-
.with(body: '', headers: { 'User-Agent' => /^baza.rb .*$/ })
|
294
|
-
.to_return(status: 200, body: '42')
|
295
|
-
assert_equal(
|
296
|
-
42,
|
297
|
-
fake_baza.recent('simple')
|
298
|
-
)
|
299
|
-
end
|
300
|
-
|
301
|
-
def test_simple_exists_check
|
302
|
-
WebMock.disable_net_connect!
|
303
|
-
stub_request(:get, 'https://example.org/exists/simple').to_return(
|
304
|
-
status: 200, body: 'yes'
|
305
|
-
)
|
306
|
-
assert(
|
307
|
-
fake_baza.name_exists?('simple')
|
308
|
-
)
|
309
|
-
end
|
310
|
-
|
311
|
-
def test_exit_code_check
|
312
|
-
WebMock.disable_net_connect!
|
313
|
-
stub_request(:get, 'https://example.org/exit/42.txt').to_return(
|
314
|
-
status: 200, body: '0'
|
315
|
-
)
|
316
|
-
assert_predicate(
|
317
|
-
fake_baza.exit_code(42), :zero?
|
318
|
-
)
|
319
|
-
end
|
320
|
-
|
321
|
-
def test_stdout_read
|
322
|
-
WebMock.disable_net_connect!
|
323
|
-
stub_request(:get, 'https://example.org/stdout/42.txt').to_return(
|
324
|
-
status: 200, body: 'hello!'
|
325
|
-
)
|
326
|
-
refute_empty(
|
327
|
-
fake_baza.stdout(42)
|
328
|
-
)
|
329
|
-
end
|
330
|
-
|
331
|
-
def test_simple_pull
|
332
|
-
WebMock.disable_net_connect!
|
333
|
-
stub_request(:get, 'https://example.org/pull/333.fb').to_return(
|
334
|
-
status: 200, body: 'hello, world!', headers: {}
|
335
|
-
)
|
336
|
-
assert(
|
337
|
-
fake_baza.pull(333).start_with?('hello')
|
338
|
-
)
|
339
|
-
end
|
340
|
-
|
341
|
-
def test_simple_lock_success
|
342
|
-
WebMock.disable_net_connect!
|
343
|
-
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
344
|
-
stub_request(:post, %r{https://example.org/lock/name}).to_return(status: 302)
|
345
|
-
fake_baza.lock('name', 'owner')
|
346
|
-
end
|
347
|
-
|
348
|
-
def test_simple_lock_failure
|
349
|
-
WebMock.disable_net_connect!
|
350
|
-
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
351
|
-
stub_request(:post, %r{https://example.org/lock/name}).to_return(status: 409)
|
352
|
-
assert_raises(StandardError) do
|
353
|
-
fake_baza.lock('name', 'owner')
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
def test_real_http
|
358
|
-
WebMock.enable_net_connect!
|
359
|
-
skip('We are offline') unless we_are_online?
|
360
|
-
req =
|
361
|
-
with_http_server(200, 'yes') do |baza|
|
362
|
-
baza.name_exists?('simple')
|
363
|
-
end
|
364
|
-
assert_equal("baza.rb #{BazaRb::VERSION}", req['user-agent'])
|
365
|
-
end
|
366
|
-
|
367
|
-
def test_push_with_meta
|
368
|
-
WebMock.enable_net_connect!
|
369
|
-
skip('We are offline') unless we_are_online?
|
370
|
-
req =
|
371
|
-
with_http_server(200, 'yes') do |baza|
|
372
|
-
baza.push('simple', 'hello, world!', ['boom!', 'хей!'])
|
373
|
-
end
|
374
|
-
assert_equal('Ym9vbSE= 0YXQtdC5IQ==', req['x-zerocracy-meta'])
|
375
|
-
end
|
376
|
-
|
377
|
-
def test_push_with_big_meta
|
378
|
-
WebMock.enable_net_connect!
|
379
|
-
skip('We are offline') unless we_are_online?
|
380
|
-
req =
|
381
|
-
with_http_server(200, 'yes') do |baza|
|
382
|
-
baza.push(
|
383
|
-
'simple',
|
384
|
-
'hello, world!',
|
385
|
-
[
|
386
|
-
'pages_url:https://zerocracy.github.io/zerocracy.html',
|
387
|
-
'others:https://zerocracy.github.io/zerocracy.html',
|
388
|
-
'duration:59595'
|
389
|
-
]
|
390
|
-
)
|
391
|
-
end
|
392
|
-
assert(req['x-zerocracy-meta'])
|
393
|
-
end
|
394
|
-
|
395
|
-
def test_push_compressed_content
|
396
|
-
WebMock.enable_net_connect!
|
397
|
-
skip('We are offline') unless we_are_online?
|
398
|
-
fb = Factbase.new
|
399
|
-
fb.insert.foo = 'test-' * 10_000
|
400
|
-
req =
|
401
|
-
with_http_server(200, 'yes') do |baza|
|
402
|
-
baza.push('simple', fb.export, %w[meta1 meta2 meta3])
|
403
|
-
end
|
404
|
-
assert_equal('application/zip', req.content_type)
|
405
|
-
assert_equal('gzip', req['content-encoding'])
|
406
|
-
body = Zlib::GzipReader.zcat(StringIO.new(req.body))
|
407
|
-
assert_equal(fb.export, body)
|
408
|
-
end
|
409
|
-
|
410
|
-
def test_push_compression_disabled
|
411
|
-
WebMock.enable_net_connect!
|
412
|
-
fb = Factbase.new
|
413
|
-
fb.insert.foo = 'test-' * 10_000
|
414
|
-
req =
|
415
|
-
with_http_server(200, 'yes', compress: false) do |baza|
|
416
|
-
baza.push('simple', fb.export, %w[meta1 meta2 meta3])
|
417
|
-
end
|
418
|
-
assert_equal('application/octet-stream', req.content_type)
|
419
|
-
assert_equal(fb.export, req.body)
|
420
|
-
end
|
421
|
-
|
422
|
-
def test_with_very_short_timeout
|
423
|
-
WebMock.enable_net_connect!
|
424
|
-
host = '127.0.0.1'
|
425
|
-
RandomPort::Pool::SINGLETON.acquire do |port|
|
426
|
-
server = TCPServer.new(host, port)
|
427
|
-
t =
|
428
|
-
Thread.new do
|
429
|
-
socket = server.accept
|
430
|
-
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
|
431
|
-
req.parse(socket)
|
432
|
-
req.body
|
433
|
-
sleep 0.1
|
434
|
-
socket.puts "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nabc"
|
435
|
-
socket.close
|
436
|
-
end
|
437
|
-
assert_includes(
|
438
|
-
assert_raises(StandardError) do
|
439
|
-
BazaRb.new(host, port, '0000', ssl: false, timeout: 0.01).push('x', 'y', [])
|
440
|
-
end.message, 'timed out in'
|
441
|
-
)
|
442
|
-
t.terminate
|
443
|
-
assert(t.join(1))
|
444
|
-
end
|
445
|
-
end
|
446
|
-
|
447
|
-
def test_durable_save
|
448
|
-
WebMock.disable_net_connect!
|
449
|
-
Dir.mktmpdir do |dir|
|
450
|
-
file = File.join(dir, 'test.txt')
|
451
|
-
File.write(file, "\x00\x00 hi, dude! \x00\xFF\xFE\x12")
|
452
|
-
stub_request(:put, 'https://example.org:443/durables/42')
|
453
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
454
|
-
.to_return(status: 200)
|
455
|
-
fake_baza.durable_save(42, file)
|
456
|
-
end
|
457
|
-
end
|
458
|
-
|
459
|
-
def test_durable_load
|
460
|
-
WebMock.disable_net_connect!
|
461
|
-
Dir.mktmpdir do |dir|
|
462
|
-
file = File.join(dir, 'loaded.txt')
|
463
|
-
data = "\x00\xE0 привет \x00\x00\xFF\xFE\x12"
|
464
|
-
stub_request(:get, 'https://example.org:443/durables/42')
|
465
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
466
|
-
.to_return(status: 200, body: data, headers: {})
|
467
|
-
fake_baza.durable_load(42, file)
|
468
|
-
assert_equal(data, File.read(file))
|
469
|
-
end
|
470
|
-
end
|
471
|
-
|
472
|
-
def test_durable_load_empty_content
|
473
|
-
WebMock.disable_net_connect!
|
474
|
-
Dir.mktmpdir do |dir|
|
475
|
-
file = File.join(dir, 'loaded.txt')
|
476
|
-
stub_request(:get, 'https://example.org:443/durables/42')
|
477
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
478
|
-
.to_return(status: 206, body: '', headers: { 'Content-Range' => 'bytes 0-0/0' })
|
479
|
-
fake_baza.durable_load(42, file)
|
480
|
-
assert_equal('', File.read(file))
|
481
|
-
end
|
482
|
-
end
|
483
|
-
|
484
|
-
def test_durable_load_in_chunks
|
485
|
-
WebMock.disable_net_connect!
|
486
|
-
Dir.mktmpdir do |dir|
|
487
|
-
file = File.join(dir, 'loaded.txt')
|
488
|
-
stub_request(:get, 'https://example.org:443/durables/42')
|
489
|
-
.with(headers: { 'Range' => 'bytes=0-' })
|
490
|
-
.to_return(status: 206, body: '', headers: { 'Content-Range' => 'bytes 0-0/*' })
|
491
|
-
stub_request(:get, 'https://example.org:443/durables/42')
|
492
|
-
.with(headers: { 'Range' => 'bytes=0-' })
|
493
|
-
.to_return(status: 206, body: 'привет', headers: { 'Content-Range' => 'bytes 0-11/25' })
|
494
|
-
stub_request(:get, 'https://example.org:443/durables/42')
|
495
|
-
.with(headers: { 'Range' => 'bytes=12-' })
|
496
|
-
.to_return(status: 206, body: " друг \xFF\xFE\x12", headers: { 'Content-Range' => 'bytes 12-24/25' })
|
497
|
-
fake_baza.durable_load(42, file)
|
498
|
-
assert_equal("привет друг \xFF\xFE\x12", File.read(file))
|
499
|
-
end
|
500
|
-
end
|
501
|
-
|
502
|
-
def test_durable_load_with_broken_compression
|
503
|
-
WebMock.disable_net_connect!
|
504
|
-
Dir.mktmpdir do |dir|
|
505
|
-
file = File.join(dir, 'loaded.txt')
|
506
|
-
stub_request(:get, 'https://example.org:443/durables/42').to_return(
|
507
|
-
status: 200, body: 'this is not gzip!', headers: { 'Content-Encoding' => 'gzip' }
|
508
|
-
)
|
509
|
-
assert_raises(BazaRb::BadCompression) { fake_baza.durable_load(42, file) }
|
510
|
-
end
|
511
|
-
end
|
512
|
-
|
513
|
-
def test_durable_lock
|
514
|
-
WebMock.disable_net_connect!
|
515
|
-
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
516
|
-
stub_request(:post, %r{https://example.org:443/durables/42/lock})
|
517
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
518
|
-
.to_return(status: 302)
|
519
|
-
fake_baza.durable_lock(42, 'test-owner')
|
520
|
-
end
|
521
|
-
|
522
|
-
def test_durable_unlock
|
523
|
-
WebMock.disable_net_connect!
|
524
|
-
stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
|
525
|
-
stub_request(:post, %r{https://example.org:443/durables/42/unlock})
|
526
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
527
|
-
.to_return(status: 302)
|
528
|
-
fake_baza.durable_unlock(42, 'test-owner')
|
529
|
-
end
|
530
|
-
|
531
|
-
def test_fee
|
532
|
-
WebMock.disable_net_connect!
|
533
|
-
stub_request(:get, 'https://example.org:443/csrf')
|
534
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
535
|
-
.to_return(status: 200, body: 'csrf-token')
|
536
|
-
stub_request(:post, 'https://example.org:443/account/fee')
|
537
|
-
.with(
|
538
|
-
headers: { 'X-Zerocracy-Token' => '000' },
|
539
|
-
body: {
|
540
|
-
'_csrf' => 'csrf-token',
|
541
|
-
'tab' => 'unknown',
|
542
|
-
'amount' => '10.500000',
|
543
|
-
'summary' => 'Test fee',
|
544
|
-
'job' => '123'
|
545
|
-
}
|
546
|
-
)
|
547
|
-
.to_return(status: 302, headers: { 'X-Zerocracy-ReceiptId' => '456' })
|
548
|
-
receipt = fake_baza.fee('unknown', 10.5, 'Test fee', 123)
|
549
|
-
assert_equal(456, receipt)
|
550
|
-
end
|
551
|
-
|
552
|
-
def test_enter
|
553
|
-
WebMock.disable_net_connect!
|
554
|
-
stub_request(:get, 'https://example.org:443/valves/result?badge=test-badge')
|
555
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
556
|
-
.to_return(status: 200, body: 'cached result')
|
557
|
-
result = fake_baza.enter('test-valve', 'test-badge', 'test reason', 123) { 'new result' }
|
558
|
-
assert_equal('cached result', result)
|
559
|
-
end
|
560
|
-
|
561
|
-
def test_enter_not_cached
|
562
|
-
WebMock.disable_net_connect!
|
563
|
-
stub_request(:get, 'https://example.org:443/valves/result?badge=test-badge')
|
564
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
565
|
-
.to_return(status: 204)
|
566
|
-
stub_request(:get, 'https://example.org:443/csrf')
|
567
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
568
|
-
.to_return(status: 200, body: 'csrf-token')
|
569
|
-
stub_request(:post, 'https://example.org:443/valves/add?job=123')
|
570
|
-
.with(
|
571
|
-
headers: { 'X-Zerocracy-Token' => '000' },
|
572
|
-
body: {
|
573
|
-
'_csrf' => 'csrf-token',
|
574
|
-
'name' => 'test-valve',
|
575
|
-
'badge' => 'test-badge',
|
576
|
-
'why' => 'test reason',
|
577
|
-
'result' => 'new result'
|
578
|
-
}
|
579
|
-
)
|
580
|
-
.to_return(status: 302)
|
581
|
-
result = fake_baza.enter('test-valve', 'test-badge', 'test reason', 123) { 'new result' }
|
582
|
-
assert_equal('new result', result)
|
583
|
-
end
|
584
|
-
|
585
|
-
def test_durable_find_found
|
586
|
-
WebMock.disable_net_connect!
|
587
|
-
stub_request(:get, 'https://example.org:443/durables/find?jname=test-job&file=test.txt')
|
588
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
589
|
-
.to_return(status: 200, body: '42')
|
590
|
-
id = fake_baza.durable_find('test-job', 'test.txt')
|
591
|
-
assert_equal(42, id)
|
592
|
-
end
|
593
|
-
|
594
|
-
def test_durable_find_not_found
|
595
|
-
WebMock.disable_net_connect!
|
596
|
-
stub_request(:get, 'https://example.org:443/durables/find?jname=test-job&file=test.txt')
|
597
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
598
|
-
.to_return(status: 404)
|
599
|
-
id = fake_baza.durable_find('test-job', 'test.txt')
|
600
|
-
assert_nil(id)
|
601
|
-
end
|
602
|
-
|
603
|
-
def test_checked_with_500_error
|
604
|
-
WebMock.disable_net_connect!
|
605
|
-
stub_request(:get, 'https://example.org:443/test')
|
606
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
607
|
-
.to_return(status: 500)
|
608
|
-
error =
|
609
|
-
assert_raises(BazaRb::ServerFailure) do
|
610
|
-
fake_baza.send(
|
611
|
-
:checked,
|
612
|
-
Typhoeus.get('https://example.org:443/test', headers: { 'X-Zerocracy-Token' => '000' })
|
613
|
-
)
|
614
|
-
end
|
615
|
-
assert_includes(error.message, 'Invalid response code #500')
|
616
|
-
assert_includes(error.message, "most probably it's an internal error on the server")
|
617
|
-
end
|
618
|
-
|
619
|
-
def test_checked_with_503_error
|
620
|
-
WebMock.disable_net_connect!
|
621
|
-
stub_request(:get, 'https://example.org:443/test')
|
622
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
623
|
-
.to_return(status: 503, headers: { 'X-Zerocracy-Failure' => 'Service unavailable' })
|
624
|
-
error =
|
625
|
-
assert_raises(BazaRb::ServerFailure) do
|
626
|
-
fake_baza.send(
|
627
|
-
:checked,
|
628
|
-
Typhoeus.get('https://example.org:443/test', headers: { 'X-Zerocracy-Token' => '000' })
|
629
|
-
)
|
630
|
-
end
|
631
|
-
assert_includes(error.message, 'Invalid response code #503')
|
632
|
-
assert_includes(error.message, "most probably it's an internal error on the server")
|
633
|
-
assert_includes(error.message, 'Service unavailable')
|
634
|
-
end
|
635
|
-
|
636
|
-
def test_checked_with_404_error
|
637
|
-
WebMock.disable_net_connect!
|
638
|
-
stub_request(:get, 'https://example.org:443/test')
|
639
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
640
|
-
.to_return(status: 404)
|
641
|
-
error =
|
642
|
-
assert_raises(BazaRb::ServerFailure) do
|
643
|
-
fake_baza.send(
|
644
|
-
:checked,
|
645
|
-
Typhoeus.get('https://example.org:443/test', headers: { 'X-Zerocracy-Token' => '000' })
|
646
|
-
)
|
647
|
-
end
|
648
|
-
assert_includes(error.message, 'Invalid response code #404')
|
649
|
-
assert_includes(error.message, 'most probably you are trying to reach a wrong server')
|
650
|
-
end
|
651
|
-
|
652
|
-
def test_checked_with_0_error
|
653
|
-
WebMock.disable_net_connect!
|
654
|
-
stub_request(:get, 'https://example.org:443/test')
|
655
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
656
|
-
.to_return(status: 0)
|
657
|
-
error =
|
658
|
-
assert_raises(BazaRb::ServerFailure) do
|
659
|
-
fake_baza.send(
|
660
|
-
:checked,
|
661
|
-
Typhoeus.get('https://example.org:443/test', headers: { 'X-Zerocracy-Token' => '000' })
|
662
|
-
)
|
663
|
-
end
|
664
|
-
assert_includes(error.message, 'Invalid response code #0')
|
665
|
-
assert_includes(error.message, 'most likely a connection failure')
|
666
|
-
end
|
667
|
-
|
668
|
-
def test_push_without_compression
|
669
|
-
WebMock.disable_net_connect!
|
670
|
-
baza = BazaRb.new('example.org', 443, '000', loog: Loog::NULL, compress: false)
|
671
|
-
stub_request(:put, 'https://example.org:443/push/test')
|
672
|
-
.with(
|
673
|
-
headers: {
|
674
|
-
'X-Zerocracy-Token' => '000',
|
675
|
-
'Content-Type' => 'application/octet-stream',
|
676
|
-
'Content-Length' => '4'
|
677
|
-
},
|
678
|
-
body: 'data'
|
679
|
-
)
|
680
|
-
.to_return(status: 200, body: '123')
|
681
|
-
baza.push('test', 'data', [])
|
682
|
-
end
|
683
|
-
|
684
|
-
def test_get_request_retries_on_429_status_code
|
685
|
-
WebMock.disable_net_connect!
|
686
|
-
stub_request(:get, 'https://example.org:443/whoami')
|
687
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
688
|
-
.to_return(status: 429)
|
689
|
-
.times(3)
|
690
|
-
stub_request(:get, 'https://example.org:443/whoami')
|
691
|
-
.with(headers: { 'X-Zerocracy-Token' => '000' })
|
692
|
-
.to_return(status: 200, body: 'testuser')
|
693
|
-
assert_equal('testuser', fake_baza.whoami)
|
694
|
-
end
|
695
|
-
|
696
|
-
def test_download_retries_on_busy_server
|
697
|
-
WebMock.disable_net_connect!
|
698
|
-
Dir.mktmpdir do |dir|
|
699
|
-
file = File.join(dir, 'download.txt')
|
700
|
-
attempts = 0
|
701
|
-
stub_request(:get, 'https://example.org:443/file')
|
702
|
-
.with(headers: { 'Range' => 'bytes=0-' })
|
703
|
-
.to_return do |_request|
|
704
|
-
attempts += 1
|
705
|
-
if attempts < 2
|
706
|
-
{ status: 429, body: 'Too Many Requests', headers: {} }
|
707
|
-
else
|
708
|
-
{ status: 200, body: 'success content', headers: {} }
|
709
|
-
end
|
710
|
-
end
|
711
|
-
baza = BazaRb.new('example.org', 443, '000', loog: Loog::NULL, compress: false, timeout: 0.1, pause: 0)
|
712
|
-
baza.send(:download, baza.send(:home).append('file'), file)
|
713
|
-
assert_equal(2, attempts, 'Expected two HTTP calls due to 429 retries')
|
714
|
-
assert_equal('success content', File.read(file))
|
715
|
-
end
|
716
|
-
end
|
717
|
-
|
718
|
-
def test_upload_retries_on_busy_server
|
719
|
-
WebMock.disable_net_connect!
|
720
|
-
Dir.mktmpdir do |dir|
|
721
|
-
file = File.join(dir, 'upload.txt')
|
722
|
-
File.write(file, 'test content')
|
723
|
-
attempts = 0
|
724
|
-
stub_request(:put, 'https://example.org:443/file')
|
725
|
-
.to_return do |_request|
|
726
|
-
attempts += 1
|
727
|
-
if attempts < 2
|
728
|
-
{ status: 429, body: 'Too Many Requests' }
|
729
|
-
else
|
730
|
-
{ status: 200, body: 'OK' }
|
731
|
-
end
|
732
|
-
end
|
733
|
-
baza = BazaRb.new('example.org', 443, '000', loog: Loog::NULL, compress: false, timeout: 0.1, pause: 0)
|
734
|
-
baza.send(:upload, baza.send(:home).append('file'), file)
|
735
|
-
assert_equal(2, attempts, 'Expected 2 HTTP calls due to 429 retries')
|
736
|
-
end
|
737
|
-
end
|
738
|
-
|
739
|
-
def test_durable_load_from_sinatra
|
740
|
-
WebMock.enable_net_connect!
|
741
|
-
Dir.mktmpdir do |dir|
|
742
|
-
with_sinatra_server do |baza|
|
743
|
-
file = File.join(dir, 'x.txt')
|
744
|
-
baza.durable_load(42, file)
|
745
|
-
assert_equal("Hello, \xFF\xFE\x12!", File.read(file))
|
746
|
-
end
|
747
|
-
end
|
748
|
-
end
|
749
|
-
|
750
|
-
private
|
751
|
-
|
752
|
-
def with_sinatra_server
|
753
|
-
Dir.mktmpdir do |dir|
|
754
|
-
app = File.join(dir, 'app.rb')
|
755
|
-
File.write(
|
756
|
-
app,
|
757
|
-
"
|
758
|
-
require 'rack'
|
759
|
-
require 'sinatra'
|
760
|
-
use Rack::Deflater
|
761
|
-
get '/' do
|
762
|
-
'I am alive'
|
763
|
-
end
|
764
|
-
get '/durables/42' do
|
765
|
-
\"Hello, \\xFF\\xFE\\x12!\"
|
766
|
-
end
|
767
|
-
"
|
768
|
-
)
|
769
|
-
RandomPort::Pool::SINGLETON.acquire do |port|
|
770
|
-
host = '127.0.0.1'
|
771
|
-
qbash("bundle exec ruby #{Shellwords.escape(app)} -p #{port}", log: Loog::NULL, accept: nil) do
|
772
|
-
loop do
|
773
|
-
break if Typhoeus::Request.get("http://#{host}:#{port}").code == 200
|
774
|
-
sleep(0.1)
|
775
|
-
end
|
776
|
-
yield BazaRb.new(host, port, '0000-0000-0000', ssl: false)
|
777
|
-
end
|
778
|
-
end
|
779
|
-
end
|
780
|
-
end
|
781
|
-
|
782
|
-
def with_http_server(code, response, opts = {})
|
783
|
-
opts = { ssl: false, timeout: 1 }.merge(opts)
|
784
|
-
WebMock.enable_net_connect!
|
785
|
-
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
|
786
|
-
host = '127.0.0.1'
|
787
|
-
RandomPort::Pool::SINGLETON.acquire do |port|
|
788
|
-
server = TCPServer.new(host, port)
|
789
|
-
t =
|
790
|
-
Thread.new do
|
791
|
-
socket = server.accept
|
792
|
-
req.parse(socket)
|
793
|
-
body = req.body
|
794
|
-
len = req.header['content-length'].first.to_i
|
795
|
-
if body.nil? || len == body.size
|
796
|
-
socket.puts "HTTP/1.1 #{code} OK\r\nContent-Length: #{response.length}\r\n\r\n#{response}"
|
797
|
-
else
|
798
|
-
socket.puts "HTTP/1.1 400 Bad Request\r\n"
|
799
|
-
end
|
800
|
-
socket.close
|
801
|
-
end
|
802
|
-
yield BazaRb.new(host, port, '0000', **opts)
|
803
|
-
t.terminate
|
804
|
-
assert(t.join(1))
|
805
|
-
end
|
806
|
-
req
|
807
|
-
end
|
808
|
-
|
809
|
-
def fake_baza(compress: true)
|
810
|
-
BazaRb.new('example.org', 443, '000', loog: Loog::NULL, compress:)
|
811
|
-
end
|
812
|
-
|
813
|
-
def fake_name
|
814
|
-
"fake#{SecureRandom.hex(8)}"
|
815
|
-
end
|
816
|
-
|
817
|
-
def we_are_online?
|
818
|
-
$we_are_online ||= !ARGV.include?('--offline') && online?
|
819
|
-
end
|
820
|
-
# rubocop:enable Style/GlobalVars
|
821
|
-
end
|