baza.rb 0.3.0 → 0.5.0

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 CHANGED
@@ -5,11 +5,12 @@
5
5
 
6
6
  require 'factbase'
7
7
  require 'loog'
8
- require 'net/ping'
8
+ require 'net/http'
9
9
  require 'random-port'
10
10
  require 'securerandom'
11
11
  require 'socket'
12
12
  require 'stringio'
13
+ require 'uri'
13
14
  require 'wait_for'
14
15
  require 'webrick'
15
16
  require_relative 'test__helper'
@@ -17,10 +18,10 @@ require_relative '../lib/baza-rb'
17
18
 
18
19
  # Test.
19
20
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
20
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
21
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
21
22
  # License:: MIT
22
23
  class TestBazaRb < Minitest::Test
23
- # The token to use for testing:
24
+ # The token to use for testing, in Zerocracy.com:
24
25
  TOKEN = '00000000-0000-0000-0000-000000000000'
25
26
 
26
27
  # The host of the production platform:
@@ -30,7 +31,7 @@ class TestBazaRb < Minitest::Test
30
31
  PORT = 443
31
32
 
32
33
  # Live agent:
33
- LIVE = BazaRb.new(HOST, PORT, TOKEN, loog: Loog::VERBOSE)
34
+ LIVE = BazaRb.new(HOST, PORT, TOKEN, loog: Loog::NULL)
34
35
 
35
36
  def test_live_push
36
37
  WebMock.enable_net_connect!
@@ -43,7 +44,7 @@ class TestBazaRb < Minitest::Test
43
44
  assert(LIVE.name_exists?(n))
44
45
  assert_predicate(LIVE.recent(n), :positive?)
45
46
  id = LIVE.recent(n)
46
- wait_for(60) { LIVE.finished?(id) }
47
+ assert(wait_for(200) { LIVE.finished?(id) })
47
48
  refute_nil(LIVE.pull(id))
48
49
  refute_nil(LIVE.stdout(id))
49
50
  refute_nil(LIVE.exit_code(id))
@@ -53,6 +54,26 @@ class TestBazaRb < Minitest::Test
53
54
  refute_nil(LIVE.unlock(n, owner))
54
55
  end
55
56
 
57
+ def test_live_whoami
58
+ WebMock.enable_net_connect!
59
+ skip('We are offline') unless we_are_online
60
+ refute_nil(LIVE.whoami)
61
+ end
62
+
63
+ def test_live_balance
64
+ WebMock.enable_net_connect!
65
+ skip('We are offline') unless we_are_online
66
+ z = LIVE.balance
67
+ refute_nil(z)
68
+ assert(z.to_f)
69
+ end
70
+
71
+ def test_live_fee_payment
72
+ WebMock.enable_net_connect!
73
+ skip('We are offline') unless we_are_online
74
+ refute_nil(LIVE.fee('unknown', 0.007, 'just for fun', 777))
75
+ end
76
+
56
77
  def test_live_push_no_compression
57
78
  WebMock.enable_net_connect!
58
79
  skip('We are offline') unless we_are_online
@@ -100,7 +121,7 @@ class TestBazaRb < Minitest::Test
100
121
  stub_request(:post, 'https://example.org/account/transfer').to_return(
101
122
  status: 302, headers: { 'X-Zerocracy-ReceiptId' => '42' }
102
123
  )
103
- id = BazaRb.new('example.org', 443, '000').transfer('jeff', 42.50, 'for fun')
124
+ id = fake_baza.transfer('jeff', 42.50, 'for fun')
104
125
  assert_equal(42, id)
105
126
  end
106
127
 
@@ -110,10 +131,40 @@ class TestBazaRb < Minitest::Test
110
131
  stub_request(:post, 'https://example.org/account/transfer').to_return(
111
132
  status: 302, headers: { 'X-Zerocracy-ReceiptId' => '42' }
112
133
  )
