peeek 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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