1
0
Fork 0
mirror of https://github.com/pry/pry.git synced 2022-11-09 12:35:05 -05:00
pry--pry/spec/helper.rb

376 lines
7.8 KiB
Ruby
Raw Normal View History

unless Object.const_defined? 'Pry'
$:.unshift File.expand_path '../../lib', __FILE__
require 'pry'
end
puts "Ruby v#{RUBY_VERSION} (#{defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"}), Pry v#{Pry::VERSION}, method_source v#{MethodSource::VERSION}, CodeRay v#{CodeRay::VERSION}, Slop v#{Slop::VERSION}"
2011-09-12 04:06:47 -04:00
require 'bacon'
require 'open4'
2012-09-09 00:42:02 -04:00
# Colorize output (based on greeneggs (c) 2009 Michael Fleet)
# TODO: Make own gem (assigned to rking)
2012-09-09 00:19:15 -04:00
module Bacon
2012-09-09 00:46:37 -04:00
COLORS = {'F' => 31, 'E' => 35, 'M' => 33, '.' => 32}
USE_COLOR = !(ENV['NO_PRY_COLORED_BACON'] == 'true') && Pry::Helpers::BaseHelpers.use_ansi_codes?
2012-09-09 00:19:15 -04:00
2012-09-09 00:42:02 -04:00
module TestUnitOutput
def handle_requirement(description)
error = yield
2012-09-09 00:19:15 -04:00
2012-09-09 00:42:02 -04:00
if error.empty?
print colorize_string('.')
else
print colorize_string(error[0..0])
end
2012-09-09 00:19:15 -04:00
end
2012-09-09 00:42:02 -04:00
def handle_summary
puts
puts ErrorLog if Backtraces
out = "%d tests, %d assertions, %d failures, %d errors" %
Counter.values_at(:specifications, :requirements, :failed, :errors)
if Counter.values_at(:failed, :errors).inject(:+) > 0
puts colorize_string(out, 'F')
else
puts colorize_string(out, '.')
end
2012-09-09 00:19:15 -04:00
end
2012-09-09 00:42:02 -04:00
def colorize_string(text, color = nil)
2012-09-09 00:46:37 -04:00
if USE_COLOR
2012-09-09 00:42:02 -04:00
"\e[#{ COLORS[color || text] }m#{ text }\e[0m"
else
text
end
2012-09-09 00:19:15 -04:00
end
end
end
# Reset toplevel binding at the beginning of each test case.
module Bacon
class Context
alias _real_it it
def it(description, &block)
Pry.toplevel_binding = nil
_real_it(description, &block)
end
end
end
Change behavior of `cd -` command Since banister begged me to do that... completely rewrite `cd -` command (implemetation is much simpler now). This commit brings such changes: * completely rewrite behavior of `cd -` command; * implement ScratchPad aka Pad for unit testing purposes (by banister); * use Pad riches in the unit tests for `cd -` command; * remove verbose and clunky unit tests; This commit brings new meaning to the `cd -` command. The main difference is that the new command saves entire binding stack, not just the last binding. Let me show you an example of the variance between these two implemetations: * Old `cd -` implementation saves *only* last binding. With our next `cd -` invocation our interjacent results are lost: [1] pry(main)> cd 1/2/3/../4 [2] pry(4):3> cd - [3] pry(main)> cd - [4] pry(4):1> nesting Nesting status: -- 0. main (Pry top level) 1. 4 Also, there are a few bugs in old `cd -` command: * you type `cd :foo`, `cd 1/2/3` and `cd -`. The last command relocates you to the scope of `3` (leaves you where you was), when `:foo` is expected; * you type `cd :foo`, `cd 1/2/3/../4`, `cd -`. The last command relocates you to the scope of `3`, when `:foo` is expected. * New and shiny `cd -` is devoid of those shortcomings: [1] pry(main)> cd 1/2/3/../4 [2] pry(4):3> cd - [3] pry(main)> cd - [4] pry(4):3> nesting Nesting status: -- 0. main (Pry top level) 1. 1 2. 2 3. 4 As I said before, this solution is *much* simpler and less error-prone. Signed-off-by: Kyrylo Silin <kyrylosilin@gmail.com>
2012-06-27 07:54:07 -04:00
# A global space for storing temporary state during tests.
Pad = OpenStruct.new
def Pad.clear
Change behavior of `cd -` command Since banister begged me to do that... completely rewrite `cd -` command (implemetation is much simpler now). This commit brings such changes: * completely rewrite behavior of `cd -` command; * implement ScratchPad aka Pad for unit testing purposes (by banister); * use Pad riches in the unit tests for `cd -` command; * remove verbose and clunky unit tests; This commit brings new meaning to the `cd -` command. The main difference is that the new command saves entire binding stack, not just the last binding. Let me show you an example of the variance between these two implemetations: * Old `cd -` implementation saves *only* last binding. With our next `cd -` invocation our interjacent results are lost: [1] pry(main)> cd 1/2/3/../4 [2] pry(4):3> cd - [3] pry(main)> cd - [4] pry(4):1> nesting Nesting status: -- 0. main (Pry top level) 1. 4 Also, there are a few bugs in old `cd -` command: * you type `cd :foo`, `cd 1/2/3` and `cd -`. The last command relocates you to the scope of `3` (leaves you where you was), when `:foo` is expected; * you type `cd :foo`, `cd 1/2/3/../4`, `cd -`. The last command relocates you to the scope of `3`, when `:foo` is expected. * New and shiny `cd -` is devoid of those shortcomings: [1] pry(main)> cd 1/2/3/../4 [2] pry(4):3> cd - [3] pry(main)> cd - [4] pry(4):3> nesting Nesting status: -- 0. main (Pry top level) 1. 1 2. 2 3. 4 As I said before, this solution is *much* simpler and less error-prone. Signed-off-by: Kyrylo Silin <kyrylosilin@gmail.com>
2012-06-27 07:54:07 -04:00
@table = {}
end
2012-01-24 03:43:20 -05:00
# turn warnings off (esp for Pry::Hooks which will generate warnings
# in tests)
$VERBOSE = nil
# inject a variable into a binding
def inject_var(name, value, b)
Thread.current[:__pry_local__] = value
b.eval("#{name} = Thread.current[:__pry_local__]")
ensure
Thread.current[:__pry_local__] = nil
end
def constant_scope(*names)
names.each do |name|
Object.remove_const name if Object.const_defined?(name)
end
yield
ensure
names.each do |name|
Object.remove_const name if Object.const_defined?(name)
end
end
def mri18_and_no_real_source_location?
Pry::Helpers::BaseHelpers.mri_18? && !(Method.instance_method(:source_location).owner == Method)
end
# used by test_show_source.rb and test_documentation.rb
class TestClassForShowSource
def alpha
end
end
class TestClassForShowSourceClassEval
def alpha
end
end
class TestClassForShowSourceInstanceEval
def alpha
end
end
# in case the tests call reset_defaults, ensure we reset them to
# amended (test friendly) values
class << Pry
alias_method :orig_reset_defaults, :reset_defaults
def reset_defaults
orig_reset_defaults
Pry.color = false
Pry.pager = false
Pry.config.should_load_rc = false
Pry.config.should_load_local_rc= false
Pry.config.should_load_plugins = false
Pry.config.history.should_load = false
Pry.config.history.should_save = false
Pry.config.auto_indent = false
Pry.config.hooks = Pry::Hooks.new
Pry.config.collision_warning = false
end
end
2012-01-08 01:01:15 -05:00
def mock_exception(*mock_backtrace)
e = StandardError.new("mock exception")
(class << e; self; end).class_eval do
define_method(:backtrace) { mock_backtrace }
end
2012-01-08 01:01:15 -05:00
e
end
Pry.reset_defaults
# this is to test exception code (cat --ex)
def broken_method
this method is broken
end
# sample doc
def sample_method
:sample
end
# Set I/O streams.
#
# Out defaults to an anonymous StringIO.
#
def redirect_pry_io(new_in, new_out = StringIO.new)
old_in = Pry.input
old_out = Pry.output
Pry.input = new_in
Pry.output = new_out
begin
yield
ensure
Pry.input = old_in
Pry.output = old_out
end
end
def mock_pry(*args)
args.flatten!
binding = args.first.is_a?(Binding) ? args.shift : binding()
input = InputTester.new(*args)
output = StringIO.new
redirect_pry_io(input, output) do
binding.pry
end
output.string
end
2011-12-31 10:21:58 -05:00
def mock_command(cmd, args=[], opts={})
output = StringIO.new
ret = cmd.new(opts.merge(:output => output)).call_safely(*args)
Struct.new(:output, :return).new(output.string, ret)
end
def redirect_global_pry_input(new_io)
old_io = Pry.input
Pry.input = new_io
begin
yield
ensure
Pry.input = old_io
end
end
def redirect_global_pry_output(new_io)
old_io = Pry.output
Pry.output = new_io
begin
yield
ensure
Pry.output = old_io
end
end
class Module
public :remove_const
public :remove_method
end
class InputTester
def initialize(*actions)
@orig_actions = actions.dup
@actions = actions
end
2011-01-09 06:51:45 -05:00
def readline(*)
@actions.shift
end
def rewind
@actions = @orig_actions.dup
end
end
2011-01-19 03:50:45 -05:00
class Pry
# null output class - doesn't write anywwhere.
class NullOutput
def self.puts(*) end
def self.string(*) end
2011-01-19 03:50:45 -05:00
end
end
# Open a temp file and yield it to the block, closing it after
# @return [String] The path of the temp file
2012-01-15 01:06:24 -05:00
def temp_file(ext='.rb')
file = Tempfile.new(['pry', ext])
yield file
ensure
2012-01-15 01:06:24 -05:00
file.close(true) if file
2012-08-18 23:58:48 -04:00
File.unlink("#{file.path}c") if File.exists?("#{file.path}c") # rbx
end
def pry_tester(*args, &block)
2012-09-09 02:12:25 -04:00
if args.length == 0 || args[0].is_a?(Hash)
args.unshift(Pry.toplevel_binding)
end
PryTester.new(*args).tap do |t|
2012-07-24 08:49:30 -04:00
(class << t; self; end).class_eval(&block) if block
2012-07-24 04:36:53 -04:00
end
end
def pry_eval(*eval_strs)
if eval_strs.first.is_a? String
2012-09-09 01:29:00 -04:00
binding = Pry.toplevel_binding
else
binding = Pry.binding_for(eval_strs.shift)
end
pry_tester(binding).eval(*eval_strs)
end
2012-07-24 04:36:53 -04:00
class PryTester
2012-07-24 08:49:30 -04:00
attr_reader :pry, :out
2012-07-24 04:36:53 -04:00
def initialize(context = TOPLEVEL_BINDING, options = {})
@pry = Pry.new(options)
2012-07-24 04:36:53 -04:00
if context
target = Pry.binding_for(context)
@pry.binding_stack << target
@pry.inject_sticky_locals(target)
2012-07-24 04:36:53 -04:00
end
2012-08-18 23:58:48 -04:00
@pry.input_array << nil # TODO: shouldn't need this
reset_output
2012-07-24 04:36:53 -04:00
end
def eval(*strs)
reset_output
2012-07-24 08:49:30 -04:00
result = nil
strs.flatten.each do |str|
str = "#{str.strip}\n"
2012-07-24 04:36:53 -04:00
if @pry.process_command(str)
result = last_command_result_or_output
2012-07-24 04:36:53 -04:00
else
2012-07-24 08:49:30 -04:00
result = @pry.evaluate_ruby(str)
2012-07-24 04:36:53 -04:00
end
2012-07-24 08:49:30 -04:00
end
result
end
2012-08-19 16:04:05 -04:00
def context=(context)
@pry.binding_stack << Pry.binding_for(context)
end
# TODO: eliminate duplication with Pry#repl
def simulate_repl
didnt_exit = nil
break_data = nil
didnt_exit = catch(:didnt_exit) do
break_data = catch(:breakout) do
yield self
throw(:didnt_exit, true)
end
nil
end
raise "Failed to exit REPL" if didnt_exit
break_data
end
2012-07-24 08:49:30 -04:00
def last_output
@out.string if @out
end
def process_command(command_str, eval_str = '')
@pry.process_command(command_str, eval_str) or raise "Not a valid command"
last_command_result_or_output
end
2012-07-24 08:49:30 -04:00
protected
def last_command_result
result = Thread.current[:__pry_cmd_result__]
result.retval if result
2012-07-24 04:36:53 -04:00
end
def last_command_result_or_output
result = last_command_result
if result != Pry::Command::VOID_VALUE
result
else
last_output
end
end
def reset_output
@out = StringIO.new
@pry.output = @out
end
2012-07-24 04:36:53 -04:00
end
2011-01-19 03:50:45 -05:00
2011-05-07 01:32:05 -04:00
CommandTester = Pry::CommandSet.new do
command "command1", "command 1 test" do
output.puts "command1"
end
command "command2", "command 2 test" do |arg|
output.puts arg
end
end
def unindent(*args)
Pry::Helpers::CommandHelpers.unindent(*args)
end
# to help with tracking down bugs that cause an infinite loop in the test suite
if ENV["SET_TRACE_FUNC"]
2011-12-27 17:38:25 -05:00
require 'set_trace' if Pry::Helpers::BaseHelpers.rbx?
set_trace_func proc { |event, file, line, id, binding, classname|
STDERR.printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}
end