113
- id = BazaRb.new('example.org', 443, '000').transfer('jeff', 42.50, 'for fun', job: 555)
134
+ id = fake_baza.transfer('jeff', 42.50, 'for fun', job: 555)
114
135
  assert_equal(42, id)
115
136
  end
116
137
 
138
+ def test_reads_whoami
139
+ WebMock.disable_net_connect!
140
+ stub_request(:get, 'https://example.org/whoami').to_return(status: 200, body: 'jeff')
141
+ assert_equal('jeff', fake_baza.whoami)
142
+ end
143
+
144
+ def test_reads_balance
145
+ WebMock.disable_net_connect!
146
+ stub_request(:get, 'https://example.org/account/balance').to_return(status: 200, body: '42.33')
147
+ assert_in_delta(42.33, fake_baza.balance)
148
+ end
149
+
150
+ def test_checks_whether_job_is_finished
151
+ WebMock.disable_net_connect!
152
+ stub_request(:get, 'https://example.org/finished/42').to_return(status: 200, body: 'yes')
153
+ assert(fake_baza.finished?(42))
154
+ end
155
+
156
+ def test_reads_verification_verdict
157
+ WebMock.disable_net_connect!
158
+ stub_request(:get, 'https://example.org/jobs/42/verified.txt').to_return(status: 200, body: 'done')
159
+ assert(fake_baza.verified(42))
160
+ end
161
+
162
+ def test_unlocks_job_by_name
163
+ WebMock.disable_net_connect!
164
+ stub_request(:get, 'https://example.org/unlock/foo?owner=x').to_return(status: 302)
165
+ assert(fake_baza.unlock('foo', 'x'))
166
+ end
167
+
117
168
  def test_durable_place
118
169
  WebMock.disable_net_connect!
119
170
  stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
@@ -123,7 +174,7 @@ class TestBazaRb < Minitest::Test
123
174
  Dir.mktmpdir do |dir|
124
175
  file = File.join(dir, 'test.bin')
125
176
  File.binwrite(file, 'hello')
126
- assert_equal(42, BazaRb.new('example.org', 443, '000').durable_place('simple', file))
177
+ assert_equal(42, fake_baza.durable_place('simple', file))
127
178
  end
128
179
  end
129
180
 
@@ -134,24 +185,71 @@ class TestBazaRb < Minitest::Test
134
185
  )
135
186
  assert_equal(
136
187
  42,
137
- BazaRb.new('example.org', 443, '000').push('simple', 'hello, world!', [])
188
+ fake_baza.push('simple', 'hello, world!', [])
138
189
  )
139
190
  end
140
191
 
141
- def test_simple_pop
192
+ def test_simple_pop_with_no_job_found
142
193
  WebMock.disable_net_connect!
143
194
  stub_request(:get, 'https://example.org/pop?owner=me').to_return(status: 204)
144
195
  Tempfile.open do |zip|
145
- refute(BazaRb.new('example.org', 443, '000').pop('me', zip.path))
196
+ refute(fake_baza.pop('me', zip.path))
146
197
  refute_path_exists(zip.path)
147
198
  end
148
199
  end
149
200
 
