baza.rb 0.10.1 → 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.
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