rbplusplus 0.8 → 0.9

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 (80) hide show
  1. data/Rakefile +13 -13
  2. data/TODO +9 -41
  3. data/lib/rbplusplus/builders/allocation_strategy.rb +57 -0
  4. data/lib/rbplusplus/builders/base.rb +115 -212
  5. data/lib/rbplusplus/builders/class.rb +129 -115
  6. data/lib/rbplusplus/builders/const.rb +30 -0
  7. data/lib/rbplusplus/builders/const_converter.rb +52 -0
  8. data/lib/rbplusplus/builders/constructor.rb +19 -0
  9. data/lib/rbplusplus/builders/director.rb +149 -0
  10. data/lib/rbplusplus/builders/director_method.rb +20 -0
  11. data/lib/rbplusplus/builders/enumeration.rb +19 -26
  12. data/lib/rbplusplus/builders/extension.rb +42 -54
  13. data/lib/rbplusplus/builders/global_function.rb +18 -0
  14. data/lib/rbplusplus/builders/helpers/class.rb +74 -0
  15. data/lib/rbplusplus/builders/helpers/enumeration.rb +28 -0
  16. data/lib/rbplusplus/builders/helpers/module.rb +22 -0
  17. data/lib/rbplusplus/builders/include.rb +32 -0
  18. data/lib/rbplusplus/builders/instance_variable.rb +36 -0
  19. data/lib/rbplusplus/builders/method.rb +14 -0
  20. data/lib/rbplusplus/builders/method_base.rb +136 -0
  21. data/lib/rbplusplus/builders/module.rb +37 -51
  22. data/lib/rbplusplus/builders/module_function.rb +16 -0
  23. data/lib/rbplusplus/builders/static_method.rb +14 -0
  24. data/lib/rbplusplus/extension.rb +140 -28
  25. data/lib/rbplusplus/logger.rb +45 -0
  26. data/lib/rbplusplus/module.rb +55 -1
  27. data/lib/rbplusplus/transformers/class.rb +116 -35
  28. data/lib/rbplusplus/transformers/function.rb +14 -16
  29. data/lib/rbplusplus/transformers/method.rb +26 -1
  30. data/lib/rbplusplus/transformers/namespace.rb +12 -0
  31. data/lib/rbplusplus/transformers/node.rb +47 -54
  32. data/lib/rbplusplus/transformers/node_cache.rb +5 -9
  33. data/lib/rbplusplus/writers/multiple_files_writer.rb +290 -88
  34. data/lib/rbplusplus/writers/single_file_writer.rb +36 -14
  35. data/lib/rbplusplus.rb +44 -18
  36. data/test/allocation_strategies_test.rb +33 -0
  37. data/test/class_methods_encapsulate_test.rb +59 -0
  38. data/test/class_methods_test.rb +2 -35
  39. data/test/classes_test.rb +72 -2
  40. data/test/compiling_test.rb +13 -0
  41. data/test/constructors_test.rb +9 -18
  42. data/test/custom_code_test.rb +53 -0
  43. data/test/default_arguments_test.rb +69 -0
  44. data/test/director_test.rb +173 -0
  45. data/test/enumerations_test.rb +29 -0
  46. data/test/extension_test.rb +7 -2
  47. data/test/file_writers_test.rb +11 -4
  48. data/test/function_pointer_test.rb +56 -0
  49. data/test/function_pointers_classes_test.rb +27 -0
  50. data/test/generated/extconf.rb +2 -2
  51. data/test/headers/Adder.cpp +8 -0
  52. data/test/headers/Adder.h +31 -1
  53. data/test/headers/alloc_strats.h +26 -0
  54. data/test/headers/class_methods.h +30 -0
  55. data/test/headers/code/custom_to_from_ruby.cpp +11 -0
  56. data/test/headers/code/custom_to_from_ruby.hpp +13 -0
  57. data/test/headers/constructors.h +8 -20
  58. data/test/headers/default_arguments.h +49 -0
  59. data/test/headers/director.h +148 -0
  60. data/test/headers/enums.h +33 -0
  61. data/test/headers/function_pointers.h +32 -0
  62. data/test/headers/function_pointers_class.h +26 -0
  63. data/test/headers/needs_code.h +10 -0
  64. data/test/headers/overload.h +0 -3
  65. data/test/headers/subclass.h +10 -0
  66. data/test/headers/to_from_ruby.h +6 -4
  67. data/test/headers/ugly_interface.h +4 -7
  68. data/test/modules_test.rb +11 -6
  69. data/test/overloading_test.rb +6 -2
  70. data/test/subclass_test.rb +20 -10
  71. data/test/test_helper.rb +6 -1
  72. data/test/to_from_ruby_test.rb +0 -2
  73. data/test/wrap_as_test.rb +28 -37
  74. metadata +89 -57
  75. data/lib/rbplusplus/builders/types_manager.rb +0 -93
  76. data/lib/rbplusplus/transformers/constructor.rb +0 -4
  77. data/lib/rbplusplus/transformers/module.rb +0 -71
  78. data/lib/rbplusplus/transformers/node_reference.rb +0 -30
  79. data/test/headers/ugly_helper.h +0 -18
  80. data/test/object_persistence_test.rb +0 -44