201
+ def test_simple_pop_with_ranges
202
+ WebMock.disable_net_connect!
203
+ owner = 'owner888'
204
+ job = 4242
205
+ stub_request(:get, 'https://example.org/pop')
206
+ .with(query: { owner: })
207
+ .to_return(
208
+ status: 206,
209
+ headers: { 'Content-Range' => 'bytes 0-0/*', 'X-Zerocracy-JobId' => job, 'Content-Length' => 0 },
210
+ body: ''
211
+ )
212
+ bin = nil
213
+ Tempfile.open do |zip|
214
+ File.binwrite(zip.path, 'the archive to return (not a real ZIP for now)')
215
+ bin = File.binread(zip.path)
216
+ stub_request(:get, 'https://example.org/pop')
217
+ .with(query: { job:, owner: })
218
+ .with(headers: { 'Range' => 'bytes=0-' })
219
+ .to_return(
220
+ status: 206,
221
+ headers: {
222
+ 'Content-Range' => "bytes 0-7/#{bin.size}",
223
+ 'X-Zerocracy-JobId' => job,
224
+ 'Content-Length' => 8
225
+ },
226
+ body: bin[0..7]
227
+ )
228
+ stub_request(:get, 'https://example.org/pop')
229
+ .with(query: { job:, owner: })
230
+ .with(headers: { 'Range' => 'bytes=8-' })
231
+ .to_return(
232
+ status: 206,
233
+ headers: {
234
+ 'Content-Range' => "bytes 8-#{bin.size - 1}/#{bin.size}",
235
+ 'X-Zerocracy-JobId' => job,
236
+ 'Content-Length' => bin.size - 8
237
+ },
238
+ body: bin[8..]
239
+ )
240
+ end
241
+ Tempfile.open do |zip|
242
+ assert(fake_baza.pop(owner, zip.path))
243
+ assert_path_exists(zip.path)
244
+ assert_equal(bin, File.binread(zip.path))
245
+ end
246
+ end
247
+
150
248
  def test_simple_finish
151
249
  WebMock.disable_net_connect!
152
250
  stub_request(:put, 'https://example.org/finish?id=42').to_return(status: 200)
153
251
  Tempfile.open do |zip|
154
- BazaRb.new('example.org', 443, '000').finish(42, zip.path)
252
+ fake_baza.finish(42, zip.path)
155
253
  end
156
254
  end
157
255
 
@@ -162,7 +260,7 @@ class TestBazaRb < Minitest::Test
162
260
  .to_return(status: 200, body: '42')
163
261
  assert_equal(
164
262
  42,
165
- BazaRb.new('example.org', 443, '000').recent('simple')
263
+ fake_baza.recent('simple')
166
264
  )
167
265
  end
168
266
 
@@ -172,7 +270,7 @@ class TestBazaRb < Minitest::Test
172
270
  status: 200, body: 'yes'
173
271
  )
174
272
  assert(
175
- BazaRb.new('example.org', 443, '000').name_exists?('simple')
273
+ fake_baza.name_exists?('simple')
176
274
  )
177
275
  end
178
276
 
@@ -182,7 +280,7 @@ class TestBazaRb < Minitest::Test
182
280
  status: 200, body: '0'
183
281
  )
184
282
  assert_predicate(
185
- BazaRb.new('example.org', 443, '000').exit_code(42), :zero?
283
+ fake_baza.exit_code(42), :zero?
186
284
  )
187
285
  end
188
286
 
@@ -192,7 +290,7 @@ class TestBazaRb < Minitest::Test
192
290
  status: 200, body: 'hello!'
193
291
  )
194
292
  refute_empty(
195
- BazaRb.new('example.org', 443, '000').stdout(42)
293
+ fake_baza.stdout(42)
196
294
  )
197
295
  end
198
296
 
@@ -202,21 +300,21 @@ class TestBazaRb < Minitest::Test
202
300
  status: 200, body: 'hello, world!'
203
301
  )
204
302
  assert(
205
- BazaRb.new('example.org', 443, '000').pull(333).start_with?('hello')
303
+ fake_baza.pull(333).start_with?('hello')
206
304
  )
207
305
  end
208
306
 
209
307
  def test_simple_lock_success
210
308
  WebMock.disable_net_connect!
211
309
  stub_request(:get, 'https://example.org/lock/name?owner=owner').to_return(status: 302)
212
- BazaRb.new('example.org', 443, '000').lock('name', 'owner')
310
+ fake_baza.lock('name', 'owner')
213
311
  end
214
312
 
215
313
  def test_simple_lock_failure
216
314
  WebMock.disable_net_connect!
217
315
  stub_request(:get, 'https://example.org/lock/name?owner=owner').to_return(status: 409)
