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