benry-recorder 1.0.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4546395dc9bc48dd67bd730e86d6b2875fffb556
4
+ data.tar.gz: c1d7c6b23e60e2b0b735aff167b6af5ef5ce8398
5
+ SHA512:
6
+ metadata.gz: 86785e3485c6dbfa1e89737dd3259f8ab1f828209e66b43254900085bca4326ede38246f84d2d0007958114362818cecd4b02d61545de7bdbf8908ef06f9575e
7
+ data.tar.gz: 7df326f888d5f522a16ef5004273b032a99356de9fa578b3016ccff8eada31bf7c0a0e4c21cdb5077c616ddedada26435f71e84d0c68ac4f8a0ec480df05863b
data/README.md ADDED
@@ -0,0 +1,125 @@
1
+ <!-- -*- coding: utf-8 -*- -->
2
+ # Benry-recorder README
3
+
4
+ Benry-recoder is a tiny utility that can:
5
+
6
+ * Record method calls of target object.
7
+ * Define fake methods on target object.
8
+ * Create fake object which has fake methods.
9
+
10
+
11
+ ## Table of Contents
12
+
13
+ <!-- TOC -->
14
+
15
+ * <a href="#how-to-record-method-calls">How to record method calls</a>
16
+ * <a href="#how-to-define-fake-methods">How to define fake methods</a>
17
+ * <a href="#how-to-create-fake-object">How to create fake object</a>
18
+ * <a href="#license-and-copyright">License and Copyright</a>
19
+
20
+ <!-- /TOC -->
21
+
22
+
23
+ ## How to record method calls
24
+
25
+ <!--
26
+ file: example1.rb
27
+ -->
28
+
29
+ ```ruby
30
+ require 'benry/recorder'
31
+
32
+ class Calc
33
+ def average(*nums) # average() calls total()
34
+ return total(*nums) / nums.length
35
+ end
36
+ def total(*nums)
37
+ t = 0; nums.each {|n| t += n }
38
+ return t # or: return nums.sum
39
+ end
40
+ end
41
+
42
+ ## target object
43
+ calc = Calc.new
44
+
45
+ ## record method calls
46
+ rec = Benry::Recorder.new
47
+ rec.record(calc, :total, :average)
48
+
49
+ ## call methods
50
+ calc.average(10, 20, 30, 40) # calls calc.total() internally
51
+
52
+ ## details of method calls
53
+ p rec.length #=> 2
54
+ puts rec.inspect
55
+ #=> 0: #<Calc:0x001234abcd>.average(10, 20, 30, 40) #=> 25
56
+ # 1: #<Calc:0x001234abcd>.total(10, 20, 30, 40) #=> 100
57
+ #
58
+ p rec[0].obj #=> #<Calc:0x001234abcd>
59
+ p rec[0].obj.equal?(calc) #=> true
60
+ p rec[0].name #=> :average
61
+ p rec[0].args #=> [10, 20, 30, 40]
62
+ p rec[0].ret #=> 25
63
+ #
64
+ p rec[1].obj #=> #<Calc:0x001234abcd>
65
+ p rec[1].obj.equal?(calc) #=> true
66
+ p rec[1].name #=> :total
67
+ p rec[1].args #=> [10, 20, 30, 40]
68
+ p rec[1].ret #=> 100
69
+ #
70
+ p rec[0].to_a #=> [obj, :average, [10, 20, 30, 40], 25]
71
+ p rec[1].to_a #=> [obj, :total, [10, 20, 30, 40], 100]
72
+ ```
73
+
74
+
75
+ ## How to define fake methods
76
+
77
+ <!--
78
+ file: example2.rb
79
+ -->
80
+
81
+ ```ruby
82
+ require 'benry/recorder'
83
+
84
+ class Calc
85
+ ....(snip)....
86
+ end
87
+
88
+ ## target object
89
+ calc = Calc.new
90
+
91
+ ## before
92
+ p calc.total(10, 20, 30, 40) #=> 100
93
+ p calc.average(10, 20, 30, 40) #=> 25
94
+
95
+ ## define fake methods
96
+ rec = Benry::Recorder.new
97
+ rec.fake_method(calc, :total=>123, :average=>34)
98
+
99
+ ## after
100
+ p calc.total(10, 20, 30, 40) #=> 123
101
+ p calc.average(10, 20, 30, 40) #=> 34
102
+ ```
103
+
104
+
105
+ ## How to create fake object
106
+
107
+ <!--
108
+ file: example3.rb
109
+ -->
110
+
111
+ ```ruby
112
+ require 'benry/recorder'
113
+
114
+ rec = Benry::Recorder.new
115
+ obj = rec.fake_object(:foo=>10, :bar=>20)
116
+ p obj.foo() #=> 10
117
+ p obj.bar() #=> 20
118
+ p obj.bar(3, 4, 'a'=>5) # accepts any arguments
119
+ ```
120
+
121
+
122
+ ## License and Copyright
123
+
124
+ * $License: MIT License $
125
+ * $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
data/Rakefile.rb ADDED
@@ -0,0 +1,21 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ PROJECT = "benry-recorder"
5
+ RELEASE = ENV['RELEASE'] || "0.0.0"
6
+ COPYRIGHT = "copyright(c) 2011-2021 kuwata-lab.com all rights reserved"
7
+ LICENSE = "MIT License"
8
+
9
+ README_EXTRACT = /^file: (.*\.rb)/
10
+
11
+ Dir.glob("./task/*.rb").each {|x| require_relative x }
12
+
13
+ def readme_extract_callback(filename, str)
14
+ if filename == 'example1.rb'
15
+ str =~ /class Calc\n(.*?)^end\n/m
16
+ $_classdef = $1
17
+ elsif filename == 'example2.rb'
18
+ str = str.sub(/^ *\.\.\.+\(snip\)\.\.\.+ *\n/, $_classdef)
19
+ end
20
+ return str
21
+ end
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'benry-recorder'
5
+ spec.version = '$Release: 1.0.0 $'.split()[1]
6
+ spec.author = 'kwatch'
7
+ spec.email = 'kwatch@gmail.com'
8
+ spec.platform = Gem::Platform::RUBY
9
+ spec.homepage = 'https://github.com/kwatch/benry-ruby/tree/ruby/benry-recorder'
10
+ spec.summary = "Record method calls, or define fake methods."
11
+ spec.description = <<-'END'
12
+ Benry-recorder is a tiny utility that can:
13
+
14
+ * Record method calls of target object.
15
+ * Define fake methods on target object.
16
+ * Create fake object which has fake methods.
17
+ END
18
+ spec.license = 'MIT'
19
+ spec.files = Dir[
20
+ 'README.md', 'MIT-LICENSE', #'CHANGES.md'
21
+ 'Rakefile.rb', 'benry-recorder.gemspec',
22
+ #'bin/*',
23
+ 'lib/**/*.rb',
24
+ 'test/**/*.rb',
25
+ 'task/**/*.rb',
26
+ ]
27
+ #spec.executables = ['benry-recorder']
28
+ #spec.bindir = 'bin'
29
+ spec.require_path = 'lib'
30
+ #spec.test_files = Dir['test/run_all.rb']
31
+ spec.test_files = Dir['test/**/*_test.rb']
32
+ #spec.extra_rdoc_files = ['README.md', 'CHANGES.md']
33
+
34
+ spec.add_development_dependency 'minitest' , '~> 0'
35
+ spec.add_development_dependency 'minitest-ok' , '~> 0'
36
+ end
@@ -0,0 +1,178 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ###
4
+ ### $Release: 1.0.0 $
5
+ ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
6
+ ### $License: MIT License $
7
+ ###
8
+
9
+
10
+ module Benry
11
+
12
+
13
+ ##
14
+ ## record method calls, or define fake methods.
15
+ ##
16
+ ## ex. record method calls
17
+ ## ## target class
18
+ ## class Calc
19
+ ## def average(*nums) # average() calls total()
20
+ ## return total(*nums) / nums.length
21
+ ## end
22
+ ## def total(*nums)
23
+ ## t = 0; nums.each {|n| t += n }
24
+ ## return t # or: return nums.sum
25
+ ## end
26
+ ## end
27
+ ## ## record method calls
28
+ ## rec = Benry::Recorder.new
29
+ ## calc = Calc.new
30
+ ## rec.record(calc, :total, :average)
31
+ ## ## call methods
32
+ ## calc.average(10, 20, 30, 40)
33
+ ## ## details of method calls
34
+ ## p rec.length #=> 2
35
+ ## puts rec.inspect
36
+ ## #=> 0: #<Calc:0x001234abcd>.average(10, 20, 30, 40) #=> 25
37
+ ## # 1: #<Calc:0x001234abcd>.total(10, 20, 30, 40) #=> 100
38
+ ## #
39
+ ## p rec[0].obj #=> #<Calc:0x001234abcd>
40
+ ## p rec[0].obj.equal?(calc) #=> true
41
+ ## p rec[0].name #=> :average
42
+ ## p rec[0].args #=> [10, 20, 30, 40]
43
+ ## p rec[0].ret #=> 25
44
+ ## #
45
+ ## p rec[1].obj #=> #<Calc:0x001234abcd>
46
+ ## p rec[1].obj.equal?(calc) #=> true
47
+ ## p rec[1].name #=> :total
48
+ ## p rec[1].args #=> [10, 20, 30, 40]
49
+ ## p rec[1].ret #=> 100
50
+ ## #
51
+ ## p rec[0].to_a #=> [obj, :average, [10, 20, 30, 40], 25]
52
+ ## p rec[1].to_a #=> [obj, :total, [10, 20, 30, 40], 100]
53
+ ##
54
+ ## ex. fake method
55
+ ## rec = Benry::Recorder.new
56
+ ## calc = Calc.new
57
+ ## ## before
58
+ ## p calc.total(10, 20, 30, 40) #=> 100
59
+ ## p calc.average(10, 20, 30, 40) #=> 25
60
+ ## ## after
61
+ ## rec.fake_method(calc, :total=>123, :average=>34)
62
+ ## p calc.total(10, 20, 30, 40) #=> 123
63
+ ## p calc.average(10, 20, 30, 40) #=> 34
64
+ ##
65
+ ## ex. fake object
66
+ ## rec = Benry::Recorder.new
67
+ ## obj = rec.fake_object(:foo=>10, :bar=>20)
68
+ ## p obj.foo() #=> 10
69
+ ## p obj.bar() #=> 20
70
+ ## p obj.bar(3, 4, 'a'=>5) # accepts any arguments
71
+ ##
72
+ class Recorder
73
+
74
+
75
+ class Called
76
+
77
+ def initialize(obj, name, args, ret)
78
+ @obj = obj
79
+ @name = name
80
+ @args = args
81
+ @ret = ret
82
+ end
83
+
84
+ #; [!m98p9] returns receiver object.
85
+ #; [!es61g] returns method name.
86
+ #; [!2yeeo] returns arguments.
87
+ #; [!yd3hl] returns arguments.
88
+ attr_accessor :obj, :name, :args, :ret
89
+
90
+ def to_a()
91
+ #; [!hrol9] returns array of obj, nae, args, and ret.
92
+ return [@obj, @name, @args, @ret]
93
+ end
94
+
95
+ def inspect()
96
+ #; [!g2iwe] represents internal data.
97
+ s = args.collect {|arg| arg.inspect }.join(", ")
98
+ return "#{obj.inspect}.#{name}(#{s}) #=> #{ret.inspect}"
99
+ end
100
+
101
+ end
102
+
103
+
104
+ def initialize()
105
+ @called = []
106
+ end
107
+
108
+ def length()
109
+ @called.length
110
+ end
111
+
112
+ alias size length
113
+
114
+ def [](index)
115
+ return @called[index]
116
+ end
117
+
118
+ def inspect()
119
+ #; [!k85bz] represents internal data.
120
+ buf = []
121
+ @called.each_with_index {|called, i| buf << "#{i}: #{called.inspect}\n" }
122
+ return buf.join()
123
+ end
124
+
125
+ def record_method(obj, *method_names)
126
+ #; [!61z3j] records method calls.
127
+ called_list = @called
128
+ proc_obj = proc do |obj, name, orig_method|
129
+ (class << obj; self; end).class_eval do
130
+ alias_method orig_method, name
131
+ define_method(name) do |*args|
132
+ called = Recorder::Called.new(obj, name.to_s.intern, args, nil)
133
+ called_list << called
134
+ #; [!9kh1f] calls original method.
135
+ ret = obj.__send__(orig_method, *args)
136
+ called.ret = ret
137
+ ret
138
+ end
139
+ end
140
+ end
141
+ method_names.each do |name|
142
+ proc_obj.call(obj, name, "__#{name}_orig".intern)
143
+ end
144
+ self
145
+ end
146
+ alias record record_method
147
+
148
+ def fake_method(obj, **name_and_values)
149
+ #; [!g112x] defines fake methods.
150
+ called_list = @called
151
+ proc_obj = proc do |obj, name, val|
152
+ (class << obj; self; end).class_eval do
153
+ #; [!kgvm1] defined methods can can take any arguments.
154
+ define_method(name) do |*args|
155
+ called_list << Recorder::Called.new(obj, name, args, val)
156
+ val
157
+ end
158
+ end
159
+ end
160
+ name_and_values.each do |name, val|
161
+ proc_obj.call(obj, name, val)
162
+ end
163
+ #; [!2p1b0] returns self.
164
+ self
165
+ end
166
+ alias fake fake_method
167
+
168
+ def fake_object(**name_and_values)
169
+ #; [!hympr] creates fake object.
170
+ obj = Object.new
171
+ fake_method(obj, **name_and_values)
172
+ return obj
173
+ end
174
+
175
+ end
176
+
177
+
178
+ end
@@ -0,0 +1,185 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ defined? PROJECT or abort "PROJECT required."
5
+ defined? RELEASE or abort "RELEASE required."
6
+ defined? COPYRIGHT or abort "COPYRIGHT required."
7
+ defined? LICENSE or abort "LICENSE required."
8
+
9
+ RELEASE =~ /\A\d+\.\d+\.\d+/ or abort "RELEASE=#{RELEASE}: invalid release number."
10
+
11
+ $ruby_versions ||= %w[2.4 2.5 2.6 2.7 3.0]
12
+
13
+
14
+ require 'rake/clean'
15
+ CLEAN << "build"
16
+ CLEAN.concat Dir.glob("#{PROJECT}-*.gem").collect {|x| x.sub(/\.gem$/, '') }
17
+ CLOBBER.concat Dir.glob("#{PROJECT}-*.gem")
18
+
19
+
20
+ desc "show release guide"
21
+ task :guide do
22
+ RELEASE != '0.0.0' or abort "rake help: required 'RELEASE=X.X.X'"
23
+ rel, proj = RELEASE, PROJECT
24
+ rel =~ /(\d+\.\d+)/
25
+ branch = "#{proj}_rel-#{$1}"
26
+ puts <<END
27
+ How to release:
28
+
29
+ $ git diff .
30
+ $ git status .
31
+ $ which ruby
32
+ $ rake test
33
+ $ rake test:all
34
+ $ rake readme:execute # optional
35
+ $ rake readme:toc # optional
36
+ $ rake package RELEASE=#{rel}
37
+ $ rake package:extract # confirm files in gem file
38
+ $ (cd #{proj}-#{rel}/data; find . -type f)
39
+ $ gem install #{proj}-#{rel}.gem # confirm gem package
40
+ $ gem uninstall #{proj}
41
+ $ gem push #{proj}-#{rel}.gem # publish gem to rubygems.org
42
+ $ git tag #{proj}-#{rel}
43
+ $ git push
44
+ $ git push --tags
45
+ END
46
+ end unless Rake::Task.task_defined?(:guide)
47
+
48
+
49
+ desc "do test"
50
+ task :test do
51
+ ruby "test/run_all.rb"
52
+ end unless Rake::Task.task_defined?(:test)
53
+
54
+
55
+ if ENV['VS_HOME'] && $ruby_versions
56
+ desc "do test for different ruby versions"
57
+ task :'test:all' do
58
+ vs_home = ENV['VS_HOME'].split(/:/).first
59
+ ENV['TC_QUIET'] = "Y" if File.exist?("test/tc.rb")
60
+ comp = proc {|x, y| x.to_s.split('.').map(&:to_i) <=> y.to_s.split('.').map(&:to_i) }
61
+ $ruby_versions.each do |ver|
62
+ dir = Dir.glob("#{vs_home}/ruby/#{ver}.*").sort_by(&comp).last
63
+ next unless dir
64
+ puts "==== ruby #{ver} (#{dir}) ===="
65
+ sh "#{dir}/bin/ruby test/run_all.rb" do |ok, res|
66
+ $stderr.puts "** test failed" unless ok
67
+ end
68
+ end
69
+ end unless Rake::Task.task_defined?(:'test:all')
70
+ end
71
+
72
+
73
+ def target_files()
74
+ $_target_files ||= begin
75
+ spec_src = File.read("#{PROJECT}.gemspec", encoding: 'utf-8')
76
+ spec = eval spec_src
77
+ spec.name == PROJECT or
78
+ abort "'#{PROJECT}' != '#{spec.name}' (project name in gemspec file)"
79
+ spec.files
80
+ end
81
+ return $_target_files
82
+ end
83
+
84
+ def edit_file(filename)
85
+ File.open(filename, 'rb+') do |f|
86
+ s1 = f.read()
87
+ s2 = yield s1
88
+ if s1 != s2
89
+ f.rewind()
90
+ f.truncate(0)
91
+ f.write(s2)
92
+ true
93
+ else
94
+ false
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+ desc "edit metadata in files"
101
+ task :edit do
102
+ target_files().each do |fname|
103
+ changed = edit_file(fname) do |s|
104
+ #s = s.gsub(/\$Release[:].*?\$/, "$"+"Release: #{RELEASE} $")
105
+ s = s.gsub(/\$Copyright[:].*?\$/, "$"+"Copyright: #{COPYRIGHT} $")
106
+ s = s.gsub(/\$License[:].*?\$/, "$"+"License: #{LICENSE} $")
107
+ s
108
+ end
109
+ puts "[C] #{fname}" if changed
110
+ puts "[U] #{fname}" unless changed
111
+ end
112
+ end unless Rake::Task.task_defined?(:edit)
113
+
114
+
115
+ desc "create package (*.gem)"
116
+ task :package do
117
+ RELEASE != '0.0.0' or abort "rake help: required 'RELEASE=X.X.X'"
118
+ ## copy
119
+ dir = "build"
120
+ rm_rf dir if File.exist?(dir)
121
+ mkdir dir
122
+ target_files().each do |file|
123
+ dest = File.join(dir, File.dirname(file))
124
+ mkdir_p dest, :verbose=>false unless File.exist?(dest)
125
+ cp file, "#{dir}/#{file}"
126
+ end
127
+ ## edit
128
+ Dir.glob("#{dir}/**/*").each do |file|
129
+ next unless File.file?(file)
130
+ edit_file(file) do |s|
131
+ s = s.gsub(/\$Release[:].*?\$/, "$"+"Release: #{RELEASE} $")
132
+ s = s.gsub(/\$Copyright[:].*?\$/, "$"+"Copyright: #{COPYRIGHT} $")
133
+ s = s.gsub(/\$License[:].*?\$/, "$"+"License: #{LICENSE} $")
134
+ s
135
+ end
136
+ end
137
+ ## build
138
+ chdir dir do
139
+ sh "gem build #{PROJECT}.gemspec"
140
+ end
141
+ mv "#{dir}/#{PROJECT}-#{RELEASE}.gem", "."
142
+ rm_rf dir
143
+ end unless Rake::Task.task_defined?(:package)
144
+
145
+
146
+ desc "extract latest gem file"
147
+ task :'package:extract' do
148
+ gemfile = Dir.glob("#{PROJECT}-*.gem").sort_by {|x| File.mtime(x) }.last
149
+ dir = gemfile.sub(/\.gem$/, '')
150
+ rm_rf dir if File.exist?(dir)
151
+ mkdir dir
152
+ mkdir "#{dir}/data"
153
+ cd dir do
154
+ sh "tar xvf ../#{gemfile}"
155
+ sh "gunzip *.gz"
156
+ cd "data" do
157
+ sh "tar xvf ../data.tar"
158
+ end
159
+ end
160
+ end unless Rake::Task.task_defined?(:'package:extract')
161
+
162
+
163
+ desc "upload gem file to rubygems.org"
164
+ task :publish do
165
+ RELEASE != '0.0.0' or abort "rake help: required 'RELEASE=X.X.X'"
166
+ gemfile = "#{PROJECT}-#{RELEASE}.gem"
167
+ print "** Are you sure to publish #{gemfile}? [y/N]: "
168
+ answer = $stdin.gets().strip()
169
+ if answer.downcase == "y"
170
+ sh "gem push #{gemfile}"
171
+ sh "git tag ruby-#{PROJECT}-#{RELEASE}"
172
+ sh "#git push --tags"
173
+ end
174
+ end unless Rake::Task.task_defined?(:publish)
175
+
176
+
177
+ desc nil
178
+ task :'relink' do
179
+ Dir.glob("task/*.rb").each do |x|
180
+ src = "../" + x
181
+ next if File.identical?(src, x)
182
+ rm x
183
+ ln src, x
184
+ end
185
+ end
@@ -0,0 +1,105 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ README_FILE = "README.md" unless defined? README_FILE
4
+ README_EXTRACT = /^file: +(\S+)/ unless defined? README_EXTRACT
5
+ README_CODESTART = /^```\w+$/ unless defined? README_CODESTART
6
+ README_CODEEND = /^```$/ unless defined? README_CODEEND
7
+ README_DESTDIR = "tmp/readme" unless defined? README_DESTDIR
8
+
9
+ require 'rake/clean'
10
+ CLEAN << "README.html"
11
+
12
+
13
+ def readme_extract_callback(filename, str)
14
+ return str
15
+ end
16
+
17
+
18
+ namespace :readme do
19
+
20
+ desc "retrieve scripts from #{README_FILE}"
21
+ task :retrieve do
22
+ dir = "tmp/readme"
23
+ rm_rf dir if File.exist?(dir)
24
+ mkdir_p dir
25
+ s = File.read(README_FILE, encoding: 'utf-8')
26
+ filename = nil
27
+ buf = nil
28
+ s.each_line do |line|
29
+ case line
30
+ when README_EXTRACT
31
+ filename = $1
32
+ next
33
+ when README_CODESTART
34
+ if filename
35
+ buf = []
36
+ end
37
+ next
38
+ when README_CODEEND
39
+ if filename && buf
40
+ newfile = "#{dir}/#{filename}"
41
+ unless File.exist?(File.dirname(newfile))
42
+ mkdir_p File.dirname(newfile)
43
+ end
44
+ str = readme_extract_callback(filename, buf.join())
45
+ File.write(newfile, str, encoding: 'utf-8')
46
+ puts "[retrieve] #{newfile}"
47
+ end
48
+ filename = nil
49
+ buf = nil
50
+ next
51
+ end
52
+ #
53
+ if buf
54
+ buf << line
55
+ end
56
+ end
57
+ end
58
+
59
+ desc "execute code in readme file"
60
+ task :execute => :retrieve do
61
+ Dir.glob(README_DESTDIR+'/**/*.rb').sort.each do |fpath|
62
+ puts "========================================"
63
+ sh "ruby -I lib #{fpath}" do end
64
+ end
65
+ end
66
+
67
+ desc "builds table of contents"
68
+ task :toc do
69
+ url = ENV['README_URL'] or abort "$README_URL required."
70
+ htmlfile = "README.html"
71
+ sh "curl -s -o #{htmlfile} #{url}"
72
+ rexp = /<h(\d)><a id="(.*?)" class="anchor".*><\/a>(.*)<\/h\1>/
73
+ html_str = File.read(htmlfile, encoding: 'utf-8')
74
+ buf = []
75
+ html_str.scan(rexp) do
76
+ level = $1.to_i
77
+ id = $2
78
+ title = $3
79
+ next if title =~ /Table of Contents/
80
+ anchor = id.sub(/^user-content-/, '')
81
+ indent = " " * (level - 1)
82
+ buf << "#{indent}* <a href=\"##{anchor}\">#{title}</a>\n"
83
+ end
84
+ buf.shift() if buf[0] && buf[0] =~ /^\* /
85
+ toc_str = buf.join()
86
+ #
87
+ changed = File.open("README.md", "r+", encoding: 'utf-8') do |f|
88
+ s1 = f.read()
89
+ s2 = s1.sub(/(<!-- TOC -->\n).*(<!-- \/TOC -->\n)/m) {
90
+ [$1, toc_str, $2].join("\n")
91
+ }
92
+ if s1 != s2
93
+ f.rewind()
94
+ f.truncate(0)
95
+ f.write(s2)
96
+ true
97
+ else
98
+ false
99
+ end
100
+ end
101
+ puts "[changed] README.md" if changed
102
+ puts "[not changed] README.md" unless changed
103
+ end
104
+
105
+ end
@@ -0,0 +1,186 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ ###
4
+ ### $Release: 1.0.0 $
5
+ ### $Copyright: copyright(c) 2011-2021 kuwata-lab.com all rights reserved $
6
+ ### $License: MIT License $
7
+ ###
8
+
9
+ File.class_eval do
10
+ libpath = join(dirname(dirname(expand_path(__FILE__))), 'lib')
11
+ $LOAD_PATH.unshift(libpath) unless $LOAD_PATH.include?(libpath)
12
+ end
13
+
14
+ require 'minitest/spec'
15
+ require 'minitest/autorun'
16
+ require 'minitest/ok'
17
+
18
+ require 'benry/recorder'
19
+
20
+
21
+ class Calc4190
22
+ def average(*nums) # average() calls total()
23
+ return total(*nums) / nums.length
24
+ end
25
+ def total(*nums)
26
+ t = 0
27
+ nums.each {|n| t += n }
28
+ return t # or return nums.sum
29
+ end
30
+ end
31
+
32
+
33
+ describe Benry::Recorder do
34
+
35
+ describe '#record_method()' do
36
+ it "[!61z3j] records method calls." do
37
+ rec = Benry::Recorder.new
38
+ calc = Calc4190.new
39
+ rec.record_method(calc, :total, :average)
40
+ avg = calc.average(10, 20, 30, 40) #=> 25
41
+ #
42
+ ok {rec.length} == 2
43
+ #
44
+ ok {rec[0].obj} == calc
45
+ ok {rec[0].name} == :average
46
+ ok {rec[0].args} == [10, 20, 30, 40]
47
+ ok {rec[0].ret} == 25
48
+ #
49
+ ok {rec[1].obj} == calc
50
+ ok {rec[1].name} == :total
51
+ ok {rec[1].args} == [10, 20, 30, 40]
52
+ ok {rec[1].ret} == 100
53
+ end
54
+ it "[!9kh1f] calls original method." do
55
+ rec = Benry::Recorder.new
56
+ calc = Calc4190.new
57
+ rec.record_method(calc, :total, :average)
58
+ ok {calc.average(10, 20, 30, 40)} == 25
59
+ ok {calc.average(1.0, 2.0, 3.0, 4.0)} == 2.5
60
+ end
61
+ end
62
+
63
+ describe '#fake_method()' do
64
+ it "[!g112x] defines fake methods." do
65
+ rec = Benry::Recorder.new
66
+ calc = Calc4190.new
67
+ rec.fake_method(calc, :total=>150)
68
+ ret = calc.average(10, 20) # calc.average() calls calc.total() internally
69
+ ok {ret} == 75 # 75 == 150/2
70
+ #
71
+ ok {rec.length} == 1
72
+ ok {rec[0].obj} == calc
73
+ ok {rec[0].name} == :total
74
+ ok {rec[0].args} == [10, 20]
75
+ ok {rec[0].ret} == 150
76
+ end
77
+ it "[!kgvm1] defined methods can can take any arguments." do
78
+ rec = Benry::Recorder.new
79
+ calc = Calc4190.new
80
+ rec.fake_method(calc, :total=>999)
81
+ ret = calc.total(10, 20, :a=>1, 'b'=>2)
82
+ ok {ret} == 999
83
+ #
84
+ ok {rec.length} == 1
85
+ #
86
+ ok {rec[0].obj} == calc
87
+ ok {rec[0].name} == :total
88
+ ok {rec[0].args} == [10, 20, {:a=>1, 'b'=>2}]
89
+ ok {rec[0].ret} == 999
90
+ end
91
+ it "[!2p1b0] returns self." do
92
+ end
93
+ end
94
+
95
+ describe '#fake_object()' do
96
+ it "[!hympr] creates fake object." do
97
+ rec = Benry::Recorder.new
98
+ obj = rec.fake_object(:foo=>123, :bar=>"abc")
99
+ ok {obj.foo(10, 20, 'a'=>1, 'b'=>2)} == 123
100
+ ok {obj.bar(30, 40, x: 8, y: 9)} == "abc"
101
+ #
102
+ ok {rec.length} == 2
103
+ #
104
+ ok {rec[0].obj} == obj
105
+ ok {rec[0].name} == :foo
106
+ ok {rec[0].args} == [10, 20, {'a'=>1, 'b'=>2}]
107
+ ok {rec[0].ret} == 123
108
+ #
109
+ ok {rec[1].obj} == obj
110
+ ok {rec[1].name} == :bar
111
+ ok {rec[1].args} == [30, 40, {:x=>8, :y=>9}]
112
+ ok {rec[1].ret} == "abc"
113
+ end
114
+ end
115
+
116
+ describe '#inspect()' do
117
+ it "[!k85bz] represents internal data." do
118
+ rec = Benry::Recorder.new
119
+ calc = Calc4190.new
120
+ rec.fake_method(calc, :total=>200)
121
+ rec.record_method(calc, :average)
122
+ ret = calc.average(10, 20, 30, 40)
123
+ #
124
+ s = rec.inspect.gsub(/#<Calc4190:0x\w+>/, '#<Calc4190:0xXXXX>')
125
+ ok {s} == ("0: #<Calc4190:0xXXXX>.average(10, 20, 30, 40) #=> 50\n"\
126
+ "1: #<Calc4190:0xXXXX>.total(10, 20, 30, 40) #=> 200\n")
127
+ end
128
+ end
129
+
130
+ end
131
+
132
+
133
+ describe Benry::Recorder::Called do
134
+
135
+ before do
136
+ @calc = Calc4190.new
137
+ @rec = Benry::Recorder.new
138
+ @rec.record_method(@calc, :total, :average)
139
+ avg = @calc.average(10, 20, 30, 40) #=> 25
140
+ @called0 = @rec[0]
141
+ @called1 = @rec[1]
142
+ end
143
+
144
+ describe '#obj' do
145
+ it "[!m98p9] returns receiver object." do
146
+ ok {@called0.obj} == @calc
147
+ ok {@called1.obj} == @calc
148
+ end
149
+ end
150
+
151
+ describe '#name' do
152
+ it "[!es61g] returns method name." do
153
+ ok {@called0.name} == :average
154
+ ok {@called1.name} == :total
155
+ end
156
+ end
157
+
158
+ describe '#args' do
159
+ it "[!2yeeo] returns arguments." do
160
+ ok {@called0.args} == [10, 20, 30, 40]
161
+ ok {@called1.args} == [10, 20, 30, 40]
162
+ end
163
+ end
164
+
165
+ describe '#ret' do
166
+ it "[!yd3hl] returns arguments." do
167
+ ok {@called0.ret} == 25
168
+ ok {@called1.ret} == 100
169
+ end
170
+ end
171
+
172
+ describe '#to_a' do
173
+ it "[!hrol9] returns array of obj, nae, args, and ret." do
174
+ ok {@called0.to_a} == [@calc, :average, [10, 20, 30, 40], 25]
175
+ ok {@called1.to_a} == [@calc, :total, [10, 20, 30, 40], 100]
176
+ end
177
+ end
178
+
179
+ describe '#inspect()' do
180
+ it "[!g2iwe] represents internal data." do
181
+ rexp = /\A#<Calc4190:0x\w+>\.average\(10, 20, 30, 40\) #=> 25\z/
182
+ ok {@called0.inspect()} =~ rexp
183
+ end
184
+ end
185
+
186
+ end
data/test/run_all.rb ADDED
@@ -0,0 +1,7 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ Dir.glob(File.join(File.dirname(__FILE__), '**/*_test.rb')).each do |x|
4
+ #require x
5
+ require File.absolute_path(x)
6
+ #load x
7
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: benry-recorder
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - kwatch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-08-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest-ok
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: |
42
+ Benry-recorder is a tiny utility that can:
43
+
44
+ * Record method calls of target object.
45
+ * Define fake methods on target object.
46
+ * Create fake object which has fake methods.
47
+ email: kwatch@gmail.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - README.md
53
+ - Rakefile.rb
54
+ - benry-recorder.gemspec
55
+ - lib/benry/recorder.rb
56
+ - task/common-task.rb
57
+ - task/readme-task.rb
58
+ - test/recorder_test.rb
59
+ - test/run_all.rb
60
+ homepage: https://github.com/kwatch/benry-ruby/tree/ruby/benry-recorder
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.5.2.3
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Record method calls, or define fake methods.
84
+ test_files:
85
+ - test/recorder_test.rb