zold 0.16.27 → 0.16.28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/zold +19 -8
  4. data/fixtures/scripts/distribute-wallet.sh +1 -1
  5. data/fixtures/scripts/pull-on-start.sh +1 -1
  6. data/fixtures/scripts/push-and-pull.sh +1 -1
  7. data/fixtures/scripts/spread-wallets.sh +1 -1
  8. data/lib/zold/commands/alias.rb +4 -1
  9. data/lib/zold/commands/calculate.rb +4 -1
  10. data/lib/zold/commands/clean.rb +1 -1
  11. data/lib/zold/commands/create.rb +6 -3
  12. data/lib/zold/commands/diff.rb +4 -1
  13. data/lib/zold/commands/fetch.rb +4 -1
  14. data/lib/zold/commands/invoice.rb +4 -1
  15. data/lib/zold/commands/list.rb +12 -4
  16. data/lib/zold/commands/merge.rb +8 -1
  17. data/lib/zold/commands/next.rb +4 -1
  18. data/lib/zold/commands/node.rb +6 -3
  19. data/lib/zold/commands/pay.rb +4 -1
  20. data/lib/zold/commands/propagate.rb +4 -1
  21. data/lib/zold/commands/pull.rb +4 -1
  22. data/lib/zold/commands/push.rb +4 -1
  23. data/lib/zold/commands/remote.rb +6 -3
  24. data/lib/zold/commands/remove.rb +4 -1
  25. data/lib/zold/commands/routines/reconnect.rb +1 -1
  26. data/lib/zold/commands/routines/spread.rb +1 -1
  27. data/lib/zold/commands/show.rb +7 -3
  28. data/lib/zold/commands/taxes.rb +4 -1
  29. data/lib/zold/commands/thread_badge.rb +47 -0
  30. data/lib/zold/copies.rb +1 -1
  31. data/lib/zold/endless.rb +1 -1
  32. data/lib/zold/http.rb +3 -3
  33. data/lib/zold/key.rb +3 -0
  34. data/lib/zold/log.rb +52 -111
  35. data/lib/zold/metronome.rb +12 -10
  36. data/lib/zold/node/async_entrance.rb +2 -2
  37. data/lib/zold/node/entrance.rb +1 -1
  38. data/lib/zold/node/farm.rb +1 -1
  39. data/lib/zold/node/farmers.rb +1 -1
  40. data/lib/zold/node/front.rb +5 -5
  41. data/lib/zold/node/nodup_entrance.rb +1 -1
  42. data/lib/zold/node/spread_entrance.rb +1 -1
  43. data/lib/zold/node/sync_entrance.rb +1 -1
  44. data/lib/zold/patch.rb +2 -2
  45. data/lib/zold/remotes.rb +1 -1
  46. data/lib/zold/signature.rb +5 -1
  47. data/lib/zold/sync_wallets.rb +1 -1
  48. data/lib/zold/upgrades.rb +1 -1
  49. data/lib/zold/verbose_thread.rb +1 -1
  50. data/lib/zold/version.rb +1 -1
  51. data/lib/zold/version_file.rb +1 -1
  52. data/lib/zold/wallet.rb +2 -2
  53. data/resources/root.pub +14 -0
  54. data/test/commands/test_list.rb +2 -1
  55. data/test/commands/test_remote.rb +35 -4
  56. data/test/commands/test_show.rb +1 -1
  57. data/test/fake_home.rb +1 -1
  58. data/test/node/fake_node.rb +3 -2
  59. data/test/node/test_farm.rb +1 -1
  60. data/test/test__helper.rb +4 -3
  61. data/test/test_dir_items.rb +1 -1
  62. data/test/test_http.rb +44 -6
  63. data/test/test_key.rb +7 -0
  64. data/test/test_log.rb +12 -1
  65. data/test/test_remotes.rb +1 -1
  66. data/test/test_signature.rb +1 -0
  67. data/test/test_verbose_thread.rb +3 -3
  68. data/test/test_zold.rb +4 -3
  69. data/zold.gemspec +3 -2
  70. metadata +8 -5
