benry-recorder 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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