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.
Files changed (97) hide show
  1. data/NEWS +5 -0
  2. data/NOTES +9 -0
  3. data/README.md +100 -183
  4. data/Rakefile +21 -6
  5. data/VERSION +1 -1
  6. data/bin/rubybreaker +34 -50
  7. data/lib/rubybreaker/debug/debug.rb +6 -0
  8. data/lib/rubybreaker/doc/rdoc.rb +37 -0
  9. data/lib/rubybreaker/doc.rb +3 -0
  10. data/lib/rubybreaker/runtime/inspector.rb +6 -28
  11. data/lib/rubybreaker/runtime/monitor.rb +21 -17
  12. data/lib/rubybreaker/runtime/object_wrapper.rb +7 -2
  13. data/lib/rubybreaker/runtime/type_system.rb +3 -5
  14. data/lib/rubybreaker/runtime/typesig_unparser.rb +1 -4
  15. data/lib/rubybreaker/runtime.rb +64 -105
  16. data/lib/rubybreaker/task.rb +97 -0
  17. data/lib/rubybreaker/test/rspec.rb +1 -1
  18. data/lib/rubybreaker/test/testcase.rb +13 -28
  19. data/lib/rubybreaker/type/type.rb +1 -1
  20. data/lib/rubybreaker/typing/subtyping.rb +10 -5
  21. data/lib/rubybreaker/util.rb +0 -1
  22. data/lib/rubybreaker.rb +163 -115
  23. data/test/integrated/tc_both_broken_breakable.rb +5 -4
  24. data/test/integrated/tc_class_methods.rb +4 -3
  25. data/test/integrated/tc_inherit_broken.rb +4 -3
  26. data/test/integrated/tc_method_missing.rb +4 -4
  27. data/test/integrated/tc_namespace.rb +4 -2
  28. data/test/integrated/tc_simple1.rb +4 -3
  29. data/test/runtime/tc_obj_wrapper.rb +25 -6
  30. data/test/runtime/tc_typesig_parser.rb +0 -1
  31. data/test/testtask/sample.rb +10 -0
  32. data/test/testtask/tc_testtask.rb +25 -0
  33. data/test/ts_rspec.rb +21 -15
  34. data/test/typing/tc_typing.rb +2 -3
  35. data/webpage/index.html +105 -193
  36. data/webpage/rdoc/Kernel.html +286 -0
  37. data/webpage/rdoc/Object.html +17 -11
  38. data/webpage/rdoc/Rake/RubyBreakerTestTask.html +374 -0
  39. data/webpage/rdoc/Rake.html +212 -0
  40. data/webpage/rdoc/RubyBreaker/Breakable.html +24 -40
  41. data/webpage/rdoc/RubyBreaker/Broken.html +21 -69
  42. data/webpage/rdoc/RubyBreaker/Context.html +16 -10
  43. data/webpage/rdoc/RubyBreaker/Errors/InternalError.html +16 -10
  44. data/webpage/rdoc/RubyBreaker/Errors/InvalidSubtypeCheck.html +16 -10
  45. data/webpage/rdoc/RubyBreaker/Errors/InvalidTypeConstruction.html +16 -10
  46. data/webpage/rdoc/RubyBreaker/Errors/SubtypeFailure.html +16 -10
  47. data/webpage/rdoc/RubyBreaker/Errors/TypeError.html +16 -10
  48. data/webpage/rdoc/RubyBreaker/Errors/UserError.html +16 -10
  49. data/webpage/rdoc/RubyBreaker/Errors.html +16 -10
  50. data/webpage/rdoc/RubyBreaker/ObjectPosition.html +16 -10
  51. data/webpage/rdoc/RubyBreaker/Position.html +16 -10
  52. data/webpage/rdoc/RubyBreaker/{TestCase.html → RDocSupport.html} +81 -82
  53. data/webpage/rdoc/RubyBreaker/RubyTypeUtils.html +16 -10
  54. data/webpage/rdoc/RubyBreaker/Runtime/Inspector.html +25 -44
  55. data/webpage/rdoc/RubyBreaker/Runtime/MethodInfo.html +16 -10
  56. data/webpage/rdoc/RubyBreaker/Runtime/Monitor.html +19 -13
  57. data/webpage/rdoc/RubyBreaker/Runtime/MonitorInstaller.html +37 -25
  58. data/webpage/rdoc/RubyBreaker/Runtime/MonitorSwitch.html +20 -14
  59. data/webpage/rdoc/RubyBreaker/Runtime/MonitorUtils.html +21 -15
  60. data/webpage/rdoc/RubyBreaker/Runtime/ObjectWrapper.html +23 -12
  61. data/webpage/rdoc/RubyBreaker/Runtime/Pluggable.html +16 -10
  62. data/webpage/rdoc/RubyBreaker/Runtime/TypeSigParser.html +16 -10
  63. data/webpage/rdoc/RubyBreaker/Runtime/{TypesigUnparser.html → TypeSigUnparser.html} +19 -16
  64. data/webpage/rdoc/RubyBreaker/Runtime/TypeSystem.html +18 -14
  65. data/webpage/rdoc/RubyBreaker/Runtime.html +145 -11
  66. data/webpage/rdoc/RubyBreaker/TypeComparer.html +16 -10
  67. data/webpage/rdoc/RubyBreaker/TypeDefs/AnyType.html +16 -10
  68. data/webpage/rdoc/RubyBreaker/TypeDefs/BlockType.html +16 -10
  69. data/webpage/rdoc/RubyBreaker/TypeDefs/DuckType.html +16 -10
  70. data/webpage/rdoc/RubyBreaker/TypeDefs/FusionType.html +16 -10
  71. data/webpage/rdoc/RubyBreaker/TypeDefs/MethodListType.html +16 -10
  72. data/webpage/rdoc/RubyBreaker/TypeDefs/MethodType.html +16 -10
  73. data/webpage/rdoc/RubyBreaker/TypeDefs/NilType.html +16 -10
  74. data/webpage/rdoc/RubyBreaker/TypeDefs/NominalType.html +16 -10
  75. data/webpage/rdoc/RubyBreaker/TypeDefs/OptionalType.html +16 -10
  76. data/webpage/rdoc/RubyBreaker/TypeDefs/OrType.html +16 -10
  77. data/webpage/rdoc/RubyBreaker/TypeDefs/SelfType.html +17 -11
  78. data/webpage/rdoc/RubyBreaker/TypeDefs/Type.html +17 -11
  79. data/webpage/rdoc/RubyBreaker/TypeDefs/VarLengthType.html +16 -10
  80. data/webpage/rdoc/RubyBreaker/TypeDefs.html +16 -10
  81. data/webpage/rdoc/RubyBreaker/TypeUnparser.html +16 -10
  82. data/webpage/rdoc/RubyBreaker/Typing.html +17 -11
  83. data/webpage/rdoc/RubyBreaker/Util.html +16 -10
  84. data/webpage/rdoc/RubyBreaker.html +167 -34
  85. data/webpage/rdoc/{RubyBreaker/Runtime/TypePlaceholder.html → Test/Unit/TestCase.html} +68 -39
  86. data/webpage/rdoc/Test/Unit.html +211 -0
  87. data/webpage/rdoc/Test.html +211 -0
  88. data/webpage/rdoc/created.rid +18 -17
  89. data/webpage/rdoc/index.html +16 -10
  90. data/webpage/rdoc/js/search_index.js +1 -1
  91. data/webpage/rdoc/table_of_contents.html +61 -48
  92. metadata +21 -12
  93. data/lib/rubybreaker/rubylib/core.rb +0 -2483
  94. data/lib/rubybreaker/rubylib.rb +0 -3
  95. data/lib/rubybreaker/runtime/type_placeholder.rb +0 -23
  96. data/webpage/rdoc/RubyBreaker/Broken/BrokenEigen.html +0 -305
  97. 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