@@ -36,7 +36,7 @@ require_relative '../dir_items'
36
36
  module Zold
37
37
  # The entrance
38
38
  class AsyncEntrance
39
- def initialize(entrance, dir, log: Log::Quiet.new, threads: [Concurrent.processor_count, 4].max)
39
+ def initialize(entrance, dir, log: Log::NULL, threads: [Concurrent.processor_count, 4].max)
40
40
  @entrance = entrance
41
41
  @dir = File.expand_path(dir)
42
42
  @log = log
@@ -103,7 +103,7 @@ in #{Age.new(start, limit: 0.05)}: #{uuid}")
103
103
  FileUtils.rm_f(item[:file])
104
104
  @entrance.push(item[:id], body)
105
105
  @log.debug("Pushed #{item[:id]}/#{Size.new(body.length)} to #{@entrance.class.name} \
106
- in #{Age.new(start, limit: 0.1)} (#{@queue.size} still in the queue)")
106
+ in #{Age.new(start, limit: 0.1)}#{@queue.size.zero? ? '' : "(#{@queue.size} still in the queue)"}")
107
107
  end
108
108
  end
109
109
  end
@@ -38,7 +38,7 @@ require_relative '../commands/push'
38
38
  module Zold
39
39
  # The entrance
40
40
  class Entrance
41
- def initialize(wallets, remotes, copies, address, log: Log::Quiet.new, network: 'test')
41
+ def initialize(wallets, remotes, copies, address, log: Log::NULL, network: 'test')
42
42
  @wallets = wallets
43
43
  @remotes = remotes
44
44
  @copies = copies
@@ -57,7 +57,7 @@ module Zold
57
57
  # <tt>lifetime</tt> is the amount of seconds for a score to live in the farm, by default
58
58
  # it's the entire day, since the Score expires in 24 hours; can be decreased for the
59
59
  # purpose of unit testing.
60
- def initialize(invoice, cache = File.join(Dir.pwd, 'farm'), log: Log::Quiet.new,
60
+ def initialize(invoice, cache = File.join(Dir.pwd, 'farm'), log: Log::NULL,
61
61
  farmer: Farmers::Plain.new, lifetime: 24 * 60 * 60)
62
62
  @log = log
63
63
  @cache = File.expand_path(cache)
@@ -44,7 +44,7 @@ module Zold
44
44
 
45
45
  # In a child process
46
46
  class Spawn
47
- def initialize(log: Log::Quiet.new)
47
+ def initialize(log: Log::NULL)
48
48
  @log = log
49
49
  end
50
50
 
@@ -434,18 +434,18 @@ in #{Age.new(@start, limit: 1)}")
434
434
  # takes a lot of time (when the amount of wallets is big, like 40K). However,
435
435
  # we must find a way to count them somehow faster.
436
436
  def total_wallets
437
- return 256 if settings.opts['network'] == Wallet::MAIN_NETWORK
437
+ return 256 if settings.opts['network'] == Wallet::MAINET
438
438
  settings.wallets.all.count
439
439
  end
440
440
 
441
441
  def all_remotes
442
- settings.zache.get(:remotes, lifetime: settings.opts['network'] == Wallet::MAIN_NETWORK ? 60 : 0) do
442
+ settings.zache.get(:remotes, lifetime: settings.opts['network'] == Wallet::MAINET ? 60 : 0) do
443
443
  settings.remotes.all
444
444
  end
445
445
  end
446
446
 
447
447
  def processes_count
448
- settings.zache.get(:processes, lifetime: settings.opts['network'] == Wallet::MAIN_NETWORK ? 60 : 0) do
448
+ settings.zache.get(:processes, lifetime: settings.opts['network'] == Wallet::MAINET ? 60 : 0) do
449
449
  processes.count
450
450
  end
451
451
  end
@@ -459,7 +459,7 @@ in #{Age.new(@start, limit: 1)}")
459
459
  end
460
460
 
461
461
  def score
462
- settings.zache.get(:score, lifetime: settings.opts['network'] == Wallet::MAIN_NETWORK ? 60 : 0) do
462
+ settings.zache.get(:score, lifetime: settings.opts['network'] == Wallet::MAINET ? 60 : 0) do
463
463
  b = settings.farm.best
464
464
  raise 'Score is empty, there is something wrong with the Farm!' if b.empty?
465
465
  b[0]
@@ -476,7 +476,7 @@ in #{Age.new(@start, limit: 1)}")
476
476
  end
477
477
  end
478
478
 
479
- def running_server?
479
+ def running_server
480
480
  false
481
481
  end
482
482
  end
@@ -33,7 +33,7 @@ require_relative '../wallet'
33
33
  module Zold
34
34
  # The safe entrance
35
35
  class NoDupEntrance
36
- def initialize(entrance, wallets, log: Log::Quiet.new)
36
+ def initialize(entrance, wallets, log: Log::NULL)
37
37
  @entrance = entrance
38
38
  @wallets = wallets
39
39
  @log = log
@@ -40,7 +40,7 @@ require_relative '../commands/clean'
40
40
  module Zold
41
41
  # The entrance
42
42
  class SpreadEntrance
43
- def initialize(entrance, wallets, remotes, address, log: Log::Quiet.new, ignore_score_weakeness: false)
43
+ def initialize(entrance, wallets, remotes, address, log: Log::NULL, ignore_score_weakeness: false)
44
44
  @entrance = entrance
45
45
  @wallets = wallets
46
46
  @remotes = remotes
@@ -33,7 +33,7 @@ require_relative '../verbose_thread'
33
33
  module Zold
34
34
  # The entrance that makes sure only one thread works with a wallet
35
35
  class SyncEntrance
36
- def initialize(entrance, dir, timeout: 30, log: Log::Quiet.new)
36
+ def initialize(entrance, dir, timeout: 30, log: Log::NULL)
37
37
  @entrance = entrance
38
38
  @dir = dir
39
39
  @timeout = timeout
@@ -32,7 +32,7 @@ require_relative 'signature'
32
32
  module Zold
33
33
  # A patch
34
34
  class Patch
35
- def initialize(wallets, log: Log::Quiet.new)
35
+ def initialize(wallets, log: Log::NULL)
36
36
  @wallets = wallets
37
37
  @txns = []
38
38
  @log = log
@@ -81,7 +81,7 @@ module Zold
81
81
  #{wallet.id}/#{Amount.new(zents: balance).to_zld}/#{@txns.size} negative: #{txn.to_text}")
82
82
  next
83
83
  end
84
- unless Signature.new.valid?(@key, wallet.id, txn)
84
+ unless Signature.new(@network).valid?(@key, wallet.id, txn)
85
85
  @log.error("Invalid RSA signature at transaction ##{txn.id} of #{wallet.id}: #{txn.to_text}")
86
86
  next
87
87
  end
@@ -74,7 +74,7 @@ module Zold
74
74
 
75
75
  # One remote.
76
76
  class Remote
77
- def initialize(host:, port:, score:, idx:, network: 'test', log: Log::Quiet.new)
77
+ def initialize(host:, port:, score:, idx:, network: 'test', log: Log::NULL)
78
78
  @host = host
79
79
  @port = port
80
80
  @score = score
@@ -33,6 +33,10 @@ require_relative 'txn'
33
33
  module Zold
34
34
  # A signature
35
35
  class Signature
36
+ def initialize(network = 'test')
37
+ @network = network
38
+ end
39
+
36
40
  # Sign the trasnsaction and return the signature.
37
41
  # +pvt+:: Private RSA key
38
42
  # +id+:: Paying wallet ID
@@ -52,7 +56,7 @@ module Zold
52
56
  raise 'pub must be of type Key' unless pub.is_a?(Key)
53
57
  raise 'id must be of type Id' unless id.is_a?(Id)
54
58
  raise 'txn must be of type Txn' unless txn.is_a?(Txn)
55
- pub.verify(txn.sign, body(id, txn))
59
+ pub.verify(txn.sign, body(id, txn)) && (@network != Wallet::MAINET || id != Id::ROOT || pub == Key::ROOT)
56
60
  end
57
61
 
58
62
  private
@@ -30,7 +30,7 @@ require_relative 'log'
30
30
  module Zold
31
31
  # Synchronized collection of wallets
32
32
  class SyncWallets
33
- def initialize(wallets, timeout: 30, log: Log::Quiet.new)
33
+ def initialize(wallets, timeout: 30, log: Log::NULL)
34
34
  @wallets = wallets
35
35
  @log = log
36
36
  @timeout = timeout
@@ -25,7 +25,7 @@ require_relative 'log'
25
25
  module Zold
26
26
  # Class to manage data upgrades (when zold itself upgrades).
27
27
  class Upgrades
28
- def initialize(version, directory, log: Log::Verbose.new)
28
+ def initialize(version, directory, log: Log::VERBOSE)
29
29
  @version = version
30
30
  @directory = directory
31
31
  @log = log
@@ -30,7 +30,7 @@ require_relative 'log'
30
30
  module Zold
31
31
  # Verbose thread
32
32
  class VerboseThread
33
- def initialize(log = Log::Quiet.new)
33
+ def initialize(log = Log::NULL)
34
34
  @log = log
35
35
  end
36
36
 
@@ -25,6 +25,6 @@
25
25
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Zold
28
- VERSION = '0.16.27'
28
+ VERSION = '0.16.28'
29
29
  PROTOCOL = 2
30
30
  end
@@ -26,7 +26,7 @@ require_relative 'log'
26
26
  module Zold
27
27
  # Read and write .zoldata/version.
28
28
  class VersionFile
29
- def initialize(path, log: Log::Verbose.new)
29
+ def initialize(path, log: Log::VERBOSE)
30
30
  @path = path
31
31
  @log = log
32
32
  end
@@ -49,7 +49,7 @@ module Zold
49
49
  class Wallet
50
50
  # The name of the main production network. All other networks
51
51
  # must have different names.
52
- MAIN_NETWORK = 'zold'
52
+ MAINET = 'zold'
53
53
 
54
54
  # The extension of the wallet files
55
55
  EXT = '.z'
@@ -136,7 +136,7 @@ module Zold
136
136
  details
137
137
  )
138
138
  txn = txn.signed(pvt, id)
139
- raise 'This is not the right private key for this wallet' unless Signature.new.valid?(key, id, txn)
139
+ raise "Invalid private key for the wallet #{id}" unless Signature.new(network).valid?(key, id, txn)
140
140
  add(txn)
141
141
  txn
142
142
  end
@@ -0,0 +1,14 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA96lM5Y+QHYr9WvUucw/
3
+ wW+dJpnYBa2/nCij3DXroCaABYL5qG4mVIjGdCBbdS78tcOlcZS+WzPcmyepg56
4
+ cIwPkpYQop4MawaaCp6QC/nybu5sDwvnnDVWCsLveEAPbHos/BpVAJn89NeJO1M
5
+ aJgaRLKvtRK/P9bgd5tORGJKFq17yipfjLtXKSOCX6U2nPUNB8TCaAtESHNdbp6
6
+ kp2J063k+Mf8CT0yhFrAU5j/nRaUTKTwyyj6dcuRTn+FyfFdjfJi2mVOLMJrunN
7
+ CSr8TNhcMB1fE5MxtwYg46s6ZkqUhQ3oNgSKBgK7DuY2TMVMgsviIZ1xkUfLR4M
8
+ CNhjcwi9wVPNkEgTJUdjEK1m4TmNa2DWnX9oCQbYfPhze3Xv4Q3GCAUUSwvxZSO
9
+ qKh/MdqStYOB8ByXp1sEBDsLMpR7DfpmPJm18f5winZ0pEX0U4N/7VTqSIb+w8s
10
+ aT6YqA4WG+9ZYLKRSxwjYwkbj3cnbeq5bGXd02XjqitTHdonv1EPQvzVMxUO9RU
11
+ bxjpPHfDIA8AdBX4rA8F5FYe2K8yMlEgbJy7Za/CAKV9c5Fut5C5eYfxQegu5ff
12
+ mnQRuTyIZuAjZojIJWctLY2OT9SqRh0ilqJ4nq4q/eOfUuSJAUEQIZdQX9MBg3l
13
+ J0Pw9aSoSAp8iQWRdNTvqvuTZqExs3Tp1UCAwEAAQ==
14
+ -----END PUBLIC KEY-----
@@ -24,6 +24,7 @@ require 'minitest/autorun'
24
24
  require 'tmpdir'
25
25
  require_relative '../test__helper'
26
26
  require_relative '../../lib/zold/wallet'
27
+ require_relative '../../lib/zold/wallets'
27
28
  require_relative '../../lib/zold/key'
28
29
  require_relative '../../lib/zold/id'
29
30
  require_relative '../../lib/zold/commands/list'
@@ -39,7 +40,7 @@ class TestList < Zold::Test
39
40
  wallets = Zold::Wallets.new(dir)
40
41
  wallets.acq(id) do |wallet|
41
42
  wallet.init(Zold::Id.new, Zold::Key.new(file: 'fixtures/id_rsa.pub'))
42
- Zold::List.new(wallets: wallets, log: test_log).run
43
+ Zold::List.new(wallets: wallets, copies: File.join(dir, 'copies'), log: test_log).run
43
44
  end
44
45
  end
45
46
  end
@@ -166,11 +166,42 @@ class TestRemote < Zold::Test
166
166
  end
167
167
  end
168
168
 
169
- # @todo #329:30min Verify that the nodes that are being selected are
170
- # really the strongest ones. The strongest nodes are the ones with
171
- # the highest score.
172
169
  def test_select_selects_the_strongest_nodes
173
- skip
170
+ Dir.mktmpdir do |dir|
171
+ remotes = Zold::Remotes.new(file: File.join(dir, 'remotes.txt'))
172
+ cmd = Zold::Remote.new(remotes: remotes, log: test_log)
173
+ suffixes = []
174
+ (5000..5010).each do |port|
175
+ score = Zold::Score.new(
176
+ host: 'example.com',
177
+ port: port,
178
+ invoice: 'MYPREFIX@ffffffffffffffff',
179
+ suffixes: suffixes << '13f7f01'
180
+ )
181
+ stub_request(:get, "http://#{score.host}:#{score.port}/remotes").to_return(
182
+ status: 200,
183
+ body: {
184
+ version: Zold::VERSION,
185
+ score: score.to_h,
186
+ all: [
187
+ { host: 'localhost', port: port }
188
+ ]
189
+ }.to_json
190
+ )
191
+ stub_request(:get, "http://localhost:#{port}/version").to_return(
192
+ status: 200,
193
+ body: {
194
+ version: Zold::VERSION
195
+ }.to_json
196
+ )
197
+ cmd.run(%W[remote add localhost #{port}])
198
+ remotes.rescore('localhost', port, score)
199
+ end
200
+ cmd.run(%w[remote select --max-nodes=5])
201
+ assert_equal(5, remotes.all.count)
202
+ scores = remotes.all.map { |r| r[:score] }
203
+ assert_equal([11, 10, 9, 8, 7], scores)
204
+ end
174
205
  end
175
206
 
176
207
  def test_select_respects_max_nodes_option
@@ -40,7 +40,7 @@ class TestShow < Zold::Test
40
40
  wallets = Zold::Wallets.new(dir)
41
41
  wallets.acq(id) do |wallet|
42
42
  wallet.init(Zold::Id.new, Zold::Key.new(file: 'fixtures/id_rsa.pub'))
43
- balance = Zold::Show.new(wallets: wallets, log: test_log).run(['show', id.to_s])
43
+ balance = Zold::Show.new(wallets: wallets, copies: File.join(dir, 'c'), log: test_log).run(['show', id.to_s])
44
44
  assert_equal(Zold::Amount::ZERO, balance)
45
45
  end
46
46
  end
@@ -37,7 +37,7 @@ require_relative '../lib/zold/remotes'
37
37
  # License:: MIT
38
38
  class FakeHome
39
39
  attr_reader :dir
40
- def initialize(dir = __dir__, log: Zold::Log::Quiet.new)
40
+ def initialize(dir = __dir__, log: Zold::Log::NULL)
41
41
  @dir = dir
42
42
  @log = log
43
43
  end
@@ -34,7 +34,7 @@ require_relative '../../lib/zold/node/front'
34
34
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
35
35
  # License:: MIT
36
36
  class FakeNode
37
- def initialize(log: Zold::Log::Quiet.new)
37
+ def initialize(log: Zold::Log::NULL)
38
38
  @log = log
39
39
  end
40
40
 
@@ -43,6 +43,7 @@ class FakeNode
43
43
  FakeHome.new(log: @log).run do |home|
44
44
  RandomPort::Pool::SINGLETON.acquire do |port|
45
45
  node = Thread.new do
46
+ Thread.current.name = 'fake_node'
46
47
  Zold::VerboseThread.new(@log).run do
47
48
  Thread.current.abort_on_exception = true
48
49
  require_relative '../../lib/zold/commands/node'
@@ -67,7 +68,7 @@ class FakeNode
67
68
  loop do
68
69
  ping = Zold::Http.new(uri: uri).get
69
70
  break unless ping.status == 599 && node.alive?
70
- @log.debug("Waiting for #{uri} (attempt no.#{attempt}): ##{ping.status}...")
71
+ @log.info("Waiting for #{uri} (attempt no.#{attempt}): ##{ping.status}...")
71
72
  sleep 0.5
72
73
  attempt += 1
73
74
  break if attempt > 10
@@ -76,7 +76,7 @@ class FarmTest < Zold::Test
76
76
  farm.best
77
77
  Time.now - start
78
78
  end.inject(&:+) / cycles
79
- test_log.debug("Average speed is #{(speed * 1000).round(2)}ms in #{cycles} cycles")
79
+ test_log.info("Average speed is #{(speed * 1000).round(2)}ms in #{cycles} cycles")
80
80
  end
81
81
  end
82
82
  end
@@ -21,13 +21,14 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  gem 'openssl'
24
- require 'minitest/fail_fast'
25
24
  require 'openssl'
26
25
  require 'minitest/autorun'
27
26
  require 'minitest/hooks/test'
28
27
  require 'concurrent'
29
28
  require 'timeout'
30
29
 
30
+ require 'minitest/fail_fast' if ENV['TEST_QUIET_LOG']
31
+
31
32
  STDOUT.sync = true
32
33
 
33
34
  ENV['RACK_ENV'] = 'test'
@@ -74,12 +75,12 @@ module Zold
74
75
 
75
76
  def test_log
76
77
  require_relative '../lib/zold/log'
77
- @test_log ||= Zold::Log::Sync.new(ENV['TEST_QUIET_LOG'] ? Zold::Log::Quiet.new : Zold::Log::Verbose.new)
78
+ @test_log ||= ENV['TEST_QUIET_LOG'] ? Zold::Log::NULL : Zold::Log::VERBOSE
78
79
  end
79
80
 
80
81
  class TestLogger
81
82
  attr_accessor :msgs
82
- def initialize(log = Zold::Log::Quiet.new)
83
+ def initialize(log = Zold::Log::NULL)
83
84
  @log = log
84
85
  @msgs = []
85
86
  end
@@ -46,7 +46,7 @@ class TestDirItems < Zold::Test
46
46
  File.open(file, 'w+') do |f|
47
47
  f.write('test')
48
48
  end
49
- test_log.debug("Saved in #{Zold::Age.new(start)}")
49
+ test_log.info("Saved in #{Zold::Age.new(start)}")
50
50
  sleep 1
51
51
  end
52
52
  back.kill
@@ -72,6 +72,24 @@ class TestHttp < Zold::Test
72
72
  assert_equal(200, res.status)
73
73
  end
74
74
 
75
+ def test_terminates_on_timeout
76
+ WebMock.allow_net_connect!
77
+ RandomPort::Pool::SINGLETON.acquire do |port|
78
+ thread = Thread.start do
79
+ Zold::VerboseThread.new(test_log).run do
80
+ server = TCPServer.new(port)
81
+ server.accept
82
+ sleep 400
83
+ end
84
+ end
85
+ sleep 0.25
86
+ res = Zold::Http.new(uri: "http://127.0.0.1:#{port}/").get(timeout: 0.1)
87
+ assert_equal(599, res.status, res)
88
+ thread.kill
89
+ thread.join
90
+ end
91
+ end
92
+
75
93
  def test_doesnt_terminate_on_long_call
76
94
  WebMock.allow_net_connect!
77
95
  RandomPort::Pool::SINGLETON.acquire do |port|
@@ -93,19 +111,39 @@ class TestHttp < Zold::Test
93
111
  end
94
112
  end
95
113
 
96
- def test_terminates_on_timeout
114
+ # @todo #444:30min It's obvious that the test works (I can see that in
115
+ # the console, but for some weird reason it doesn't work in Minitest. Try
116
+ # to run it: ruby test/test_http.rb -n test_sends_correct_http_headers
117
+ # If fails because of PUT HTTP request timeout. Let's find the problem,
118
+ # fix it, and un-skip the test.
119
+ def test_sends_correct_http_headers
120
+ skip
97
121
  WebMock.allow_net_connect!
122
+ body = ''
98
123
  RandomPort::Pool::SINGLETON.acquire do |port|
99
124
  thread = Thread.start do
100
125
  Zold::VerboseThread.new(test_log).run do
101
126
  server = TCPServer.new(port)
102
- server.accept
103
- sleep 400
127
+ socket = server.accept
128
+ loop do
129
+ line = socket.gets
130
+ break if line.nil?
131
+ test_log.info(line.inspect)
132
+ body += line
133
+ end
134
+ socket.print("HTTP/1.1 200 OK\r\n")
135
+ socket.print("Content-Length: 4\r\n")
136
+ socket.print("\r\n")
137
+ socket.print('Done')
138
+ socket.close
104
139
  end
105
140
  end
106
- sleep 0.25
107
- res = Zold::Http.new(uri: "http://127.0.0.1:#{port}/").get(timeout: 0.1)
108
- assert_equal(599, res.status, res)
141
+ res = Zold::Http.new(uri: "http://127.0.0.1:#{port}/").put('how are you?')
142
+ assert_equal(200, res.status, res)
143
+ assert(body.include?('Content-Length: 12'), body)
144
+ assert(body.include?('Content-Type: text/plain'))
145
+ headers = body.split("\n").select { |t| t =~ /^[a-zA-Z-]+:.+$/ }
146
+ assert_equal(headers.count, headers.uniq.count)
109
147
  thread.kill
110
148
  thread.join
111
149
  end