218
316
  assert_raises(StandardError) do
219
- BazaRb.new('example.org', 443, '000').lock('name', 'owner')
317
+ fake_baza.lock('name', 'owner')
220
318
  end
221
319
  end
222
320
 
@@ -225,7 +323,7 @@ class TestBazaRb < Minitest::Test
225
323
  stub_request(:put, 'https://example.org/push/foo')
226
324
  .to_return(status: 503, body: 'oops', headers: { 'X-Zerocracy-Failure': 'the failure' })
227
325
  .to_raise('why second time?')
228
- e = assert_raises(StandardError) { BazaRb.new('example.org', 443, '000').push('foo', 'data', []) }
326
+ e = assert_raises(StandardError) { fake_baza.push('foo', 'data', []) }
229
327
  [
230
328
  'Invalid response code #503',
231
329
  '"the failure"'
@@ -319,6 +417,162 @@ class TestBazaRb < Minitest::Test
319
417
  end
320
418
  end
321
419
 
420
+ def test_durable_save
421
+ Dir.mktmpdir do |dir|
422
+ file = File.join(dir, 'test.txt')
423
+ File.write(file, 'test content')
424
+ stub_request(:put, 'https://example.org:443/durables/42')
425
+ .with(headers: { 'X-Zerocracy-Token' => '000' }, body: 'test content')
426
+ .to_return(status: 200)
427
+ fake_baza.durable_save(42, file)
428
+ end
429
+ end
430
+
431
+ def test_durable_load
432
+ Dir.mktmpdir do |dir|
433
+ file = File.join(dir, 'loaded.txt')
434
+ stub_request(:get, 'https://example.org:443/durables/42')
435
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
436
+ .to_return(status: 200, body: 'loaded content')
437
+ fake_baza.durable_load(42, file)
438
+ assert_equal('loaded content', File.read(file))
439
+ end
440
+ end
441
+
442
+ def test_durable_lock
443
+ stub_request(:get, 'https://example.org:443/durables/42/lock?owner=test-owner')
444
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
445
+ .to_return(status: 302)
446
+ fake_baza.durable_lock(42, 'test-owner')
447
+ end
448
+
449
+ def test_durable_unlock
450
+ stub_request(:get, 'https://example.org:443/durables/42/unlock?owner=test-owner')
451
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
452
+ .to_return(status: 302)
453
+ fake_baza.durable_unlock(42, 'test-owner')
454
+ end
455
+
456
+ def test_fee
457
+ stub_request(:get, 'https://example.org:443/csrf')
458
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
459
+ .to_return(status: 200, body: 'csrf-token')
460
+ stub_request(:post, 'https://example.org:443/account/fee')
461
+ .with(
462
+ headers: { 'X-Zerocracy-Token' => '000' },
463
+ body: {
464
+ '_csrf' => 'csrf-token',
465
+ 'tab' => 'unknown',
466
+ 'amount' => '10.500000',
467
+ 'summary' => 'Test fee',
468
+ 'job' => '123'
469
+ }
470
+ )
471
+ .to_return(status: 302, headers: { 'X-Zerocracy-ReceiptId' => '456' })
472
+ receipt = fake_baza.fee('unknown', 10.5, 'Test fee', 123)
473
+ assert_equal(456, receipt)
474
+ end
475
+
476
+ def test_enter
477
+ stub_request(:get, 'https://example.org:443/valves/result?badge=test-badge')
478
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
479
+ .to_return(status: 200, body: 'cached result')
480
+ result = fake_baza.enter('test-valve', 'test-badge', 'test reason', 123) { 'new result' }
481
+ assert_equal('cached result', result)
482
+ end
483
+
484
+ def test_enter_not_cached
485
+ stub_request(:get, 'https://example.org:443/valves/result?badge=test-badge')
486
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
487
+ .to_return(status: 204)
488
+ stub_request(:get, 'https://example.org:443/csrf')
489
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
490
+ .to_return(status: 200, body: 'csrf-token')
491
+ stub_request(:post, 'https://example.org:443/valves/add?job=123')
492
+ .with(
493
+ headers: { 'X-Zerocracy-Token' => '000' },
494
+ body: {
495
+ '_csrf' => 'csrf-token',
496
+ 'name' => 'test-valve',
497
+ 'badge' => 'test-badge',
498
+ 'why' => 'test reason',
499
+ 'result' => 'new result'
500
+ }
501
+ )
502
+ .to_return(status: 302)
503
+ result = fake_baza.enter('test-valve', 'test-badge', 'test reason', 123) { 'new result' }
504
+ assert_equal('new result', result)
505
+ end
506
+
507
+ def test_checked_with_500_error
508
+ stub_request(:get, 'https://example.org:443/test')
509
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
510
+ .to_return(status: 500)
511
+ error =
512
+ assert_raises(BazaRb::ServerFailure) do
513
+ fake_baza.send(:checked,
514
+ Typhoeus.get('https://example.org:443/test', headers: { 'X-Zerocracy-Token' => '000' }))
515
+ end
516
+ assert_includes(error.message, 'Invalid response code #500')
517
+ assert_includes(error.message, "most probably it's an internal error on the server")
518
+ end
519
+
520
+ def test_checked_with_503_error
521
+ stub_request(:get, 'https://example.org:443/test')
522
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
523
+ .to_return(status: 503, headers: { 'X-Zerocracy-Failure' => 'Service unavailable' })
524
+ error =
525
+ assert_raises(BazaRb::ServerFailure) do
526
+ fake_baza.send(:checked,
527
+ Typhoeus.get('https://example.org:443/test', headers: { 'X-Zerocracy-Token' => '000' }))
528
+ end
529
+ assert_includes(error.message, 'Invalid response code #503')
530
+ assert_includes(error.message, "most probably it's an internal error on the server")
531
+ assert_includes(error.message, 'Service unavailable')
532
+ end
533
+
534
+ def test_checked_with_404_error
535
+ stub_request(:get, 'https://example.org:443/test')
536
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
537
+ .to_return(status: 404)
538
+ error =
539
+ assert_raises(BazaRb::ServerFailure) do
540
+ fake_baza.send(:checked,
541
+ Typhoeus.get('https://example.org:443/test', headers: { 'X-Zerocracy-Token' => '000' }))
542
+ end
543
+ assert_includes(error.message, 'Invalid response code #404')
544
+ assert_includes(error.message, 'most probably you are trying to reach a wrong server')
545
+ end
546
+
547
+ def test_checked_with_0_error
548
+ stub_request(:get, 'https://example.org:443/test')
549
+ .with(headers: { 'X-Zerocracy-Token' => '000' })
550
+ .to_return(status: 0)
551
+ error =
552
+ assert_raises(BazaRb::ServerFailure) do
553
+ fake_baza.send(:checked,
554
+ Typhoeus.get('https://example.org:443/test', headers: { 'X-Zerocracy-Token' => '000' }))
555
+ end
556
+ assert_includes(error.message, 'Invalid response code #0')
557
+ assert_includes(error.message, 'most likely an internal error')
558
+ end
559
+
560
+ def test_push_without_compression
561
+ baza = BazaRb.new('example.org', 443, '000', loog: Loog::NULL, compress: false)
562
+ stub_request(:put, 'https://example.org:443/push/test')
563
+ .with(
564
+ headers: {
565
+ 'X-Zerocracy-Token' => '000',
566
+ 'Content-Type' => 'application/octet-stream',
567
+ 'Content-Length' => '4'
568
+ },
569
+ body: 'data'
570
+ )
571
+ .to_return(status: 200, body: '123')
572
+ id = baza.push('test', 'data', [])
573
+ assert_equal(123, id)
574
+ end
575
+
322
576
  private
323
577
 
324
578
  def with_http_server(code, response, opts = {})
@@ -343,11 +597,28 @@ class TestBazaRb < Minitest::Test
343
597
  req
344
598
  end
345
599
 
600
+ def fake_baza
601
+ BazaRb.new('example.org', 443, '000', loog: Loog::NULL)
602
+ end
603
+
346
604
  def fake_name
347
605
  "fake#{SecureRandom.hex(8)}"
348
606
  end
349
607
 
350
608
  def we_are_online
351
- @we_are_online ||= Net::Ping::External.new('8.8.8.8').ping?
609
+ $we_are_online ||= !ARGV.include?('--offline') && uri_is_alive('https://www.zerocracy.com')
610
+ end
611
+ # rubocop:enable Style/GlobalVars
612
+
613
+ # Checks whether this URI is alive (HTTP status is 200).
614
+ def uri_is_alive(uri)
615
+ Timeout.timeout(4) do
616
+ require 'net/http'
617
+ WebMock.enable_net_connect!
618
+ Net::HTTP.get_response(URI(uri)).is_a?(Net::HTTPSuccess)
619
+ rescue Timeout::Error, Timeout::ExitException, Socket::ResolutionError, Errno::EHOSTUNREACH, Errno::EINVAL
620
+ puts "Ping failed to #{uri}"
621
+ false
622
+ end
352
623
  end
353
624
  end
data/test/test_fake.rb CHANGED
@@ -8,9 +8,21 @@ require_relative '../lib/baza-rb/fake'
8
8
 
9
9
  # Test fake object.
10
10
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
11
- # Copyright:: Copyright (c) 2024 Yegor Bugayenko
11
+ # Copyright:: Copyright (c) 2024-2025 Yegor Bugayenko
12
12
  # License:: MIT
13
13
  class TestFake < Minitest::Test
14
+ def test_whoami
15
+ baza = BazaRb::Fake.new
16
+ nick = baza.whoami
17
+ refute_nil(nick)
18
+ end
19
+
20
+ def test_balance
21
+ baza = BazaRb::Fake.new
22
+ z = baza.balance
23
+ refute_nil(z)
24
+ end
25
+
14
26
  def test_pull
15
27
  baza = BazaRb::Fake.new
16
28
  bin = baza.pull(42)
@@ -82,6 +94,12 @@ class TestFake < Minitest::Test
82
94
  assert_equal(42, receipt_id)
83
95
  end
84
96
 
97
+ def test_pays_fee
98
+ baza = BazaRb::Fake.new
99
+ receipt_id = baza.fee('unknown', 43.0, 'for fun', 44)
100
+ assert_equal(42, receipt_id)
101
+ end
102
+
85
103
  def test_pop
86
104
  baza = BazaRb::Fake.new
87
105
  Dir.mktmpdir do |tmp|
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: baza.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-04-06 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: backtrace
@@ -170,8 +170,8 @@ email: yegor256@gmail.com
170
170
  executables: []
171
171
  extensions: []
172
172
  extra_rdoc_files:
173
- - README.md
174
173
  - LICENSE.txt
174
+ - README.md
175
175
  files:
176
176
  - ".0pdd.yml"
177
177
  - ".gitattributes"
@@ -182,6 +182,7 @@ files:
182
182
  - ".github/workflows/pdd.yml"
183
183
  - ".github/workflows/rake.yml"
184
184
  - ".github/workflows/reuse.yml"
185
+ - ".github/workflows/typos.yml"
185
186
  - ".github/workflows/xcop.yml"
186
187
  - ".github/workflows/yamllint.yml"
187
188
  - ".gitignore"
@@ -225,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
225
226
  - !ruby/object:Gem::Version
226
227
  version: '0'
227
228
  requirements: []
228
- rubygems_version: 3.6.2
229
+ rubygems_version: 3.6.7
229
230
  specification_version: 4
230
231
  summary: Zerocracy API Ruby Client
231
232
  test_files: []