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.
- data/Rakefile +13 -13
- data/TODO +9 -41
- data/lib/rbplusplus/builders/allocation_strategy.rb +57 -0
- data/lib/rbplusplus/builders/base.rb +115 -212
- data/lib/rbplusplus/builders/class.rb +129 -115
- data/lib/rbplusplus/builders/const.rb +30 -0
- data/lib/rbplusplus/builders/const_converter.rb +52 -0
- data/lib/rbplusplus/builders/constructor.rb +19 -0
- data/lib/rbplusplus/builders/director.rb +149 -0
- data/lib/rbplusplus/builders/director_method.rb +20 -0
- data/lib/rbplusplus/builders/enumeration.rb +19 -26
- data/lib/rbplusplus/builders/extension.rb +42 -54
- data/lib/rbplusplus/builders/global_function.rb +18 -0
- data/lib/rbplusplus/builders/helpers/class.rb +74 -0
- data/lib/rbplusplus/builders/helpers/enumeration.rb +28 -0
- data/lib/rbplusplus/builders/helpers/module.rb +22 -0
- data/lib/rbplusplus/builders/include.rb +32 -0
- data/lib/rbplusplus/builders/instance_variable.rb +36 -0
- data/lib/rbplusplus/builders/method.rb +14 -0
- data/lib/rbplusplus/builders/method_base.rb +136 -0
- data/lib/rbplusplus/builders/module.rb +37 -51
- data/lib/rbplusplus/builders/module_function.rb +16 -0
- data/lib/rbplusplus/builders/static_method.rb +14 -0
- data/lib/rbplusplus/extension.rb +140 -28
- data/lib/rbplusplus/logger.rb +45 -0
- data/lib/rbplusplus/module.rb +55 -1
- data/lib/rbplusplus/transformers/class.rb +116 -35
- data/lib/rbplusplus/transformers/function.rb +14 -16
- data/lib/rbplusplus/transformers/method.rb +26 -1
- data/lib/rbplusplus/transformers/namespace.rb +12 -0
- data/lib/rbplusplus/transformers/node.rb +47 -54
- data/lib/rbplusplus/transformers/node_cache.rb +5 -9
- data/lib/rbplusplus/writers/multiple_files_writer.rb +290 -88
- data/lib/rbplusplus/writers/single_file_writer.rb +36 -14
- data/lib/rbplusplus.rb +44 -18
- data/test/allocation_strategies_test.rb +33 -0
- data/test/class_methods_encapsulate_test.rb +59 -0
- data/test/class_methods_test.rb +2 -35
- data/test/classes_test.rb +72 -2
- data/test/compiling_test.rb +13 -0
- data/test/constructors_test.rb +9 -18
- data/test/custom_code_test.rb +53 -0
- data/test/default_arguments_test.rb +69 -0
- data/test/director_test.rb +173 -0
- data/test/enumerations_test.rb +29 -0
- data/test/extension_test.rb +7 -2
- data/test/file_writers_test.rb +11 -4
- data/test/function_pointer_test.rb +56 -0
- data/test/function_pointers_classes_test.rb +27 -0
- data/test/generated/extconf.rb +2 -2
- data/test/headers/Adder.cpp +8 -0
- data/test/headers/Adder.h +31 -1
- data/test/headers/alloc_strats.h +26 -0
- data/test/headers/class_methods.h +30 -0
- data/test/headers/code/custom_to_from_ruby.cpp +11 -0
- data/test/headers/code/custom_to_from_ruby.hpp +13 -0
- data/test/headers/constructors.h +8 -20
- data/test/headers/default_arguments.h +49 -0
- data/test/headers/director.h +148 -0
- data/test/headers/enums.h +33 -0
- data/test/headers/function_pointers.h +32 -0
- data/test/headers/function_pointers_class.h +26 -0
- data/test/headers/needs_code.h +10 -0
- data/test/headers/overload.h +0 -3
- data/test/headers/subclass.h +10 -0
- data/test/headers/to_from_ruby.h +6 -4
- data/test/headers/ugly_interface.h +4 -7
- data/test/modules_test.rb +11 -6
- data/test/overloading_test.rb +6 -2
- data/test/subclass_test.rb +20 -10
- data/test/test_helper.rb +6 -1
- data/test/to_from_ruby_test.rb +0 -2
- data/test/wrap_as_test.rb +28 -37
- metadata +89 -57
- data/lib/rbplusplus/builders/types_manager.rb +0 -93
- data/lib/rbplusplus/transformers/constructor.rb +0 -4
- data/lib/rbplusplus/transformers/module.rb +0 -71
- data/lib/rbplusplus/transformers/node_reference.rb +0 -30
- data/test/headers/ugly_helper.h +0 -18
- 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
|
-
|
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,
|
19
|
-
autoload :RbModule,
|
18
|
+
autoload :Extension, "rbplusplus/extension"
|
19
|
+
autoload :RbModule, "rbplusplus/module"
|
20
|
+
autoload :Logger, "rbplusplus/logger"
|
20
21
|
|
21
22
|
module Builders
|
22
|
-
|
23
|
-
autoload :
|
24
|
-
autoload :
|
25
|
-
|
26
|
-
autoload :
|
27
|
-
autoload :
|
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,
|
32
|
-
autoload :ExtensionWriter,
|
33
|
-
autoload :MultipleFilesWriter,
|
34
|
-
autoload :SingleFileWriter,
|
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
|
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/
|
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
|
+
|
data/test/class_methods_test.rb
CHANGED
@@ -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 "
|
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 '
|
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
|
-
|
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
|
|
data/test/compiling_test.rb
CHANGED
@@ -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
|
data/test/constructors_test.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
16
|
-
|
17
|
-
|
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(
|
20
|
+
d = DoubleStringHolder.new("one", "two")
|
28
21
|
one = d.get_one
|
29
|
-
|
30
|
-
|
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
|