data/lib/rbplusplus.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  $:.unshift File.expand_path(File.dirname(__FILE__))
2
2
  $:.unshift File.expand_path(File.dirname(__FILE__) + "/rbplusplus")
3
3
 
4
- gem 'rbgccxml'
4
+ require 'rubygems'
5
5
  require 'rbgccxml'
6
6
 
7
7
  require 'inflector'
@@ -15,23 +15,50 @@ module RbPlusPlus
15
15
 
16
16
  RBPP_COMMENT = "// This file generated by rb++"
17
17
 
18
- autoload :Extension, "rbplusplus/extension"
19
- autoload :RbModule, "rbplusplus/module"
18
+ autoload :Extension, "rbplusplus/extension"
19
+ autoload :RbModule, "rbplusplus/module"
20
+ autoload :Logger, "rbplusplus/logger"
20
21
 
21
22
  module Builders
22
- autoload :Base, "rbplusplus/builders/base"
23
- autoload :ClassBuilder, "rbplusplus/builders/class"
24
- autoload :ExtensionBuilder, "rbplusplus/builders/extension"
25
- autoload :ModuleBuilder, "rbplusplus/builders/module"
26
- autoload :EnumerationBuilder, "rbplusplus/builders/enumeration"
27
- autoload :TypesManager, "rbplusplus/builders/types_manager"
23
+
24
+ autoload :Base, "rbplusplus/builders/base"
25
+ autoload :ExtensionNode, "rbplusplus/builders/extension"
26
+
27
+ autoload :ConstNode, "rbplusplus/builders/const"
28
+ autoload :ModuleNode, "rbplusplus/builders/module"
29
+ autoload :IncludeNode, "rbplusplus/builders/include"
30
+ autoload :EnumerationNode, "rbplusplus/builders/enumeration"
31
+
32
+ # Class related nodes
33
+ autoload :ClassNode, "rbplusplus/builders/class"
34
+ autoload :DirectorNode, "rbplusplus/builders/director"
35
+ autoload :ConstructorNode, "rbplusplus/builders/constructor"
36
+ autoload :InstanceVariableNode, "rbplusplus/builders/instance_variable"
37
+
38
+ # Rice type-management nodes
39
+ autoload :ConstConverterNode, "rbplusplus/builders/const_converter"
40
+ autoload :AllocationStrategyNode, "rbplusplus/builders/allocation_strategy"
41
+
42
+ # Method Nodes
43
+ autoload :MethodBase, "rbplusplus/builders/method_base"
44
+ autoload :MethodNode, "rbplusplus/builders/method"
45
+ autoload :StaticMethodNode, "rbplusplus/builders/static_method"
46
+ autoload :DirectorMethodNode, "rbplusplus/builders/director_method"
47
+ autoload :ModuleFunctionNode, "rbplusplus/builders/module_function"
48
+ autoload :GlobalFunctionNode, "rbplusplus/builders/global_function"
49
+
50
+ # Helpers
51
+ autoload :ClassHelpers, "rbplusplus/builders/helpers/class"
52
+ autoload :EnumerationHelpers, "rbplusplus/builders/helpers/enumeration"
53
+ autoload :ModuleHelpers, "rbplusplus/builders/helpers/module"
54
+
28
55
  end
