power_assert 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2c2656987c0dd57b4eaccc2309d1b5f9c4eac0d3
4
- data.tar.gz: 04d870b66c36f4ba7beba83c3a0a764f27ee9da5
3
+ metadata.gz: 1444d874d5d014e20312a4644073d9fc166211ff
4
+ data.tar.gz: 3be96faed9006385ebd30d2d6694aaead254c426
5
5
  SHA512:
6
- metadata.gz: ea20c40cb70c29ad969f89e39a5e9d9974a2e3e3102d62dc04e0c817f91acb51b10c0bdeaadf88a7577ce8cfc5f2392894b3f156c0bf4f587386109b47f29b11
7
- data.tar.gz: 196d7ce2dbfb15a2b08a117d7bdb760dc40b9c437902fd1c5a0a1a1ae8c8e07ea8fb9101e9c791f32e2002ce0c4c81c10dad1831eff2b7dc7adc44f86881abe4
6
+ metadata.gz: 4f19ff06f13f40abb6f4f70516618634b5b5131e2e4119fa8430ff857b01f17e82330ec9e6477b545a4d1641476e4949f0125ccd0b2fddf81ff13f09241351a8
7
+ data.tar.gz: 2f9b2f75d552b3c25bbbab548d8990bbcfb540b00e35ab9a57a987f6125cb497c79dc475c31f88a1ed4a057f9e61797c08258957fecdfa0ab11c2474e7d8c3a8
@@ -3,12 +3,19 @@ language: ruby
3
3
  rvm:
4
4
  - 2.0.0-p648
5
5
  - 2.1.10
6
- - 2.2.6
7
- - 2.3.3
8
- - 2.4.0
6
+ - 2.2.7
7
+ - 2.3.4
8
+ - 2.4.1
9
9
  - ruby-head
10
+ env:
11
+ - TEST_SYMLINK="no"
12
+ - TEST_SYMLINK="yes"
10
13
  matrix:
11
14
  allow_failures:
12
15
  - rvm: ruby-head
13
16
  before_install:
14
17
  - gem update bundler
18
+ before_script:
19
+ - bundle exec rake before_script
20
+ after_script:
21
+ - bundle exec rake after_script
@@ -6,12 +6,16 @@ Power Assert shows each value of variables and method calls in the expression.
6
6
  It is useful for testing, providing which value wasn't correct when the condition is not satisfied.
7
7
 
8
8
  == Related Projects
