peeek 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  class Peeek
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'
3
3
  end
@@ -19,7 +19,6 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ['lib']
21
21
 
22
- spec.add_development_dependency 'bundler', '~> 1.3'
23
22
  spec.add_development_dependency 'rake'
24
23
  spec.add_development_dependency 'rspec'
25
24
  end
@@ -19,60 +19,39 @@ def sample_exception
19
19
  Peeek::Call::Exception.new(:exception)
20
20
  end
21
21
 
22
- describe Peeek::Call, '#initialize' do
23
- it 'raises ArgumentError if the result is invalid' do
24
- lambda { sample_call(:result => :result) }.should raise_error(ArgumentError, 'invalid as result')
25
- end
26
- end
27
-
28
- describe Peeek::Call, '#hook' do
29
- it 'returns the value when constructed the call' do
30
- hook = :hook
31
- call = sample_call(:hook => hook)
32
- call.hook.should == hook
33
- end
34
- end
35
-
36
- describe Peeek::Call, '#backtrace' do
37
- it 'returns the value when constructed the call' do
38
- call = sample_call
39
- call.backtrace.should == sample_backtrace
40
- end
41
- end
42
-
43
- describe Peeek::Call, '#file' do
44
- it 'returns name of top file on the backtrace' do
45
- call = sample_call
46
- call.file.should == 'koyomi.rb'
22
+ describe Peeek::Call do
23
+ describe '#initialize' do
24
+ it do
25
+ expect {
26
+ described_class.new(:hook, ["koyomi.rb:7:in `print'"], '%s (%d)', ['Koyomi', 18], :result)
27
+ }.to raise_error(ArgumentError, 'invalid as result')
28
+ end
47
29
  end
48
- end
49
30
 
50
- describe Peeek::Call, '#line' do
51
- it 'returns top line number on the backtrace' do
52
- call = sample_call
53
- call.line.should == 7
54
- end
55
- end
31
+ context 'basic instance attributes' do
32
+ subject {
33
+ described_class.new(
34
+ :hook,
35
+ ["koyomi.rb:7:in `print'", "koyomi.rb:21:in `<main>'"],
36
+ '%s (%d)',
37
+ ['Koyomi', 18],
38
+ Peeek::Call::ReturnValue.new('Koyomi (18)')
39
+ )
40
+ }
56
41
 
57
- describe Peeek::Call, '#receiver' do
58
- it 'returns the value when constructed the call' do
59
- call = sample_call
60
- call.receiver.should == '%s (%d)'
42
+ its(:hook) { should == :hook }
43
+ its(:backtrace) { should == ["koyomi.rb:7:in `print'", "koyomi.rb:21:in `<main>'"] }
44
+ its(:file) { should == 'koyomi.rb' }
45
+ its(:line) { should == 7 }
46
+ its(:receiver) { should == '%s (%d)' }
47
+ its(:arguments) { should == ['Koyomi', 18] }
48
+ its(:result) { should == Peeek::Call::ReturnValue.new('Koyomi (18)') }
61
49
  end
62
50
  end
63
51
 
64
- describe Peeek::Call, '#arguments' do
65
- it 'returns the value when constructed the call' do
66
- call = sample_call
67
- call.arguments.should == ['Koyomi', 18]
68
- end
69
- end
70
-
71
- describe Peeek::Call, '#result' do
72
- it 'returns the value when constructed the call' do
73
- result = sample_return_value
74
- call = sample_call(:result => result)
75
- call.result.should == result
52
+ describe Peeek::Call, '#initialize' do
53
+ it 'raises ArgumentError if the result is invalid' do
54
+ lambda { sample_call(:result => :result) }.should raise_error(ArgumentError, 'invalid as result')
76
55
  end
77
56
  end
78
57
 
