zold 0.16.9 → 0.16.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5fa4b6ced7df2e9773120703da57a11e317396caedc756a8b42d9316fb900ff7
4
- data.tar.gz: e1e4f91dda7d2954bb7cb34adf5f56b71202ebe59102a7a85a805e4425041be0
3
+ metadata.gz: 5bdb355d25ef5197cfcc131d383d5391bec683efb8f5db52ba6b60d690bf4e3f
4
+ data.tar.gz: dc2f83cf4bdbc787de4232aa56fb3570f721f887b93069b4fa766fc0eeee2597
5
5
  SHA512:
6
- metadata.gz: f5b2ccce4eec666e4036448517f18ee4e36e71637100b85d900536891bf7e04306b5e7fd764037df5616b07998526b472759f9aa873874ffedaa640256217b2f
7
- data.tar.gz: 16287fd3da5be69b02e5d3ef232ca18eaa6cd1dafaeafbbe07ec3d4fc98f34e21f23fcd867591b19f5fe18ff6302a66aba3901432d8781fe672c82ef283d2f56
6
+ metadata.gz: de19e0642f74972e9a28f7506fea7397d51473d7bc308b0da64353e9177cea7c2f16a56f1f0ca537f15f90d8001b6625c9762b9f1294eda20888539dc018c890
7
+ data.tar.gz: 19275bbdfe0cc8baea050d14656edcacad9b1d87846f4ddd9752f85517c20009515079c46050727bbb843b8448a5bd5feebcf8406584536720f9323c565b5011
@@ -5,6 +5,8 @@ AllCops:
5
5
  DisplayCopNames: true
6
6
  TargetRubyVersion: 2.3.3
7
7
 
8
+ Layout/EmptyLineAfterGuardClause:
9
+ Enabled: false
8
10
  Metrics/CyclomaticComplexity:
9
11
  Max: 25
10
12
  Metrics/MethodLength:
@@ -6,7 +6,7 @@ function start_node {
6
6
  cd ${port}
7
7
  zold node --trace --invoice=DISTRWALLET@ffffffffffffffff \
8
8
  --host=localhost --port=${port} --bind-port=${port} \
9
- --threads=0 --routine-immediately > log.txt &
9
+ --threads=0 --routine-immediately --never-reboot > log.txt &
10
10
  pid=$!
11
11
  echo ${pid} > pid
12
12
  cd ..
@@ -21,8 +21,8 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'slop'
24
+ require 'zold/score'
24
25
  require_relative '../log'
25
- require_relative '../score'
26
26
 
27
27
  # SCORE command.
28
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -26,12 +26,12 @@ require 'time'
26
26
  require 'futex'
27
27
  require 'slop'
28
28
  require 'rainbow'
29
+ require 'zold/score'
29
30
  require_relative 'args'
30
31
  require_relative '../age'
31
32
  require_relative '../size'
32
33
  require_relative '../log'
33
34
  require_relative '../http'
34
- require_relative '../score'
35
35
  require_relative '../copies'
36
36
 
37
37
  # CLEAN command.
@@ -27,12 +27,12 @@ require 'tempfile'
27
27
  require 'slop'
28
28
  require 'rainbow'
29
29
  require 'concurrent/atomics'
30
+ require 'zold/score'
30
31
  require_relative 'args'
31
32
  require_relative '../log'
32
33
  require_relative '../age'
33
34
  require_relative '../http'
34
35
  require_relative '../size'
35
- require_relative '../score'
36
36
  require_relative '../json_page'
37
37
  require_relative '../copies'
38
38
 
@@ -21,8 +21,8 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'slop'
24
+ require 'zold/score'
24
25
  require_relative '../log'
25
- require_relative '../score'
26
26
 
27
27
  # NEXT command.
28
28
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -24,9 +24,9 @@ require 'open3'
24
24
  require 'slop'
25
25
  require 'backtrace'
26
26
  require 'concurrent'
27
+ require 'zold/score'
27
28
  require_relative '../version'
28
29
  require_relative '../age'
29
- require_relative '../score'
30
30
  require_relative '../metronome'
31
31
  require_relative '../wallet'
32
32
  require_relative '../wallets'
@@ -79,8 +79,8 @@ module Zold
79
79
  "The strength of the score (default: #{Score::STRENGTH})",
80
80
  default: Score::STRENGTH
81
81
  o.integer '--threads',
82
- "How many threads to use for scores finding (default: #{Concurrent.processor_count})",
83
- default: Concurrent.processor_count
82
+ "How many threads to use for scores finding (default: #{[Concurrent.processor_count, 4].max})",
83
+ default: [Concurrent.processor_count, 4].max
84
84
  o.bool '--dump-errors',
85
85
  'Make HTTP front-end errors visible in the log (false by default)',
86
86
  default: false
@@ -95,8 +95,7 @@ total score for #{id} is #{total}")
95
95
  response = r.http(uri).put(content)
96
96
  @wallets.find(id) do |wallet|
97
97
  if response.code == '304'
98
- @log.info("#{r}: same version #{Size.new(content.length)} of #{wallet.memo} \
99
- there, in #{Age.new(start, limit: 0.5)}")
98
+ @log.info("#{r}: same version of #{wallet.memo} there, in #{Age.new(start, limit: 0.5)}")
100
99
  return 0
101
100
  end
102
101
  r.assert_code(200, response)
@@ -105,8 +104,8 @@ there, in #{Age.new(start, limit: 0.5)}")
105
104
  r.assert_valid_score(score)
106
105
  r.assert_score_ownership(score)
107
106
  r.assert_score_strength(score) unless opts['ignore-score-weakness']
108
- @log.info("#{r} accepted #{Size.new(content.length)} of #{wallet.memo} \
109
- in #{Age.new(start, limit: 4)}: #{Rainbow(score.value).green} (#{json['version']})")
107
+ @log.info("#{r} accepted #{wallet.memo} in #{Age.new(start, limit: 4)}: \
108
+ #{Rainbow(score.value).green} (#{json['version']})")
110
109
  score.value
111
110
  end
112
111
  end
@@ -26,6 +26,7 @@ require 'rainbow'
26
26
  require 'net/http'
27
27
  require 'json'
28
28
  require 'time'
29
+ require 'zold/score'
29
30
  require_relative 'args'
30
31
  require_relative '../node/farm'
31
32
  require_relative '../log'
@@ -33,7 +34,6 @@ require_relative '../age'
33
34
  require_relative '../json_page'
34
35
  require_relative '../http'
35
36
  require_relative '../remotes'
36
- require_relative '../score'
37
37
  require_relative '../wallet'
38
38
  require_relative '../gem'
39
39
 
@@ -23,11 +23,11 @@
23
23
  require 'slop'
24
24
  require 'json'
25
25
  require 'rainbow'
26
+ require 'zold/score'
26
27
  require_relative 'args'
27
28
  require_relative 'pay'
28
29
  require_relative '../log'
29
30
  require_relative '../json_page'
30
- require_relative '../score'
31
31
  require_relative '../id'
32
32
  require_relative '../tax'
33
33
  require_relative '../http'
@@ -121,13 +121,14 @@ the balance is #{wallet.balance}: #{tax.to_text}")
121
121
  @log.debug("No need to pay taxes yet, while the debt is less than #{Tax::TRIAL} (#{Tax::TRIAL.to_i} zents)")
122
122
  return
123
123
  end
124
- top = everybody = top_scores(opts)
124
+ top = top_scores(opts)
125
+ everybody = top.dup
125
126
  paid = 0
126
127
  while debt > Tax::TRIAL
127
128
  if top.empty?
128
129
  msg = [
129
130
  "There were #{everybody.count} remote nodes as tax collecting candidates;",
130
- "#{paid} payments have been made",
131
+ "#{paid} payments have been made;",
131
132
  "there was not enough score power to pay the total debt of #{total} for #{wallet.id};",
132
133
  "the residual amount to pay is #{debt} (trial amount is #{Tax::TRIAL});",
133
134
  "the formula ingredients are #{tax.to_text}"
@@ -21,9 +21,9 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'uri'
24
+ require 'zold/score'
24
25
  require_relative 'json_page'
25
26
  require_relative 'http'
26
- require_relative 'score'
27
27
 
28
28
  # Class representing the Zold gem on Rubygems
29
29
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -36,6 +36,8 @@ module Zold
36
36
  JsonPage.new(
37
37
  Http.new(uri: 'https://rubygems.org/api/v1/versions/zold/latest.json', score: Score::ZERO).get.body
38
38
  ).to_hash['version']
39
+ rescue StandardError => _
40
+ '0.0.0'
39
41
  end
40
42
  end
41
43
  end
@@ -25,8 +25,8 @@ require 'uri'
25
25
  require 'timeout'
26
26
  require 'net/http'
27
27
  require 'backtrace'
28
+ require 'zold/score'
28
29
  require_relative 'version'
29
- require_relative 'score'
30
30
 
31
31
  # HTTP page.
32
32
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -25,8 +25,8 @@ require 'open3'
25
25
  require 'backtrace'
26
26
  require 'futex'
27
27
  require 'json'
28
+ require 'zold/score'
28
29
  require_relative '../log'
29
- require_relative '../score'
30
30
  require_relative '../age'
31
31
  require_relative '../verbose_thread'
32
32
  require_relative 'farmers'
@@ -45,16 +45,32 @@ module Zold
45
45
  end
46
46
  end
47
47
 
48
+ # Makes an instance of a farm. There should be only farm in the entire
49
+ # application, but you can, of course, start as many of them as necessary for the
50
+ # purpose of unit testing.
51
+ #
52
+ # <tt>cache</tt> is the file where the farm will keep all the scores it
53
+ # manages to find. If the file is absent, it will be created, together with
54
+ # the necesary parent directories.
55
+ #
56
+ # <tt>lifetime</tt> is the amount of seconds for a score to live in the farm, by default
57
+ # it's the entire day, since the Score expires in 24 hours; can be decreased for the
58
+ # purpose of unit testing.
48
59
  def initialize(invoice, cache = File.join(Dir.pwd, 'farm'), log: Log::Quiet.new,
49
- farmer: Farmers::Plain.new)
60
+ farmer: Farmers::Plain.new, lifetime: 24 * 60 * 60)
50
61
  @log = log
51
- @cache = cache
62
+ @cache = File.expand_path(cache)
52
63
  @invoice = invoice
53
64
  @pipeline = Queue.new
54
65
  @farmer = farmer
55
66
  @threads = []
67
+ @lifetime = lifetime
56
68
  end
57
69
 
70
+ # Returns the list of best scores the farm managed to find up to now. The
71
+ # list is NEVER empty, even if the farm has just started. If it's empty,
72
+ # it's definitely a bug. If the farm is just fresh start, the list will
73
+ # contain a single score with a zero value.
58
74
  def best
59
75
  load
60
76
  end
@@ -62,7 +78,7 @@ module Zold
62
78
  def to_text
63
79
  [
64
80
  "Current time: #{Time.now.utc.iso8601}",
65
- "Ruby processes: #{`ps -a | grep zold | wc -l`}",
81
+ "Ruby processes: #{`ps ax | grep zold | wc -l`}",
66
82
  JSON.pretty_generate(to_json),
67
83
  @threads.map do |t|
68
84
  trace = t.backtrace || []
@@ -87,10 +103,25 @@ module Zold
87
103
  }
88
104
  end
89
105
 
106
+ # Starts a farm, all threads, and yields the block provided. You are
107
+ # supposed to use it only with the block:
108
+ #
109
+ # Farm.new.start('example.org', 4096) do |farm|
110
+ # score = farm.best[0]
111
+ # # Everything else...
112
+ # end
113
+ #
114
+ # The farm will stop all its threads and close all resources safely
115
+ # right after the block provided exists.
90
116
  def start(host, port, strength: 8, threads: 8)
117
+ raise 'Block is required for the farm to start' unless block_given?
91
118
  @log.info('Zero-threads farm won\'t score anything!') if threads.zero?
119
+ if best.empty?
120
+ @log.info("No scores found in cache at #{@cache}")
121
+ else
122
+ @log.info("#{best.size} scores pre-loaded from #{@cache}, the best is: #{best[0]}")
123
+ end
92
124
  cleanup(host, port, strength, threads)
93
- @log.info("#{@pipeline.size} scores pre-loaded, the best is: #{best[0]}")
94
125
  @alive = true
95
126
  @threads = (1..threads).map do |t|
96
127
  Thread.new do
@@ -108,9 +139,9 @@ module Zold
108
139
  Thread.current.abort_on_exception = true
109
140
  Thread.current.name = 'cleanup'
110
141
  loop do
111
- max = 600
112
- a = (0..max).take_while do
113
- sleep 0.1
142
+ max = 100
143
+ a = (0..max - 1).take_while do
144
+ sleep 0.01
114
145
  @alive
115
146
  end
116
147
  unless a.count == max
@@ -131,7 +162,7 @@ module Zold
131
162
  start = Time.now
132
163
  finish(@cleanup)
133
164
  @threads.each { |t| finish(t) }
134
- @log.info("Farm stopped in #{Age.new(start)}")
165
+ @log.info("Farm stopped in #{Age.new(start)} (threads=#{threads}, strength=#{strength})")
135
166
  end
136
167
  end
137
168
 
@@ -144,7 +175,7 @@ module Zold
144
175
  loop do
145
176
  delay = Time.now - start
146
177
  if thread.join(0.1)
147
- @log.info("Thread \"#{thread.name}\" finished in #{Age.new(start)}")
178
+ @log.info("Thread \"#{thread.name}\" peacefully finished in #{Age.new(start)}")
148
179
  break
149
180
  end
150
181
  if delay > 1
@@ -157,16 +188,13 @@ module Zold
157
188
  def cleanup(host, port, strength, threads)
158
189
  scores = load
159
190
  before = scores.map(&:value).max.to_i
160
- save(threads, [Score.new(time: Time.now, host: host, port: port, invoice: @invoice, strength: strength)])
191
+ save(threads, [Score.new(host: host, port: port, invoice: @invoice, strength: strength)])
161
192
  scores = load
162
- push(scores)
163
- after = scores.map(&:value).max.to_i
164
- @log.debug("#{Thread.current.name}: best score is #{scores[0]}") if before != after && !after.zero?
165
- end
166
-
167
- def push(scores)
168
193
  free = scores.reject { |s| @threads.find { |t| t.name == s.to_mnemo } }
169
194
  @pipeline << free[0] if @pipeline.size.zero? && !free.empty?
195
+ after = scores.map(&:value).max.to_i
196
+ return unless before != after && !after.zero?
197
+ @log.debug("#{Thread.current.name}: best score of #{scores.count} is #{scores[0]}")
170
198
  end
171
199
 
172
200
  def cycle(host, port, strength, threads)
@@ -189,14 +217,14 @@ module Zold
189
217
  Thread.current.name = s.to_mnemo
190
218
  Thread.current.thread_variable_set(:start, Time.now.utc.iso8601)
191
219
  score = @farmer.up(s)
192
- @log.debug("New score discovered: #{score}")
220
+ @log.debug("New score discovered: #{score}") if strength > 4
193
221
  save(threads, [score])
194
222
  cleanup(host, port, strength, threads)
195
223
  end
196
224
 
197
225
  def save(threads, list = [])
198
226
  scores = load + list
199
- period = 24 * 60 * 60 / [threads, 1].max
227
+ period = @lifetime / [threads, 1].max
200
228
  Futex.new(@cache, log: @log).open do |f|
201
229
  IO.write(
202
230
  f,
@@ -216,20 +244,18 @@ module Zold
216
244
  def load
217
245
  Futex.new(@cache, log: @log).open do |f|
218
246
  if File.exist?(f)
219
- IO.read(f).split(/\n/)
220
- .map { |t| parse_score_line(t) }
221
- .reject(&:zero?)
247
+ IO.read(f).split(/\n/).map do |t|
248
+ begin
249
+ Score.parse(t)
250
+ rescue StandardError => e
251
+ @log.error(Backtrace.new(e).to_s)
252
+ nil
253
+ end
254
+ end.compact
222
255
  else
223
256
  []
224
257
  end
225
258
  end
226
259
  end
227
-
228
- def parse_score_line(line)
229
- Score.parse(line)
230
- rescue StandardError => e
231
- @log.error(Backtrace.new(e).to_s)
232
- Score::ZERO
233
- end
234
260
  end
235
261
  end
@@ -22,8 +22,8 @@
22
22
 
23
23
  require 'open3'
24
24
  require 'backtrace'
25
+ require 'zold/score'
25
26
  require_relative '../log'
26
- require_relative '../score'
27
27
  require_relative '../age'
28
28
 
29
29
  # Farmers.
@@ -38,6 +38,7 @@ require_relative '../wallet'
38
38
  require_relative '../age'
39
39
  require_relative '../copies'
40
40
  require_relative '../log'
41
+ require_relative '../tax'
41
42
  require_relative '../id'
42
43
  require_relative '../http'
43
44
 
@@ -298,6 +299,7 @@ in #{Age.new(@start, limit: 1)}")
298
299
  '--',
299
300
  "Balance: #{wallet.balance.to_zld(8)} ZLD (#{wallet.balance.to_i} zents)",
300
301
  "Transactions: #{wallet.txns.count}",
302
+ "Taxes: #{Tax.new(wallet).paid} paid, the debt is #{Tax.new(wallet).debt}",
301
303
  "File size: #{File.size(wallet.path)} bytes (#{Copies.new(File.join(settings.copies, id)).all.count} copies)",
302
304
  "Modified: #{wallet.mtime.utc.iso8601} (#{Age.new(wallet.mtime.utc.iso8601)} ago)",
303
305
  "Digest: #{wallet.digest}"
@@ -28,8 +28,8 @@ require 'time'
28
28
  require 'futex'
29
29
  require 'fileutils'
30
30
  require 'backtrace'
31
+ require 'zold/score'
31
32
  require_relative 'age'
32
- require_relative 'score'
33
33
  require_relative 'http'
34
34
  require_relative 'node/farm'
35
35
 
@@ -119,7 +119,7 @@ module Zold
119
119
  end
120
120
  end
121
121
 
122
- def initialize(file:, network: 'test', timeout: 16)
122
+ def initialize(file:, network: 'test', timeout: Http::READ_TIMEOUT + Http::CONNECT_TIMEOUT)
123
123
  @file = file
124
124
  @network = network
125
125
  @timeout = timeout
@@ -181,7 +181,6 @@ module Zold
181
181
  list = all
182
182
  return if list.empty?
183
183
  best = farm.best[0]
184
- require_relative 'score'
185
184
  score = best.nil? ? Score::ZERO : best
186
185
  idx = 0
187
186
  pool = Concurrent::FixedThreadPool.new([list.count, Concurrent.processor_count * 4].min, max_queue: 0)
@@ -202,7 +201,7 @@ module Zold
202
201
  raise 'Took too long to execute' if (Time.now - start).round > @timeout
203
202
  rescue StandardError => e
204
203
  error(r[:host], r[:port])
205
- log.info("#{Rainbow("#{r[:host]}:#{r[:port]}").red}: \"#{e.message}\" in #{Age.new(start)}")
204
+ log.info("#{Rainbow("#{r[:host]}:#{r[:port]}").red}: #{e.message} in #{Age.new(start)}")
206
205
  log.debug(Backtrace.new(e).to_s)
207
206
  remove(r[:host], r[:port]) if errors > Remotes::TOLERANCE
208
207
  end
@@ -25,6 +25,6 @@
25
25
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Zold
28
- VERSION = '0.16.9'
28
+ VERSION = '0.16.10'
29
29
  PROTOCOL = 2
30
30
  end
@@ -72,7 +72,7 @@ module Zold
72
72
  end
73
73
 
74
74
  def memo
75
- "#{id}/#{balance.to_zld(4)}/#{txns.count}t/#{digest[0, 6]}/Size.new(File.size(@file))}"
75
+ "#{id}/#{balance.to_zld(4)}/#{txns.count}t/#{digest[0, 6]}/#{Size.new(File.size(@file))}"
76
76
  end
77
77
 
78
78
  def to_text
@@ -25,6 +25,7 @@ require 'tmpdir'
25
25
  require 'json'
26
26
  require 'time'
27
27
  require 'webmock/minitest'
28
+ require 'zold/score'
28
29
  require_relative '../test__helper'
29
30
  require_relative '../fake_home'
30
31
  require_relative '../../lib/zold/wallet'
@@ -33,7 +34,6 @@ require_relative '../../lib/zold/remotes'
33
34
  require_relative '../../lib/zold/id'
34
35
  require_relative '../../lib/zold/copies'
35
36
  require_relative '../../lib/zold/key'
36
- require_relative '../../lib/zold/score'
37
37
  require_relative '../../lib/zold/commands/fetch'
38
38
 
39
39
  # FETCH test.
@@ -44,7 +44,7 @@ class TestFetch < Minitest::Test
44
44
  def test_fetches_wallet
45
45
  FakeHome.new(log: test_log).run do |home|
46
46
  wallet = home.create_wallet
47
- stub_request(:get, "http://localhost:80/wallet/#{wallet.id}").to_return(
47
+ stub_request(:get, "http://localhost:4096/wallet/#{wallet.id}").to_return(
48
48
  status: 200,
49
49
  body: {
50
50
  'score': Zold::Score::ZERO.to_h,
@@ -56,7 +56,7 @@ class TestFetch < Minitest::Test
56
56
  status: 404
57
57
  )
58
58
  remotes = home.remotes
59
- remotes.add('localhost', 80)
59
+ remotes.add('localhost', 4096)
60
60
  remotes.add('localhost', 81)
61
61
  copies = home.copies(wallet)
62
62
  begin
@@ -24,6 +24,7 @@ require 'minitest/autorun'
24
24
  require 'tmpdir'
25
25
  require 'time'
26
26
  require 'webmock/minitest'
27
+ require 'zold/score'
27
28
  require_relative '../test__helper'
28
29
  require_relative '../fake_home'
29
30
  require_relative '../../lib/zold/wallet'
@@ -31,7 +32,6 @@ require_relative '../../lib/zold/wallets'
31
32
  require_relative '../../lib/zold/id'
32
33
  require_relative '../../lib/zold/copies'
33
34
  require_relative '../../lib/zold/key'
34
- require_relative '../../lib/zold/score'
35
35
  require_relative '../../lib/zold/patch'
36
36
  require_relative '../../lib/zold/commands/merge'
37
37
  require_relative '../../lib/zold/commands/pay'
@@ -36,10 +36,10 @@ class TestPull < Minitest::Test
36
36
  def test_pull_wallet
37
37
  FakeHome.new(log: test_log).run do |home|
38
38
  remotes = home.remotes
39
- remotes.add('localhost', 80)
39
+ remotes.add('localhost', 4096)
40
40
  json = home.create_wallet_json
41
41
  id = Zold::JsonPage.new(json).to_hash['id']
42
- stub_request(:get, "http://localhost:80/wallet/#{id}").to_return(status: 200, body: json)
42
+ stub_request(:get, "http://localhost:4096/wallet/#{id}").to_return(status: 200, body: json)
43
43
  Zold::Pull.new(wallets: home.wallets, remotes: remotes, copies: home.copies.root.to_s, log: test_log).run(
44
44
  ['--ignore-this-stupid-option', 'pull', id.to_s]
45
45
  )
@@ -23,13 +23,13 @@
23
23
  require 'minitest/autorun'
24
24
  require 'tmpdir'
25
25
  require 'webmock/minitest'
26
+ require 'zold/score'
26
27
  require_relative '../test__helper'
27
28
  require_relative '../../lib/zold/version'
28
29
  require_relative '../../lib/zold/wallets'
29
30
  require_relative '../../lib/zold/remotes'
30
31
  require_relative '../../lib/zold/key'
31
32
  require_relative '../../lib/zold/log'
32
- require_relative '../../lib/zold/score'
33
33
  require_relative '../../lib/zold/commands/remote'
34
34
 
35
35
  # REMOTE test.
@@ -133,7 +133,7 @@ class TestRemote < Minitest::Test
133
133
  Dir.mktmpdir do |dir|
134
134
  remotes = Zold::Remotes.new(file: File.join(dir, 'remotes.txt'))
135
135
  score = Zold::Score.new(
136
- time: Time.now, host: 'aa1.example.org', port: 9999, invoice: 'NOPREFIX4@ffffffffffffffff'
136
+ host: 'aa1.example.org', port: 9999, invoice: 'NOPREFIX4@ffffffffffffffff'
137
137
  )
138
138
  stub_request(:get, 'http://localhost:8883/version').to_return(
139
139
  status: 200,
@@ -70,7 +70,7 @@ class TestTaxes < Minitest::Test
70
70
  )
71
71
  wallet.flush
72
72
  assert(tax.paid.positive?, tax.paid)
73
- assert_equal(before - debt, wallet.balance)
73
+ assert_equal((before - debt).to_zld(6), wallet.balance.to_zld(6))
74
74
  end
75
75
  end
76
76
  end
@@ -63,7 +63,7 @@ class FakeHome
63
63
  end
64
64
 
65
65
  def create_wallet_json(id = Zold::Id.new)
66
- require_relative '../lib/zold/score'
66
+ require 'zold/score'
67
67
  score = Zold::Score::ZERO
68
68
  Dir.mktmpdir 'wallets' do |external_dir|
69
69
  wallet = create_wallet(id, external_dir)
@@ -49,6 +49,16 @@ class FarmTest < Minitest::Test
49
49
  end
50
50
  end
51
51
 
52
+ def test_makes_many_scores
53
+ Dir.mktmpdir do |dir|
54
+ farm = Zold::Farm.new('NOPREFIX6@ffffffffffffffff', File.join(dir, 'f'),
55
+ log: test_log, lifetime: 10, farmer: Zold::Farmers::Plain.new)
56
+ farm.start('localhost', 80, threads: 4, strength: 1) do
57
+ assert_wait { farm.best.length == 4 }
58
+ end
59
+ end
60
+ end
61
+
52
62
  def test_makes_best_score_in_background
53
63
  Dir.mktmpdir do |dir|
54
64
  farm = Zold::Farm.new('NOPREFIX1@ffffffffffffffff', File.join(dir, 'f'), log: test_log)
@@ -76,10 +86,12 @@ class FarmTest < Minitest::Test
76
86
 
77
87
  def test_pre_loads_history
78
88
  Dir.mktmpdir do |dir|
79
- cache = File.join(dir, 'cache')
89
+ cache = File.join(dir, 'a/b/c/cache')
80
90
  farm = Zold::Farm.new('NOPREFIX3@cccccccccccccccc', cache, log: test_log)
81
91
  farm.start('example.com', 8080, threads: 0, strength: 1) do
82
92
  score = farm.best[0]
93
+ assert(!score.nil?, 'The list of best scores can\'t be empty!')
94
+ assert(File.exist?(cache), 'The cache file has to be created!')
83
95
  assert_equal(0, score.value)
84
96
  assert(!score.expired?)
85
97
  assert_equal('example.com', score.host)
@@ -22,8 +22,8 @@
22
22
 
23
23
  require 'minitest/autorun'
24
24
  require 'time'
25
+ require 'zold/score'
25
26
  require_relative '../test__helper'
26
- require_relative '../../lib/zold/score'
27
27
  require_relative '../../lib/zold/node/farmers'
28
28
 
29
29
  class FarmersTest < Minitest::Test
@@ -25,13 +25,13 @@ require 'json'
25
25
  require 'time'
26
26
  require 'securerandom'
27
27
  require 'threads'
28
+ require 'zold/score'
28
29
  require_relative '../test__helper'
29
30
  require_relative 'fake_node'
30
31
  require_relative '../fake_home'
31
32
  require_relative '../../lib/zold/http'
32
33
  require_relative '../../lib/zold/age'
33
34
  require_relative '../../lib/zold/json_page'
34
- require_relative '../../lib/zold/score'
35
35
 
36
36
  class FrontTest < Minitest::Test
37
37
  def app
@@ -96,7 +96,7 @@ class FrontTest < Minitest::Test
96
96
  def test_updates_list_of_remotes
97
97
  FakeNode.new(log: test_log).run(['--ignore-score-weakness']) do |port|
98
98
  score = Zold::Score.new(
99
- time: Time.now, host: 'localhost', port: port, invoice: 'NOPREFIX@ffffffffffffffff', strength: 1
99
+ host: 'localhost', port: port, invoice: 'NOPREFIX@ffffffffffffffff', strength: 1
100
100
  ).next.next.next.next
101
101
  response = Zold::Http.new(uri: "http://localhost:#{port}/remotes", score: score).get
102
102
  assert_equal('200', response.code, response.body)
@@ -207,7 +207,7 @@ class FrontTest < Minitest::Test
207
207
  '16' => 'https://www.zold.io/images/logo-green.png'
208
208
  }.each do |num, path|
209
209
  score = Zold::Score.new(
210
- time: Time.now, host: 'localhost', port: 999,
210
+ host: 'localhost', port: 999,
211
211
  invoice: 'NOPREFIX@ffffffffffffffff',
212
212
  strength: 1
213
213
  )
@@ -24,8 +24,8 @@ require 'minitest/autorun'
24
24
  require 'tmpdir'
25
25
  require 'uri'
26
26
  require 'webmock/minitest'
27
+ require 'zold/score'
27
28
  require_relative '../lib/zold/http'
28
- require_relative '../lib/zold/score'
29
29
 
30
30
  # Http test.
31
31
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -21,6 +21,7 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'minitest/autorun'
24
+ require 'zold/score'
24
25
  require 'time'
25
26
  require_relative 'test__helper'
26
27
  require_relative 'fake_home'
@@ -31,7 +32,6 @@ require_relative '../lib/zold/tax'
31
32
  require_relative '../lib/zold/key'
32
33
  require_relative '../lib/zold/amount'
33
34
  require_relative '../lib/zold/prefixes'
34
- require_relative '../lib/zold/score'
35
35
 
36
36
  # Tax test.
37
37
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -73,7 +73,7 @@ class TestTax < Minitest::Test
73
73
  )
74
74
  end
75
75
  score = Zold::Score.new(
76
- time: Time.now, host: 'localhost', port: 80, invoice: 'NOPREFIX@cccccccccccccccc',
76
+ host: 'localhost', port: 80, invoice: 'NOPREFIX@cccccccccccccccc',
77
77
  suffixes: %w[A B C D E F G H I J K L M N O P Q R S T U V]
78
78
  )
79
79
  tax = Zold::Tax.new(wallet)
@@ -126,7 +126,7 @@ class TestTax < Minitest::Test
126
126
  invoice = "#{Zold::Prefixes.new(target).create}@#{target.id}"
127
127
  tax = Zold::Tax.new(wallet)
128
128
  score = Zold::Score.new(
129
- time: Time.now, host: 'localhost', port: 80, invoice: invoice,
129
+ host: 'localhost', port: 80, invoice: invoice,
130
130
  suffixes: %w[A B C D E F G H I J K L M N O P Q R S T U V]
131
131
  )
132
132
  tax.pay(Zold::Key.new(file: 'fixtures/id_rsa'), score)
@@ -65,7 +65,7 @@ and suggests a different architecture for digital wallet maintenance.'
65
65
  s.add_runtime_dependency 'posix-spawn', '~>0.3'
66
66
  s.add_runtime_dependency 'rainbow', '~>3'
67
67
  s.add_runtime_dependency 'rake', '~>12' # has to stay here for Heroku
68
- s.add_runtime_dependency 'rubocop', '0.58.1' # has to stay here for Heroku
68
+ s.add_runtime_dependency 'rubocop', '0.60.0' # has to stay here for Heroku
69
69
  s.add_runtime_dependency 'rubocop-rspec', '~>1' # has to stay here for Heroku
70
70
  s.add_runtime_dependency 'semantic', '~>1'
71
71
  s.add_runtime_dependency 'sinatra', '~>2'
@@ -76,6 +76,7 @@ and suggests a different architecture for digital wallet maintenance.'
76
76
  s.add_runtime_dependency 'usagewatch_ext', '~>0'
77
77
  s.add_runtime_dependency 'xcop', '~>0'
78
78
  s.add_runtime_dependency 'zache', '~>0'
79
+ s.add_runtime_dependency 'zold-score', '~>0'
79
80
  s.add_development_dependency 'codecov', '~>0'
80
81
  s.add_development_dependency 'minitest', '~>5'
81
82
  s.add_development_dependency 'random-port', '~>0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zold
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.9
4
+ version: 0.16.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-02 00:00:00.000000000 Z
11
+ date: 2018-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -170,14 +170,14 @@ dependencies:
170
170
  requirements:
171
171
  - - '='
172
172
  - !ruby/object:Gem::Version
173
- version: 0.58.1
173
+ version: 0.60.0
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - '='
179
179
  - !ruby/object:Gem::Version
180
- version: 0.58.1
180
+ version: 0.60.0
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: rubocop-rspec
183
183
  requirement: !ruby/object:Gem::Requirement
@@ -318,6 +318,20 @@ dependencies:
318
318
  - - "~>"
319
319
  - !ruby/object:Gem::Version
320
320
  version: '0'
321
+ - !ruby/object:Gem::Dependency
322
+ name: zold-score
323
+ requirement: !ruby/object:Gem::Requirement
324
+ requirements:
325
+ - - "~>"
326
+ - !ruby/object:Gem::Version
327
+ version: '0'
328
+ type: :runtime
329
+ prerelease: false
330
+ version_requirements: !ruby/object:Gem::Requirement
331
+ requirements:
332
+ - - "~>"
333
+ - !ruby/object:Gem::Version
334
+ version: '0'
321
335
  - !ruby/object:Gem::Dependency
322
336
  name: codecov
323
337
  requirement: !ruby/object:Gem::Requirement
@@ -536,7 +550,6 @@ files:
536
550
  - lib/zold/patch.rb
537
551
  - lib/zold/prefixes.rb
538
552
  - lib/zold/remotes.rb
539
- - lib/zold/score.rb
540
553
  - lib/zold/signature.rb
541
554
  - lib/zold/size.rb
542
555
  - lib/zold/sync_wallets.rb
@@ -601,7 +614,6 @@ files:
601
614
  - test/test_patch.rb
602
615
  - test/test_prefixes.rb
603
616
  - test/test_remotes.rb
604
- - test/test_score.rb
605
617
  - test/test_signature.rb
606
618
  - test/test_size.rb
607
619
  - test/test_sync_wallets.rb
@@ -701,7 +713,6 @@ test_files:
701
713
  - test/test_patch.rb
702
714
  - test/test_prefixes.rb
703
715
  - test/test_remotes.rb
704
- - test/test_score.rb
705
716
  - test/test_signature.rb
706
717
  - test/test_size.rb
707
718
  - test/test_sync_wallets.rb
@@ -1,203 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright (c) 2018 Yegor Bugayenko
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the 'Software'), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in all
13
- # copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- # SOFTWARE.
22
-
23
- require 'openssl'
24
- require 'time'
25
-
26
- # The score.
27
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
28
- # Copyright:: Copyright (c) 2018 Yegor Bugayenko
29
- # License:: MIT
30
- module Zold
31
- # Score
32
- class Score
33
- # Default strength for the entire system, in production mode.
34
- STRENGTH = 6
35
-
36
- attr_reader :time, :host, :port, :invoice, :suffixes, :strength, :created
37
-
38
- def initialize(time: Time.now, host:, port:, invoice:, suffixes: [],
39
- strength: Score::STRENGTH, created: Time.now)
40
- @time = time
41
- @host = host
42
- @port = port
43
- @invoice = invoice
44
- @suffixes = suffixes
45
- @strength = strength
46
- @created = created
47
- end
48
-
49
- # The default no-value score.
50
- ZERO = Score.new(time: Time.now, host: 'localhost', port: 80, invoice: 'NOPREFIX@ffffffffffffffff')
51
-
52
- def self.parse_json(json)
53
- raise "Time in JSON is broken: #{json}" unless json['time'] =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/
54
- raise "Host is wrong: #{json}" unless json['host'] =~ /^[0-9a-z\.\-]+$/
55
- raise "Port is wrong: #{json}" unless json['port'].is_a?(Integer)
56
- raise "Invoice is wrong: #{json}" unless json['invoice'] =~ /^[a-zA-Z0-9]{8,32}@[a-f0-9]{16}$/
57
- raise "Suffixes not array: #{json}" unless json['suffixes'].is_a?(Array)
58
- Score.new(
59
- time: Time.parse(json['time']), host: json['host'],
60
- port: json['port'], invoice: json['invoice'], suffixes: json['suffixes'],
61
- strength: json['strength']
62
- )
63
- end
64
-
65
- def self.parse(text)
66
- re = Regexp.new(
67
- '^' + [
68
- '([0-9]+)/(?<strength>[0-9]+):',
69
- ' (?<time>[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z)',
70
- ' (?<host>[0-9a-z\.\-]+)',
71
- ' (?<port>[0-9]+)',
72
- ' (?<invoice>[a-zA-Z0-9]{8,32}@[a-f0-9]{16})',
73
- '(?<suffixes>( [a-zA-Z0-9]+)*)'
74
- ].join + '$'
75
- )
76
- m = re.match(text.strip)
77
- raise "Invalid score '#{text}', doesn't match: #{re}" if m.nil?
78
- Score.new(
79
- time: Time.parse(m[:time]), host: m[:host],
80
- port: m[:port].to_i, invoice: m[:invoice],
81
- suffixes: m[:suffixes].split(' '),
82
- strength: m[:strength].to_i
83
- )
84
- end
85
-
86
- def self.parse_text(text)
87
- parts = text.split(' ', 7)
88
- Score.new(
89
- time: Time.at(parts[1].hex),
90
- host: parts[2],
91
- port: parts[3].hex,
92
- invoice: "#{parts[4]}@#{parts[5]}",
93
- suffixes: parts[6] ? parts[6].split(' ') : [],
94
- strength: parts[0].to_i
95
- )
96
- end
97
-
98
- def hash
99
- raise 'Score has zero value, there is no hash' if @suffixes.empty?
100
- @suffixes.reduce(prefix) do |pfx, suffix|
101
- OpenSSL::Digest::SHA256.new("#{pfx} #{suffix}").hexdigest
102
- end
103
- end
104
-
105
- def to_mnemo
106
- "#{value}:#{@time.strftime('%H%M')}"
107
- end
108
-
109
- def to_text
110
- pfx, bnf = @invoice.split('@')
111
- [
112
- @strength,
113
- @time.to_i.to_s(16),
114
- @host,
115
- @port.to_s(16),
116
- pfx,
117
- bnf,
118
- @suffixes.join(' ')
119
- ].join(' ')
120
- end
121
-
122
- def to_s
123
- [
124
- "#{value}/#{@strength}:",
125
- @time.utc.iso8601,
126
- @host,
127
- @port,
128
- @invoice,
129
- @suffixes.join(' ')
130
- ].join(' ').strip
131
- end
132
-
133
- def to_h
134
- {
135
- value: value,
136
- host: @host,
137
- port: @port,
138
- invoice: @invoice,
139
- time: @time.utc.iso8601,
140
- suffixes: @suffixes,
141
- strength: @strength,
142
- hash: value.zero? ? nil : hash,
143
- expired: expired?,
144
- valid: valid?,
145
- age: (age / 60).round,
146
- created: @created.utc.iso8601
147
- }
148
- end
149
-
150
- def reduced(max = 4)
151
- Score.new(
152
- time: @time, host: @host, port: @port, invoice: @invoice,
153
- suffixes: @suffixes[0..[max, suffixes.count].min - 1],
154
- strength: @strength
155
- )
156
- end
157
-
158
- def next
159
- raise 'This score is not valid' unless valid?
160
- idx = 0
161
- loop do
162
- suffix = idx.to_s(16)
163
- score = Score.new(
164
- time: @time, host: @host, port: @port,
165
- invoice: @invoice, suffixes: @suffixes + [suffix],
166
- strength: @strength
167
- )
168
- return score if score.valid?
169
- if score.expired?
170
- return Score.new(
171
- time: Time.now, host: @host, port: @port, invoice: @invoice,
172
- suffixes: [], strength: @strength
173
- )
174
- end
175
- idx += 1
176
- end
177
- end
178
-
179
- def age
180
- Time.now - @time
181
- end
182
-
183
- def expired?(hours = 24)
184
- age > hours * 60 * 60
185
- end
186
-
187
- def prefix
188
- "#{@time.utc.iso8601} #{@host} #{@port} #{@invoice}"
189
- end
190
-
191
- def valid?
192
- @suffixes.empty? || hash.end_with?('0' * @strength)
193
- end
194
-
195
- def value
196
- @suffixes.length
197
- end
198
-
199
- def zero?
200
- equal?(Score::ZERO)
201
- end
202
- end
203
- end
@@ -1,161 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright (c) 2018 Yegor Bugayenko
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining a copy
6
- # of this software and associated documentation files (the 'Software'), to deal
7
- # in the Software without restriction, including without limitation the rights
8
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- # copies of the Software, and to permit persons to whom the Software is
10
- # furnished to do so, subject to the following conditions:
11
- #
12
- # The above copyright notice and this permission notice shall be included in all
13
- # copies or substantial portions of the Software.
14
- #
15
- # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
18
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- # SOFTWARE.
22
-
23
- require 'minitest/autorun'
24
- require 'tmpdir'
25
- require 'time'
26
- require_relative 'test__helper'
27
- require_relative '../lib/zold/score'
28
-
29
- # Score test.
30
- # Author:: Yegor Bugayenko (yegor256@gmail.com)
31
- # Copyright:: Copyright (c) 2018 Yegor Bugayenko
32
- # License:: MIT
33
- class TestScore < Minitest::Test
34
- def test_reduces_itself
35
- score = Zold::Score.new(
36
- time: Time.parse('2017-07-19T21:24:51Z'),
37
- host: 'localhost', port: 443, invoice: 'NOPREFIX@ffffffffffffffff',
38
- suffixes: %w[A B C D E F G]
39
- ).reduced(2)
40
- assert_equal(2, score.value)
41
- assert_equal(64, score.hash.length)
42
- end
43
-
44
- def test_drops_to_zero_when_expired
45
- score = Zold::Score.new(
46
- time: Time.now - 24 * 60 * 60,
47
- host: 'some-host', port: 9999, invoice: 'NOPREFIX@ffffffffffffffff',
48
- strength: 50
49
- ).next
50
- assert(score.valid?)
51
- assert(!score.expired?)
52
- assert_equal(0, score.value)
53
- end
54
-
55
- def test_validates_wrong_score
56
- score = Zold::Score.new(
57
- time: Time.parse('2017-07-19T21:24:51Z'),
58
- host: 'localhost', port: 443, invoice: 'NOPREFIX@ffffffffffffffff',
59
- suffixes: %w[xxx yyy zzz]
60
- )
61
- assert_equal(3, score.value)
62
- assert(!score.valid?)
63
- end
64
-
65
- def test_prints_mnemo
66
- score = Zold::Score.new(
67
- time: Time.parse('2017-07-19T22:32:51Z'),
68
- host: 'localhost', port: 443, invoice: 'NOPREFIX@ffffffffffffffff'
69
- )
70
- assert_equal('0:2232', score.to_mnemo)
71
- end
72
-
73
- def test_prints_and_parses
74
- time = Time.now
75
- score = Zold::Score.parse(
76
- Zold::Score.new(
77
- time: time, host: 'localhost', port: 999, invoice: 'NOPREFIX@ffffffffffffffff',
78
- strength: 1
79
- ).next.next.to_s
80
- )
81
- assert_equal(2, score.value)
82
- assert_equal(score.time.to_s, time.to_s)
83
- assert_equal('localhost', score.host)
84
- assert_equal(999, score.port)
85
- end
86
-
87
- def test_prints_and_parses_text
88
- time = Time.now
89
- score = Zold::Score.parse_text(
90
- Zold::Score.new(
91
- time: time, host: 'a.example.com', port: 999, invoice: 'NOPREFIX@ffffffffffffffff',
92
- strength: 1
93
- ).next.next.next.to_text
94
- )
95
- assert_equal(3, score.value)
96
- assert_equal(score.time.utc.to_s, time.utc.to_s)
97
- assert_equal('a.example.com', score.host)
98
- assert_equal(999, score.port)
99
- end
100
-
101
- def test_prints_and_parses_text_zero_score
102
- time = Time.now
103
- score = Zold::Score.parse_text(
104
- Zold::Score.new(
105
- time: time, host: '192.168.0.1', port: 1, invoice: 'NOPREFIX@ffffffffffffffff', suffixes: []
106
- ).to_text
107
- )
108
- assert_equal(0, score.value)
109
- assert(!score.expired?)
110
- end
111
-
112
- def test_prints_and_parses_zero_score
113
- time = Time.now
114
- score = Zold::Score.parse(
115
- Zold::Score.new(
116
- time: time, host: '192.168.0.1', port: 1, invoice: 'NOPREFIX@ffffffffffffffff', suffixes: []
117
- ).to_s
118
- )
119
- assert_equal(0, score.value)
120
- assert(!score.expired?)
121
- end
122
-
123
- def test_finds_next_score
124
- score = Zold::Score.new(
125
- time: Time.now, host: 'localhost', port: 443,
126
- invoice: 'NOPREFIX@ffffffffffffffff', strength: 2
127
- ).next.next.next
128
- assert_equal(3, score.value)
129
- assert(score.valid?)
130
- assert(!score.expired?)
131
- end
132
-
133
- def test_dont_expire_correctly
134
- score = Zold::Score.new(
135
- time: Time.now - 10 * 60 * 60, host: 'localhost', port: 443,
136
- invoice: 'NOPREFIX@ffffffffffffffff', strength: 2
137
- ).next.next.next
138
- assert(!score.expired?)
139
- end
140
-
141
- def test_correct_number_of_zeroes
142
- score = Zold::Score.new(
143
- time: Time.now, host: 'localhost', port: 443,
144
- invoice: 'NOPREFIX@ffffffffffffffff', strength: 3
145
- ).next
146
- assert(score.hash.end_with?('000'))
147
- end
148
-
149
- def test_generates_hash_correctly
150
- score = Zold::Score.new(
151
- time: Time.parse('2018-06-27T06:22:41Z'), host: 'b2.zold.io', port: 4096,
152
- invoice: 'THdonv1E@abcdabcdabcdabcd', suffixes: ['3a934b']
153
- )
154
- assert_equal('c9c72efbf6beeea13408c5e720ec42aec017c11c3db335e05595c03755000000', score.hash)
155
- score = Zold::Score.new(
156
- time: Time.parse('2018-06-27T06:22:41Z'), host: 'b2.zold.io', port: 4096,
157
- invoice: 'THdonv1E@abcdabcdabcdabcd', suffixes: %w[3a934b 1421217]
158
- )
159
- assert_equal('e04ab4e69f86aa17be1316a52148e7bc3187c6d3df581d885a862d8850000000', score.hash)
160
- end
161
- end