29
56
 
30
57
  module Writers
31
- autoload :Base, "rbplusplus/writers/base"
32
- autoload :ExtensionWriter, "rbplusplus/writers/extension"
33
- autoload :MultipleFilesWriter, "rbplusplus/writers/multiple_files_writer"
34
- autoload :SingleFileWriter, "rbplusplus/writers/single_file_writer"
58
+ autoload :Base, "rbplusplus/writers/base"
59
+ autoload :ExtensionWriter, "rbplusplus/writers/extension"
60
+ autoload :MultipleFilesWriter, "rbplusplus/writers/multiple_files_writer"
61
+ autoload :SingleFileWriter, "rbplusplus/writers/single_file_writer"
35
62
  end
36
63
  end
37
64
 
@@ -39,18 +66,17 @@ class String #:nodoc:
39
66
  # Functionize attempts to rename a string in a cpp function friendly way.
40
67
  #
41
68
  # vector<float>::x => vector_float__x
42
- def functionize
69
+ def as_variable
43
70
  gsub("::","_").gsub(/[ ,<>]/, "_").gsub("*", "Ptr")
44
71
  end
45
72
  end
46
73
 
74
+ # Transformer classes that reopen RbGCCXML classes to add functionality
47
75
  require 'rbplusplus/transformers/rbgccxml'
48
76
  require 'rbplusplus/transformers/node_cache'
49
77
  require 'rbplusplus/transformers/node'
50
- require 'rbplusplus/transformers/node_reference'
51
78
  require 'rbplusplus/transformers/function'
52
- require 'rbplusplus/transformers/method'
53
- require 'rbplusplus/transformers/constructor'
54
79
  require 'rbplusplus/transformers/class'
55
- require 'rbplusplus/transformers/module'
80
+ require 'rbplusplus/transformers/method'
81
+ require 'rbplusplus/transformers/namespace'
56
82
 
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Allocation Strategies" do
4
+
5
+ def setup
6
+ if !defined?(@@alloc_strat_built)
7
+ super
8
+ @@alloc_strat_built = true
9
+ Extension.new "alloc_strats" do |e|
10
+ e.sources full_dir("headers/alloc_strats.h")
11
+ node = e.namespace "alloc_strats"
12
+ end
13
+ end
14
+ end
15
+
16
+ # The test here is simple because if the allocation
17
+ # strategies aren't properly defined, the extension
18
+ # won't even compile. GCC will complain about trying to
19
+ # instantiate an object with a non-public constructor
20
+ # and it all dies.
21
+ specify "properly figures out what allocation to do" do
22
+ assert_nothing_raised LoadError do
23
+ require 'alloc_strats'
24
+ end
25
+
26
+ # Private constructor, public destructor
27
+ assert defined?(NoConstructor)
28
+
29
+ # Private constructor and destructor
30
+ assert defined?(Neither)
31
+ end
32
+
33
+ end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Correct handling of encapsulated methods" do
4
+ def setup
5
+ if !defined?(@@encapsulated)
6
+ super
7
+ @@encapsulated = true
8
+ Extension.new "encapsulation" do |e|
9
+ e.sources full_dir("headers/class_methods.h")
10
+ node = e.namespace "encapsulation"
11
+ end
12
+
13
+ require 'encapsulation'
14
+ end
15
+ end
16
+
17
+ specify "should handle private/protected/public" do
18
+ ext = Extended.new
19
+ ext.public_method.should == 1
20
+ should.raise NoMethodError do
21
+ ext.private_method
22
+ end
23
+ should.raise NoMethodError do
24
+ ext.protected_method
25
+ end
26
+ end
27
+
28
+ specify "should handle virtual methods" do
29
+ ext_factory = ExtendedFactory.new
30
+ ext = ext_factory.new_instance
31
+ ext.fundamental_type_virtual_method.should == 1
32
+ ext.user_defined_type_virtual_method.class.should == Base
33
+ end
34
+
35
+ specify "don't wrap methods that use non-public types in their arguments" do
36
+ arg = ArgumentAccess.new
37
+
38
+ # Single argument methods
39
+ should.raise NoMethodError do
40
+ arg.wrap_me_private
41
+ end
42
+ should.raise NoMethodError do
43
+ arg.wrap_me_protected
44
+ end
45
+
46
+ should.not.raise NoMethodError do
47
+ arg.wrap_me_public ArgumentAccess::PublicStruct.new
48
+ end
49
+
50
+ # Multiple argument methods
51
+ should.raise NoMethodError do
52
+ arg.wrap_me_many_no
53
+ end
54
+ should.not.raise NoMethodError do
55
+ arg.wrap_me_many_yes(1, 2.0, ArgumentAccess::PublicStruct.new)
56
+ end
57
+ end
58
+ end
59
+
@@ -5,12 +5,12 @@ context "Correct handling of static methods" do
5
5
  if !defined?(@@complex_static)
