baza.rb 0.4.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))
@@ -120,7 +121,7 @@ class TestBazaRb < Minitest::Test
120
121
  stub_request(:post, 'https://example.org/account/transfer').to_return(
121
122
  status: 302, headers: { 'X-Zerocracy-ReceiptId' => '42' }
122
123
  )
123
- id = BazaRb.new('example.org', 443, '000').transfer('jeff', 42.50, 'for fun')
124
+ id = fake_baza.transfer('jeff', 42.50, 'for fun')
124
125
  assert_equal(42, id)
125
126
  end
126
127
 
@@ -130,10 +131,40 @@ class TestBazaRb < Minitest::Test
130
131
  stub_request(:post, 'https://example.org/account/transfer').to_return(
131
132
  status: 302, headers: { 'X-Zerocracy-ReceiptId' => '42' }
132
133
  )
133
- 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)
134
135
  assert_equal(42, id)
135
136
  end
136
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
+
137
168
  def test_durable_place
138
169
  WebMock.disable_net_connect!
139
170
  stub_request(:get, 'https://example.org/csrf').to_return(body: 'token')
@@ -143,7 +174,7 @@ class TestBazaRb < Minitest::Test
143
174
  Dir.mktmpdir do |dir|
144
175
  file = File.join(dir, 'test.bin')
145
176
  File.binwrite(file, 'hello')
146
- assert_equal(42, BazaRb.new('example.org', 443, '000').durable_place('simple', file))
177
+ assert_equal(42, fake_baza.durable_place('simple', file))
147
178
  end
148
179
  end
149
180
 
@@ -154,24 +185,71 @@ class TestBazaRb < Minitest::Test
154
185
  )
155
186
  assert_equal(
156
187
  42,
157
- BazaRb.new('example.org', 443, '000').push('simple', 'hello, world!', [])
188
+ fake_baza.push('simple', 'hello, world!', [])
158
189
  )
159
190
  end
160
191
 
161
- def test_simple_pop
192
+ def test_simple_pop_with_no_job_found
162
193
  WebMock.disable_net_connect!
163
194
  stub_request(:get, 'https://example.org/pop?owner=me').to_return(status: 204)
164
195
  Tempfile.open do |zip|
165
- refute(BazaRb.new('example.org', 443, '000').pop('me', zip.path))
196
+ refute(fake_baza.pop('me', zip.path))
166
197
  refute_path_exists(zip.path)
167
198
  end
168
199
  end
169
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
+
170
248
  def test_simple_finish
171
249
  WebMock.disable_net_connect!
172
250
  stub_request(:put, 'https://example.org/finish?id=42').to_return(status: 200)
173
251
  Tempfile.open do |zip|
174
- BazaRb.new('example.org', 443, '000').finish(42, zip.path)
252
+ fake_baza.finish(42, zip.path)
175
253
  end
176
254
  end
177
255
 
@@ -182,7 +260,7 @@ class TestBazaRb < Minitest::Test
182
260
  .to_return(status: 200, body: '42')
183
261
  assert_equal(
184
262
  42,
185
- BazaRb.new('example.org', 443, '000').recent('simple')
263
+ fake_baza.recent('simple')
186
264
  )
187
265
  end
188
266
 
@@ -192,7 +270,7 @@ class TestBazaRb < Minitest::Test
192
270
  status: 200, body: 'yes'
193
271
  )
194
272
  assert(
195
- BazaRb.new('example.org', 443, '000').name_exists?('simple')
273
+ fake_baza.name_exists?('simple')
196
274
  )
197
275
  end
198
276
 
@@ -202,7 +280,7 @@ class TestBazaRb < Minitest::Test
202
280
  status: 200, body: '0'
203
281
  )
204
282
  assert_predicate(
205
- BazaRb.new('example.org', 443, '000').exit_code(42), :zero?
283
+ fake_baza.exit_code(42), :zero?
206
284
  )
207
285
  end
208
286
 
@@ -212,7 +290,7 @@ class TestBazaRb < Minitest::Test
212
290
  status: 200, body: 'hello!'
213
291
  )
214
292
  refute_empty(
215
- BazaRb.new('example.org', 443, '000').stdout(42)
293
+ fake_baza.stdout(42)
216
294
  )
217
295
  end
218
296
 
@@ -222,21 +300,21 @@ class TestBazaRb < Minitest::Test
222
300
  status: 200, body: 'hello, world!'
223
301
  )
224
302
  assert(
225
- BazaRb.new('example.org', 443, '000').pull(333).start_with?('hello')
303
+ fake_baza.pull(333).start_with?('hello')
226
304
  )
227
305
  end
228
306
 
229
307
  def test_simple_lock_success
230
308
  WebMock.disable_net_connect!
231
309
  stub_request(:get, 'https://example.org/lock/name?owner=owner').to_return(status: 302)
232
- BazaRb.new('example.org', 443, '000').lock('name', 'owner')
310
+ fake_baza.lock('name', 'owner')
233
311
  end
234
312
 
235
313
  def test_simple_lock_failure
236
314
  WebMock.disable_net_connect!
237
315
  stub_request(:get, 'https://example.org/lock/name?owner=owner').to_return(status: 409)
238
316
  assert_raises(StandardError) do
239
- BazaRb.new('example.org', 443, '000').lock('name', 'owner')
317
+ fake_baza.lock('name', 'owner')
240
318
  end
241
319
  end
242
320
 
@@ -245,7 +323,7 @@ class TestBazaRb < Minitest::Test
245
323
  stub_request(:put, 'https://example.org/push/foo')
246
324
  .to_return(status: 503, body: 'oops', headers: { 'X-Zerocracy-Failure': 'the failure' })
247
325
  .to_raise('why second time?')
248
- e = assert_raises(StandardError) { BazaRb.new('example.org', 443, '000').push('foo', 'data', []) }
326
+ e = assert_raises(StandardError) { fake_baza.push('foo', 'data', []) }
249
327
  [
250
328
  'Invalid response code #503',
251
329
  '"the failure"'
@@ -339,6 +417,162 @@ class TestBazaRb < Minitest::Test
339
417
  end
340
418
  end
341
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
+
342
576
  private
343
577
 
344
578
  def with_http_server(code, response, opts = {})
@@ -363,11 +597,28 @@ class TestBazaRb < Minitest::Test
363
597
  req
364
598
  end
365
599
 
600
+ def fake_baza
601
+ BazaRb.new('example.org', 443, '000', loog: Loog::NULL)
602
+ end
603
+
366
604
  def fake_name
367
605
  "fake#{SecureRandom.hex(8)}"
368
606
  end
369
607
 
370
608
  def we_are_online
371
- @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
372
623
  end
373
624
  end
data/test/test_fake.rb CHANGED
@@ -8,7 +8,7 @@ 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
14
  def test_whoami
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.4.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-14 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: []