- # documents type information automatically.
13
+ # generates type documentation for Ruby programs.
12
14
  module RubyBreaker
13
-
14
- # This constant contains the copyright information.
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 => false, # in debug mode?
20
- :verbose => false, # in RubyBreaker.verbose mode?
21
- :mode => :lib, # bin or lib?
22
- :io_file => nil, # generate input/output other than default?
23
- :append => true, # append to the input file (if there is)?
24
- :stdout => true, # also display on the screen?
25
- :rubylib => true, # include core ruby library documentation?
26
- :file => nil, # the input Ruby program (as typed by the user)
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 array lists modules/classes that are actually instrumented with a
30
- # monitor.
31
- INSTALLED = []
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
- include TypeDefs
41
- include Runtime
35
+ opts.banner = "Usage: #{File.basename(__FILE__)} [options] prog[.rb]"
42
36
 
43
- public
37
+ opts.on("--debug", "Run in debug mode") do
38
+ OPTIONS[:debug] = true
39
+ end
44
40
 
45
- # This method is the trigger point to install a monitor in each
46
- # module/class.
47
- def self.setup()
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
- BREAKABLE.each do |mod|
45
+ opts.on("--io-file FILE","Specify I/O file") do |f|
46
+ OPTIONS[:io_file] = f
47
+ end
50
48
 
51
- # Remember, RubyBreaker now supports a hybrid of Breakable and
52
- # Broken module. Just check if the module has already been
53
- # instrumented.
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
- end
53
+ opts.on("-s","--[no-]stdout","Show output on screen") do |b|
54
+ OPTIONS[:stdout] = b
55
+ end
60
56
 