6
6
  super
7
7
  @@complex_static = true
8
- Extension.new "complex" do |e|
8
+ Extension.new "complex_test" do |e|
9
9
  e.sources full_dir("headers/complex_static_methods.h")
10
10
  node = e.namespace "complex"
11
11
  end
12
12
 
13
- require 'complex'
13
+ require 'complex_test'
14
14
  end
15
15
  end
16
16
 
@@ -20,36 +20,3 @@ context "Correct handling of static methods" do
20
20
 
21
21
  end
22
22
 
23
- context "Correct handling of encapsulated methods" do
24
- def setup
25
- if !defined?(@@encapsulated)
26
- super
27
- @@encapsulated = true
28
- Extension.new "encapsulation" do |e|
29
- e.sources full_dir("headers/class_methods.h")
30
- node = e.namespace "encapsulation"
31
- end
32
-
33
- require 'encapsulation'
34
- end
35
- end
36
-
37
- specify "should handle private/protected/public" do
38
- ext = Extended.new
39
- ext.public_method.should == 1
40
- should.raise NoMethodError do
41
- ext.private_method
42
- end
43
- should.raise NoMethodError do
44
- ext.protected_method
45
- end
46
- end
47
-
48
- specify "should handle virtual methods" do
49
- ext_factory = ExtendedFactory.new
50
- ext = ext_factory.new_instance
51
- ext.fundamental_type_virtual_method.should == 1
52
- ext.user_defined_type_virtual_method.class.should == Base
53
- end
54
- end
55
-
data/test/classes_test.rb CHANGED
@@ -7,8 +7,19 @@ context "Extension with wrapped classes" do
7
7
  super
8
8
  @@adder_built = true
9
9
  Extension.new "adder" do |e|
10
- e.sources full_dir("headers/Adder.h")
11
- e.namespace "classes"
10
+ e.sources full_dir("headers/Adder.h"),
11
+ :include_source_files => [
12
+ full_dir("headers/Adder.h"),
13
+ full_dir("headers/Adder.cpp")
14
+ ]
15
+ node = e.namespace "classes"
16
+ adder = node.classes("Adder")
17
+ adder.use_constructor(
18
+ adder.constructors.find(:arguments => [])
19
+ )
20
+
21
+ adder.constants("HideMe").ignore
22
+ adder.disable_typedef_lookup
12
23
  end
13
24
 
14
25
  require 'adder'
@@ -38,5 +49,64 @@ context "Extension with wrapped classes" do
38
49
  Adder.do_adding(1, 2, 3, 4, 5).should == 15
39
50
  end
40
51
 