@@ -0,0 +1,331 @@
1
+ require 'peeek/cli/options'
2
+
3
+ describe Peeek::CLI::Options do
4
+ let(:default_options) { described_class.new }
5
+
6
+ describe 'deafult options' do
7
+ subject { default_options }
8
+
9
+ context 'encoding options', :if => described_class.encoding_options_enabled? do
10
+ its(:external_encoding) { should == Encoding.default_external }
11
+ its(:internal_encoding) { should == Encoding.default_internal }
12
+ end
13
+
14
+ its(:debug) { should be_false }
15
+ its(:verbose) { should be_false }
16
+ its(:working_directory) { should be_nil }
17
+ its(:directories_to_load) { should == [] }
18
+ its(:required_libraries) { should == [] }
19
+ its(:hook_targets) { should == [] }
20
+ its(:command) { should == '' }
21
+ its(:arguments) { should == [] }
22
+
23
+ it { should_not be_version_requested }
24
+ it { should_not be_command_given }
25
+ it { should_not be_arguments_given }
26
+ it { should be_continued }
27
+ end
28
+
29
+ subject { described_class.new(argv) }
30
+
31
+ describe '-C option' do
32
+ let(:argv) { %w(-C directory) }
33
+
34
+ its(:working_directory) { should == 'directory' }
35
+ end
36
+
37
+ shared_examples_for 'accepting debug option' do
38
+ let(:argv) { [option] }
39
+
40
+ its(:debug) { should be_true }
41
+ end
42
+
43
+ describe '-d option' do
44
+ it_behaves_like 'accepting debug option' do
45
+ let(:option) { '-d' }
46
+ end
47
+ end
48
+
49
+ describe '--debug option' do
50
+ it_behaves_like 'accepting debug option' do
51
+ let(:option) { '--debug' }
52
+ end
53
+ end
54
+
55
+ describe '-e option' do
56
+ let(:option) { '-e' }
57
+
58
+ context 'when a command is specified' do
59
+ let(:argv) { [option, 'puts "%s (%d)" % ["Koyomi", 18]'] }
60
+
61
+ it { should be_command_given }
62
+ its(:command) { should == 'puts "%s (%d)" % ["Koyomi", 18]' }
63
+ end
64
+
65
+ context 'when multiple commands are specified' do
66
+ let(:argv) { [option, 'format = "%s (%d)"', option, 'puts format % ["Koyomi", 18]'] }
67
+
68
+ it { should be_command_given }
69
+ its(:command) { should == 'format = "%s (%d)"; puts format % ["Koyomi", 18]' }
70
+ end
71
+
72
+ context 'when commands is omitted' do
73
+ let(:argv) { [option] }
74
+
75
+ it do
76
+ lambda { subject }.should raise_error(OptionParser::MissingArgument)
77
+ end
78
+ end
79
+ end
80
+
81
+ shared_examples_for 'accepting encoding option' do
82
+ let(:utf_8) { Encoding::UTF_8 }
83
+ let(:us_ascii) { Encoding::US_ASCII }
84
+
85
+ context 'when both external encoding and internal encoding are specifid' do
86
+ let(:argv) { [option, 'utf-8:us-ascii'] }
87
+
88
+ its(:external_encoding) { should == utf_8 }
89
+ its(:internal_encoding) { should == us_ascii }
90
+ end
91
+
92
+ context 'when external encoding only is specified' do
93
+ let(:argv) { [option, 'utf-8'] }
94
+
95
+ its(:external_encoding) { should == utf_8 }
96
+ its(:internal_encoding) { should == default_options.internal_encoding }
97
+ end
98
+
99
+ context 'when internal encoding only is specified' do
100
+ let(:argv) { [option, ':us-ascii'] }
101
+
102
+ its(:external_encoding) { should == default_options.external_encoding }
103
+ its(:internal_encoding) { should == us_ascii }
104
+ end
105
+
106
+ context 'when external encoding is unknown encoding name' do
107
+ let(:argv) { [option, 'undefined-encoding'] }
108
+
109
+ it do
110
+ lambda { subject }.should raise_error(ArgumentError, 'unknown encoding name - undefined-encoding')
111
+ end
112
+ end
113
+
114
+ context 'when internal encoding is unknown encoding name' do
115
+ let(:argv) { [option, ':undefined-encoding'] }
116
+
117
+ it do
118
+ lambda { subject }.should raise_error(ArgumentError, 'unknown encoding name - undefined-encoding')
119
+ end
120
+ end
121
+
122
+ context 'when encodings is omitted' do
123
+ let(:argv) { [option] }
124
+
125
+ it do
126
+ lambda { subject }.should raise_error(OptionParser::MissingArgument)
127
+ end
128
+ end
129
+ end
130
+
131
+ describe '-E option', :if => described_class.encoding_options_enabled? do
132
+ it_behaves_like 'accepting encoding option' do
133
+ let(:option) { '-E' }
134
+ end
135
+ end
136
+
137
+ describe '--encoding option', :if => described_class.encoding_options_enabled? do
138
+ it_behaves_like 'accepting encoding option' do
139
+ let(:option) { '--encoding' }
140
+ end
141
+ end
142
+
143
+ describe '-H option' do
144
+ let(:option) { '-H' }
145
+
146
+ context 'when a hook specifier is specified' do
147
+ let(:argv) { [option, 'String#%'] }
148
+
149
+ its(:hook_targets) {
150
+ should == [Peeek::Hook::Specifier.new('String', '#', :%)]
151
+ }
152
+ end
153
+
154
+ context 'when multiple hook specifiers is specified' do
155
+ let(:argv) { [option, 'String#%', option, 'String#index'] }
156
+
157
+ its(:hook_targets) {
158
+ should == [
159
+ Peeek::Hook::Specifier.new('String', '#', :%),
160
+ Peeek::Hook::Specifier.new('String', '#', :index)
161
+ ]
162
+ }
163
+ end
164
+
165
+ context 'when hook specifiers is duplicated' do
166
+ let(:argv) { [option, 'String#%', option, 'String#%'] }
167
+
168
+ its(:hook_targets) {
169
+ should == [Peeek::Hook::Specifier.new('String', '#', :%)]
170
+ }
171
+ end
172
+
173
+ context 'when hook specifiers is omitted' do
174
+ let(:argv) { [option] }
175
+
176
+ it do
177
+ lambda { subject }.should raise_error(OptionParser::MissingArgument)
178
+ end
179
+ end
180
+ end
181
+
182
+ shared_examples_for 'accepting multiple values' do |attr|
183
+ context 'when a value is specified' do
184
+ let(:argv) { [option, 'value'] }
185
+
186
+ its(attr) { should == %w(value) }
187
+ end
188
+
189
+ context 'when multiple values is specified' do
190
+ let(:argv) { [option, 'value1', option, 'value2'] }
191
+
192
+ its(attr) { should == %w(value1 value2) }
193
+ end
194
+
195
+ context 'when values is duplicated' do
196
+ let(:argv) { [option, 'value', option, 'value'] }
197
+
198
+ its(attr) { should == %w(value) }
199
+ end
200
+
201
+ context 'when value is omitted' do
202
+ let(:argv) { [option] }
203
+
204
+ it do
205
+ lambda { subject }.should raise_error(OptionParser::MissingArgument)
206
+ end
207
+ end
208
+ end
209
+
210
+ describe '-I option' do
211
+ it_behaves_like 'accepting multiple values', :directories_to_load do
212
+ let(:option) { '-I' }
213
+ end
214
+ end
215
+
216
+ describe '-r option' do
217
+ it_behaves_like 'accepting multiple values', :required_libraries do
218
+ let(:option) { '-r' }
219
+ end
220
+ end
221
+
222
+ shared_examples_for 'accepting version option' do
223
+ let(:argv) { [option] }
224
+
225
+ it { should be_version_requested }
226
+ end
227
+
228
+ describe '-v option' do
229
+ let(:argv) { %w(-v) }
230
+
231
+ it { should be_version_requested }
232
+ its(:verbose) { should be_true }
233
+ end
234
+
235
+ shared_examples_for 'accepting verbose option' do
236
+ let(:argv) { [option] }
237
+
238
+ its(:verbose) { should be_true }
239
+ end
240
+
241
+ describe '-w option' do
242
+ it_behaves_like 'accepting verbose option' do
243
+ let(:option) { '-w' }
244
+ end
245
+ end
246
+
247
+ describe '--verbose option' do
248
+ it_behaves_like 'accepting verbose option' do
249
+ let(:option) { '--verbose' }
250
+ end
251
+ end
252
+
253
+ describe '-W option' do
254
+ let(:option) { '-W' }
255
+
256
+ context 'when the leve is 0' do
257
+ let(:argv) { ["#{option}0"] }
258
+
259
+ its(:verbose) { should be_nil }
260
+ end
261
+
262
+ context 'when the level is 1' do
263
+ let(:argv) { ["#{option}1"] }
264
+
265
+ its(:verbose) { should be_false }
266
+ end
267
+
268
+ context 'when the leve is 2' do
269
+ let(:argv) { ["#{option}2"] }
270
+
271
+ its(:verbose) { should be_true }
272
+ end
273
+
274
+ context 'when the level is other' do
275
+ let(:argv) { ["#{option}3"] }
276
+
277
+ it do
278
+ lambda { subject }.should raise_error(ArgumentError, 'invalid warning level - 3')
279
+ end
280
+ end
281
+
282
+ context 'when a level is omitted' do
283
+ let(:argv) { [option] }
284
+
285
+ its(:verbose) { should be_true }
286
+ end
287
+ end
288
+
289
+ describe '--version option' do
290
+ let(:argv) { %w(--version) }
291
+
292
+ it { should be_version_requested }
293
+ it { should_not be_continued }
294
+ end
295
+
296
+ shared_examples_for 'accepting help option' do
297
+ let(:argv) { [option] }
298
+
299
+ it do
300
+ lambda { subject }.should raise_error(Peeek::CLI::Help, /^Usage: peeek/)
301
+ end
302
+ end
303
+
304
+ describe '-h option' do
305
+ it_behaves_like 'accepting help option' do
306
+ let(:option) { '-h' }
307
+ end
308
+ end
309
+
310
+ describe '--help option' do
311
+ it_behaves_like 'accepting help option' do
312
+ let(:option) { '--help' }
313
+ end
314
+ end
315
+
316
+ describe 'extra options' do
317
+ context 'when extra options is specified' do
318
+ let(:argv) { %w(-HString#% example.rb) }
319
+
320
+ it { should be_arguments_given }
321
+ its(:arguments) { should == %w(example.rb) }
322
+ end
323
+
324
+ context 'when extra options is omitted' do
325
+ let(:argv) { ['-HString#%', %(-e'puts "%s (%d)" % ["Koyomi", 18]')] }
326
+
327
+ it { should_not be_arguments_given }
328
+ its(:arguments) { should be_empty }
329
+ end
330
+ end
331
+ end
@@ -0,0 +1,2 @@
1
+ puts "#{File.basename(__FILE__)} here"
2
+ puts ARGV
@@ -0,0 +1,254 @@
1
+ require 'peeek/cli'
2
+ require 'stringio'
3
+ require 'pathname'
4
+
5
+ describe Peeek::CLI do
6
+ let(:test_input) { StringIO.new }
7
+ let(:test_output) { StringIO.new }
8
+
9
+ describe '#initialize' do
10
+ it "calls #{described_class}::Options.new with the argv" do
11
+ Peeek::CLI::Options.should_receive(:new).with(['-v'])
12
+ described_class.new(test_input, test_output, ['-v'])
13
+ end
14
+
15
+ context 'when need help' do
16
+ it 'writes the help message to the output IO' do
17
+ begin
18
+ described_class.new(test_input, test_output, ['-h'])
19
+ rescue SystemExit
20
+ end
21
+
22
+ test_output.string.should =~ /^Usage: peeek/
23
+ end
24
+
25
+ it 'raises SystemExit' do
26
+ raised = begin
27
+ described_class.new(test_input, test_output, ['-h'])
28
+ false
29
+ rescue SystemExit
30
+ true
31
+ end
32
+
33
+ raised.should be_true
34
+ end
35
+ end
36
+ end
37
+
38
+ describe '#options' do
39
+ before { Peeek::CLI::Options.stub!(:new => 'options') }
40
+
41
+ subject { described_class.new(test_input, test_output, ['-v']).options }
42
+
43
+ it 'returns the options that was set when construct' do
44
+ should == 'options'
45
+ end
46
+ end
47
+
48
+ describe '#run' do
49
+ def cli(command = nil)
50
+ argv = command ? ['-e', command] : []
51
+ cli = Peeek::CLI.new(test_input, test_output, argv)
52
+ yield cli.options if block_given?
53
+ cli
54
+ end
55
+
56
+ def local(expr)
57
+ value = eval(expr)
58
+ yield
59
+ eval("#{expr} = value")
60
+ end
61
+
62
+ it 'sets options.external_encoding to Encoding.default_external', :if => Peeek::CLI::Options.encoding_options_enabled? do
63
+ cli = cli('print Encoding.default_external') do |options|
64
+ options.external_encoding = 'utf-8'
65
+ end
66
+
67
+ local 'Encoding.default_external' do
68
+ cli.run(binding)
69
+ test_output.string.should == 'UTF-8'
70
+ end
71
+ end
72
+
73
+ it 'sets options.internal_encoding to Encoding.default_internal', :if => Peeek::CLI::Options.encoding_options_enabled? do
74
+ cli = cli('print Encoding.default_internal') do |options|
75
+ options.internal_encoding = 'us-ascii'
76
+ end
77
+
78
+ local 'Encoding.default_internal' do
79
+ cli.run(binding)
80
+ test_output.string.should == 'US-ASCII'
81
+ end
82
+ end
83
+
84
+ it 'sets false to $DEBUG if options.debug is false' do
85
+ cli = cli('print $DEBUG.inspect') do |options|
86
+ options.debug = false
87
+ end
88
+
89
+ local '$DEBUG' do
90
+ cli.run(binding)
91
+ test_output.string.should == 'false'
92
+ end
93
+ end
94
+
95
+ it 'sets true to $DEBUG if options.debug is true' do
96
+ cli = cli('print $DEBUG.inspect') do |options|
97
+ options.debug = true
98
+ end
99
+
100
+ local '$DEBUG' do
101
+ cli.run(binding)
102
+ test_output.string.should == 'true'
103
+ end
104
+ end
105
+
106
+ it 'sets nil to $VERBOSE if options.verbose is nil' do
107
+ cli = cli('print $VERBOSE.inspect') do |options|
108
+ options.verbose = nil
109
+ end
110
+
111
+ local '$VERBOSE' do
112
+ cli.run(binding)
113
+ test_output.string.should == 'nil'
114
+ end
115
+ end
116
+
117
+ it 'sets false to $VERBOSE if options.verbose is false' do
118
+ cli = cli('print $VERBOSE.inspect') do |options|
119
+ options.verbose = false
120
+ end
121
+
122
+ local '$VERBOSE' do
123
+ cli.run(binding)
124
+ test_output.string.should == 'false'
125
+ end
126
+ end
127
+
128
+ it 'sets true to $VERBOSE if options.verbose is true' do
129
+ cli = cli('print $VERBOSE.inspect') do |options|
130
+ options.verbose = true
131
+ end
132
+
133
+ local '$VERBOSE' do
134
+ cli.run(binding)
135
+ test_output.string.should == 'true'
136
+ end
137
+ end
138
+
139
+ it 'changes current directory to options.working_directory' do
140
+ cli = cli('print Dir.pwd') do |options|
141
+ options.working_directory = '..'
142
+ end
143
+
144
+ current_dir = Pathname(Dir.pwd)
145
+ cli.run(binding)
146
+ test_output.string.should == current_dir.parent.to_s
147
+ Dir.chdir(current_dir.to_s)
148
+ end
149
+
150
+ it 'adds options.directories_to_load to head of $LOAD_PATH' do
151
+ cli = cli('puts $LOAD_PATH') do |options|
152
+ options.directories_to_load = %w(.. ../..)
153
+ end
154
+
155
+ output = StringIO.new
156
+ output.puts('..')
157
+ output.puts('../..')
158
+ output.puts($LOAD_PATH)
159
+
160
+ cli.run(binding)
161
+ test_output.string.should == output.string
162
+ 2.times { $LOAD_PATH.shift }
163
+ end
164
+
165
+ it 'loads options.required_libraries' do
166
+ cli = cli('print defined? Net::HTTP') do |options|
167
+ options.required_libraries = %w(net/http)
168
+ end
169
+
170
+ defined?(Net::HTTP).should be_nil # assert
171
+ cli.run(binding)
172
+ test_output.string.should_not be_nil
173
+ end
174
+
175
+ it 'prints version' do
176
+ cli = cli('puts "peeek"') do |options|
177
+ options.stub!(:version_requested? => true)
178
+ end
179
+
180
+ output = StringIO.new
181
+ output.puts("peeek-#{Peeek::VERSION}")
182
+ output.puts('peeek')
183
+
184
+ cli.run(binding)
185
+ test_output.string.should == output.string
186
+ end
187
+
188
+ it 'hooks options.hook_targets' do
189
+ cli = cli('print Peeek.current.hooks.inspect') do |options|
190
+ options.hook_targets = [Peeek::Hook::Specifier.new('String', '#', :%)]
191
+ end
192
+
193
+ cli.run(binding)
194
+ test_output.string.should == '[#<Peeek::Hook String#% (linked)>]'
195
+ end
196
+
197
+ it 'sets options.arguments to ARGV' do
198
+ cli = cli('puts ARGV') do |options|
199
+ options.arguments = %w(arg1 arg2)
200
+ end
201
+
202
+ output = StringIO.new
203
+ output.puts('arg1')
204
+ output.puts('arg2')
205
+
206
+ cli.run(binding)
207
+ test_output.string.should == output.string
208
+ end
209
+
210
+ it 'aborts process if options.continued? is false' do
211
+ cli = cli('puts "peeek"') do |options|
212
+ options.stub!(:version_requested? => true, :continued? => false)
213
+ end
214
+
215
+ output = StringIO.new
216
+ output.puts("peeek-#{Peeek::VERSION}")
217
+
218
+ cli.run(binding)
219
+ test_output.string.should == output.string
220
+ end
221
+
222
+ it 'loads head of options.arguments as program file with tail of options.arguments' do
223
+ cli = cli do |options|
224
+ options.arguments = [File.join(File.dirname(__FILE__), 'cli_sample.rb'), *%w(arg1 arg2)]
225
+ end
226
+
227
+ output = StringIO.new
228
+ output.puts('cli_sample.rb here')
229
+ output.puts('arg1')
230
+ output.puts('arg2')
231
+
232
+ cli.run(binding)
233
+ test_output.string.should == output.string
234
+ end
235
+
236
+ it 'evaluates content of input' do
237
+ cli = cli()
238
+ test_input.print('print "peeek"')
239
+ test_input.rewind
240
+ cli.run(binding)
241
+ test_output.string.should == 'peeek'
242
+ end
243
+
244
+ it 'removes information about peeek gem from the backtrace of the raised exception' do
245
+ cli = cli('fail')
246
+
247
+ begin
248
+ line = __LINE__; cli.run(binding)
249
+ rescue => e
250
+ e.backtrace[1].should =~ /#{__FILE__}:#{line}/
251
+ end
252
+ end
253
+ end
254
+ end