rubybreaker 0.0.4 → 0.0.5
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.
- data/NEWS +5 -0
- data/NOTES +9 -0
- data/README.md +100 -183
- data/Rakefile +21 -6
- data/VERSION +1 -1
- data/bin/rubybreaker +34 -50
- data/lib/rubybreaker/debug/debug.rb +6 -0
- data/lib/rubybreaker/doc/rdoc.rb +37 -0
- data/lib/rubybreaker/doc.rb +3 -0
- data/lib/rubybreaker/runtime/inspector.rb +6 -28
- data/lib/rubybreaker/runtime/monitor.rb +21 -17
- data/lib/rubybreaker/runtime/object_wrapper.rb +7 -2
- data/lib/rubybreaker/runtime/type_system.rb +3 -5
- data/lib/rubybreaker/runtime/typesig_unparser.rb +1 -4
- data/lib/rubybreaker/runtime.rb +64 -105
- data/lib/rubybreaker/task.rb +97 -0
- data/lib/rubybreaker/test/rspec.rb +1 -1
- data/lib/rubybreaker/test/testcase.rb +13 -28
- data/lib/rubybreaker/type/type.rb +1 -1
- data/lib/rubybreaker/typing/subtyping.rb +10 -5
- data/lib/rubybreaker/util.rb +0 -1
- data/lib/rubybreaker.rb +163 -115
- data/test/integrated/tc_both_broken_breakable.rb +5 -4
- data/test/integrated/tc_class_methods.rb +4 -3
- data/test/integrated/tc_inherit_broken.rb +4 -3
- data/test/integrated/tc_method_missing.rb +4 -4
- data/test/integrated/tc_namespace.rb +4 -2
- data/test/integrated/tc_simple1.rb +4 -3
- data/test/runtime/tc_obj_wrapper.rb +25 -6
- data/test/runtime/tc_typesig_parser.rb +0 -1
- data/test/testtask/sample.rb +10 -0
- data/test/testtask/tc_testtask.rb +25 -0
- data/test/ts_rspec.rb +21 -15
- data/test/typing/tc_typing.rb +2 -3
- data/webpage/index.html +105 -193
- data/webpage/rdoc/Kernel.html +286 -0
- data/webpage/rdoc/Object.html +17 -11
- data/webpage/rdoc/Rake/RubyBreakerTestTask.html +374 -0
- data/webpage/rdoc/Rake.html +212 -0
- data/webpage/rdoc/RubyBreaker/Breakable.html +24 -40
- data/webpage/rdoc/RubyBreaker/Broken.html +21 -69
- data/webpage/rdoc/RubyBreaker/Context.html +16 -10
- data/webpage/rdoc/RubyBreaker/Errors/InternalError.html +16 -10
- data/webpage/rdoc/RubyBreaker/Errors/InvalidSubtypeCheck.html +16 -10
- data/webpage/rdoc/RubyBreaker/Errors/InvalidTypeConstruction.html +16 -10
- data/webpage/rdoc/RubyBreaker/Errors/SubtypeFailure.html +16 -10
- data/webpage/rdoc/RubyBreaker/Errors/TypeError.html +16 -10
- data/webpage/rdoc/RubyBreaker/Errors/UserError.html +16 -10
- data/webpage/rdoc/RubyBreaker/Errors.html +16 -10
- data/webpage/rdoc/RubyBreaker/ObjectPosition.html +16 -10
- data/webpage/rdoc/RubyBreaker/Position.html +16 -10
- data/webpage/rdoc/RubyBreaker/{TestCase.html → RDocSupport.html} +81 -82
- data/webpage/rdoc/RubyBreaker/RubyTypeUtils.html +16 -10
- data/webpage/rdoc/RubyBreaker/Runtime/Inspector.html +25 -44
- data/webpage/rdoc/RubyBreaker/Runtime/MethodInfo.html +16 -10
- data/webpage/rdoc/RubyBreaker/Runtime/Monitor.html +19 -13
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorInstaller.html +37 -25
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorSwitch.html +20 -14
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorUtils.html +21 -15
- data/webpage/rdoc/RubyBreaker/Runtime/ObjectWrapper.html +23 -12
- data/webpage/rdoc/RubyBreaker/Runtime/Pluggable.html +16 -10
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSigParser.html +16 -10
- data/webpage/rdoc/RubyBreaker/Runtime/{TypesigUnparser.html → TypeSigUnparser.html} +19 -16
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSystem.html +18 -14
- data/webpage/rdoc/RubyBreaker/Runtime.html +145 -11
- data/webpage/rdoc/RubyBreaker/TypeComparer.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/AnyType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/BlockType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/DuckType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/FusionType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/MethodListType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/MethodType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/NilType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/NominalType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/OptionalType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/OrType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs/SelfType.html +17 -11
- data/webpage/rdoc/RubyBreaker/TypeDefs/Type.html +17 -11
- data/webpage/rdoc/RubyBreaker/TypeDefs/VarLengthType.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeDefs.html +16 -10
- data/webpage/rdoc/RubyBreaker/TypeUnparser.html +16 -10
- data/webpage/rdoc/RubyBreaker/Typing.html +17 -11
- data/webpage/rdoc/RubyBreaker/Util.html +16 -10
- data/webpage/rdoc/RubyBreaker.html +167 -34
- data/webpage/rdoc/{RubyBreaker/Runtime/TypePlaceholder.html → Test/Unit/TestCase.html} +68 -39
- data/webpage/rdoc/Test/Unit.html +211 -0
- data/webpage/rdoc/Test.html +211 -0
- data/webpage/rdoc/created.rid +18 -17
- data/webpage/rdoc/index.html +16 -10
- data/webpage/rdoc/js/search_index.js +1 -1
- data/webpage/rdoc/table_of_contents.html +61 -48
- metadata +21 -12
- data/lib/rubybreaker/rubylib/core.rb +0 -2483
- data/lib/rubybreaker/rubylib.rb +0 -3
- data/lib/rubybreaker/runtime/type_placeholder.rb +0 -23
- data/webpage/rdoc/RubyBreaker/Broken/BrokenEigen.html +0 -305
- data/webpage/rdoc/RubyBreaker/Main.html +0 -458
data/lib/rubybreaker.rb
CHANGED
|
@@ -3,164 +3,212 @@
|
|
|
3
3
|
# observed at runtime and generates type annotation at the end. It can be
|
|
4
4
|
# run as either a stand-alone script or as a Ruby library.
|
|
5
5
|
|
|
6
|
+
require "set"
|
|
7
|
+
require "optparse"
|
|
6
8
|
require_relative "rubybreaker/debug"
|
|
7
9
|
require_relative "rubybreaker/runtime"
|
|
8
10
|
require_relative "rubybreaker/test"
|
|
9
11
|
|
|
10
12
|
# RubyBreaker is a dynamic instrumentation and monitoring tool that
|
|
11
|
-
#
|
|
13
|
+
# generates type documentation for Ruby programs.
|
|
12
14
|
module RubyBreaker
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
COPYRIGHT = "Copyright (c) 2012 Jong-hoon (David) An. All Rights Reserved."
|
|
15
|
+
include TypeDefs
|
|
16
|
+
include Runtime
|
|
16
17
|
|
|
17
18
|
# Options for RubyBreaker
|
|
18
19
|
OPTIONS = {
|
|
19
|
-
:debug
|
|
20
|
-
:
|
|
21
|
-
:
|
|
22
|
-
:
|
|
23
|
-
:
|
|
24
|
-
:
|
|
25
|
-
:
|
|
26
|
-
:
|
|
20
|
+
:debug => false, # in debug mode?
|
|
21
|
+
:style => :underscore, # type signature style-underscore or camelize
|
|
22
|
+
:io_file => nil, # generate input/output other than default?
|
|
23
|
+
:append => false, # append to the input file (if there is)?
|
|
24
|
+
:stdout => false, # also display on the screen?
|
|
25
|
+
:verbose => false, # in RubyBreaker.verbose mode?
|
|
26
|
+
:save_output => true, # save output to a file?
|
|
27
|
+
:prog_file => nil, # INTERNAL USE ONLY
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
# This
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
# Extension used by RubyBreaker for output/input
|
|
34
|
-
EXTENSION = "rubybreaker"
|
|
35
|
-
|
|
36
|
-
# This module has a set of entry points to the program and misc. methods
|
|
37
|
-
# for running RubyBreaker.
|
|
38
|
-
module Main
|
|
30
|
+
# This option parser may be used for the command-line mode or for the
|
|
31
|
+
# library mode when used with Rakefile. See rubybreaker/task.rb for how
|
|
32
|
+
# this can be used in the latter.
|
|
33
|
+
OPTION_PARSER = OptionParser.new do |opts|
|
|
39
34
|
|
|
40
|
-
|
|
41
|
-
include Runtime
|
|
35
|
+
opts.banner = "Usage: #{File.basename(__FILE__)} [options] prog[.rb]"
|
|
42
36
|
|
|
43
|
-
|
|
37
|
+
opts.on("--debug", "Run in debug mode") do
|
|
38
|
+
OPTIONS[:debug] = true
|
|
39
|
+
end
|
|
44
40
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
opts.on("--style STYLE", "Select type signature style - underscore or camelize") do |v|
|
|
42
|
+
OPTIONS[:style] = v.downcase.to_sym
|
|
43
|
+
end
|
|
48
44
|
|
|
49
|
-
|
|
45
|
+
opts.on("--io-file FILE","Specify I/O file") do |f|
|
|
46
|
+
OPTIONS[:io_file] = f
|
|
47
|
+
end
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
unless INSTALLED.include?(mod)
|
|
55
|
-
MonitorInstaller.install_module_monitor(mod)
|
|
56
|
-
INSTALLED << mod
|
|
57
|
-
end
|
|
49
|
+
opts.on("--save-output", "Save output to file") do b|
|
|
50
|
+
OPTIONS[:save_output] = b
|
|
51
|
+
end
|
|
58
52
|
|
|
59
|
-
|
|
53
|
+
opts.on("-s","--[no-]stdout","Show output on screen") do |b|
|
|
54
|
+
OPTIONS[:stdout] = b
|
|
55
|
+
end
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
end
|
|
57
|
+
opts.on("-a", "--[no-]append", "Append output to input file") do |b|
|
|
58
|
+
OPTIONS[:append] = b
|
|
59
|
+
end
|
|
65
60
|
|
|
61
|
+
opts.on("-v","--verbose","Show messages in detail") do
|
|
62
|
+
OPTIONS[:verbose] = true
|
|
66
63
|
end
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
RubyBreaker.verbose("RubyBreaker input file exists...loading")
|
|
72
|
-
eval "load \"#{OPTIONS[:io_file]}\"", TOPLEVEL_BINDING
|
|
65
|
+
opts.on("-h","--help","Show this help text") do
|
|
66
|
+
puts opts
|
|
67
|
+
exit
|
|
73
68
|
end
|
|
74
69
|
|
|
75
|
-
|
|
76
|
-
def self.output()
|
|
70
|
+
end
|
|
77
71
|
|
|
78
|
-
|
|
72
|
+
# This constant contains the copyright information.
|
|
73
|
+
COPYRIGHT = "Copyright (c) 2012 Jong-hoon (David) An. All Rights Reserved."
|
|
79
74
|
|
|
80
|
-
|
|
75
|
+
# Extension used for files that contain RubyBreaker task information
|
|
76
|
+
TASK_EXTENSION = "rb"
|
|
81
77
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
78
|
+
# Extension used for files that contain type information in YAML format
|
|
79
|
+
YAML_EXTENSION = "yaml"
|
|
80
|
+
|
|
81
|
+
# Extension used for files that contain type information in Ruby format
|
|
82
|
+
IO_EXTENSION = "rubybreaker.rb"
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
# This method determines if RubyBreaker is running as a task.
|
|
87
|
+
def self.running_as_task?(); return $__rubybreaker_task != nil end
|
|
88
|
+
|
|
89
|
+
# This method returns the task currently being run.
|
|
90
|
+
def self.task(); return $__rubybreaker_task end
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
# This method loads the IO file by loading it.
|
|
93
|
+
def self.load_input(fname)
|
|
94
|
+
return fname
|
|
95
|
+
eval "load \"#{fname}\"", TOPLEVEL_BINDING
|
|
96
|
+
RubyBreaker.verbose("RubyBreaker input file #{fname} is loaded")
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# This method will generate the output to the given filename.
|
|
100
|
+
def self.output(fname)
|
|
101
|
+
|
|
102
|
+
RubyBreaker.verbose("Generating type documentation")
|
|
94
103
|
|
|
104
|
+
code = ""
|
|
105
|
+
|
|
106
|
+
# Document each module that was monitored.
|
|
107
|
+
INSTALLED.each { |mod|
|
|
108
|
+
str = Runtime::TypeSigUnparser.unparse(mod)
|
|
109
|
+
code << str
|
|
110
|
+
print str if OPTIONS[:stdout] # display on the screen if requested
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if fname && OPTIONS[:save_output]
|
|
114
|
+
# Check if the file already exists--that is, if it was used for input
|
|
115
|
+
io_exist = File.exists?(fname)
|
|
116
|
+
RubyBreaker.verbose("Saving it to #{fname}")
|
|
95
117
|
# Append the result to the input file (or create a new file)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
118
|
+
fmode = OPTIONS[:append] ? "a" : "w"
|
|
119
|
+
open(fname, fmode) do |f|
|
|
120
|
+
# When append, do not write the header
|
|
121
|
+
unless OPTIONS[:append]
|
|
122
|
+
f.puts "# This file is auto-generated by RubyBreaker"
|
|
100
123
|
end
|
|
124
|
+
# But time stamp always
|
|
125
|
+
f.puts "# Last modified: #{Time.now}"
|
|
126
|
+
f.puts "require \"rubybreaker\"" unless OPTIONS[:append]
|
|
101
127
|
f.print code
|
|
102
128
|
end
|
|
129
|
+
end
|
|
103
130
|
|
|
104
|
-
|
|
131
|
+
RubyBreaker.verbose("Done generating type documentation")
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# This method finds the IO file for this run. It is either specified in
|
|
135
|
+
# io-file option or using the program name or the task name.
|
|
136
|
+
def self.io_file(prog_or_task)
|
|
137
|
+
if OPTIONS[:io_file]
|
|
138
|
+
fname = OPTIONS[:io_file]
|
|
139
|
+
elsif prog_or_task
|
|
140
|
+
fname = "#{File.basename(prog_or_task.to_s, ".rb")}.#{IO_EXTENSION}"
|
|
105
141
|
end
|
|
142
|
+
return nil unless fname
|
|
143
|
+
fname = File.absolute_path(fname)
|
|
144
|
+
return fname
|
|
145
|
+
end
|
|
106
146
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
RubyBreaker.verbose("Running RubyBreaker")
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
exit(1)
|
|
132
|
-
end
|
|
147
|
+
public
|
|
148
|
+
|
|
149
|
+
# This method runs RubyBreaker for a particular test case (class). This
|
|
150
|
+
# is a bit different from running RubyBreaker as a shell program.
|
|
151
|
+
def self.run(*mods)
|
|
152
|
+
RubyBreaker.setup_logger() unless RubyBreaker.defined_logger?()
|
|
153
|
+
|
|
154
|
+
# Task based run should use the rubybreaker options same as in shell
|
|
155
|
+
# mode. So, parse the options first.
|
|
156
|
+
if self.running_as_task?() # running in task mode
|
|
157
|
+
RubyBreaker.verbose("Running RubyBreaker within a testcase")
|
|
158
|
+
task = self.task
|
|
159
|
+
OPTION_PARSER.parse(*task[:rubybreaker_opts])
|
|
160
|
+
Runtime.breakable(*task[:breakable])
|
|
161
|
+
task_name = task[:name]
|
|
162
|
+
RubyBreaker.verbose("Done reading task information")
|
|
163
|
+
io_file = self.io_file(task_name)
|
|
164
|
+
elsif OPTIONS[:prog_file] # running in shell mode
|
|
165
|
+
Runtime.breakable(*mods)
|
|
166
|
+
io_file = self.io_file(OPTIONS[:prog_file])
|
|
167
|
+
else
|
|
168
|
+
# Otherwise, assume there are no explicit IO files.
|
|
169
|
+
end
|
|
170
|
+
self.load_input(io_file)
|
|
133
171
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
OPTIONS[:io_file] = "#{File.basename(argv0, ".rb")}.#{EXTENSION}"
|
|
137
|
-
end
|
|
138
|
-
OPTIONS[:io_file] = File.absolute_path(OPTIONS[:io_file])
|
|
172
|
+
# The following is deprecated but doing this for backward compatibility
|
|
173
|
+
Runtime.instrument()
|
|
139
174
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
175
|
+
# At the end, we WILL generate an output of the type information.
|
|
176
|
+
at_exit { self.output(io_file) }
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
end
|
|
145
180
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
Main.input()
|
|
181
|
+
# This method is available by default.
|
|
182
|
+
module Kernel
|
|
149
183
|
|
|
150
|
-
|
|
151
|
-
|
|
184
|
+
def typesig(str)
|
|
185
|
+
_TypeDefs = RubyBreaker::TypeDefs
|
|
152
186
|
|
|
153
|
-
|
|
187
|
+
# This MUST BE set for self type to work in type signatures.
|
|
188
|
+
_TypeDefs::SelfType.set_self(self)
|
|
154
189
|
|
|
155
|
-
|
|
190
|
+
t = RubyBreaker::Runtime::TypeSigParser.parse(str)
|
|
191
|
+
t_map = RubyBreaker::Runtime::TYPE_MAP[self]
|
|
156
192
|
|
|
157
|
-
|
|
193
|
+
# If the type map doesn't exist, create it on the fly. Now this module
|
|
194
|
+
# is broken!
|
|
195
|
+
if !t_map
|
|
196
|
+
t_map = {}
|
|
197
|
+
RubyBreaker::Runtime::TYPE_MAP[self] = t_map
|
|
198
|
+
end
|
|
158
199
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
200
|
+
meth_type = t_map[t.meth_name]
|
|
201
|
+
if meth_type
|
|
202
|
+
if meth_type.instance_of?(_TypeDefs::MethodListType)
|
|
203
|
+
meth_type.types << t
|
|
204
|
+
else
|
|
205
|
+
# then promote it to a method list type
|
|
206
|
+
t_map[t.meth_name] = _TypeDefs::MethodListType.new([meth_type, t])
|
|
207
|
+
end
|
|
208
|
+
else
|
|
209
|
+
t_map[t.meth_name] = t
|
|
210
|
+
end
|
|
211
|
+
return t
|
|
163
212
|
end
|
|
164
|
-
|
|
165
213
|
end
|
|
166
214
|
|
|
@@ -3,18 +3,19 @@ require_relative "../../lib/rubybreaker"
|
|
|
3
3
|
|
|
4
4
|
class IntegratedBothBrokenBreakableTest < Test::Unit::TestCase
|
|
5
5
|
include RubyBreaker
|
|
6
|
-
include RubyBreaker::TestCase
|
|
7
6
|
|
|
8
7
|
class A
|
|
9
|
-
include RubyBreaker::Breakable
|
|
10
|
-
include RubyBreaker::Broken
|
|
8
|
+
# include RubyBreaker::Breakable
|
|
11
9
|
typesig("foo(fixnum[to_s]) -> string")
|
|
12
10
|
def foo(x); x.to_s end
|
|
13
11
|
def bar(x); x.to_sym end
|
|
14
12
|
end
|
|
15
13
|
|
|
14
|
+
def setup
|
|
15
|
+
RubyBreaker.breakable(A)
|
|
16
|
+
end
|
|
17
|
+
|
|
16
18
|
def test_both_broken_and_breakable
|
|
17
|
-
# A.new.foo(1)
|
|
18
19
|
A.new.bar("abc")
|
|
19
20
|
a_foo_meth_type = Runtime::Inspector.inspect_meth(A, :foo)
|
|
20
21
|
a_bar_meth_type = Runtime::Inspector.inspect_meth(A, :bar)
|
|
@@ -3,21 +3,22 @@ require_relative "../../lib/rubybreaker"
|
|
|
3
3
|
|
|
4
4
|
class IntegratedClassMethodsTest < Test::Unit::TestCase
|
|
5
5
|
include RubyBreaker
|
|
6
|
-
include RubyBreaker::TestCase
|
|
7
6
|
|
|
8
7
|
class A
|
|
9
|
-
include RubyBreaker::Breakable
|
|
10
8
|
def self.foo(x); x.to_s end
|
|
11
9
|
end
|
|
12
10
|
|
|
13
11
|
class B
|
|
14
|
-
include RubyBreaker::Broken
|
|
15
12
|
class << self
|
|
16
13
|
typesig("bar(fixnum[to_s]) -> string")
|
|
17
14
|
def bar(x); x.to_s end
|
|
18
15
|
end
|
|
19
16
|
end
|
|
20
17
|
|
|
18
|
+
def setup()
|
|
19
|
+
RubyBreaker.breakable(A, B)
|
|
20
|
+
end
|
|
21
|
+
|
|
21
22
|
def test_class_methods
|
|
22
23
|
A.foo(1)
|
|
23
24
|
a_foo_meth_type = Runtime::Inspector.inspect_class_meth(A, :foo)
|
|
@@ -3,19 +3,20 @@ require_relative "../../lib/rubybreaker"
|
|
|
3
3
|
|
|
4
4
|
class IntegratedInheritBrokenTest < Test::Unit::TestCase
|
|
5
5
|
include RubyBreaker
|
|
6
|
-
include RubyBreaker::TestCase
|
|
7
6
|
|
|
8
7
|
class A
|
|
9
|
-
include RubyBreaker::Broken
|
|
10
8
|
typesig("foo(fixnum[to_s]) -> string")
|
|
11
9
|
def foo(x); x.to_s end
|
|
12
10
|
end
|
|
13
11
|
|
|
14
12
|
class B < A
|
|
15
|
-
include RubyBreaker::Breakable
|
|
16
13
|
def bar(x); foo(x) end
|
|
17
14
|
end
|
|
18
15
|
|
|
16
|
+
def setup()
|
|
17
|
+
RubyBreaker.breakable(B)
|
|
18
|
+
end
|
|
19
|
+
|
|
19
20
|
def test_both
|
|
20
21
|
b = B.new
|
|
21
22
|
b.bar(1)
|
|
@@ -3,16 +3,16 @@ require_relative "../../lib/rubybreaker"
|
|
|
3
3
|
|
|
4
4
|
class IntegratedMethodMissingTest < Test::Unit::TestCase
|
|
5
5
|
include RubyBreaker
|
|
6
|
-
include RubyBreaker::TestCase
|
|
7
6
|
|
|
8
7
|
class A
|
|
9
|
-
include RubyBreaker::Breakable
|
|
10
|
-
|
|
11
8
|
def method_missing(mname, *args, &blk)
|
|
12
9
|
method_name = mname.to_s
|
|
13
10
|
return method_name + "_" + args.join("_")
|
|
14
11
|
end
|
|
15
|
-
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def setup()
|
|
15
|
+
RubyBreaker.breakable(A)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# TODO: This must be fixed once variable length argument type is supported
|
|
@@ -3,7 +3,6 @@ require_relative "../../lib/rubybreaker"
|
|
|
3
3
|
|
|
4
4
|
class IntegratedNamespaceTest < Test::Unit::TestCase
|
|
5
5
|
include RubyBreaker
|
|
6
|
-
include RubyBreaker::TestCase
|
|
7
6
|
|
|
8
7
|
class A < String
|
|
9
8
|
class C < String
|
|
@@ -17,12 +16,15 @@ class IntegratedNamespaceTest < Test::Unit::TestCase
|
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
class B
|
|
20
|
-
include RubyBreaker::Breakable
|
|
21
19
|
def foo(x); x.to_s end
|
|
22
20
|
def bar(x); x.to_s end
|
|
23
21
|
def baz(x); x.to_s end
|
|
24
22
|
end
|
|
25
23
|
|
|
24
|
+
def setup()
|
|
25
|
+
RubyBreaker.breakable(B)
|
|
26
|
+
end
|
|
27
|
+
|
|
26
28
|
def test_namspace_b_foo
|
|
27
29
|
a = A.new
|
|
28
30
|
b = B.new
|
|
@@ -3,10 +3,8 @@ require_relative "../../lib/rubybreaker"
|
|
|
3
3
|
|
|
4
4
|
class IntegratedSimpleTest < Test::Unit::TestCase
|
|
5
5
|
include RubyBreaker
|
|
6
|
-
include RubyBreaker::TestCase
|
|
7
6
|
|
|
8
7
|
class A
|
|
9
|
-
include RubyBreaker::Breakable
|
|
10
8
|
|
|
11
9
|
def foo(x)
|
|
12
10
|
x.to_s
|
|
@@ -33,12 +31,15 @@ class IntegratedSimpleTest < Test::Unit::TestCase
|
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
class B
|
|
36
|
-
include RubyBreaker::Broken
|
|
37
34
|
typesig("baz(string[size], true_class) -> fixnum")
|
|
38
35
|
typesig("baz(string[to_s], false_class) -> string")
|
|
39
36
|
def baz(x,b); end
|
|
40
37
|
end
|
|
41
38
|
|
|
39
|
+
def setup()
|
|
40
|
+
RubyBreaker.breakable(A)
|
|
41
|
+
end
|
|
42
|
+
|
|
42
43
|
def test_simple1_a_foo
|
|
43
44
|
a = A.new
|
|
44
45
|
a.foo("test_simple1 >> string")
|
|
@@ -16,6 +16,16 @@ class ObjectWrapperTest < Test::Unit::TestCase
|
|
|
16
16
|
x.to_s
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
def baz(x)
|
|
20
|
+
x.send(:foo,1)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class A
|
|
24
|
+
def foo(x)
|
|
25
|
+
x.to_s
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
19
29
|
def test_empty()
|
|
20
30
|
x = 42
|
|
21
31
|
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
@@ -24,28 +34,37 @@ class ObjectWrapperTest < Test::Unit::TestCase
|
|
|
24
34
|
assert_equal("fixnum[]",str)
|
|
25
35
|
end
|
|
26
36
|
|
|
27
|
-
def
|
|
37
|
+
def setup
|
|
38
|
+
Runtime::GLOBAL_MONITOR_SWITCH.turn_on()
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_foo()
|
|
28
42
|
x = 42
|
|
29
43
|
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
30
|
-
Runtime::GLOBAL_MONITOR_SWITCH.turn_on()
|
|
31
44
|
foo(wrapped_x)
|
|
32
|
-
Runtime::GLOBAL_MONITOR_SWITCH.turn_off()
|
|
33
45
|
type = wrapped_x.__rubybreaker_type()
|
|
34
46
|
str = TypeUnparser.unparse(type)
|
|
35
47
|
assert_equal("fixnum[to_f, to_s]",str)
|
|
36
48
|
end
|
|
37
49
|
|
|
38
|
-
def
|
|
50
|
+
def test_bar()
|
|
39
51
|
x = 42
|
|
40
52
|
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
41
|
-
Runtime::GLOBAL_MONITOR_SWITCH.turn_on()
|
|
42
53
|
bar(wrapped_x)
|
|
43
|
-
Runtime::GLOBAL_MONITOR_SWITCH.turn_off()
|
|
44
54
|
type = wrapped_x.__rubybreaker_type()
|
|
45
55
|
str = TypeUnparser.unparse(type)
|
|
46
56
|
assert_equal("fixnum[to_f, to_s]",str)
|
|
47
57
|
end
|
|
48
58
|
|
|
59
|
+
def test_baz()
|
|
60
|
+
x = A.new
|
|
61
|
+
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
62
|
+
baz(wrapped_x)
|
|
63
|
+
type = wrapped_x.__rubybreaker_type()
|
|
64
|
+
str = TypeUnparser.unparse(type)
|
|
65
|
+
assert_equal("object_wrapper_test/a[foo]", str)
|
|
66
|
+
end
|
|
67
|
+
|
|
49
68
|
def test_object_id()
|
|
50
69
|
x = 42
|
|
51
70
|
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require "test/unit"
|
|
2
|
+
require_relative "sample"
|
|
3
|
+
require "rubybreaker"
|
|
4
|
+
|
|
5
|
+
class SampleClassB # re-opening
|
|
6
|
+
typesig("foo(fixnum[to_s]) -> string")
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class RubyBreakerTestTaskTest < Test::Unit::TestCase
|
|
10
|
+
|
|
11
|
+
def test_breakable()
|
|
12
|
+
SampleClassA.new.foo(2)
|
|
13
|
+
t = RubyBreaker::Runtime::Inspector.inspect_meth(SampleClassA, :foo)
|
|
14
|
+
str = t.unparse()
|
|
15
|
+
assert_equal("foo(fixnum[to_s]) -> string", str)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_broken()
|
|
19
|
+
t = RubyBreaker::Runtime::Inspector.inspect_meth(SampleClassB, :foo)
|
|
20
|
+
str = t.unparse()
|
|
21
|
+
assert_equal("foo(fixnum[to_s]) -> string", str)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
data/test/ts_rspec.rb
CHANGED
|
@@ -2,30 +2,36 @@ require "rspec"
|
|
|
2
2
|
require_relative "../lib/rubybreaker"
|
|
3
3
|
|
|
4
4
|
class RSpecTestA
|
|
5
|
-
include RubyBreaker::Breakable
|
|
6
5
|
def foo(x); x.to_s end
|
|
7
6
|
end
|
|
8
7
|
|
|
9
8
|
class RSpecTestB
|
|
10
|
-
include RubyBreaker::Broken
|
|
11
9
|
typesig("foo(fixnum[to_s]) -> string")
|
|
12
10
|
end
|
|
13
11
|
|
|
14
|
-
describe
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
a_foo_type = RubyBreaker::Runtime::Inspector.inspect_meth(RSpecTestA, :foo)
|
|
19
|
-
str = a_foo_type.unparse()
|
|
20
|
-
str.should == "foo(fixnum[to_s]) -> string"
|
|
12
|
+
describe "RSpec Test" do
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
RubyBreaker.breakable(RSpecTestA)
|
|
21
16
|
end
|
|
22
|
-
end
|
|
23
17
|
|
|
24
|
-
describe
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
describe RSpecTestA do
|
|
19
|
+
it "should return a string of number" do
|
|
20
|
+
a = RSpecTestA.new
|
|
21
|
+
a.foo(1)
|
|
22
|
+
a_foo_type = RubyBreaker::Runtime::Inspector.inspect_meth(RSpecTestA, :foo)
|
|
23
|
+
str = a_foo_type.unparse()
|
|
24
|
+
str.should == "foo(fixnum[to_s]) -> string"
|
|
25
|
+
end
|
|
29
26
|
end
|
|
27
|
+
|
|
28
|
+
describe RSpecTestB do
|
|
29
|
+
it "should return the documented type of B#foo" do
|
|
30
|
+
b_foo_type = RubyBreaker::Runtime::Inspector.inspect_meth(RSpecTestB, :foo)
|
|
31
|
+
str = b_foo_type.unparse()
|
|
32
|
+
str.should == "foo(fixnum[to_s]) -> string"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
30
36
|
end
|
|
31
37
|
|
data/test/typing/tc_typing.rb
CHANGED
|
@@ -8,7 +8,6 @@ class TypingTest < Test::Unit::TestCase
|
|
|
8
8
|
include RubyBreaker
|
|
9
9
|
|
|
10
10
|
class A
|
|
11
|
-
include RubyBreaker::Broken
|
|
12
11
|
typesig("foo(fixnum) -> fixnum")
|
|
13
12
|
typesig("bar(fixnum) {|fixnum| -> string} -> string")
|
|
14
13
|
typesig("baz(fixnum, string?) -> fixnum")
|
|
@@ -100,14 +99,14 @@ class TypingTest < Test::Unit::TestCase
|
|
|
100
99
|
assert(t1.subtype_of?(t2), msg(t1, t2))
|
|
101
100
|
assert(t2.subtype_of?(t1), msg(t1, t2))
|
|
102
101
|
# XXX: The following assert will succeed because Fixnum and String are
|
|
103
|
-
# not
|
|
102
|
+
# not "broken" at this point.
|
|
104
103
|
assert(t1.subtype_of?(t3), msg(t1, t3, true))
|
|
105
104
|
end
|
|
106
105
|
|
|
107
106
|
def test_duck_fusion_types()
|
|
108
107
|
t1 = DuckType.new([:to_s, :to_f])
|
|
109
108
|
t2 = FusionType.new(NominalType.new(Fixnum), [:to_f, :to_s])
|
|
110
|
-
# Again, this works because Fixnum is not
|
|
109
|
+
# Again, this works because Fixnum is not "broken" yet
|
|
111
110
|
assert(t1.subtype_of?(t2), msg(t1, t2))
|
|
112
111
|
assert(t2.subtype_of?(t1), msg(t1, t2))
|
|
113
112
|
end
|