judges 0.22.1 → 0.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/actionlint.yml +1 -1
- data/.github/workflows/codecov.yml +2 -2
- data/.github/workflows/copyrights.yml +1 -1
- data/.github/workflows/markdown-lint.yml +1 -1
- data/.github/workflows/pdd.yml +1 -1
- data/.github/workflows/rake.yml +2 -2
- data/.github/workflows/xcop.yml +1 -1
- data/.github/workflows/yamllint.yml +1 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +34 -7
- data/assets/index.xsl +30 -28
- data/bin/judges +2 -2
- data/features/pull.feature +1 -1
- data/judges.gemspec +2 -1
- data/lib/judges/commands/pull.rb +2 -2
- data/lib/judges/commands/push.rb +2 -2
- data/lib/judges.rb +1 -1
- data/test/commands/test_print.rb +5 -1
- metadata +16 -4
- data/lib/judges/baza.rb +0 -327
- data/test/test_baza.rb +0 -175
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8e8b3c462c8c85767f611787af11de8c7966829c43866c31bab6626101e9762
|
4
|
+
data.tar.gz: 0c87fba4ce9a6f8c79149acecc07b3036804e2b51941fef4bf676ef1c2c79ef5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 217b87a1d9154652a255377e1a8919e1841895aa6d3b86c1f2e24eb66cda198a931ad3fb91062962234bea707c0af90ceaf7c1da6eccd6cbc4af37de33f67379
|
7
|
+
data.tar.gz: f0dfac8980ba3588b52f0aa38175bba961b7f786d1d567878e394e901b644edeef99446ebab1e41af8ce3e29d49ff4e7727c1e017b35fba6e05e821735cb20c2
|
@@ -25,12 +25,12 @@ name: codecov
|
|
25
25
|
- master
|
26
26
|
jobs:
|
27
27
|
codecov:
|
28
|
-
runs-on: ubuntu-
|
28
|
+
runs-on: ubuntu-24.04
|
29
29
|
steps:
|
30
30
|
- uses: actions/checkout@v4
|
31
31
|
- uses: ruby/setup-ruby@v1
|
32
32
|
with:
|
33
|
-
ruby-version: 3.
|
33
|
+
ruby-version: 3.3
|
34
34
|
bundler-cache: true
|
35
35
|
- run: bundle install
|
36
36
|
- run: bundle exec rake
|
data/.github/workflows/pdd.yml
CHANGED
data/.github/workflows/rake.yml
CHANGED
data/.github/workflows/xcop.yml
CHANGED
data/Gemfile
CHANGED
@@ -32,7 +32,7 @@ gem 'random-port', '~>0.0', require: false
|
|
32
32
|
gem 'rspec-rails', '6.1.3', require: false
|
33
33
|
gem 'rubocop', '1.65.1', require: false
|
34
34
|
gem 'rubocop-performance', '1.21.1', require: false
|
35
|
-
gem 'rubocop-rspec', '3.0.
|
35
|
+
gem 'rubocop-rspec', '3.0.4', require: false
|
36
36
|
gem 'simplecov', '0.22.0', require: false
|
37
37
|
gem 'simplecov-cobertura', '2.1.0', require: false
|
38
38
|
gem 'webmock', '3.23.1', require: false
|
data/Gemfile.lock
CHANGED
@@ -3,6 +3,7 @@ PATH
|
|
3
3
|
specs:
|
4
4
|
judges (0.0.0)
|
5
5
|
backtrace (~> 0)
|
6
|
+
baza.rb (~> 0)
|
6
7
|
concurrent-ruby (~> 1.2)
|
7
8
|
factbase (~> 0)
|
8
9
|
gli (~> 2.21)
|
@@ -50,6 +51,16 @@ GEM
|
|
50
51
|
ast (2.4.2)
|
51
52
|
backtrace (0.4.0)
|
52
53
|
base64 (0.2.0)
|
54
|
+
baza.rb (0.0.1)
|
55
|
+
backtrace (> 0)
|
56
|
+
faraday (> 0)
|
57
|
+
faraday-http-cache (> 0)
|
58
|
+
faraday-multipart (> 0)
|
59
|
+
faraday-retry (> 0)
|
60
|
+
iri (> 0)
|
61
|
+
loog (> 0)
|
62
|
+
retries (~> 0)
|
63
|
+
typhoeus (~> 1.3)
|
53
64
|
bigdecimal (3.1.8)
|
54
65
|
builder (3.3.0)
|
55
66
|
concurrent-ruby (1.3.3)
|
@@ -79,7 +90,7 @@ GEM
|
|
79
90
|
bigdecimal
|
80
91
|
cucumber-gherkin (27.0.0)
|
81
92
|
cucumber-messages (>= 19.1.4, < 23)
|
82
|
-
cucumber-html-formatter (21.
|
93
|
+
cucumber-html-formatter (21.6.0)
|
83
94
|
cucumber-messages (> 19, < 25)
|
84
95
|
cucumber-messages (22.0.0)
|
85
96
|
cucumber-tag-expressions (6.1.0)
|
@@ -90,7 +101,7 @@ GEM
|
|
90
101
|
erubi (1.13.0)
|
91
102
|
ethon (0.16.0)
|
92
103
|
ffi (>= 1.15.0)
|
93
|
-
factbase (0.
|
104
|
+
factbase (0.3.0)
|
94
105
|
backtrace (> 0)
|
95
106
|
decoor (> 0)
|
96
107
|
json (~> 2.7)
|
@@ -99,6 +110,17 @@ GEM
|
|
99
110
|
others (> 0)
|
100
111
|
tago (> 0)
|
101
112
|
yaml (~> 0.3)
|
113
|
+
faraday (2.10.1)
|
114
|
+
faraday-net_http (>= 2.0, < 3.2)
|
115
|
+
logger
|
116
|
+
faraday-http-cache (2.5.1)
|
117
|
+
faraday (>= 0.8)
|
118
|
+
faraday-multipart (1.0.4)
|
119
|
+
multipart-post (~> 2)
|
120
|
+
faraday-net_http (3.1.1)
|
121
|
+
net-http
|
122
|
+
faraday-retry (2.2.1)
|
123
|
+
faraday (~> 2.0)
|
102
124
|
ffi (1.17.0-aarch64-linux-gnu)
|
103
125
|
ffi (1.17.0-arm-linux-gnu)
|
104
126
|
ffi (1.17.0-arm64-darwin)
|
@@ -117,6 +139,7 @@ GEM
|
|
117
139
|
iri (0.8.0)
|
118
140
|
json (2.7.2)
|
119
141
|
language_server-protocol (3.17.0.3)
|
142
|
+
logger (1.6.0)
|
120
143
|
loofah (2.22.0)
|
121
144
|
crass (~> 1.0.2)
|
122
145
|
nokogiri (>= 1.12.0)
|
@@ -130,7 +153,10 @@ GEM
|
|
130
153
|
ruby-progressbar
|
131
154
|
moments (0.3.0)
|
132
155
|
multi_test (1.1.0)
|
156
|
+
multipart-post (2.4.1)
|
133
157
|
mutex_m (0.2.0)
|
158
|
+
net-http (0.4.1)
|
159
|
+
uri
|
134
160
|
net-ping (2.0.8)
|
135
161
|
nokogiri (1.16.7-aarch64-linux)
|
136
162
|
racc (~> 1.4)
|
@@ -147,8 +173,8 @@ GEM
|
|
147
173
|
nokogiri (1.16.7-x86_64-linux)
|
148
174
|
racc (~> 1.4)
|
149
175
|
others (0.0.3)
|
150
|
-
parallel (1.
|
151
|
-
parser (3.3.4.
|
176
|
+
parallel (1.26.1)
|
177
|
+
parser (3.3.4.2)
|
152
178
|
ast (~> 2.4.1)
|
153
179
|
racc
|
154
180
|
psych (5.1.2)
|
@@ -217,12 +243,12 @@ GEM
|
|
217
243
|
rubocop-ast (>= 1.31.1, < 2.0)
|
218
244
|
ruby-progressbar (~> 1.7)
|
219
245
|
unicode-display_width (>= 2.4.0, < 3.0)
|
220
|
-
rubocop-ast (1.
|
246
|
+
rubocop-ast (1.32.0)
|
221
247
|
parser (>= 3.3.1.0)
|
222
248
|
rubocop-performance (1.21.1)
|
223
249
|
rubocop (>= 1.48.1, < 2.0)
|
224
250
|
rubocop-ast (>= 1.31.1, < 2.0)
|
225
|
-
rubocop-rspec (3.0.
|
251
|
+
rubocop-rspec (3.0.4)
|
226
252
|
rubocop (~> 1.61)
|
227
253
|
ruby-progressbar (1.13.0)
|
228
254
|
simplecov (0.22.0)
|
@@ -245,6 +271,7 @@ GEM
|
|
245
271
|
tzinfo (2.0.6)
|
246
272
|
concurrent-ruby (~> 1.0)
|
247
273
|
unicode-display_width (2.5.0)
|
274
|
+
uri (0.13.0)
|
248
275
|
webmock (3.23.1)
|
249
276
|
addressable (>= 2.8.0)
|
250
277
|
crack (>= 0.3.2)
|
@@ -274,7 +301,7 @@ DEPENDENCIES
|
|
274
301
|
rspec-rails (= 6.1.3)
|
275
302
|
rubocop (= 1.65.1)
|
276
303
|
rubocop-performance (= 1.21.1)
|
277
|
-
rubocop-rspec (= 3.0.
|
304
|
+
rubocop-rspec (= 3.0.4)
|
278
305
|
simplecov (= 0.22.0)
|
279
306
|
simplecov-cobertura (= 2.1.0)
|
280
307
|
webmock (= 3.23.1)
|
data/assets/index.xsl
CHANGED
@@ -22,7 +22,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
22
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
23
|
SOFTWARE.
|
24
24
|
-->
|
25
|
-
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="
|
25
|
+
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
26
26
|
<xsl:output method="xml" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes"/>
|
27
27
|
<xsl:param name="title"/>
|
28
28
|
<xsl:param name="date"/>
|
@@ -65,13 +65,15 @@ SOFTWARE.
|
|
65
65
|
section { width: 100%; }
|
66
66
|
article { border: none; }
|
67
67
|
header img { width: 3em; height: 3em; }
|
68
|
+
table { table-layout: fixed; }
|
69
|
+
td { word-wrap: break-word; }
|
68
70
|
.sorter { cursor: pointer; }
|
69
|
-
.S { color: #
|
71
|
+
.S { color: #4A5240; }
|
70
72
|
.T { color: #2471A3; }
|
71
|
-
.I { color: #
|
72
|
-
.F { color: #
|
73
|
-
.BR { color:
|
74
|
-
.hidden { color:
|
73
|
+
.I { color: #61304B; }
|
74
|
+
.F { color: #5C0029; }
|
75
|
+
.BR { color: #B6C649; }
|
76
|
+
.hidden { color: #C1C1C1; }
|
75
77
|
</style>
|
76
78
|
<script type="text/javascript">
|
77
79
|
$(function() {
|
@@ -131,6 +133,11 @@ SOFTWARE.
|
|
131
133
|
</xsl:template>
|
132
134
|
<xsl:template match="fb">
|
133
135
|
<table id="facts">
|
136
|
+
<colgroup>
|
137
|
+
<xsl:call-template name="col">
|
138
|
+
<xsl:with-param name="cols" select="$columns"/>
|
139
|
+
</xsl:call-template>
|
140
|
+
</colgroup>
|
134
141
|
<thead>
|
135
142
|
<tr>
|
136
143
|
<xsl:call-template name="th">
|
@@ -151,6 +158,20 @@ SOFTWARE.
|
|
151
158
|
</xsl:call-template>
|
152
159
|
</tr>
|
153
160
|
</xsl:template>
|
161
|
+
<xsl:template name="col">
|
162
|
+
<xsl:param name="cols"/>
|
163
|
+
<xsl:choose>
|
164
|
+
<xsl:when test="string-length($cols) > 0">
|
165
|
+
<col style="width: 10em;"/>
|
166
|
+
<xsl:call-template name="col">
|
167
|
+
<xsl:with-param name="cols" select="substring-after($cols, ',')"/>
|
168
|
+
</xsl:call-template>
|
169
|
+
</xsl:when>
|
170
|
+
<xsl:otherwise>
|
171
|
+
<col style=""/>
|
172
|
+
</xsl:otherwise>
|
173
|
+
</xsl:choose>
|
174
|
+
</xsl:template>
|
154
175
|
<xsl:template name="th">
|
155
176
|
<xsl:param name="cols"/>
|
156
177
|
<xsl:choose>
|
@@ -190,7 +211,7 @@ SOFTWARE.
|
|
190
211
|
<xsl:for-each select="$f/*">
|
191
212
|
<xsl:text> </xsl:text>
|
192
213
|
<xsl:variable name="visible" select="string-length(substring-before(concat(' ,', $hidden, ','), concat(',', name(), ','))) = 0"/>
|
193
|
-
<xsl:if test="string-length(substring-before(concat(',', $columns, ','), concat(',', name(), ','))) = 0">
|
214
|
+
<xsl:if test="string-length(substring-before(concat(' ,', $columns, ','), concat(',', name(), ','))) = 0">
|
194
215
|
<xsl:choose>
|
195
216
|
<xsl:when test="$visible">
|
196
217
|
<xsl:value-of select="name()"/>
|
@@ -233,28 +254,9 @@ SOFTWARE.
|
|
233
254
|
<xsl:attribute name="class">
|
234
255
|
<xsl:value-of select="$v/@t"/>
|
235
256
|
</xsl:attribute>
|
236
|
-
<xsl:
|
237
|
-
<xsl:with-param name="v" select="$v"/>
|
238
|
-
</xsl:call-template>
|
239
|
-
</span>
|
240
|
-
</xsl:otherwise>
|
241
|
-
</xsl:choose>
|
242
|
-
</xsl:template>
|
243
|
-
<xsl:template name="just-value">
|
244
|
-
<xsl:param name="v"/>
|
245
|
-
<xsl:choose>
|
246
|
-
<xsl:when test="string-length($v) > 64">
|
247
|
-
<xsl:value-of select="substring($v, 0, 64)"/>
|
248
|
-
<span class="BR">
|
249
|
-
<xsl:text>-</xsl:text>
|
257
|
+
<xsl:value-of select="$v"/>
|
250
258
|
</span>
|
251
|
-
<xsl:call-template name="just-value">
|
252
|
-
<xsl:with-param name="v" select="substring($v, 64)"/>
|
253
|
-
</xsl:call-template>
|
254
|
-
</xsl:when>
|
255
|
-
<xsl:otherwise>
|
256
|
-
<xsl:value-of select="$v"/>
|
257
259
|
</xsl:otherwise>
|
258
260
|
</xsl:choose>
|
259
261
|
</xsl:template>
|
260
|
-
</xsl:stylesheet>
|
262
|
+
</xsl:stylesheet>
|
data/bin/judges
CHANGED
@@ -155,7 +155,7 @@ class JudgesGLI extend GLI::App
|
|
155
155
|
c.desc 'Authentication token'
|
156
156
|
c.flag([:token])
|
157
157
|
c.desc 'The IP/hostname of the server'
|
158
|
-
c.flag([:host], default_value: '
|
158
|
+
c.flag([:host], default_value: 'api.zerocracy.com')
|
159
159
|
c.desc 'The TCP port number of the server'
|
160
160
|
c.flag([:port], default_value: 443, type: Integer)
|
161
161
|
c.desc 'Connection and read time in seconds'
|
@@ -180,7 +180,7 @@ class JudgesGLI extend GLI::App
|
|
180
180
|
c.desc 'How many seconds to wait'
|
181
181
|
c.flag([:wait], default_value: 10 * 60, arg_name: '<seconds>', type: Integer)
|
182
182
|
c.desc 'The IP/hostname of the server'
|
183
|
-
c.flag([:host], default_value: '
|
183
|
+
c.flag([:host], default_value: 'api.zerocracy.com')
|
184
184
|
c.desc 'The TCP port number of the server'
|
185
185
|
c.flag([:port], default_value: 443, type: Integer)
|
186
186
|
c.desc 'Connection and read time in seconds'
|
data/features/pull.feature
CHANGED
@@ -5,6 +5,6 @@ Feature: Pull
|
|
5
5
|
Given We are online
|
6
6
|
Given I make a temp directory
|
7
7
|
Then I run bin/judges with "--verbose pull --token 00000000-0000-0000-0000-000000000000 --wait=15 {FAKE-NAME} simple.fb"
|
8
|
-
Then Stdout contains "doesn't exist at
|
8
|
+
Then Stdout contains "doesn't exist at api.zerocracy.com"
|
9
9
|
And Exit code is zero
|
10
10
|
|
data/judges.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
27
27
|
s.required_ruby_version = '>=3.2'
|
28
28
|
s.name = 'judges'
|
29
|
-
s.version = '0.
|
29
|
+
s.version = '0.23.0'
|
30
30
|
s.license = 'MIT'
|
31
31
|
s.summary = 'Command-Line Tool for a Factbase'
|
32
32
|
s.description =
|
@@ -43,6 +43,7 @@ Gem::Specification.new do |s|
|
|
43
43
|
s.rdoc_options = ['--charset=UTF-8']
|
44
44
|
s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
|
45
45
|
s.add_dependency 'backtrace', '~>0'
|
46
|
+
s.add_dependency 'baza.rb', '~>0'
|
46
47
|
s.add_dependency 'concurrent-ruby', '~>1.2'
|
47
48
|
s.add_dependency 'factbase', '~>0'
|
48
49
|
s.add_dependency 'gli', '~>2.21'
|
data/lib/judges/commands/pull.rb
CHANGED
@@ -22,9 +22,9 @@
|
|
22
22
|
|
23
23
|
require 'typhoeus'
|
24
24
|
require 'iri'
|
25
|
+
require 'baza'
|
25
26
|
require_relative '../../judges'
|
26
27
|
require_relative '../../judges/impex'
|
27
|
-
require_relative '../../judges/baza'
|
28
28
|
|
29
29
|
# The +pull+ command.
|
30
30
|
#
|
@@ -42,7 +42,7 @@ class Judges::Pull
|
|
42
42
|
def run(opts, args)
|
43
43
|
raise 'Exactly two arguments required' unless args.size == 2
|
44
44
|
fb = Factbase.new
|
45
|
-
baza =
|
45
|
+
baza = Baza.new(
|
46
46
|
opts['host'], opts['port'].to_i, opts['token'],
|
47
47
|
ssl: opts['ssl'],
|
48
48
|
timeout: (opts['timeout'] || 30).to_i,
|
data/lib/judges/commands/push.rb
CHANGED
@@ -22,9 +22,9 @@
|
|
22
22
|
|
23
23
|
require 'typhoeus'
|
24
24
|
require 'iri'
|
25
|
+
require 'baza'
|
25
26
|
require_relative '../../judges'
|
26
27
|
require_relative '../../judges/impex'
|
27
|
-
require_relative '../../judges/baza'
|
28
28
|
|
29
29
|
# The +push+ command.
|
30
30
|
#
|
@@ -43,7 +43,7 @@ class Judges::Push
|
|
43
43
|
raise 'Exactly two arguments required' unless args.size == 2
|
44
44
|
name = args[0]
|
45
45
|
fb = Judges::Impex.new(@loog, args[1]).import
|
46
|
-
baza =
|
46
|
+
baza = Baza.new(
|
47
47
|
opts['host'], opts['port'].to_i, opts['token'],
|
48
48
|
ssl: opts['ssl'],
|
49
49
|
timeout: (opts['timeout'] || 30).to_i,
|
data/lib/judges.rb
CHANGED
data/test/commands/test_print.rb
CHANGED
@@ -24,6 +24,7 @@ require 'minitest/autorun'
|
|
24
24
|
require 'loog'
|
25
25
|
require 'factbase'
|
26
26
|
require 'yaml'
|
27
|
+
require 'fileutils'
|
27
28
|
require 'securerandom'
|
28
29
|
require_relative '../../lib/judges'
|
29
30
|
require_relative '../../lib/judges/commands/print'
|
@@ -56,14 +57,17 @@ class TestPrint < Minitest::Test
|
|
56
57
|
f.details = 'hey, друг'
|
57
58
|
f.ticket = 42
|
58
59
|
f.ticket = 55
|
60
|
+
f.pi = 3.1416
|
59
61
|
f.long_property = 'test_' * 100
|
60
62
|
end
|
63
|
+
html = File.join(__dir__, '../../temp/base.html')
|
64
|
+
FileUtils.rm_f(html)
|
61
65
|
Dir.mktmpdir do |d|
|
62
66
|
f = File.join(d, 'base.fb')
|
63
67
|
File.binwrite(f, fb.export)
|
64
68
|
Judges::Print.new(Loog::NULL).run(
|
65
69
|
{ 'format' => 'html', 'columns' => 'what,when,ticket' },
|
66
|
-
[f,
|
70
|
+
[f, html]
|
67
71
|
)
|
68
72
|
end
|
69
73
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: judges
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.23.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-08-
|
11
|
+
date: 2024-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backtrace
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: baza.rb
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: concurrent-ruby
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -231,7 +245,6 @@ files:
|
|
231
245
|
- fixtures/try/try.rb
|
232
246
|
- judges.gemspec
|
233
247
|
- lib/judges.rb
|
234
|
-
- lib/judges/baza.rb
|
235
248
|
- lib/judges/categories.rb
|
236
249
|
- lib/judges/churn.rb
|
237
250
|
- lib/judges/commands/eval.rb
|
@@ -262,7 +275,6 @@ files:
|
|
262
275
|
- test/commands/test_trim.rb
|
263
276
|
- test/commands/test_update.rb
|
264
277
|
- test/test__helper.rb
|
265
|
-
- test/test_baza.rb
|
266
278
|
- test/test_bin.rb
|
267
279
|
- test/test_categories.rb
|
268
280
|
- test/test_churn.rb
|
data/lib/judges/baza.rb
DELETED
@@ -1,327 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright (c) 2024 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 NONINFRINGEMENT. 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 'typhoeus'
|
24
|
-
require 'retries'
|
25
|
-
require 'iri'
|
26
|
-
require 'loog'
|
27
|
-
require 'base64'
|
28
|
-
require_relative '../judges'
|
29
|
-
require_relative '../judges/elapsed'
|
30
|
-
|
31
|
-
# Interface to the API of zerocracy.com.
|
32
|
-
#
|
33
|
-
# You make an instance of this class and then call one of its methods.
|
34
|
-
# The object will make HTTP request to www.zerocracy.com and interpret the
|
35
|
-
# results returned.
|
36
|
-
#
|
37
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
38
|
-
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
39
|
-
# License:: MIT
|
40
|
-
class Judges::Baza
|
41
|
-
def initialize(host, port, token, ssl: true, timeout: 30, retries: 3, loog: Loog::NULL, compression: true)
|
42
|
-
@host = host
|
43
|
-
@port = port
|
44
|
-
@ssl = ssl
|
45
|
-
@token = token
|
46
|
-
@timeout = timeout
|
47
|
-
@loog = loog
|
48
|
-
@retries = retries
|
49
|
-
@compression = compression
|
50
|
-
end
|
51
|
-
|
52
|
-
# Push factbase to the server.
|
53
|
-
# @param [String] name The name of the job on the server
|
54
|
-
# @param [Bytes] data The data to push to the server (binary)
|
55
|
-
# @param [Array<String>] meta List of metas, possibly empty
|
56
|
-
# @return [Integer] Job ID on the server
|
57
|
-
def push(name, data, meta)
|
58
|
-
id = 0
|
59
|
-
hdrs = headers.merge(
|
60
|
-
'Content-Type' => 'application/octet-stream',
|
61
|
-
'Content-Length' => data.size
|
62
|
-
)
|
63
|
-
unless meta.empty?
|
64
|
-
hdrs = hdrs.merge('X-Zerocracy-Meta' => meta.map { |v| Base64.encode64(v).gsub("\n", '') }.join(' '))
|
65
|
-
end
|
66
|
-
params = {
|
67
|
-
connecttimeout: @timeout,
|
68
|
-
timeout: @timeout,
|
69
|
-
body: data,
|
70
|
-
headers: hdrs
|
71
|
-
}
|
72
|
-
elapsed(@loog) do
|
73
|
-
ret =
|
74
|
-
with_retries(max_tries: @retries) do
|
75
|
-
checked(
|
76
|
-
Typhoeus::Request.put(
|
77
|
-
home.append('push').append(name).to_s,
|
78
|
-
@compression ? zipped(params) : params
|
79
|
-
)
|
80
|
-
)
|
81
|
-
end
|
82
|
-
id = ret.body.to_i
|
83
|
-
throw :"Pushed #{data.size} bytes to #{@host}, job ID is ##{id}"
|
84
|
-
end
|
85
|
-
id
|
86
|
-
end
|
87
|
-
|
88
|
-
# Pull factbase from the server.
|
89
|
-
# @param [Integer] id The ID of the job on the server
|
90
|
-
# @return [Bytes] Binary data pulled
|
91
|
-
def pull(id)
|
92
|
-
data = 0
|
93
|
-
elapsed(@loog) do
|
94
|
-
Tempfile.open do |file|
|
95
|
-
File.open(file, 'wb') do |f|
|
96
|
-
request = Typhoeus::Request.new(
|
97
|
-
home.append('pull').append("#{id}.fb").to_s,
|
98
|
-
headers: headers.merge(
|
99
|
-
'Accept' => 'application/octet-stream'
|
100
|
-
),
|
101
|
-
connecttimeout: @timeout,
|
102
|
-
timeout: @timeout
|
103
|
-
)
|
104
|
-
request.on_body do |chunk|
|
105
|
-
f.write(chunk)
|
106
|
-
end
|
107
|
-
with_retries(max_tries: @retries) do
|
108
|
-
request.run
|
109
|
-
end
|
110
|
-
checked(request.response)
|
111
|
-
end
|
112
|
-
data = File.binread(file)
|
113
|
-
throw :"Pulled #{data.size} bytes of job ##{id} factbase at #{@host}"
|
114
|
-
end
|
115
|
-
end
|
116
|
-
data
|
117
|
-
end
|
118
|
-
|
119
|
-
# The job with this ID is finished already?
|
120
|
-
# @param [Integer] id The ID of the job on the server
|
121
|
-
# @return [Boolean] TRUE if the job is already finished
|
122
|
-
def finished?(id)
|
123
|
-
finished = false
|
124
|
-
elapsed(@loog) do
|
125
|
-
ret =
|
126
|
-
with_retries(max_tries: @retries) do
|
127
|
-
checked(
|
128
|
-
Typhoeus::Request.get(
|
129
|
-
home.append('finished').append(id).to_s,
|
130
|
-
headers:
|
131
|
-
)
|
132
|
-
)
|
133
|
-
end
|
134
|
-
finished = ret.body == 'yes'
|
135
|
-
throw :"The job ##{id} is #{finished ? '' : 'not yet '}finished at #{@host}"
|
136
|
-
end
|
137
|
-
finished
|
138
|
-
end
|
139
|
-
|
140
|
-
# Read and return the stdout of the job.
|
141
|
-
# @param [Integer] id The ID of the job on the server
|
142
|
-
# @return [String] The stdout, as a text
|
143
|
-
def stdout(id)
|
144
|
-
stdout = ''
|
145
|
-
elapsed(@loog) do
|
146
|
-
ret =
|
147
|
-
with_retries(max_tries: @retries) do
|
148
|
-
checked(
|
149
|
-
Typhoeus::Request.get(
|
150
|
-
home.append('stdout').append("#{id}.txt").to_s,
|
151
|
-
headers:
|
152
|
-
)
|
153
|
-
)
|
154
|
-
end
|
155
|
-
stdout = ret.body
|
156
|
-
throw :"The stdout of the job ##{id} has #{stdout.split("\n")} lines"
|
157
|
-
end
|
158
|
-
stdout
|
159
|
-
end
|
160
|
-
|
161
|
-
# Read and return the exit code of the job.
|
162
|
-
# @param [Integer] id The ID of the job on the server
|
163
|
-
# @return [Integer] The exit code
|
164
|
-
def exit_code(id)
|
165
|
-
code = 0
|
166
|
-
elapsed(@loog) do
|
167
|
-
ret =
|
168
|
-
with_retries(max_tries: @retries) do
|
169
|
-
checked(
|
170
|
-
Typhoeus::Request.get(
|
171
|
-
home.append('exit').append("#{id}.txt").to_s,
|
172
|
-
headers:
|
173
|
-
)
|
174
|
-
)
|
175
|
-
end
|
176
|
-
code = ret.body.to_i
|
177
|
-
throw :"The exit code of the job ##{id} is #{code}"
|
178
|
-
end
|
179
|
-
code
|
180
|
-
end
|
181
|
-
|
182
|
-
# Lock the name.
|
183
|
-
# @param [String] name The name of the job on the server
|
184
|
-
# @param [String] owner The owner of the lock (any string)
|
185
|
-
def lock(name, owner)
|
186
|
-
elapsed(@loog) do
|
187
|
-
with_retries(max_tries: @retries) do
|
188
|
-
checked(
|
189
|
-
Typhoeus::Request.get(
|
190
|
-
home.append('lock').append(name).add(owner:).to_s,
|
191
|
-
headers:
|
192
|
-
),
|
193
|
-
302
|
194
|
-
)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
# Unlock the name.
|
200
|
-
# @param [String] name The name of the job on the server
|
201
|
-
# @param [String] owner The owner of the lock (any string)
|
202
|
-
def unlock(name, owner)
|
203
|
-
elapsed(@loog) do
|
204
|
-
with_retries(max_tries: @retries) do
|
205
|
-
checked(
|
206
|
-
Typhoeus::Request.get(
|
207
|
-
home.append('unlock').append(name).add(owner:).to_s,
|
208
|
-
headers:
|
209
|
-
),
|
210
|
-
302
|
211
|
-
)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
# Get the ID of the job by the name.
|
217
|
-
# @param [String] name The name of the job on the server
|
218
|
-
# @return [Integer] The ID of the job on the server
|
219
|
-
def recent(name)
|
220
|
-
job = 0
|
221
|
-
elapsed(@loog) do
|
222
|
-
ret =
|
223
|
-
with_retries(max_tries: @retries) do
|
224
|
-
checked(
|
225
|
-
Typhoeus::Request.get(
|
226
|
-
home.append('recent').append("#{name}.txt").to_s,
|
227
|
-
headers:
|
228
|
-
)
|
229
|
-
)
|
230
|
-
end
|
231
|
-
job = ret.body.to_i
|
232
|
-
throw :"The recent \"#{name}\" job's ID is ##{job} at #{@host}"
|
233
|
-
end
|
234
|
-
job
|
235
|
-
end
|
236
|
-
|
237
|
-
# Check whether the name of the job exists on the server.
|
238
|
-
# @param [String] name The name of the job on the server
|
239
|
-
# @return [Boolean] TRUE if such name exists
|
240
|
-
def name_exists?(name)
|
241
|
-
exists = 0
|
242
|
-
elapsed(@loog) do
|
243
|
-
ret =
|
244
|
-
with_retries(max_tries: @retries) do
|
245
|
-
checked(
|
246
|
-
Typhoeus::Request.get(
|
247
|
-
home.append('exists').append(name).to_s,
|
248
|
-
headers:
|
249
|
-
)
|
250
|
-
)
|
251
|
-
end
|
252
|
-
exists = ret.body == 'yes'
|
253
|
-
throw :"The name \"#{name}\" #{exists ? 'exists' : "doesn't exist"} at #{@host}"
|
254
|
-
end
|
255
|
-
exists
|
256
|
-
end
|
257
|
-
|
258
|
-
private
|
259
|
-
|
260
|
-
def headers
|
261
|
-
{
|
262
|
-
'User-Agent' => "judges #{Judges::VERSION}",
|
263
|
-
'Connection' => 'close',
|
264
|
-
'X-Zerocracy-Token' => @token
|
265
|
-
}
|
266
|
-
end
|
267
|
-
|
268
|
-
def zipped(params)
|
269
|
-
body = gzip(params.fetch(:body))
|
270
|
-
headers = params
|
271
|
-
.fetch(:headers)
|
272
|
-
.merge({
|
273
|
-
'Content-Type' => 'application/zip',
|
274
|
-
'Content-Encoding' => 'gzip',
|
275
|
-
'Content-Length' => body.size
|
276
|
-
})
|
277
|
-
params.merge(body:, headers:)
|
278
|
-
end
|
279
|
-
|
280
|
-
def gzip(data)
|
281
|
-
''.dup.tap do |result|
|
282
|
-
io = StringIO.new(result)
|
283
|
-
gz = Zlib::GzipWriter.new(io)
|
284
|
-
gz.write(data)
|
285
|
-
gz.close
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
def home
|
290
|
-
Iri.new('')
|
291
|
-
.host(@host)
|
292
|
-
.port(@port)
|
293
|
-
.scheme(@ssl ? 'https' : 'http')
|
294
|
-
end
|
295
|
-
|
296
|
-
def checked(ret, allowed = [200])
|
297
|
-
allowed = [allowed] unless allowed.is_a?(Array)
|
298
|
-
mtd = (ret.request.original_options[:method] || '???').upcase
|
299
|
-
url = ret.effective_url
|
300
|
-
log = "#{mtd} #{url} -> #{ret.code}"
|
301
|
-
if allowed.include?(ret.code)
|
302
|
-
@loog.debug(log)
|
303
|
-
return ret
|
304
|
-
end
|
305
|
-
@loog.debug("#{log}\n #{(ret.headers || {}).map { |k, v| "#{k}: #{v}" }.join("\n ")}")
|
306
|
-
msg =
|
307
|
-
"Invalid response code ##{ret.code} " \
|
308
|
-
"at #{mtd} #{url} (#{ret.headers['X-Zerocracy-Flash'].inspect})"
|
309
|
-
case ret.code
|
310
|
-
when 500
|
311
|
-
msg +=
|
312
|
-
', most probably it\'s an internal error on the server, ' \
|
313
|
-
'please report this to https://github.com/zerocracy/baza'
|
314
|
-
when 503
|
315
|
-
msg +=
|
316
|
-
", most probably it's an internal error on the server (#{ret.headers['X-Zerocracy-Failure'].inspect}), " \
|
317
|
-
'please report this to https://github.com/yegor256/judges'
|
318
|
-
when 404
|
319
|
-
msg +=
|
320
|
-
', most probably you are trying to reach a wrong server, which doesn\'t ' \
|
321
|
-
'have the URL that it is expected to have'
|
322
|
-
when 0
|
323
|
-
msg += ', most likely an internal error'
|
324
|
-
end
|
325
|
-
raise msg
|
326
|
-
end
|
327
|
-
end
|
data/test/test_baza.rb
DELETED
@@ -1,175 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright (c) 2024 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 NONINFRINGEMENT. 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 'webmock/minitest'
|
25
|
-
require 'webrick'
|
26
|
-
require 'loog'
|
27
|
-
require 'socket'
|
28
|
-
require 'stringio'
|
29
|
-
require 'random-port'
|
30
|
-
require_relative '../lib/judges'
|
31
|
-
require_relative '../lib/judges/baza'
|
32
|
-
|
33
|
-
# Test.
|
34
|
-
# Author:: Yegor Bugayenko (yegor256@gmail.com)
|
35
|
-
# Copyright:: Copyright (c) 2024 Yegor Bugayenko
|
36
|
-
# License:: MIT
|
37
|
-
class TestBaza < Minitest::Test
|
38
|
-
def test_simple_push
|
39
|
-
WebMock.disable_net_connect!
|
40
|
-
stub_request(:put, 'https://example.org/push/simple').to_return(
|
41
|
-
status: 200, body: '42'
|
42
|
-
)
|
43
|
-
assert_equal(
|
44
|
-
42,
|
45
|
-
Judges::Baza.new('example.org', 443, '000').push('simple', 'hello, world!', [])
|
46
|
-
)
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_simple_recent_check
|
50
|
-
WebMock.disable_net_connect!
|
51
|
-
stub_request(:get, 'https://example.org/recent/simple.txt')
|
52
|
-
.with(body: '', headers: { 'User-Agent' => /^judges .*$/ })
|
53
|
-
.to_return(status: 200, body: '42')
|
54
|
-
assert_equal(
|
55
|
-
42,
|
56
|
-
Judges::Baza.new('example.org', 443, '000').recent('simple')
|
57
|
-
)
|
58
|
-
end
|
59
|
-
|
60
|
-
def test_simple_exists_check
|
61
|
-
WebMock.disable_net_connect!
|
62
|
-
stub_request(:get, 'https://example.org/exists/simple').to_return(
|
63
|
-
status: 200, body: 'yes'
|
64
|
-
)
|
65
|
-
assert(
|
66
|
-
Judges::Baza.new('example.org', 443, '000').name_exists?('simple')
|
67
|
-
)
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_exit_code_check
|
71
|
-
WebMock.disable_net_connect!
|
72
|
-
stub_request(:get, 'https://example.org/exit/42.txt').to_return(
|
73
|
-
status: 200, body: '0'
|
74
|
-
)
|
75
|
-
assert(
|
76
|
-
Judges::Baza.new('example.org', 443, '000').exit_code(42).zero?
|
77
|
-
)
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_stdout_read
|
81
|
-
WebMock.disable_net_connect!
|
82
|
-
stub_request(:get, 'https://example.org/stdout/42.txt').to_return(
|
83
|
-
status: 200, body: 'hello!'
|
84
|
-
)
|
85
|
-
assert(
|
86
|
-
!Judges::Baza.new('example.org', 443, '000').stdout(42).empty?
|
87
|
-
)
|
88
|
-
end
|
89
|
-
|
90
|
-
def test_simple_pull
|
91
|
-
WebMock.disable_net_connect!
|
92
|
-
stub_request(:get, 'https://example.org/pull/333.fb').to_return(
|
93
|
-
status: 200, body: 'hello, world!'
|
94
|
-
)
|
95
|
-
assert(
|
96
|
-
Judges::Baza.new('example.org', 443, '000').pull(333).start_with?('hello')
|
97
|
-
)
|
98
|
-
end
|
99
|
-
|
100
|
-
def test_real_http
|
101
|
-
req =
|
102
|
-
with_http_server(200, 'yes') do |baza|
|
103
|
-
baza.name_exists?('simple')
|
104
|
-
end
|
105
|
-
assert_equal("judges #{Judges::VERSION}", req['user-agent'])
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_push_with_meta
|
109
|
-
req =
|
110
|
-
with_http_server(200, 'yes') do |baza|
|
111
|
-
baza.push('simple', 'hello, world!', ['boom!', 'хей!'])
|
112
|
-
end
|
113
|
-
assert_equal('Ym9vbSE= 0YXQtdC5IQ==', req['x-zerocracy-meta'])
|
114
|
-
end
|
115
|
-
|
116
|
-
def test_push_with_big_meta
|
117
|
-
req =
|
118
|
-
with_http_server(200, 'yes') do |baza|
|
119
|
-
baza.push(
|
120
|
-
'simple',
|
121
|
-
'hello, world!',
|
122
|
-
[
|
123
|
-
'pages_url:https://zerocracy.github.io/zerocracy.html',
|
124
|
-
'others:https://zerocracy.github.io/zerocracy.html',
|
125
|
-
'duration:59595'
|
126
|
-
]
|
127
|
-
)
|
128
|
-
end
|
129
|
-
assert(req['x-zerocracy-meta'])
|
130
|
-
end
|
131
|
-
|
132
|
-
def test_push_compressed_content
|
133
|
-
skip # this test is not stable, see https://github.com/yegor256/judges/issues/105
|
134
|
-
req =
|
135
|
-
with_http_server(200, 'yes') do |baza|
|
136
|
-
baza.push('simple', 'hello, world!', %w[meta1 meta2 meta3])
|
137
|
-
end
|
138
|
-
assert_equal('application/zip', req.content_type)
|
139
|
-
assert_equal('gzip', req['content-encoding'])
|
140
|
-
body = Zlib::GzipReader.zcat(StringIO.new(req.body))
|
141
|
-
assert_equal('hello, world!', body)
|
142
|
-
end
|
143
|
-
|
144
|
-
def test_push_compression_disabled
|
145
|
-
req =
|
146
|
-
with_http_server(200, 'yes', compression: false) do |baza|
|
147
|
-
baza.push('simple', 'hello, world!', %w[meta1 meta2 meta3])
|
148
|
-
end
|
149
|
-
assert_equal('application/octet-stream', req.content_type)
|
150
|
-
assert_equal('hello, world!', req.body)
|
151
|
-
end
|
152
|
-
|
153
|
-
private
|
154
|
-
|
155
|
-
def with_http_server(code, response, opts = {})
|
156
|
-
opts = { ssl: false, timeout: 1 }.merge(opts)
|
157
|
-
WebMock.enable_net_connect!
|
158
|
-
req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
|
159
|
-
host = '127.0.0.1'
|
160
|
-
RandomPort::Pool::SINGLETON.acquire do |port|
|
161
|
-
server = TCPServer.new(host, port)
|
162
|
-
t =
|
163
|
-
Thread.new do
|
164
|
-
socket = server.accept
|
165
|
-
req.parse(socket)
|
166
|
-
req.body
|
167
|
-
socket.puts "HTTP/1.1 #{code} OK\r\nContent-Length: #{response.length}\r\n\r\n#{response}"
|
168
|
-
socket.close
|
169
|
-
end
|
170
|
-
yield Judges::Baza.new(host, port, '0000', **opts)
|
171
|
-
t.join
|
172
|
-
end
|
173
|
-
req
|
174
|
-
end
|
175
|
-
end
|