61
- # At the end, we generate an output of the type information.
62
- at_exit do
63
- self.output
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
- # Reads the input file if specified or exists
69
- def self.input()
70
- return unless OPTIONS[:io_file] && File.exist?(OPTIONS[:io_file])
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
- # This method will generate the output.
76
- def self.output()
70
+ end
77
71
 
78
- RubyBreaker.verbose("Generating type documentation")
72
+ # This constant contains the copyright information.
73
+ COPYRIGHT = "Copyright (c) 2012 Jong-hoon (David) An. All Rights Reserved."
79
74
 
80
- io_exist = OPTIONS[:io_file] && File.exist?(OPTIONS[:io_file])
75
+ # Extension used for files that contain RubyBreaker task information
76
+ TASK_EXTENSION = "rb"
81
77
 
82
- code = ""
83
- # Document each module that was monitored
84
- INSTALLED.each { |mod|
85
- str = Runtime::TypesigUnparser.unparse(mod)
86
- code << str
87
- if OPTIONS[:mode] == :lib
88
- print str
89
- end
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
- # If this was a library mode run, exit now.
93
- return if OPTIONS[:mode] == :lib
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
- open(OPTIONS[:io_file],"a") do |f|
97
- unless io_exist
98
- f.puts "# This file is auto-generated by RubyBreaker"
99
- f.puts "require \"rubybreaker\""
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
- RubyBreaker.verbose("Done generating type documentation")
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
- # This method will run do things in the following order:
108
- #
109
- # * Checks to see if the user program and an input file exists
110
- # * Loads the documentation for Ruby Core Library (TODO)
111
- # * Reads the input type documentation if any
112
- # * Reads (require's) the user program
113
- #
114
- def self.run()
115
-
116
- RubyBreaker.setup_logger()
117
- RubyBreaker.verbose("Running RubyBreaker")
118
-
119
- # First, take care of the program file.
120
- argv0 = OPTIONS[:file]
121
- prog_file = argv0
122
- prog_file = File.expand_path(prog_file)
123
-
124
- # It is ok to omit .rb extension. So try to see if prog_file.rb exists
125
- if !File.exist?(prog_file) && !File.extname(prog_file) == ".rb"
126
- prog_file = "#{prog_file}.rb"
127
- end
128
-
129
- if !File.exist?(prog_file)
130
- fatal("#{argv0} is an invalid file.")
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
- # Then, input/output file if specified
135
- if !OPTIONS[:io_file] || OPTIONS[:io_file].empty?
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
- if OPTIONS[:rubylib]
141
- RubyBreaker.verbose("Loading RubyBreaker's Ruby Core Library documentation")
142
- # Load the core library type documentation
143
- eval("require \"rubybreaker/rubylib\"", TOPLEVEL_BINDING)
144
- end
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
- # Read the input file first (as it might contain type documentation
147
- # already)
148
- Main.input()
181
+ # This method is available by default.
182
+ module Kernel
149
183
 
150
- # Finally, require the program file! Let it run! Wheeee!
151
- eval("require '#{prog_file}'", TOPLEVEL_BINDING)
184
+ def typesig(str)
185
+ _TypeDefs = RubyBreaker::TypeDefs
152
186
 
153
- RubyBreaker.verbose("Done running the input program")
187
+ # This MUST BE set for self type to work in type signatures.
188
+ _TypeDefs::SelfType.set_self(self)
154
189
 
155
- end
190
+ t = RubyBreaker::Runtime::TypeSigParser.parse(str)
191
+ t_map = RubyBreaker::Runtime::TYPE_MAP[self]
156
192
 
157
- end
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
- # This is the manual indicator for the program entry point. It simply
160
- # redirects to the monitor setup code.
161
- def self.monitor()
162
- Main.setup()
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 test_simple_foo()
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 test_simple_bar()
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)
@@ -9,7 +9,6 @@ class TypeSigTest < Test::Unit::TestCase
9
9
  include RubyBreaker
10
10
 
11
11
  class A
12
- include RubyBreaker::Broken
13
12
  typesig("foo(fixnum) -> fixnum")
14
13
  typesig("bar(fixnum) -> self")
15
14
  end
@@ -0,0 +1,10 @@
1
+ # Below classes are used for internal testing
2
+
3
+ class SampleClassA
4
+ def foo(x); x.to_s end
5
+ end
6
+
7
+ class SampleClassB
8
+ def foo(x); x.to_s end
9
+ end
10
+
@@ -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 RSpecTestA do
15
- it "should return a string of number" do
16
- a = RSpecTestA.new
17
- a.foo(1)
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 RSpecTestB do
25
- it "should return the documented type of B#foo" do
26
- b_foo_type = RubyBreaker::Runtime::Inspector.inspect_meth(RSpecTestB, :foo)
27
- str = b_foo_type.unparse()
28
- str.should == "foo(fixnum[to_s]) -> string"
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
 
@@ -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 Broken at this point.
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 Broken yet
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