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