52
+ specify "should use typedefs when findable" do
53
+ assert defined?(IntAdder), "Did not use the typedef for TemplateAdder"
54
+ end
55
+
56
+ specify "finds and uses multi-nested typedefs" do
57
+ assert defined?(ShouldFindMe), "Didn't find top level typedef for NestedTemplate"
58
+ end
59
+
60
+ specify "can turn off typedef lookup for certain classes" do
61
+ assert !defined?(DontFindMeBro), "Found a typedef we shouldn't have"
62
+ end
63
+
64
+ specify "makes class constants available" do
65
+ Adder::MY_VALUE.should == 10
66
+ end
67
+
68
+ specify "can ignore constants" do
69
+ assert !defined?(Adder::HideMe), "Found HideMe when I shouldn't have"
70
+ end
71
+
72
+ specify "makes public instance variables accessible" do
73
+ a = Adder.new
74
+ a.value1 = 10
75
+ a.value2 = 15.5
76
+ a.value3 = "This is a value!"
77
+ a.should_be_transformed = "TRANSFORM"
78
+
79
+ a.value1.should.equal 10
80
+ a.value2.should.be.close 15.5, 0.01
81
+ a.value3.should.equal "This is a value!"
82
+
83
+ a.should_be_transformed.should.equal "TRANSFORM"
84
+ end
85
+
86
+ specify "const variables are exported as read-only" do
87
+ a = Adder.new
88
+
89
+ should.raise NoMethodError do
90
+ a.const_var = "This is a value!"
91
+ end
92
+
93
+ a.const_var.should.equal 14
94
+ end
95
+
96
+ specify "can subclass a wrapped class and go from there" do
97
+ class MyAdder < Adder
98
+ def add_integers(a, b)
99
+ a * b
100
+ end
101
+
102
+ def add_strings(a, b)
103
+ super(a, b) + "woot"
104
+ end
105
+ end
106
+
107
+ a = MyAdder.new
108
+ a.add_integers(3, 7).should.equal 21
109
+ a.add_strings("piz", "owned").should.equal "pizownedwoot"
110
+ end
41
111
  end
42
112
 
@@ -156,4 +156,17 @@ context "Compiler settings" do
156
156
  # is a symbol lookup failure and death to the Ruby VM
157
157
  needs_to_ruby(3).value.should == 3
158
158
  end
159
+
160
+ specify "can specify a directory containing code to be included into compilation process" do
161
+ Extension.new "code_dir" do |e|
162
+ e.sources full_dir("headers/needs_code.h"),
163
+ :include_source_dir => full_dir("headers/code")
164
+
165
+ e.namespace "needs_code"
166
+ end
167
+
168
+ require 'code_dir'
169
+
170
+ get_number(2).should == 2
171
+ end
159
172
  end
@@ -2,34 +2,25 @@ require File.dirname(__FILE__) + '/test_helper'
2
2
 
3
3
  context "Extension with constructors out the whazoo" do
4
4
 
5
- # Test is currently broken due to something Rice is or isn't doing.
6
- xspecify "should make constructors available" do
5
+ specify "should make constructors available" do
7
6
  Extension.new "constructors" do |e|
8
7
  e.sources full_dir("headers/constructors.h")
9
8
  node = e.namespace "constructors"
10
- e.writer_mode :single
11
- end
12
9
 
13
- require 'constructors'
14
10
 
15
- should.not.raise NameError do
16
- # Constructor overloading not yet supported
17
- # s = StringHolder.new
18
- # s.set_name "two"
19
- # s.get_name.should == "two"
20
-
21
- s2 = StringHolder.new "one"
22
- s2.get_name.should == "one"
11
+ node.classes("DoubleStringHolder").use_constructor(
12
+ node.classes("DoubleStringHolder").constructors.find(:arguments => [nil, nil])
13
+ )
23
14
  end
24
15
 
16
+ require 'constructors'
17
+
25
18
  should.not.raise NameError do
26
19
  # Test complex constructors
27
- d = DoubleStringHolder.new(StringHolder.new("one"), StringHolder.new("two"))
20
+ d = DoubleStringHolder.new("one", "two")
28
21
  one = d.get_one
29
- puts "Got one #{one.inspect}"
30
- puts "Name is #{one.get_name}"
31
- # d.get_one.get_name.should == "one"
32
- # d.get_two.get_name.should == "two"
22
+ d.get_one.should == "one"
23
+ d.get_two.should == "two"
33
24
  end
34
25
 
35
26
  should.raise TypeError do
