2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-23 05:42:30 +00:00

added first virtual function tests

[SVN r13183]
This commit is contained in:
Dave Abrahams
2002-03-12 21:14:03 +00:00
parent 3caa91cc36
commit c18d8fa967
2 changed files with 218 additions and 0 deletions

118
test/virtual_functions.cpp Normal file
View File

@@ -0,0 +1,118 @@
// Copyright David Abrahams 2002. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
#include <boost/python/class.hpp>
#include <boost/python/module.hpp>
#include <boost/python/returning.hpp>
#include <boost/ref.hpp>
using namespace boost::python;
struct X
{
explicit X(int x) : x(x), magic(7654321) { ++counter; }
X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; }
virtual ~X() { assert(magic == 7654321); magic = 6666666; x = 9999; --counter; }
void set(int x) { assert(magic == 7654321); this->x = x; }
int value() const { assert(magic == 7654321); return x; }
static int count() { return counter; }
private:
void operator=(X const&);
private:
int x;
long magic;
static int counter;
};
struct Y : X
{
Y(int x) : X(x) {};
};
struct abstract : X
{
abstract(int x) : X(x) {};
int call_f(Y const& y) { return f(y); }
virtual int f(Y const& y) = 0;
};
struct concrete : X
{
concrete(int x) : X(x) {};
int call_f(Y const& y) { return f(y); }
virtual int f(Y const& y) { set(y.value()); return y.value(); }
};
struct abstract_callback : abstract
{
abstract_callback(PyObject* p, int x)
: abstract(x), self(p)
{}
int f(Y const& y)
{
return returning<int>::call_method(self, "f", boost::ref(y));
}
PyObject* self;
};
struct concrete_callback : concrete
{
concrete_callback(PyObject* p, int x)
: concrete(x), self(p)
{}
int f(Y const& y)
{
return returning<int>::call_method(self, "f", boost::ref(y));
}
int f_impl(Y const& y)
{
return this->concrete::f(y);
}
PyObject* self;
};
int X::counter;
BOOST_PYTHON_MODULE_INIT(virtual_functions_ext)
{
module("virtual_functions_ext")
.add(
class_<concrete, bases<>, objects::value_holder_generator<concrete_callback> >("concrete")
.def_init(args<int>())
.def("value", &concrete::value)
.def("set", &concrete::set)
.def("call_f", &concrete::call_f)
.def("f", &concrete_callback::f_impl))
#if 0
.add(
class_<abstract, bases<>
, objects::pointer_holder_generator<
boost::python::objects::shared_ptr_generator
, abstract_callback>
>("abstract")
.def_init(args<int>())
.def("value", &abstract::value)
.def("call_f", &abstract::call_f)
.def("set", &abstract::set))
#endif
.add(
class_<Y>("Y")
.def_init(args<int>())
.def("value", &Y::value)
.def("set", &Y::set)
)
;
}
#include "module_tail.cpp"

100
test/virtual_functions.py Normal file
View File

@@ -0,0 +1,100 @@
'''
>>> from virtual_functions_ext import *
>>> class C1(concrete):
... def f(self, y):
... return concrete.f(self, Y(-y.value()))
>>> class C2(concrete):
... pass
<<<>>> class A1(abstract):
<<<... def f(self, y):
<<<... return abstract.f(self, Y(-y.value()))
<<<
<<<>>> class A2(abstract):
<<<... pass
<<<
>>> y1 = Y(16)
>>> y2 = Y(17)
#
# Test abstract with f overridden
#
<<<>>> a1 = A1(42)
<<<>>> a1.value()
<<<42
<<<
<<<# Call f indirectly from C++
<<<>>> a1.call_f(y1)
<<<-16
<<<
<<<# Call f directly from Python
<<<>>> a1.f(y2)
<<<-17
<<<
<<<#
<<<# Test abstract with f not overridden
<<<#
<<<>>> a2 = A2(42)
<<<>>> A2.value()
<<<42
<<<
<<<# Call f indirectly from C++
<<<>>> c1.call_f(y1)
<<<16
<<<
<<<# Call f directly from Python
<<<>>> c1.f(y2)
<<<17
<<<
############# Concrete Tests ############
#
# Test concrete with f overridden
#
>>> c1 = C1(42)
>>> c1.value()
42
# Call f indirectly from C++
>>> c1.call_f(y1)
-16
# Call f directly from Python
>>> c1.f(y2)
-17
#
# Test concrete with f not overridden
#
>>> c2 = C2(42)
>>> c2.value()
42
# Call f indirectly from C++
>>> c2.call_f(y1)
16
# Call f directly from Python
>>> c2.f(y2)
17
'''
def run(args = None):
import sys
import doctest
if args is not None:
sys.argv = args
return doctest.testmod(sys.modules.get(__name__))
if __name__ == '__main__':
print "running..."
import sys
sys.exit(run()[0])