rgot 1.1.0 → 1.3.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/main.yml +5 -5
- data/.gitignore +1 -1
- data/Gemfile +4 -0
- data/Gemfile.lock +73 -0
- data/README.md +72 -2
- data/Rakefile +3 -0
- data/Steepfile +4 -0
- data/bin/rgot +1 -1
- data/lib/rgot/b.rb +17 -14
- data/lib/rgot/benchmark_result.rb +6 -0
- data/lib/rgot/cli.rb +99 -72
- data/lib/rgot/common.rb +8 -4
- data/lib/rgot/example_parser.rb +6 -1
- data/lib/rgot/f.rb +230 -0
- data/lib/rgot/m.rb +121 -22
- data/lib/rgot/pb.rb +2 -2
- data/lib/rgot/t.rb +8 -4
- data/lib/rgot/version.rb +3 -1
- data/lib/rgot.rb +12 -8
- data/rbs_collection.lock.yaml +49 -0
- data/rbs_collection.yaml +53 -0
- data/rgot.gemspec +1 -1
- data/sig/patch.rbs +3 -0
- data/sig/rgot.rbs +232 -0
- metadata +10 -3
data/lib/rgot/f.rb
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
module Rgot
|
2
|
+
# def fuzz_foo(f)
|
3
|
+
# f.add(5, "hello")
|
4
|
+
# f.fuzz do |t, i, s|
|
5
|
+
# ...
|
6
|
+
# end
|
7
|
+
class F < Common
|
8
|
+
class Options
|
9
|
+
# @dynamic fuzz, fuzz=, fuzztime, fuzztime=
|
10
|
+
attr_accessor :fuzz
|
11
|
+
attr_accessor :fuzztime
|
12
|
+
def initialize(fuzz:, fuzztime:)
|
13
|
+
@fuzz = fuzz
|
14
|
+
@fuzztime = fuzztime
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class CorpusEntry
|
19
|
+
# @dynamic values, values=, is_seed, is_seed=, path, path=
|
20
|
+
attr_accessor :values
|
21
|
+
attr_accessor :is_seed
|
22
|
+
attr_accessor :path
|
23
|
+
def initialize(values:, is_seed:, path:)
|
24
|
+
@values = values
|
25
|
+
@is_seed = is_seed
|
26
|
+
@path = path
|
27
|
+
end
|
28
|
+
|
29
|
+
def mutate_values
|
30
|
+
@values.map do |value|
|
31
|
+
if generator = SUPPORTED_TYPES[value.class]
|
32
|
+
generator.call(value)
|
33
|
+
else
|
34
|
+
raise "unsupported type #{value.class}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Coordinator
|
41
|
+
# @dynamic count, count=, interesting_count, interesting_count=
|
42
|
+
attr_accessor :count
|
43
|
+
attr_accessor :interesting_count
|
44
|
+
|
45
|
+
def initialize(warmup_input_count:)
|
46
|
+
@warmup_input_count = warmup_input_count
|
47
|
+
@before_cov = 0
|
48
|
+
@start_time = Rgot.now
|
49
|
+
@count = 0
|
50
|
+
@interesting_count = 0
|
51
|
+
@count_last_log = 0
|
52
|
+
@time_last_log = 0.0
|
53
|
+
end
|
54
|
+
|
55
|
+
def start_logger
|
56
|
+
Thread.new do
|
57
|
+
loop do
|
58
|
+
log_stats
|
59
|
+
sleep 3
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def diff_coverage
|
65
|
+
current_cov = Coverage.peek_result.sum do |path, hash|
|
66
|
+
hash.map do |_, covs|
|
67
|
+
covs.length
|
68
|
+
end.sum
|
69
|
+
end
|
70
|
+
(current_cov - @before_cov).tap { @before_cov = current_cov }
|
71
|
+
end
|
72
|
+
|
73
|
+
def log_stats
|
74
|
+
rate = Float(count - @count_last_log) / (Rgot.now - @time_last_log)
|
75
|
+
total = @warmup_input_count + interesting_count
|
76
|
+
printf "fuzz: elapsed: %ds, execs: %d (%d/sec), new interesting: %d (total: %d)\n",
|
77
|
+
elapsed, count, rate, interesting_count, total
|
78
|
+
|
79
|
+
duration = Rgot.now - @time_last_log
|
80
|
+
@count_last_log = count
|
81
|
+
@time_last_log = Rgot.now
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def elapsed
|
87
|
+
(Rgot.now - @start_time).round
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
SUPPORTED_TYPES = {
|
92
|
+
TrueClass => ->(v) { [true, false].sample },
|
93
|
+
FalseClass => ->(v) { [true, false].sample },
|
94
|
+
Integer => ->(v) { Random.rand(v) },
|
95
|
+
Float => ->(v) { Random.rand(v) },
|
96
|
+
String => ->(v) { Random.bytes(v.length) },
|
97
|
+
}
|
98
|
+
|
99
|
+
# @dynamic name
|
100
|
+
attr_reader :name
|
101
|
+
|
102
|
+
def initialize(fuzz_target:, opts:)
|
103
|
+
super()
|
104
|
+
@opts = opts
|
105
|
+
@fuzz_target = fuzz_target
|
106
|
+
@fuzz_block = nil
|
107
|
+
@module = fuzz_target.module
|
108
|
+
@name = fuzz_target.name
|
109
|
+
@corpus = []
|
110
|
+
end
|
111
|
+
|
112
|
+
# TODO: DRY with T
|
113
|
+
def run
|
114
|
+
catch(:skip) { call }
|
115
|
+
finish!
|
116
|
+
rescue => e
|
117
|
+
fail!
|
118
|
+
raise e
|
119
|
+
end
|
120
|
+
|
121
|
+
def run_testing
|
122
|
+
run
|
123
|
+
report if !fuzz? || failed?
|
124
|
+
end
|
125
|
+
|
126
|
+
def run_fuzzing
|
127
|
+
return unless fuzz?
|
128
|
+
raise("must call after #fuzz") unless @fuzz_block
|
129
|
+
|
130
|
+
coordinator = Coordinator.new(
|
131
|
+
warmup_input_count: @corpus.length
|
132
|
+
)
|
133
|
+
coordinator.start_logger
|
134
|
+
|
135
|
+
t = T.new(@fuzz_target.module, @fuzz_target.name)
|
136
|
+
|
137
|
+
begin
|
138
|
+
Timeout.timeout(@opts.fuzztime.to_f) do
|
139
|
+
loop do
|
140
|
+
@corpus.each do |entry|
|
141
|
+
values = entry.mutate_values
|
142
|
+
|
143
|
+
@fuzz_block.call(t, *values)
|
144
|
+
|
145
|
+
if 0 < coordinator.diff_coverage
|
146
|
+
coordinator.interesting_count += 1
|
147
|
+
end
|
148
|
+
coordinator.count += 1
|
149
|
+
fail! if t.failed?
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
rescue Timeout::Error, Interrupt
|
154
|
+
coordinator.log_stats
|
155
|
+
end
|
156
|
+
|
157
|
+
report
|
158
|
+
end
|
159
|
+
|
160
|
+
def add(*args)
|
161
|
+
args.each do |arg|
|
162
|
+
unless SUPPORTED_TYPES.key?(arg.class)
|
163
|
+
raise "unsupported type to Add #{arg.class}"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
entry = CorpusEntry.new(
|
167
|
+
values: args.dup,
|
168
|
+
is_seed: true,
|
169
|
+
path: "seed##{@corpus.length}"
|
170
|
+
)
|
171
|
+
@corpus.push(entry)
|
172
|
+
end
|
173
|
+
|
174
|
+
def fuzz(&block)
|
175
|
+
unless block
|
176
|
+
raise LocalJumpError, "must set block"
|
177
|
+
end
|
178
|
+
unless 2 <= block.arity
|
179
|
+
raise "fuzz target must receive at least two arguments"
|
180
|
+
end
|
181
|
+
|
182
|
+
t = T.new(@fuzz_target.module, @fuzz_target.name)
|
183
|
+
|
184
|
+
@corpus.each do |entry|
|
185
|
+
unless entry.values.length == (block.arity - 1)
|
186
|
+
raise "wrong number of values in corpus entry: #{entry.values.length}, want #{block.arity - 1}"
|
187
|
+
end
|
188
|
+
block.call(t, *entry.values.dup)
|
189
|
+
fail! if t.failed?
|
190
|
+
end
|
191
|
+
|
192
|
+
@fuzz_block = block
|
193
|
+
|
194
|
+
nil
|
195
|
+
end
|
196
|
+
|
197
|
+
def fuzz?
|
198
|
+
return false unless @opts.fuzz
|
199
|
+
return false unless Regexp.new(@opts.fuzz.to_s).match?(@fuzz_target.name)
|
200
|
+
true
|
201
|
+
end
|
202
|
+
|
203
|
+
def report
|
204
|
+
puts @output if Rgot.verbose? && !@output.empty?
|
205
|
+
duration = Rgot.now - @start
|
206
|
+
template = "--- \e[%sm%s\e[m: %s (%.2fs)\n"
|
207
|
+
if failed?
|
208
|
+
printf template, [41, 1].join(';'), "FAIL", @name, duration
|
209
|
+
elsif Rgot.verbose?
|
210
|
+
if skipped?
|
211
|
+
printf template, [44, 1].join(';'), "SKIP", @name, duration
|
212
|
+
else
|
213
|
+
printf template, [42, 1].join(';'), "PASS", @name, duration
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
private
|
219
|
+
|
220
|
+
def call
|
221
|
+
test_method = @module.instance_method(@name).bind(@module)
|
222
|
+
if test_method.arity == 0
|
223
|
+
path, line = test_method.source_location
|
224
|
+
warn "#{path}:#{line} `#{test_method.name}' is not running. It's a testing method name, But not have argument"
|
225
|
+
else
|
226
|
+
test_method.call(self)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
data/lib/rgot/m.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'stringio'
|
2
4
|
require 'etc'
|
3
5
|
require 'timeout'
|
@@ -10,45 +12,101 @@ module Rgot
|
|
10
12
|
:timeout,
|
11
13
|
:cpu,
|
12
14
|
:thread,
|
15
|
+
:fuzz,
|
16
|
+
:fuzztime,
|
13
17
|
); end
|
14
18
|
|
15
|
-
def initialize(tests:, benchmarks:, examples:, opts: Options.new)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
j
|
26
|
-
}
|
19
|
+
def initialize(tests:, benchmarks:, examples:, fuzz_targets: nil, test_module: nil, opts: Options.new)
|
20
|
+
unless fuzz_targets
|
21
|
+
raise "Require `fuzz_targets` keyword" if Gem::Version.new("2.0") <= Gem::Version.new(Rgot::VERSION)
|
22
|
+
warn "`Rgot::M#initialize` will require the `fuzz_targets` keyword in the next major version."
|
23
|
+
end
|
24
|
+
unless test_module
|
25
|
+
raise "Require `test_module` keyword" if Gem::Version.new("2.0") <= Gem::Version.new(Rgot::VERSION)
|
26
|
+
warn "`Rgot::M#initialize` will require the `test_module` keyword in the next major version."
|
27
|
+
end
|
28
|
+
|
27
29
|
@tests = tests
|
28
30
|
@benchmarks = benchmarks
|
29
31
|
@examples = examples
|
32
|
+
@fuzz_targets = fuzz_targets || []
|
33
|
+
@test_module = test_module
|
30
34
|
@opts = opts
|
35
|
+
|
36
|
+
@cpu_list = []
|
37
|
+
@thread_list = []
|
38
|
+
@fs = @fuzz_targets.map do |fuzz_target|
|
39
|
+
F.new(
|
40
|
+
fuzz_target: fuzz_target,
|
41
|
+
opts: F::Options.new(
|
42
|
+
fuzz: opts.fuzz,
|
43
|
+
fuzztime: opts.fuzztime,
|
44
|
+
)
|
45
|
+
)
|
46
|
+
end
|
31
47
|
end
|
32
48
|
|
33
49
|
def run
|
50
|
+
duration = Rgot.now
|
34
51
|
test_ok = false
|
52
|
+
fuzz_targets_ok = false
|
35
53
|
example_ok = false
|
36
54
|
|
55
|
+
if @tests.empty? && @benchmarks.empty? && @examples.empty? && @fuzz_targets.empty?
|
56
|
+
warn "rgot: warning: no tests to run"
|
57
|
+
end
|
58
|
+
|
59
|
+
begin
|
60
|
+
parse_option
|
61
|
+
rescue Rgot::OptionError
|
62
|
+
puts sprintf("%s\t%s\t%.3fs", "FAIL", @test_module, Rgot.now - duration)
|
63
|
+
raise
|
64
|
+
end
|
65
|
+
|
37
66
|
Timeout.timeout(@opts.timeout.to_f) do
|
38
67
|
test_ok = run_tests
|
68
|
+
fuzz_targets_ok = run_fuzz_tests
|
39
69
|
example_ok = run_examples
|
40
70
|
end
|
41
|
-
|
71
|
+
|
72
|
+
if !test_ok || !example_ok || !fuzz_targets_ok
|
73
|
+
puts "FAIL"
|
74
|
+
puts "exit status 1"
|
75
|
+
puts sprintf("%s\t%s\t%.3fs", "FAIL", @test_module, Rgot.now - duration)
|
76
|
+
return 1
|
77
|
+
end
|
78
|
+
|
79
|
+
if !run_fuzzing()
|
42
80
|
puts "FAIL"
|
81
|
+
puts "exit status 1"
|
82
|
+
puts sprintf("%s\t%s\t%.3fs", "FAIL", @test_module, Rgot.now - duration)
|
43
83
|
return 1
|
44
84
|
end
|
85
|
+
|
45
86
|
puts "PASS"
|
46
87
|
run_benchmarks
|
88
|
+
puts sprintf("%s\t%s\t%.3fs", "ok ", @test_module, Rgot.now - duration)
|
89
|
+
|
47
90
|
0
|
48
91
|
end
|
49
92
|
|
50
93
|
private
|
51
94
|
|
95
|
+
def parse_option
|
96
|
+
cpu = @opts.cpu || (Etc.respond_to?(:nprocessors) ? Etc.nprocessors : '1').to_s
|
97
|
+
@cpu_list = cpu.split(',').map { |i|
|
98
|
+
j = i.to_i
|
99
|
+
raise Rgot::OptionError, "invalid value #{i.inspect} for --cpu" unless 0 < j
|
100
|
+
j
|
101
|
+
}
|
102
|
+
|
103
|
+
@thread_list = (@opts.thread || "1").split(',').map { |i|
|
104
|
+
j = i.to_i
|
105
|
+
raise Rgot::OptionError, "invalid value #{i.inspect} for --thread" unless 0 < j
|
106
|
+
j
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
52
110
|
def run_tests
|
53
111
|
ok = true
|
54
112
|
@tests.each do |test|
|
@@ -57,10 +115,7 @@ module Rgot
|
|
57
115
|
puts "=== RUN #{test.name}"
|
58
116
|
end
|
59
117
|
t.run
|
60
|
-
t.
|
61
|
-
if t.failed?
|
62
|
-
ok = false
|
63
|
-
end
|
118
|
+
ok = ok && !t.failed?
|
64
119
|
end
|
65
120
|
ok
|
66
121
|
end
|
@@ -98,6 +153,50 @@ module Rgot
|
|
98
153
|
ok
|
99
154
|
end
|
100
155
|
|
156
|
+
def run_fuzz_tests
|
157
|
+
ok = true
|
158
|
+
@fs.each do |f|
|
159
|
+
if Rgot.verbose?
|
160
|
+
if f.fuzz?
|
161
|
+
puts "=== FUZZ #{f.name}"
|
162
|
+
else
|
163
|
+
puts "=== RUN #{f.name}"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
f.run_testing
|
167
|
+
ok = ok && !f.failed?
|
168
|
+
end
|
169
|
+
ok
|
170
|
+
end
|
171
|
+
|
172
|
+
def run_fuzzing
|
173
|
+
if @fuzz_targets.empty? || @opts.fuzz.nil?
|
174
|
+
return true
|
175
|
+
end
|
176
|
+
|
177
|
+
fuzzing_fs = @fs.select(&:fuzz?)
|
178
|
+
|
179
|
+
if fuzzing_fs.empty?
|
180
|
+
puts "rgot: warning: no fuzz tests to fuzz"
|
181
|
+
return true
|
182
|
+
end
|
183
|
+
|
184
|
+
if fuzzing_fs.length > 1
|
185
|
+
names = fuzzing_fs.map(&:name)
|
186
|
+
puts "rgot: will not fuzz, --fuzz matches more than one fuzz test: #{names.inspect}"
|
187
|
+
return false
|
188
|
+
end
|
189
|
+
|
190
|
+
ok = true
|
191
|
+
|
192
|
+
fuzzing_fs.each do |f|
|
193
|
+
f.run_fuzzing
|
194
|
+
ok = ok && !f.failed?
|
195
|
+
end
|
196
|
+
|
197
|
+
ok
|
198
|
+
end
|
199
|
+
|
101
200
|
def run_examples
|
102
201
|
ok = true
|
103
202
|
@examples.each do |example|
|
@@ -111,13 +210,13 @@ module Rgot
|
|
111
210
|
out, _ = capture do
|
112
211
|
method.call
|
113
212
|
end
|
114
|
-
file = method.source_location[0
|
115
|
-
|
116
|
-
|
117
|
-
e =
|
213
|
+
file = method.source_location&.[](0) or raise("bug")
|
214
|
+
example_parser = ExampleParser.new(File.read(file))
|
215
|
+
example_parser.parse
|
216
|
+
e = example_parser.examples.find { |er| er.name == example.name } or raise("bug")
|
118
217
|
|
119
218
|
duration = Rgot.now - start
|
120
|
-
if e
|
219
|
+
if e.output.strip != out.strip
|
121
220
|
printf("--- FAIL: %s (%.2fs)\n", e.name, duration)
|
122
221
|
ok = false
|
123
222
|
puts "got:"
|
data/lib/rgot/pb.rb
CHANGED
data/lib/rgot/t.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rgot
|
2
4
|
class T < Common
|
3
5
|
def initialize(test_module, name)
|
@@ -10,6 +12,7 @@ module Rgot
|
|
10
12
|
def run
|
11
13
|
catch(:skip) { call }
|
12
14
|
finish!
|
15
|
+
report
|
13
16
|
rescue => e
|
14
17
|
fail!
|
15
18
|
report
|
@@ -17,15 +20,16 @@ module Rgot
|
|
17
20
|
end
|
18
21
|
|
19
22
|
def report
|
23
|
+
puts @output if Rgot.verbose? && !@output.empty?
|
20
24
|
duration = Rgot.now - @start
|
21
|
-
template = "--- %s: %s (%.2fs)\n
|
25
|
+
template = "--- \e[%sm%s\e[m: %s (%.2fs)\n"
|
22
26
|
if failed?
|
23
|
-
printf template, "FAIL", @name, duration
|
27
|
+
printf template, [41, 1].join(';'), "FAIL", @name, duration
|
24
28
|
elsif Rgot.verbose?
|
25
29
|
if skipped?
|
26
|
-
printf template, "SKIP", @name, duration
|
30
|
+
printf template, [44, 1].join(';'), "SKIP", @name, duration
|
27
31
|
else
|
28
|
-
printf template, "PASS", @name, duration
|
32
|
+
printf template, [42, 1].join(';'), "PASS", @name, duration
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
data/lib/rgot/version.rb
CHANGED
data/lib/rgot.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rgot
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
autoload :VERSION, 'rgot/version'
|
5
|
+
autoload :Common, 'rgot/common'
|
6
|
+
autoload :M, 'rgot/m'
|
7
|
+
autoload :T, 'rgot/t'
|
8
|
+
autoload :B, 'rgot/b'
|
9
|
+
autoload :PB, 'rgot/pb'
|
10
|
+
autoload :BenchmarkResult, 'rgot/benchmark_result'
|
11
|
+
autoload :F, 'rgot/f'
|
12
|
+
autoload :ExampleParser, 'rgot/example_parser'
|
10
13
|
|
11
14
|
OptionError = Class.new(StandardError)
|
12
15
|
InternalTest = Struct.new(:module, :name)
|
13
16
|
InternalBenchmark = Struct.new(:module, :name)
|
14
17
|
InternalExample = Struct.new(:module, :name)
|
18
|
+
InternalFuzzTarget = Struct.new(:module, :name)
|
15
19
|
ExampleOutput = Struct.new(:name, :output)
|
16
20
|
|
17
21
|
class << self
|
@@ -0,0 +1,49 @@
|
|
1
|
+
---
|
2
|
+
sources:
|
3
|
+
- name: ruby/gem_rbs_collection
|
4
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
5
|
+
revision: main
|
6
|
+
repo_dir: gems
|
7
|
+
path: ".gem_rbs_collection"
|
8
|
+
gems:
|
9
|
+
- name: pathname
|
10
|
+
version: '0'
|
11
|
+
source:
|
12
|
+
type: stdlib
|
13
|
+
- name: optparse
|
14
|
+
version: '0'
|
15
|
+
source:
|
16
|
+
type: stdlib
|
17
|
+
- name: timeout
|
18
|
+
version: '0'
|
19
|
+
source:
|
20
|
+
type: stdlib
|
21
|
+
- name: etc
|
22
|
+
version: '0'
|
23
|
+
source:
|
24
|
+
type: stdlib
|
25
|
+
- name: coverage
|
26
|
+
version: '0'
|
27
|
+
source:
|
28
|
+
type: stdlib
|
29
|
+
- name: concurrent-ruby
|
30
|
+
version: '1.1'
|
31
|
+
source:
|
32
|
+
type: git
|
33
|
+
name: ruby/gem_rbs_collection
|
34
|
+
revision: 9576ce5b109170f1ba8a42671bfafb64ab95bd23
|
35
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
36
|
+
repo_dir: gems
|
37
|
+
- name: io-console
|
38
|
+
version: '0'
|
39
|
+
source:
|
40
|
+
type: stdlib
|
41
|
+
- name: logger
|
42
|
+
version: '0'
|
43
|
+
source:
|
44
|
+
type: stdlib
|
45
|
+
- name: monitor
|
46
|
+
version: '0'
|
47
|
+
source:
|
48
|
+
type: stdlib
|
49
|
+
gemfile_lock_path: Gemfile.lock
|
data/rbs_collection.yaml
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Download sources
|
2
|
+
sources:
|
3
|
+
- name: ruby/gem_rbs_collection
|
4
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
5
|
+
revision: main
|
6
|
+
repo_dir: gems
|
7
|
+
|
8
|
+
# A directory to install the downloaded RBSs
|
9
|
+
path: .gem_rbs_collection
|
10
|
+
|
11
|
+
gems:
|
12
|
+
- name: pathname
|
13
|
+
- name: optparse
|
14
|
+
- name: timeout
|
15
|
+
- name: etc
|
16
|
+
- name: coverage
|
17
|
+
|
18
|
+
# Skip loading rbs gem's RBS.
|
19
|
+
# It's unnecessary if you don't use rbs as a library.
|
20
|
+
- name: rbs
|
21
|
+
ignore: true
|
22
|
+
- name: steep
|
23
|
+
ignore: true
|
24
|
+
- name: activesupport
|
25
|
+
ignore: true
|
26
|
+
- name: ast
|
27
|
+
ignore: true
|
28
|
+
- name: csv
|
29
|
+
ignore: true
|
30
|
+
- name: i18n
|
31
|
+
ignore: true
|
32
|
+
- name: json
|
33
|
+
ignore: true
|
34
|
+
- name: listen
|
35
|
+
ignore: true
|
36
|
+
- name: fileutils
|
37
|
+
ignore: true
|
38
|
+
- name: minitest
|
39
|
+
ignore: true
|
40
|
+
- name: parallel
|
41
|
+
ignore: true
|
42
|
+
- name: rainbow
|
43
|
+
ignore: true
|
44
|
+
- name: rgot
|
45
|
+
ignore: true
|
46
|
+
- name: securerandom
|
47
|
+
ignore: true
|
48
|
+
- name: strscan
|
49
|
+
ignore: true
|
50
|
+
- name: forwardable
|
51
|
+
ignore: true
|
52
|
+
- name: mutex_m
|
53
|
+
ignore: true
|
data/rgot.gemspec
CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.homepage = "https://github.com/ksss/rgot"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|go)/}) }
|
18
18
|
spec.bindir = "bin"
|
19
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
data/sig/patch.rbs
ADDED