9
+ In general, you don't need to use this library directly.
10
+ Use following test frameworks or extensions instead.
11
+
9
12
  * {test-unit}[https://github.com/test-unit/test-unit](>= 3.0.0)
13
+ * {Document}[http://test-unit.github.io/test-unit/en/Test/Unit/Assertions.html#assert-instance_method]
10
14
  * {minitest-power_assert}[https://github.com/hsbt/minitest-power_assert]
11
- * {pry-power_assert}[https://github.com/yui-knk/pry-power_assert]
12
15
  * {rspec-power_assert}[https://github.com/joker1007/rspec-power_assert]
13
- * {power_p}[https://github.com/k-tsj/power_p]
16
+ * {pry-power_assert}[https://github.com/yui-knk/pry-power_assert]
14
17
  * {pry-byebug-power_assert}[https://github.com/k-tsj/pry-byebug-power_assert]
18
+ * {power_p}[https://github.com/k-tsj/power_p]
15
19
 
16
20
  == Requirement
17
21
  * CRuby 2.0.0 or later
data/Rakefile CHANGED
@@ -4,7 +4,8 @@ require "rake/testtask"
4
4
  task :default => :test
5
5
  Rake::TestTask.new(:test) do |t|
6
6
  # helper(simplecov) must be required before loading power_assert
7
- t.ruby_opts = ["-w", "-r./test/test_helper"]
7
+ helper_path = File.realpath("test/test_helper.rb")
8
+ t.ruby_opts = ["-w", "-r#{helper_path}"]
8
9
  t.test_files = FileList["test/**/*_test.rb"].exclude do |i|
9
10
  begin
10
11
  return false unless defined?(RubyVM)
@@ -16,9 +17,43 @@ Rake::TestTask.new(:test) do |t|
16
17
  end
17
18
  end
18
19
 
20
+ # ruby/ruby:test/pathname/test_pathname.rb
21
+ def has_symlink?
22
+ begin
23
+ File.symlink("", "")
24
+ rescue NotImplementedError, Errno::EACCES
25
+ return false
26
+ rescue Errno::ENOENT
27
+ end
28
+ return true
29
+ end
30
+
31
+ SYMLINK_DIRS = ["lib", "test"]
32
+
33
+ task :before_script do
34
+ if ENV["TEST_SYMLINK"] == "yes" and has_symlink?
35
+ SYMLINK_DIRS.each do |d|
36
+ File.rename(d, ".#{d}")
37
+ File.symlink(".#{d}", d)
38
+ end
39
+ end
40
+ end
41
+
42
+ task :after_script do
43
+ SYMLINK_DIRS.each do |d|
44
+ if File.symlink?(d) and File.directory?(".#{d}")
45
+ File.unlink(d)
46
+ File.rename(".#{d}", d)
47
+ end
48
+ unless File.directory?(d)
49
+ raise "#{d} should be directory"
50
+ end
51
+ end
52
+ end
53
+
19
54
  desc "Run the benchmark suite"
20
- task('benchmark') do
21
- Dir.glob('benchmarks/bm_*.rb').each do |f|
55
+ task :benchmark do
56
+ Dir.glob("benchmark/bm_*.rb").each do |f|
22
57
  load(f)
23
58
  end
24
59
  end
@@ -22,9 +22,16 @@ require 'power_assert/configuration'
22
22
  require 'power_assert/context'
23
23
 
24
24
  module PowerAssert
25
- POWER_ASSERT_LIB_DIR = __dir__
26
- IGNORED_LIB_DIRS = {PowerAssert => POWER_ASSERT_LIB_DIR}
27
- private_constant :POWER_ASSERT_LIB_DIR, :IGNORED_LIB_DIRS
25
+ POWER_ASSERT_LIB_DIR = File.dirname(caller_locations(1, 1).first.path)
26
+ INTERNAL_LIB_DIRS = {PowerAssert => POWER_ASSERT_LIB_DIR}
27
+ private_constant :POWER_ASSERT_LIB_DIR, :INTERNAL_LIB_DIRS
28
+
29
+ # For backward compatibility
30
+ IGNORED_LIB_DIRS = INTERNAL_LIB_DIRS
31
+ private_constant :IGNORED_LIB_DIRS
32
+ if respond_to?(:deprecate_constant)
33
+ deprecate_constant :IGNORED_LIB_DIRS
34
+ end
28
35
 
29
36
  class << self
30
37
  def start(assertion_proc_or_source, assertion_method: nil, source_binding: TOPLEVEL_BINDING)
@@ -46,27 +53,27 @@ module PowerAssert
46
53
  end
47
54
 
48
55
  def app_caller_locations
49
- caller_locations.drop_while {|i| ignored_file?(i.path) }.take_while {|i| ! ignored_file?(i.path) }
56
+ caller_locations.drop_while {|i| internal_file?(i.path) }.take_while {|i| ! internal_file?(i.path) }
50
57
  end
51
58
 
52
59
  def app_context?
53
60
  top_frame = caller_locations.drop_while {|i| i.path.start_with?(POWER_ASSERT_LIB_DIR) }.first
54
- top_frame and ! ignored_file?(top_frame.path)
61
+ top_frame and ! internal_file?(top_frame.path)
55
62
  end
56
63
 
57
64
  private
58
65
 
59
- def ignored_file?(file)
60
- setup_ignored_lib_dir(Byebug, :attach, 2) if defined?(Byebug)
61
- setup_ignored_lib_dir(PryByebug, :start_with_pry_byebug, 2, Pry) if defined?(PryByebug)
62
- IGNORED_LIB_DIRS.find do |_, dir|
66
+ def internal_file?(file)
67
+ setup_internal_lib_dir(Byebug, :attach, 2) if defined?(Byebug)
68
+ setup_internal_lib_dir(PryByebug, :start_with_pry_byebug, 2, Pry) if defined?(PryByebug)
69
+ INTERNAL_LIB_DIRS.find do |_, dir|
63
70
  file.start_with?(dir)
64
71
  end
65
72
  end
66
73
 
67
- def setup_ignored_lib_dir(lib, mid, depth, lib_obj = lib)
68
- unless IGNORED_LIB_DIRS.key?(lib)
69
- IGNORED_LIB_DIRS[lib] = lib_dir(lib_obj, mid, depth)
74
+ def setup_internal_lib_dir(lib, mid, depth, lib_obj = lib)
75
+ unless INTERNAL_LIB_DIRS.key?(lib)
76
+ INTERNAL_LIB_DIRS[lib] = lib_dir(lib_obj, mid, depth)
70
77
  end
71
78
  rescue NameError
72
79
  end
@@ -76,8 +83,11 @@ module PowerAssert
76
83
  end
77
84
 
78
85
  if defined?(RubyVM)
86
+ CLEAR_CACHE_ISEQ = RubyVM::InstructionSequence.compile('using PowerAssert.const_get(:Empty)')
87
+ private_constant :CLEAR_CACHE_ISEQ
88
+
79
89
  def clear_global_method_cache
80
- eval('using PowerAssert.const_get(:Empty)', TOPLEVEL_BINDING)
90
+ CLEAR_CACHE_ISEQ.eval
81
91
  end
82
92
  end
83
93
  end
@@ -5,18 +5,19 @@ require 'power_assert/parser'
5
5
 
6
6
  module PowerAssert
7
7
  class Context
8
- Value = Struct.new(:name, :value, :column)
9
-
10
- attr_reader :message_proc
8
+ Value = Struct.new(:name, :value, :lineno, :column)
11
9
 
12
10
  def initialize(base_caller_length)
13
11
  @fired = false
14
12
  @target_thread = Thread.current
15
13
  method_id_set = nil
16
- return_values = []
14
+ @return_values = []
17
15
  trace_alias_method = PowerAssert.configuration._trace_alias_method
18
16
  @trace_return = TracePoint.new(:return, :c_return) do |tp|
19
- method_id_set ||= @parser.method_id_set
17
+ unless method_id_set
18
+ next unless Thread.current == @target_thread
19
+ method_id_set = @parser.method_id_set
20
+ end
20
21
  method_id = SUPPORT_ALIAS_METHOD ? tp.callee_id :
21
22
  trace_alias_method && tp.event == :return ? tp.binding.eval('::Kernel.__callee__') :
22
23
  tp.method_id
@@ -31,18 +32,19 @@ module PowerAssert
31
32
  val = PowerAssert.configuration.lazy_inspection ?
32
33
  tp.return_value :
33
34
  InspectedValue.new(SafeInspectable.new(tp.return_value).inspect)
34
- return_values << Value[method_id.to_s, val, nil]
35
+ @return_values << Value[method_id.to_s, val, locs[idx].lineno, nil]
35
36
  end
36
37
  end
37
38
  end
38
- @message_proc = -> {
39
- raise RuntimeError, 'call #yield or #enable at first' unless fired?
40
- @message ||= build_assertion_message(@parser.line, @parser.idents, @parser.binding, return_values).freeze
41
- }
42
39
  end
43
40
 
44
41
  def message
45
- @message_proc.()
42
+ raise 'call #yield or #enable at first' unless fired?
43
+ @message ||= build_assertion_message(@parser, @return_values).freeze
44
+ end
45
+
46
+ def message_proc
47
+ -> { message }
46
48
  end
47
49
 
48
50
  private
@@ -51,24 +53,26 @@ module PowerAssert
51
53
  @fired
52
54
  end
53
55
 
54
- def build_assertion_message(line, idents, proc_binding, return_values)
56
+ def build_assertion_message(parser, return_values)
55
57
  if PowerAssert.configuration._colorize_message
56
- line = Pry::Code.new(line).highlighted
58
+ line = Pry::Code.new(parser.line).highlighted
59
+ else
60
+ line = parser.line
57
61
  end
58
62
 
59
- path = detect_path(idents, return_values)
63
+ path = detect_path(parser, return_values)
60
64
  return line unless path
61
65
 
62
- delete_unidentified_calls(return_values, path)
63
- methods, refs = path.partition {|i| i.type == :method }
64
- return_values.zip(methods) do |i, j|
66
+ return_values, methods_in_path = find_all_identified_calls(return_values, path)
67
+ return_values.zip(methods_in_path) do |i, j|
65
68
  unless i.name == j.name
66
69
  warn "power_assert: [BUG] Failed to get column: #{i.name}"
67
70
  return line
68
71
  end
69
72
  i.column = j.column
70
73
  end
71
- ref_values = refs.map {|i| Value[i.name, proc_binding.eval(i.name), i.column] }
74
+ refs_in_path = path.find_all {|i| i.type == :ref }
75
+ ref_values = refs_in_path.map {|i| Value[i.name, parser.binding.eval(i.name), parser.lineno, i.column] }
72
76
  vals = (return_values + ref_values).find_all(&:column).sort_by(&:column).reverse
73
77
  return line if vals.empty?
74
78
 
@@ -88,9 +92,9 @@ module PowerAssert
88
92
  lines.join("\n")
89
93
  end
90
94
 
91
- def detect_path(idents, return_values)
92
- return @parser.call_paths.flatten.uniq if @parser.method_id_set.empty?
93
- all_paths = @parser.call_paths
95
+ def detect_path(parser, return_values)
96
+ return parser.call_paths.flatten.uniq if parser.method_id_set.empty?
97
+ all_paths = parser.call_paths
94
98
  return_value_names = return_values.map(&:name)
95
99
  uniq_calls = uniq_calls(all_paths)
96
100
  uniq_call = return_value_names.find {|i| uniq_calls.include?(i) }
@@ -108,12 +112,14 @@ module PowerAssert
108
112
  all_calls.find_all {|_, call_count| call_count == 1 }.map {|name, _| name }
109
113
  end
110
114
 
111
- def delete_unidentified_calls(return_values, path)
115
+ def find_all_identified_calls(return_values, path)
112
116
  return_value_num_of_calls = enum_count_by(return_values, &:name)
113
117
  path_num_of_calls = enum_count_by(path.find_all {|ident| ident.type == :method }, &:name)
114
118
  identified_calls = return_value_num_of_calls.find_all {|name, num| path_num_of_calls[name] == num }.map(&:first)
115
- return_values.delete_if {|val| ! identified_calls.include?(val.name) }
116
- path.delete_if {|ident| ident.type == :method and ! identified_calls.include?(ident.name) }
119
+ [
120
+ return_values.find_all {|val| identified_calls.include?(val.name) },
121
+ path.find_all {|ident| ident.type == :method and identified_calls.include?(ident.name) }
122
+ ]
117
123
  end
118
124
 
119
125
  def enum_count_by(enum, &blk)
@@ -152,7 +158,7 @@ module PowerAssert
152
158
  lineno = locs.last.lineno
153
159
  if File.exist?(path)
154
160
  line ||= open(path).each_line.drop(lineno - 1).first
155
- @parser = Parser.new(line, path, lineno, @assertion_proc.binding, assertion_method.to_s)
161
+ @parser = Parser.new(line, path, lineno, @assertion_proc.binding, assertion_method.to_s, @assertion_proc)
156
162
  end
157
163
  end
158
164
  end
@@ -13,37 +13,37 @@ if defined?(RubyVM)
13
13
  module PowerAssert
14
14
  # set redefined flag
15
15
  basic_classes = [
16
- Fixnum, Float, String, Array, Hash, Bignum, Symbol, Time, Regexp
16
+ Fixnum, Float, String, Array, Hash, Bignum, Symbol, Time, Regexp, NilClass, TrueClass, FalseClass
17
17
  ]
18
18
 
19
19
  basic_operators = [
20
20
  :+, :-, :*, :/, :%, :==, :===, :<, :<=, :<<, :[], :[]=,
21
- :length, :size, :empty?, :succ, :>, :>=, :!, :!=, :=~, :freeze
21
+ :length, :size, :empty?, :succ, :>, :>=, :!, :!=, :=~, :freeze, :-@, :max, :min
22
22
  ]
23
23
 
24
- class Bug11182
24
+ bug11182 = Class.new do
25
25
  def fixed?
26
26
  true
27
27
  end
28
28
  end
29
- private_constant :Bug11182
30
29
 
31
- refine Bug11182 do
30
+ refine bug11182 do
32
31
  def fixed?
33
32
  end
34
33
  end
35
34
 
36
- class Bug11182Sub < Bug11182
35
+ _ = Class.new(bug11182) do
37
36
  alias _fixed? fixed?
38
37
  protected :_fixed?
39
38
  end
40
- private_constant :Bug11182Sub
41
39
 
42
- if (Bug11182.new.fixed? rescue false)
40
+ if (bug11182.new.fixed? rescue false)
43
41
  basic_classes.each do |klass|
44
42
  basic_operators.each do |bop|
45
- refine(klass) do
46
- define_method(bop) {}
43
+ if klass.public_method_defined?(bop)
44
+ refine(klass) do
45
+ define_method(bop) {}
46
+ end
47
47
  end
48
48
  end
49
49
  end
@@ -6,7 +6,7 @@ module PowerAssert
6
6
 
7
7
  attr_reader :line, :path, :lineno, :binding
8
8
 
9
- def initialize(line, path, lineno, binding, assertion_method_name = nil)
9
+ def initialize(line, path, lineno, binding, assertion_method_name = nil, assertion_proc = nil)
10
10
  @line = line
11
11
  @line_for_parsing = valid_syntax?(line) ? line : slice_expression(line)
12
12
  @path = path
@@ -14,6 +14,7 @@ module PowerAssert
14
14
  @binding = binding
15
15
  @proc_local_variables = binding.eval('local_variables').map(&:to_s)
16
16
  @assertion_method_name = assertion_method_name
17
+ @assertion_proc = assertion_proc
17
18
  end
18
19
 
19
20
  def idents
@@ -1,3 +1,3 @@
1
1
  module PowerAssert
2
- VERSION = "1.0.2"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.description = "Power Assert for Ruby. Power Assert shows each value of variables and method calls in the expression. It is useful for testing, providing which value wasn't correct when the condition is not satisfied."
14
14
 
15
15
  s.files = `git ls-files -z`.split("\x0").reject do |f|
16
- f.match(%r{^(test|spec|features|benchmarks)/})
16
+ f.match(%r{^(test|spec|features|benchmark)/})
17
17
  end
18
18
  s.bindir = 'exe'
19
19
  s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: power_assert
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kazuki Tsujimoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-04 00:00:00.000000000 Z
11
+ date: 2017-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: test-unit
@@ -146,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
146
  version: '0'
147
147
  requirements: []
148
148
  rubyforge_project:
149
- rubygems_version: 2.6.8
149
+ rubygems_version: 2.6.11
150
150
  signing_key:
151
151
  specification_version: 4
152
152
  summary: Power Assert for Ruby