seeing_is_believing 3.0.0.beta.3 → 3.0.0.beta.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/features/deprecated-flags.feature +12 -0
- data/features/flags.feature +2 -16
- data/features/regression.feature +46 -0
- data/features/xmpfilter-style.feature +55 -0
- data/lib/seeing_is_believing/binary/interpret_flags.rb +1 -5
- data/lib/seeing_is_believing/binary/parse_args.rb +12 -12
- data/lib/seeing_is_believing/binary/remove_annotations.rb +1 -1
- data/lib/seeing_is_believing/binary.rb +3 -3
- data/lib/seeing_is_believing/evaluate_by_moving_files.rb +60 -11
- data/lib/seeing_is_believing/event_stream/consumer.rb +61 -37
- data/lib/seeing_is_believing/event_stream/events.rb +3 -1
- data/lib/seeing_is_believing/event_stream/producer.rb +38 -21
- data/lib/seeing_is_believing/event_stream/update_result.rb +6 -2
- data/lib/seeing_is_believing/inspect_expressions.rb +5 -1
- data/lib/seeing_is_believing/parser_helpers.rb +11 -1
- data/lib/seeing_is_believing/result.rb +6 -1
- data/lib/seeing_is_believing/the_matrix.rb +18 -18
- data/lib/seeing_is_believing/version.rb +1 -1
- data/lib/seeing_is_believing/wrap_expressions.rb +0 -1
- data/lib/seeing_is_believing.rb +0 -2
- data/seeing_is_believing.gemspec +2 -4
- data/spec/binary/interpret_flags_spec.rb +0 -14
- data/spec/binary/parse_args_spec.rb +5 -6
- data/spec/event_stream_spec.rb +161 -70
- data/spec/seeing_is_believing_spec.rb +29 -63
- metadata +8 -37
- data/features/safe.feature +0 -33
- data/lib/seeing_is_believing/evaluate_with_eval_in.rb +0 -27
@@ -6,10 +6,12 @@ class SeeingIsBelieving
|
|
6
6
|
Stdout = Struct.new(:value)
|
7
7
|
Stderr = Struct.new(:value)
|
8
8
|
MaxLineCaptures = Struct.new(:value)
|
9
|
+
Filename = Struct.new(:value)
|
9
10
|
NumLines = Struct.new(:value)
|
11
|
+
SiBVersion = Struct.new(:value)
|
12
|
+
RubyVersion = Struct.new(:value)
|
10
13
|
Exitstatus = Struct.new(:value)
|
11
14
|
Exception = Struct.new(:line_number, :class_name, :message, :backtrace)
|
12
|
-
Finish = Class.new
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
@@ -1,8 +1,16 @@
|
|
1
1
|
require 'seeing_is_believing/event_stream/events'
|
2
|
+
require 'thread'
|
3
|
+
|
2
4
|
class SeeingIsBelieving
|
3
5
|
module EventStream
|
4
|
-
require 'thread'
|
5
6
|
class Producer
|
7
|
+
|
8
|
+
module NullQueue
|
9
|
+
extend self
|
10
|
+
def <<(*) end
|
11
|
+
def shift() end
|
12
|
+
end
|
13
|
+
|
6
14
|
attr_accessor :exitstatus, :max_line_captures, :num_lines, :filename
|
7
15
|
|
8
16
|
def initialize(resultstream)
|
@@ -11,31 +19,38 @@ class SeeingIsBelieving
|
|
11
19
|
self.max_line_captures = Float::INFINITY
|
12
20
|
self.num_lines = 0
|
13
21
|
self.recorded_results = []
|
14
|
-
self.queue =
|
22
|
+
self.queue = Queue.new
|
15
23
|
self.producer_thread = Thread.new do
|
16
|
-
finish = "finish"
|
17
24
|
begin
|
18
25
|
resultstream.sync = true
|
19
26
|
loop do
|
20
27
|
to_publish = queue.shift
|
21
|
-
if to_publish ==
|
22
|
-
|
23
|
-
break
|
24
|
-
else
|
25
|
-
resultstream << (to_publish << "\n")
|
26
|
-
end
|
28
|
+
break if to_publish == :break
|
29
|
+
resultstream << (to_publish << "\n")
|
27
30
|
end
|
28
31
|
rescue IOError, Errno::EPIPE
|
29
|
-
|
32
|
+
queue.clear
|
30
33
|
ensure
|
31
34
|
resultstream.flush rescue nil
|
32
35
|
end
|
36
|
+
self.queue = NullQueue
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
36
|
-
|
37
|
-
|
38
|
-
|
40
|
+
attr_reader :version
|
41
|
+
alias ver version
|
42
|
+
def record_sib_version(sib_version)
|
43
|
+
@version = sib_version
|
44
|
+
queue << "sib_version #{to_string_token sib_version}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def record_ruby_version(ruby_version)
|
48
|
+
queue << "ruby_version #{to_string_token ruby_version}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def record_max_line_captures(max_line_captures)
|
52
|
+
self.max_line_captures = max_line_captures
|
53
|
+
queue << "max_line_captures #{max_line_captures}"
|
39
54
|
end
|
40
55
|
|
41
56
|
StackErrors = [SystemStackError]
|
@@ -89,25 +104,27 @@ class SeeingIsBelieving
|
|
89
104
|
queue << "end"
|
90
105
|
end
|
91
106
|
|
92
|
-
def
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
def record_stderr(stderr)
|
97
|
-
queue << "stderr #{to_string_token stderr}"
|
107
|
+
def record_filename(filename)
|
108
|
+
self.filename = filename
|
109
|
+
queue << "filename #{to_string_token filename}"
|
98
110
|
end
|
99
111
|
|
112
|
+
# note that producer will continue reading until stream is closed
|
100
113
|
def finish!
|
101
|
-
queue << "max_line_captures #{max_line_captures}"
|
102
114
|
queue << "num_lines #{num_lines}"
|
103
115
|
queue << "exitstatus #{exitstatus}"
|
104
|
-
queue <<
|
116
|
+
queue << :break
|
105
117
|
producer_thread.join
|
106
118
|
end
|
107
119
|
|
108
120
|
private
|
109
121
|
|
110
122
|
attr_accessor :resultstream, :queue, :producer_thread, :recorded_results
|
123
|
+
|
124
|
+
# for a consideration of many different ways of doing this, see 5633064
|
125
|
+
def to_string_token(string)
|
126
|
+
[Marshal.dump(string.to_s)].pack('m0')
|
127
|
+
end
|
111
128
|
end
|
112
129
|
end
|
113
130
|
end
|
@@ -1,17 +1,21 @@
|
|
1
1
|
require 'seeing_is_believing/event_stream/events'
|
2
2
|
class SeeingIsBelieving
|
3
3
|
module EventStream
|
4
|
+
# Adapter between EventStream and Result
|
4
5
|
module UpdateResult
|
5
6
|
def self.call(result, event)
|
6
7
|
case event
|
7
8
|
when EventStream::Events::LineResult then result.record_result(event.type, event.line_number, event.inspected)
|
8
9
|
when EventStream::Events::UnrecordedResult then result.record_result(event.type, event.line_number, '...') # <-- is this really what I want?
|
9
10
|
when EventStream::Events::Exception then result.record_exception event.line_number, event.class_name, event.message, event.backtrace
|
10
|
-
when EventStream::Events::Stdout then result.stdout
|
11
|
-
when EventStream::Events::Stderr then result.stderr
|
11
|
+
when EventStream::Events::Stdout then result.stdout << event.value
|
12
|
+
when EventStream::Events::Stderr then result.stderr << event.value
|
12
13
|
when EventStream::Events::MaxLineCaptures then result.number_of_captures = event.value
|
13
14
|
when EventStream::Events::Exitstatus then result.exitstatus = event.value
|
14
15
|
when EventStream::Events::NumLines then result.num_lines = event.value
|
16
|
+
when EventStream::Events::SiBVersion then result.sib_version = event.value
|
17
|
+
when EventStream::Events::RubyVersion then result.ruby_version = event.value
|
18
|
+
when EventStream::Events::Filename then result.filename = event.value
|
15
19
|
else raise "Unknown event: #{event.inspect}"
|
16
20
|
end
|
17
21
|
end
|
@@ -7,7 +7,11 @@ class SeeingIsBelieving
|
|
7
7
|
number_of_captures_as_str = 'Float::INFINITY' if number_of_captures == Float::INFINITY
|
8
8
|
|
9
9
|
wrap_expressions_callbacks = {}
|
10
|
-
wrap_expressions_callbacks[:before_all] = options.fetch :before_all, -> { "$SiB.
|
10
|
+
wrap_expressions_callbacks[:before_all] = options.fetch :before_all, -> { "$SiB.record_ruby_version RUBY_VERSION;"\
|
11
|
+
"$SiB.record_sib_version #{VERSION.inspect};"\
|
12
|
+
"$SiB.record_filename #{filename.inspect};"\
|
13
|
+
"$SiB.record_max_line_captures #{number_of_captures_as_str};"\
|
14
|
+
"$SiB.num_lines = #{program.lines.count}; " }
|
11
15
|
wrap_expressions_callbacks[:after_all] = options.fetch :after_all, -> { "" }
|
12
16
|
wrap_expressions_callbacks[:before_each] = options.fetch :before_each, -> line_number { "(" }
|
13
17
|
wrap_expressions_callbacks[:after_each] = options.fetch :after_each, -> line_number { ").tap { |v| $SiB.record_result(:inspect, #{line_number}, v) }" }
|
@@ -1,4 +1,14 @@
|
|
1
|
-
|
1
|
+
module Parser
|
2
|
+
class << self
|
3
|
+
# With new versioning, there's lots of small versions
|
4
|
+
# we don't need it to complain that we're on 2.1.1 and its parsing 2.1.5
|
5
|
+
# https://github.com/whitequark/parser/blob/e2249d7051b1adb6979139928e14a81bc62f566e/lib/parser/current.rb#L3
|
6
|
+
def warn(*) end
|
7
|
+
require 'parser/current'
|
8
|
+
remove_method :warn
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
2
12
|
class SeeingIsBelieving
|
3
13
|
module ParserHelpers
|
4
14
|
|
@@ -3,7 +3,12 @@ class SeeingIsBelieving
|
|
3
3
|
include Enumerable
|
4
4
|
RecordedException = Struct.new :line_number, :class_name, :message, :backtrace
|
5
5
|
|
6
|
-
attr_accessor :stdout, :stderr, :exitstatus, :number_of_captures, :exception, :num_lines
|
6
|
+
attr_accessor :stdout, :stderr, :exitstatus, :number_of_captures, :exception, :num_lines, :sib_version, :ruby_version, :filename
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
self.stdout = ''
|
10
|
+
self.stderr = ''
|
11
|
+
end
|
7
12
|
|
8
13
|
alias has_exception? exception
|
9
14
|
|
@@ -8,28 +8,28 @@
|
|
8
8
|
require_relative 'version'
|
9
9
|
require_relative 'event_stream/producer'
|
10
10
|
|
11
|
-
event_stream =
|
11
|
+
event_stream = IO.open(ARGV.shift.to_i, "w")
|
12
12
|
$SiB = SeeingIsBelieving::EventStream::Producer.new(event_stream)
|
13
13
|
|
14
|
-
stdout = STDOUT
|
15
|
-
|
16
|
-
|
14
|
+
stdout, stderr = STDOUT, STDERR
|
15
|
+
finish = lambda do
|
16
|
+
$SiB.finish!
|
17
|
+
event_stream.close
|
18
|
+
stdout.flush
|
19
|
+
stderr.flush
|
20
|
+
end
|
17
21
|
|
18
|
-
|
19
|
-
|
20
|
-
|
22
|
+
real_exec = method :exec
|
23
|
+
Kernel.module_eval do
|
24
|
+
private
|
25
|
+
define_method :exec do |*args, &block| # TODO: Add an event for exec?
|
26
|
+
finish.call
|
27
|
+
real_exec.call(*args, &block)
|
28
|
+
end
|
29
|
+
end
|
21
30
|
|
22
31
|
at_exit do
|
23
|
-
_, blackhole = IO.pipe
|
24
|
-
stdout.reopen(blackhole)
|
25
|
-
stderr.reopen(blackhole)
|
26
|
-
|
27
|
-
write_stdout.close unless write_stdout.closed?
|
28
|
-
$SiB.record_stdout read_stdout.read
|
29
|
-
|
30
|
-
write_stderr.close unless write_stderr.closed?
|
31
|
-
$SiB.record_stderr read_stderr.read
|
32
|
-
|
33
32
|
$SiB.record_exception nil, $! if $!
|
34
|
-
|
33
|
+
finish.call
|
34
|
+
Kernel.exit! 0 # clear the exception so it doesn't print to stderr and change the processes actual exit status (we recorded what it should be)
|
35
35
|
end
|
data/lib/seeing_is_believing.rb
CHANGED
@@ -23,7 +23,6 @@ class SeeingIsBelieving
|
|
23
23
|
@encoding = options.fetch :encoding, nil
|
24
24
|
@timeout = options[:timeout]
|
25
25
|
@debugger = options.fetch :debugger, Debugger.new(stream: nil)
|
26
|
-
@ruby_executable = options.fetch :ruby_executable, 'ruby'
|
27
26
|
@number_of_captures = options.fetch :number_of_captures, Float::INFINITY
|
28
27
|
@evaluator = options.fetch :evaluator, EvaluateByMovingFiles
|
29
28
|
@record_expressions = options.fetch :record_expressions, InspectExpressions # TODO: rename to wrap_expressions
|
@@ -42,7 +41,6 @@ class SeeingIsBelieving
|
|
42
41
|
load_path: @load_path,
|
43
42
|
encoding: @encoding,
|
44
43
|
timeout: @timeout,
|
45
|
-
ruby_executable: @ruby_executable,
|
46
44
|
debugger: @debugger
|
47
45
|
|
48
46
|
@debugger.context("RESULT") { result.inspect }
|
data/seeing_is_believing.gemspec
CHANGED
@@ -19,11 +19,9 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_dependency "
|
23
|
-
s.add_dependency "parser", ">= 2.1.4", "< 2.3"
|
22
|
+
s.add_dependency "parser", ">= 2.2", "< 3.0"
|
24
23
|
|
25
|
-
s.add_development_dependency "
|
26
|
-
s.add_development_dependency "haiti", ">= 0.1", "< 0.3"
|
24
|
+
s.add_development_dependency "haiti", ">= 0.1", "< 0.3"
|
27
25
|
s.add_development_dependency "rake", "~> 10.0"
|
28
26
|
s.add_development_dependency "rspec", "~> 3.0"
|
29
27
|
s.add_development_dependency "cucumber", "~> 1.2"
|
@@ -131,12 +131,6 @@ class SeeingIsBelieving
|
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
|
-
context 'shebang' do
|
135
|
-
it 'sets shebang to the value' do
|
136
|
-
expect(call(shebang: 'whatevz').shebang).to eq 'whatevz'
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
134
|
context 'filename' do
|
141
135
|
it 'sets this as the filename' do
|
142
136
|
expect(call(filename: 'somefilename').filename).to eq 'somefilename'
|
@@ -239,20 +233,12 @@ class SeeingIsBelieving
|
|
239
233
|
expect(call[:evaluate_with]).to eq EvaluateByMovingFiles
|
240
234
|
end
|
241
235
|
|
242
|
-
specify 'evaluate_with is EvaluateWithEvalIn if safe is set' do
|
243
|
-
expect(call(safe: true)[:evaluate_with]).to eq EvaluateWithEvalIn
|
244
|
-
end
|
245
|
-
|
246
236
|
specify 'filename is the as option or the provided filename' do
|
247
237
|
expect(call(filename: 'from_fn')[:filename]).to eq 'from_fn'
|
248
238
|
expect(call(as: 'from_as')[:filename]).to eq 'from_as'
|
249
239
|
expect(call(as: 'from_as', filename: 'from_fn')[:filename]).to eq 'from_as'
|
250
240
|
end
|
251
241
|
|
252
|
-
specify 'ruby_executable is the shebang' do
|
253
|
-
expect(call(shebang: 'shebangprog')[:ruby_executable]).to eq 'shebangprog'
|
254
|
-
end
|
255
|
-
|
256
242
|
specify 'stdin is empty when the program is on stdin, and is stdin otherwise' do
|
257
243
|
# NOTE: the lib will normalize this into a stream
|
258
244
|
expect(call(filename: nil, program_from_args: nil)[:stdin]).to eq ''
|
@@ -341,12 +341,11 @@ RSpec.describe SeeingIsBelieving::Binary::ParseArgs do
|
|
341
341
|
end
|
342
342
|
|
343
343
|
describe ':shebang' do
|
344
|
-
it '
|
345
|
-
expect(parse([])[:
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
expect(parse(['--shebang', 'not_ruby'])[:shebang]).to eq 'not_ruby'
|
344
|
+
it 'is added to the list of deprecated flags' do
|
345
|
+
expect(parse([])[:deprecated_flags]).to eq []
|
346
|
+
parsed = parse(['--shebang', 'not_ruby', 'other'])
|
347
|
+
expect(parsed[:shebang]).to eq nil
|
348
|
+
expect(parsed[:deprecated_flags]).to eq ['--shebang', 'not_ruby']
|
350
349
|
end
|
351
350
|
|
352
351
|
it 'sets an error if not given a next arg to execute' do
|
data/spec/event_stream_spec.rb
CHANGED
@@ -5,28 +5,54 @@ require 'seeing_is_believing/event_stream/consumer'
|
|
5
5
|
|
6
6
|
module SeeingIsBelieving::EventStream
|
7
7
|
RSpec.describe SeeingIsBelieving::EventStream do
|
8
|
-
attr_accessor :producer, :consumer
|
8
|
+
attr_accessor :producer, :consumer
|
9
|
+
attr_accessor :eventstream_consumer, :eventstream_producer
|
10
|
+
attr_accessor :stdout_consumer, :stdout_producer
|
11
|
+
attr_accessor :stderr_consumer, :stderr_producer
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
self.producer = SeeingIsBelieving::EventStream::Producer.new(writestream)
|
13
|
-
self.consumer = SeeingIsBelieving::EventStream::Consumer.new(readstream)
|
13
|
+
def close_streams(*streams)
|
14
|
+
streams.each { |fd| fd.close unless fd.closed? }
|
14
15
|
end
|
15
16
|
|
16
|
-
|
17
|
+
def finish!
|
17
18
|
producer.finish!
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
close_streams eventstream_producer, stdout_producer, stderr_producer
|
20
|
+
end
|
21
|
+
|
22
|
+
before do
|
23
|
+
self.eventstream_consumer, self.eventstream_producer = IO.pipe
|
24
|
+
self.stdout_consumer, self.stdout_producer = IO.pipe
|
25
|
+
self.stderr_consumer, self.stderr_producer = IO.pipe
|
26
|
+
|
27
|
+
self.producer = SeeingIsBelieving::EventStream::Producer.new eventstream_producer
|
28
|
+
self.consumer = SeeingIsBelieving::EventStream::Consumer.new \
|
29
|
+
events: eventstream_consumer,
|
30
|
+
stdout: stdout_consumer,
|
31
|
+
stderr: stderr_consumer
|
32
|
+
end
|
33
|
+
|
34
|
+
after do
|
35
|
+
finish!
|
36
|
+
close_streams eventstream_consumer, stdout_consumer, stderr_consumer
|
37
|
+
end
|
21
38
|
|
22
39
|
describe 'emitting an event' do
|
23
|
-
|
24
|
-
|
25
|
-
|
40
|
+
def has_message?(io)
|
41
|
+
io.read_nonblock(1) # ~> IO::EAGAINWaitReadable: Resource temporarily unavailable - read would block
|
42
|
+
rescue Errno::EAGAIN
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'writes its events to the event stream' do
|
47
|
+
read, write = IO.pipe
|
48
|
+
producer = SeeingIsBelieving::EventStream::Producer.new(write)
|
49
|
+
expect(has_message? read).to eq false
|
50
|
+
producer.record_filename "whatever.rb"
|
51
|
+
expect(read.gets).to start_with 'filename'
|
52
|
+
end
|
26
53
|
|
27
|
-
# This test is irrelevant on MRI b/c of the GIL,
|
28
|
-
|
29
|
-
it 'is wrapped in a mutex to prevent multiple values from writing at the same time' do
|
54
|
+
# This test is irrelevant on MRI b/c of the GIL, but I ran it on Rbx to make sure it works
|
55
|
+
it 'is threadsafe as multiple events can occur at once' do
|
30
56
|
num_threads = 10
|
31
57
|
num_results = 600
|
32
58
|
line_nums_and_inspections = num_threads.times.flat_map { |line_num|
|
@@ -51,58 +77,58 @@ module SeeingIsBelieving::EventStream
|
|
51
77
|
expect(producer_threads).to be_none(&:alive?)
|
52
78
|
end
|
53
79
|
|
54
|
-
it 'raises NoMoreInput
|
55
|
-
|
80
|
+
it 'raises NoMoreInput if input is closed before it finishes reading the number of requested inputs' do
|
81
|
+
finish!
|
56
82
|
expect { consumer.call 10 }.to raise_error SeeingIsBelieving::EventStream::Consumer::NoMoreInput
|
57
83
|
end
|
58
84
|
|
59
|
-
it 'raises NoMoreInput
|
85
|
+
it 'raises NoMoreInput once it its input streams are all closed' do
|
60
86
|
producer.finish!
|
61
|
-
|
87
|
+
close_streams eventstream_producer, stdout_producer, stderr_producer
|
88
|
+
consumer.call 2
|
62
89
|
expect { consumer.call }.to raise_error SeeingIsBelieving::EventStream::Consumer::NoMoreInput
|
63
|
-
expect(consumer).to be_finished
|
64
90
|
end
|
65
91
|
|
66
|
-
it 'raises NoMoreInput
|
67
|
-
|
92
|
+
it 'raises NoMoreInput if its end of the stream is closed and there is no more stdout/stderr' do
|
93
|
+
close_streams eventstream_consumer, stdout_producer, stderr_producer
|
94
|
+
expect { consumer.call }.to raise_error SeeingIsBelieving::EventStream::Consumer::WtfWhoClosedMyShit
|
68
95
|
expect { consumer.call }.to raise_error SeeingIsBelieving::EventStream::Consumer::NoMoreInput
|
69
|
-
expect(consumer).to be_finished
|
70
96
|
end
|
71
97
|
|
72
|
-
it 'raises WtfWhoClosedMyShit
|
73
|
-
|
98
|
+
it 'raises WtfWhoClosedMyShit if its end of the stream is closed' do
|
99
|
+
close_streams eventstream_consumer, stdout_producer, stderr_producer
|
74
100
|
expect { consumer.call }.to raise_error SeeingIsBelieving::EventStream::Consumer::WtfWhoClosedMyShit
|
75
|
-
expect(consumer).to be_finished
|
76
101
|
end
|
77
102
|
end
|
78
103
|
|
79
104
|
describe 'each' do
|
80
|
-
it 'loops through and yields all events
|
105
|
+
it 'loops through and yields all events' do
|
81
106
|
producer.record_result :inspect, 100, 2
|
82
|
-
|
107
|
+
finish!
|
83
108
|
|
84
109
|
events = []
|
85
110
|
consumer.each { |e| events << e }
|
86
|
-
finish_event = events.find { |e| e.kind_of? Events::Finish }
|
87
111
|
line_result = events.find { |e| e.kind_of? Events::LineResult }
|
88
112
|
exitstatus = events.find { |e| e.kind_of? Events::Exitstatus }
|
89
|
-
expect(finish_event).to be_nil
|
90
113
|
expect(line_result.line_number).to eq 100
|
91
114
|
expect(exitstatus.value).to eq 0
|
92
115
|
end
|
93
116
|
|
94
117
|
it 'stops looping if there is no more input' do
|
95
|
-
|
96
|
-
expect(consumer.each.map { |e| e }).to eq [
|
118
|
+
finish!
|
119
|
+
expect(consumer.each.map { |e| e }).to eq [
|
120
|
+
Events::NumLines.new(0),
|
121
|
+
Events::Exitstatus.new(0),
|
122
|
+
]
|
97
123
|
end
|
98
124
|
|
99
125
|
it 'returns nil' do
|
100
|
-
|
126
|
+
finish!
|
101
127
|
expect(consumer.each { 1 }).to eq nil
|
102
128
|
end
|
103
129
|
|
104
130
|
it 'returns an enumerator if not given a block' do
|
105
|
-
|
131
|
+
finish!
|
106
132
|
expect(consumer.each.map &:class).to include Events::Exitstatus
|
107
133
|
end
|
108
134
|
end
|
@@ -257,6 +283,29 @@ module SeeingIsBelieving::EventStream
|
|
257
283
|
end
|
258
284
|
end
|
259
285
|
|
286
|
+
describe 'max_line_captures (value and recording)' do
|
287
|
+
it 'is infinity by default' do
|
288
|
+
expect(producer.max_line_captures).to eq Float::INFINITY
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'emits the event and sets the max_line_captures' do
|
292
|
+
producer.record_max_line_captures 123
|
293
|
+
expect(producer.max_line_captures).to eq 123
|
294
|
+
expect(consumer.call).to eq Events::MaxLineCaptures.new(123)
|
295
|
+
end
|
296
|
+
|
297
|
+
it 'interprets numbers' do
|
298
|
+
producer.record_max_line_captures 12
|
299
|
+
expect(consumer.call).to eq Events::MaxLineCaptures.new(12)
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'interprets infinity' do
|
303
|
+
producer.record_max_line_captures Float::INFINITY
|
304
|
+
expect(consumer.call).to eq Events::MaxLineCaptures.new(Float::INFINITY)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
|
260
309
|
describe 'exceptions' do
|
261
310
|
def record_exception(linenum=nil, &raises_exception)
|
262
311
|
raises_exception.call
|
@@ -326,45 +375,45 @@ module SeeingIsBelieving::EventStream
|
|
326
375
|
context 'recorded line number | line num is provided | it knows the file | exception comes from within file' do
|
327
376
|
let(:exception) { begin; raise "zomg"; rescue; $!; end }
|
328
377
|
let(:linenum) { __LINE__ - 1 }
|
329
|
-
|
378
|
+
example "provided one | true | true | true" do
|
330
379
|
producer.filename = __FILE__
|
331
380
|
producer.record_exception 12, exception
|
332
381
|
assert_exception consumer.call, recorded_line_no: 12
|
333
382
|
end
|
334
|
-
|
383
|
+
example "provided one | true | true | false" do
|
335
384
|
exception.backtrace.replace ['otherfile.rb']
|
336
385
|
producer.record_exception 12, exception
|
337
386
|
producer.filename = __FILE__
|
338
387
|
assert_exception consumer.call, recorded_line_no: 12
|
339
388
|
end
|
340
|
-
|
389
|
+
example "provided one | true | false | true" do
|
341
390
|
producer.filename = nil
|
342
391
|
producer.record_exception 12, exception
|
343
392
|
assert_exception consumer.call, recorded_line_no: 12
|
344
393
|
end
|
345
|
-
|
394
|
+
example "provided one | true | false | false" do
|
346
395
|
exception.backtrace.replace ['otherfile.rb']
|
347
396
|
producer.filename = nil
|
348
397
|
producer.record_exception 12, exception
|
349
398
|
assert_exception consumer.call, recorded_line_no: 12
|
350
399
|
end
|
351
|
-
|
400
|
+
example "from backtrace | false | true | true" do
|
352
401
|
producer.filename = __FILE__
|
353
402
|
producer.record_exception nil, exception
|
354
403
|
assert_exception consumer.call, recorded_line_no: linenum
|
355
404
|
end
|
356
|
-
|
405
|
+
example "-1 | false | true | false" do
|
357
406
|
exception.backtrace.replace ['otherfile.rb']
|
358
407
|
producer.filename = __FILE__
|
359
408
|
producer.record_exception nil, exception
|
360
409
|
assert_exception consumer.call, recorded_line_no: -1
|
361
410
|
end
|
362
|
-
|
411
|
+
example "-1 | false | false | true" do
|
363
412
|
producer.filename = nil
|
364
413
|
producer.record_exception nil, exception
|
365
414
|
assert_exception consumer.call, recorded_line_no: -1
|
366
415
|
end
|
367
|
-
|
416
|
+
example "-1 | false | false | false" do
|
368
417
|
exception.backtrace.replace ['otherfile.rb']
|
369
418
|
producer.filename = nil
|
370
419
|
producer.record_exception nil, exception
|
@@ -373,40 +422,83 @@ module SeeingIsBelieving::EventStream
|
|
373
422
|
end
|
374
423
|
end
|
375
424
|
|
425
|
+
describe 'seeing is believing version' do
|
426
|
+
describe 'recording the version' do
|
427
|
+
it 'emits the version info' do
|
428
|
+
producer.record_sib_version '1.2.3'
|
429
|
+
expect(consumer.call).to eq Events::SiBVersion.new("1.2.3")
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
specify 'version return the version, if it has been set' do
|
434
|
+
expect(producer.version).to eq nil
|
435
|
+
producer.record_sib_version '4.5.6'
|
436
|
+
expect(producer.version).to eq '4.5.6'
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
describe 'record_ruby_version' do
|
441
|
+
it 'emits the ruby version info' do
|
442
|
+
producer.record_ruby_version 'o.m.g.'
|
443
|
+
expect(consumer.call).to eq Events::RubyVersion.new('o.m.g.')
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
describe 'record_filename' do
|
448
|
+
it 'sets the filename' do
|
449
|
+
producer.record_filename 'this-iz-mah-file.rb'
|
450
|
+
expect(producer.filename).to eq 'this-iz-mah-file.rb'
|
451
|
+
end
|
452
|
+
it 'emits the filename' do
|
453
|
+
producer.record_filename 'this-iz-mah-file.rb'
|
454
|
+
expect(consumer.call).to eq Events::Filename.new('this-iz-mah-file.rb')
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
376
458
|
describe 'stdout' do
|
377
|
-
it 'is
|
378
|
-
|
379
|
-
expect(consumer.call).to eq Events::Stdout.new("this is the stdout
|
459
|
+
it 'is emitted along with the events from the event stream' do
|
460
|
+
stdout_producer.puts "this is the stdout¡"
|
461
|
+
expect(consumer.call).to eq Events::Stdout.new("this is the stdout¡\n")
|
462
|
+
end
|
463
|
+
specify 'each line is emitted as an event' do
|
464
|
+
stdout_producer.puts "first"
|
465
|
+
stdout_producer.puts "second\nthird"
|
466
|
+
expect(consumer.call).to eq Events::Stdout.new("first\n")
|
467
|
+
expect(consumer.call).to eq Events::Stdout.new("second\n")
|
468
|
+
expect(consumer.call).to eq Events::Stdout.new("third\n")
|
380
469
|
end
|
381
470
|
end
|
382
471
|
|
383
472
|
describe 'stderr' do
|
384
|
-
it 'is
|
385
|
-
|
386
|
-
expect(consumer.call).to eq Events::Stderr.new("this is the stderr
|
473
|
+
it 'is emitted along with the events from the event stream' do
|
474
|
+
stderr_producer.puts "this is the stderr¡"
|
475
|
+
expect(consumer.call).to eq Events::Stderr.new("this is the stderr¡\n")
|
476
|
+
end
|
477
|
+
specify 'each line is emitted as an event' do
|
478
|
+
stderr_producer.puts "first"
|
479
|
+
stderr_producer.puts "second\nthird"
|
480
|
+
expect(consumer.call).to eq Events::Stderr.new("first\n")
|
481
|
+
expect(consumer.call).to eq Events::Stderr.new("second\n")
|
482
|
+
expect(consumer.call).to eq Events::Stderr.new("third\n")
|
387
483
|
end
|
388
484
|
end
|
389
485
|
|
486
|
+
|
390
487
|
describe 'finish!' do
|
391
488
|
def final_event(producer, consumer, event_class)
|
392
|
-
|
393
|
-
consumer.call(
|
489
|
+
finish!
|
490
|
+
consumer.call(2).find { |e| e.class == event_class }
|
394
491
|
end
|
395
492
|
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
end
|
406
|
-
|
407
|
-
it 'is infinity by default' do
|
408
|
-
expect(final_event(producer, consumer, Events::MaxLineCaptures).value).to eq Float::INFINITY
|
409
|
-
end
|
493
|
+
it 'stops the producer from producing' do
|
494
|
+
read, write = IO.pipe
|
495
|
+
producer = SeeingIsBelieving::EventStream::Producer.new write
|
496
|
+
producer.finish!
|
497
|
+
read.gets
|
498
|
+
read.gets
|
499
|
+
producer.record_filename("zomg")
|
500
|
+
write.close
|
501
|
+
expect(read.gets).to eq nil
|
410
502
|
end
|
411
503
|
|
412
504
|
describe 'num_lines' do
|
@@ -443,13 +535,12 @@ module SeeingIsBelieving::EventStream
|
|
443
535
|
expect(final_event(producer, consumer, Events::Exitstatus).value).to eq 74
|
444
536
|
end
|
445
537
|
end
|
538
|
+
end
|
446
539
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
end
|
452
|
-
end
|
540
|
+
specify 'if an incomprehensible event is received, it raises an UnknownEvent' do
|
541
|
+
eventstream_producer.puts "this is nonsense!"
|
542
|
+
eventstream_producer.close
|
543
|
+
expect{ consumer.call }.to raise_error SeeingIsBelieving::EventStream::Consumer::UnknownEvent, /nonsense/
|
453
544
|
end
|
454
545
|
end
|
455
546
|
end
|