@@ -0,0 +1,53 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Extension with wrapped classes" do
4
+
5
+ def setup
6
+ if !defined?(@@adder_built)
7
+ super
8
+ @@adder_built = true
9
+ Extension.new "adder" do |e|
10
+ e.sources full_dir("headers/Adder.h"),
11
+ :include_source_files => [
12
+ full_dir("headers/Adder.h"),
13
+ full_dir("headers/Adder.cpp")
14
+ ]
15
+ node = e.namespace "classes"
16
+ adder = node.classes("Adder")
17
+
18
+ adder.use_constructor( adder.constructors.find(:arguments => []))
19
+ adder.disable_typedef_lookup
20
+
21
+ decl = <<-END
22
+ int subtractIntegers(classes::Adder* self, int a, int b) {
23
+ return a - b;
24
+ }
25
+
26
+ int multiplyIntegers(classes::Adder* self, int a, int b) {
27
+ return a * b;
28
+ }
29
+ END
30
+
31
+ wrapping = <<-END
32
+ <class>.define_method(\"sub_ints\", &subtractIntegers);
33
+ <class>.define_method(\"mult_ints\", &multiplyIntegers);
34
+ END
35
+
36
+ adder.add_custom_code( decl, wrapping )
37
+ end
38
+
39
+ require 'adder'
40
+ end
41
+ end
42
+
43
+ specify "Adder has new custom methods" do
44
+ a = Adder.new
45
+ a.should.respond_to(:sub_ints)
46
+ a.should.respond_to(:mult_ints)
47
+
48
+ a.sub_ints(5, 4).should.equal 1
49
+ a.mult_ints(5, 4).should.equal 20
50
+ end
51
+
52
+ end
53
+
@@ -0,0 +1,69 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Default arguments properly exposed" do
4
+
5
+ def setup
6
+ if !defined?(@@defargs_built)
7
+ super
8
+ @@defargs_built = true
9
+ Extension.new "defargs" do |e|
10
+ e.sources full_dir("headers/default_arguments.h")
11
+ e.writer_mode :single
12
+ node = e.namespace "default_args"
13
+
14
+ e.module "Inner" do |m|
15
+ m.includes node.functions("module_do")
16
+ end
17
+
18
+ node.classes("Directed").director
19
+ end
20
+
21
+ require 'defargs'
22
+ end
23
+ end
24
+
25
+ specify "global functions" do
26
+ global_do(1, 4, 5).should.equal 20
27
+ global_do(1, 4).should.equal 40
28
+ global_do(1).should.equal 30
29
+ end
30
+
31
+ specify "module functions" do
32
+ Inner.module_do(5).should.equal 18
33
+ Inner.module_do(5, 5).should.equal 20
34
+ Inner.module_do(5, 5, 5).should.equal 15
35
+ end
36
+
37
+ specify "class instance methods" do
38
+ tester = Tester.new
39
+ tester.concat("this", "that").should.equal "this-that"
40
+ tester.concat("this", "that", ";").should.equal "this;that"
41
+ end
42
+
43
+ specify "class static methods" do
44
+ Tester.build("base").should.equal "basebasebase"
45
+ Tester.build("woot", 5).should.equal "wootwootwootwootwoot"
46
+ end
47
+
48
+ specify "director methods" do
49
+ d = Directed.new
50
+ d.virtual_do(3).should.equal 30
51
+ d.virtual_do(3, 9).should.equal 27
52
+
53
+ class MyD < Directed
54
+ def virtual_do(x, y = 10)
55
+ super(x * 3, y)
56
+ end
57
+ end
58
+
59
+ myd = MyD.new
60
+ myd.virtual_do(10).should.equal 300
61
+ end
62
+
63
+ specify "throw argument error on bad types" do
64
+ should.raise TypeError do
65
+ global_do(1, "three")
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,173 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Director proxy generation" do
4
+
5
+ def setup
6
+ if !defined?(@@director_built)
7
+ super
8
+ @@director_built = true
9
+ Extension.new "director" do |e|
10
+ e.sources full_dir("headers/director.h")
11
+
12
+ node = e.namespace "director"
13
+
14
+ # As director is pretty complicated to get right
15
+ # automatically for now, we force-specify which
16
+ # classes to have directors set on.
17
+ %w(Worker MultiplyWorker BadNameClass VirtualWithArgs NoConstructor VBase VOne VTwo).each do |k|
18
+ node.classes(k).director
19
+ end
20
+
21
+ node.classes("Worker").methods("doProcessImpl").default_return_value(0)
22
+
23
+ klass = node.classes("BadNameClass")
24
+ klass.wrap_as("BetterNamedClass")
25
+ klass.methods("_is_x_ok_to_run").wrap_as("x_ok?")
26
+ klass.methods("__do_someProcessing").wrap_as("do_processing")
27
+ end
28
+
29
+ require 'director'
30
+ end
31
+ end
32
+
33
+ specify "polymorphic calls extend into Ruby" do
34
+ class MyWorker < Worker
35
+ def process(num)
36
+ num + 10
37
+ end
38
+ end
39
+
40
+ h = Handler.new
41
+ h.add_worker(MyWorker.new)
42
+
43
+ h.process_workers(5).should.equal 15
44
+ end
45
+
46
+ specify "super calls on pure virtual raise exception" do
47
+ class SuperBadWorker < Worker
48
+ def process(num)
49
+ super + 10
50
+ end
51
+ end
52
+
53
+ should.raise NotImplementedError do
54
+ SuperBadWorker.new.process(10)
55
+ end
56
+ end
57
+
58
+ specify "allows super calls to continue back into C++ classes" do
59
+ class SuperGoodWorker < Worker
60
+ def do_something(num)
61
+ super + 10
62
+ end
63
+ end
64
+
65
+ should.not.raise NotImplementedError do
66
+ SuperGoodWorker.new.do_something(10).should.equal 50
67
+ end
68
+ end
69
+
70
+ specify "can specify a default return value in the wrapper" do
71
+ class MyAwesomeWorker < Worker
72
+ def do_process_impl(num)
73
+ num + 7
74
+ end
75
+
76
+ def process(num)
77
+ num + 8
78
+ end
79
+ end
80
+
81
+ w = MyAwesomeWorker.new
82
+ w.do_process(3).should.equal 10
83
+
84
+ h = Handler.new
85
+ h.add_worker(w)
86
+
87
+ h.process_workers(10).should.equal 18
88
+ end
89
+
90
+ specify "properly adds all constructor arguments" do
91
+ v = VirtualWithArgs.new 14, true
92
+ v.process_a("hi").should.equal 16
93
+ v.process_b.should.be true
94
+ end
95
+
96
+ specify "takes into account renamed methods / classes" do
97
+ c = BetterNamedClass.new
98
+ assert !c.x_ok?
99
+
100
+ c.do_processing.should.equal 14
101
+ end
102
+
103
+ specify "handles no constructors" do
104
+ class MyThing < NoConstructor
105
+ end
106
+
107
+ n = MyThing.new
108
+ n.do_something.should.equal 4
109
+ end
110
+
111
+ specify "only builds method wrappers for virtual methods" do
112
+ class NumberWorker < Worker
113
+ def get_number
114
+ super + 15
115
+ end
116
+ end
117
+
118
+ # Super calls still work
119
+ w = NumberWorker.new
120
+ w.get_number.should.equal 27
121
+
122
+ # But polymorphism stops in the C++
123
+ h = Handler.new
124
+ h.add_worker(w)
125
+
126
+ h.add_worker_numbers.should.equal 12
127
+ end
128
+
129
+ specify "Directors implement all pure virtual methods up the inheritance tree" do
130
+ vbase = VBase.new
131
+ v1 = VOne.new
132
+ v2 = VTwo.new
133
+
134
+ v1.method_one.should.equal "methodOne"
135
+
136
+ should.raise NotImplementedError do
137
+ v1.method_two
138
+ end
139
+ should.raise NotImplementedError do
140
+ v1.method_three
141
+ end
142
+
143
+ v2.method_one.should.equal "methodOne"
144
+ v2.method_two.should.equal "methodTwo"
145
+
146
+ should.raise NotImplementedError do
147
+ v2.method_three
148
+ end
149
+ end
150
+
151
+ specify "handles superclasses of the class with virtual methods" do
152
+ class QuadWorker < MultiplyWorker
153
+ def process(num)
154
+ num * 4
155
+ end
156
+ end
157
+
158
+ h = Handler.new
159
+
160
+ h.add_worker(MultiplyWorker.new)
161
+ h.process_workers(5).should.equal 10
162
+
163
+ h.add_worker(QuadWorker.new)
164
+ h.process_workers(5).should.equal 40
165
+ end
166
+
167
+ specify "multiple files writer properly handles directors and nested nodes" do
168
+ assert defined?(Worker::ZeeEnum)
169
+ assert defined?(Worker::ZeeEnum::VALUE)
170
+ Worker::ZeeEnum::VALUE.to_i.should.equal 4
171
+ end
172
+
173
+ end