From 1c5450292d4f0549e28ab6797397c5c3f7c9deaa Mon Sep 17 00:00:00 2001 From: Raoul Gough Date: Wed, 15 Oct 2003 14:11:40 +0000 Subject: [PATCH] Reorganisation of indexing test suite [SVN r20388] --- test/Jamfile | 16 ++- test/test_array.py | 6 +- test/test_array_common.py | 32 +++--- test/test_array_ext.cpp | 98 ++++++++++++++++++ test/test_array_ref.py | 62 +++++++++++ test/test_deque_ext.cpp | 77 ++++++++++++++ test/test_deque_plain.py | 43 ++++++++ test/test_deque_proxy.py | 46 +++++++++ test/test_deque_ref.py | 63 ++++++++++++ test/test_list_ext.cpp | 60 +++++++++++ test/test_list_plain.py | 4 +- test/test_python_list.py | 20 +++- test/test_python_ref_common.py | 102 +++++++++++++++++++ test/test_vector_common.py | 27 ++--- test/{testlinear.cpp => test_vector_ext.cpp} | 49 +++------ test/test_vector_plain.py | 4 +- test/test_vector_proxy.py | 92 ++--------------- test/test_vector_ref.py | 13 ++- 18 files changed, 652 insertions(+), 162 deletions(-) create mode 100755 test/test_array_ext.cpp create mode 100644 test/test_array_ref.py create mode 100755 test/test_deque_ext.cpp create mode 100644 test/test_deque_plain.py create mode 100644 test/test_deque_proxy.py create mode 100644 test/test_deque_ref.py create mode 100755 test/test_list_ext.cpp create mode 100644 test/test_python_ref_common.py rename test/{testlinear.cpp => test_vector_ext.cpp} (61%) diff --git a/test/Jamfile b/test/Jamfile index af1bec54..43ad7696 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -51,6 +51,18 @@ rule bpl-test ( name ? : files * : requirements * ) boost-python-runtest $(name) : $(py) $(modules) ; } +bpl-test test_array : test_array.py test_array_ext.cpp ; +bpl-test test_array_ref : test_array_ref.py test_array_ext.cpp ; +bpl-test test_vector_plain : test_vector_plain.py test_vector_ext.cpp ; +bpl-test test_vector_ref : test_vector_ref.py test_vector_ext.cpp ; +bpl-test test_vector_proxy : test_vector_proxy.py test_vector_ext.cpp ; +bpl-test test_deque_plain : test_deque_plain.py test_deque_ext.cpp ; +bpl-test test_deque_ref : test_deque_ref.py test_deque_ext.cpp ; +bpl-test test_deque_proxy : test_deque_proxy.py test_deque_ext.cpp ; +bpl-test test_list_plain : test_list_plain.py test_list_ext.cpp ; +bpl-test test_map_plain : test_map_plain.py testnonlinear.cpp ; +bpl-test test_set_plain : test_set_plain.py testnonlinear.cpp ; + run ../test/embedding.cpp ../build/boost_python : # program args : # input files @@ -141,8 +153,8 @@ bpl-test nested ; bpl-test docstring ; -bpl-test vector_indexing_suite ; -bpl-test map_indexing_suite ; +# bpl-test vector_indexing_suite ; +# bpl-test map_indexing_suite ; if $(TEST_BIENSTMAN_NON_BUGS) { diff --git a/test/test_array.py b/test/test_array.py index a0cf04ed..67df266a 100644 --- a/test/test_array.py +++ b/test/test_array.py @@ -16,9 +16,9 @@ # $Id$ # -'''>>> from testlinear import * ->>> setTrace (0) ->>> v = getArray() +'''>>> from test_array_ext import * +>>> element_type = int +>>> v = get_array_plain() ''' def run(args = None): diff --git a/test/test_array_common.py b/test/test_array_common.py index 46818eee..f2661f3a 100644 --- a/test/test_array_common.py +++ b/test/test_array_common.py @@ -29,15 +29,15 @@ [8, 6, 4, 2, 1, 3, 5, 7, 0] >>> print len(v) 9 ->>> print v.count (9) # Count with no matches +>>> print v.count (element_type(9)) # Count with no matches 0 ->>> print v.count (2) # Count with unique match +>>> print v.count (element_type(2)) # Count with unique match 1 ->>> print v.index (0) # Index with match +>>> print v.index (element_type(0)) # Index with match 8 ->>> assert 0 in v # contains with match ->>> assert 8 in v # contains with match ->>> assert not -1 in v # contains without match +>>> assert element_type(0) in v # contains with match +>>> assert element_type(8) in v # contains with match +>>> assert not element_type(-1) in v # contains without match >>> print v[0] # Get first element OK (zero index) 8 >>> print v[len(v)-1] # Get last element OK (+ve index) @@ -46,16 +46,16 @@ 0 >>> print v[-len(v)] # Get first element OK (-ve index) 8 ->>> v[0] = 9 # Replace first element OK (zero index) +>>> v[0] = element_type(9) # Replace first element OK (zero index) >>> print [ x for x in v ] [9, 6, 4, 2, 1, 3, 5, 7, 0] ->>> v[len(v)-1] = 1 # Replace last element OK (+ve index) +>>> v[len(v)-1] = element_type(1) # Replace last element OK (+ve index) >>> print [ x for x in v ] [9, 6, 4, 2, 1, 3, 5, 7, 1] ->>> v[-1] = 0 # Replace last element OK (-ve index) +>>> v[-1] = element_type(0) # Replace last element OK (-ve index) >>> print [ x for x in v ] [9, 6, 4, 2, 1, 3, 5, 7, 0] ->>> v[-len(v)] = 8 # Replace first element OK (-ve index) +>>> v[-len(v)] = element_type(8) # Replace first element OK (-ve index) >>> print [ x for x in v ] [8, 6, 4, 2, 1, 3, 5, 7, 0] >>> try: @@ -71,13 +71,13 @@ Got expected exception ... Got expected exception >>> try: -... v[len(v)] = 9 # Set element index out of range +... v[len(v)] = element_type(9) # Set element index out of range ... except IndexError, e: ... print "Got expected exception" ... Got expected exception >>> try: -... print v.index (9) # Search for nonexistant value +... print v.index (element_type(9)) # Search for nonexistant value ... except ValueError, e: ... print "Got expected exception" ... @@ -88,12 +88,12 @@ Got expected exception >>> v.sort() # Sort >>> print [ x for x in v ] [0, 1, 2, 3, 4, 5, 6, 7, 8] ->>> v[0] = 8 # Single element replace ->>> print v.count(8) # Count with multiple matches +>>> v[0] = element_type(8) # Single element replace +>>> print v.count(element_type(8)) # Count with multiple matches 2 ->>> print v[v.index(3)] # Check index and lookup +>>> print v[v.index(element_type(3))] # Check index and lookup 3 ->>> v[:] = [4, 5, 6, 7, 8, 8, 1, 2, 3] # Equal length slice replace (list) +>>> v[:] = [ element_type(x) for x in [4, 5, 6, 7, 8, 8, 1, 2, 3] ] # slice rep >>> print [ x for x in v ] [4, 5, 6, 7, 8, 8, 1, 2, 3] >>> print [ x for x in v[7:] ] # Slice from index to end diff --git a/test/test_array_ext.cpp b/test/test_array_ext.cpp new file mode 100755 index 00000000..3fbfc98e --- /dev/null +++ b/test/test_array_ext.cpp @@ -0,0 +1,98 @@ +// -*- mode:c++ -*- +// +// Module test_array_ext.cpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) +// +// History +// ======= +// 2003/10/15 rmg File creation from testlinear.cpp +// +// $Id$ +// + +#include "int_wrapper.hpp" + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +// More messiness from not having a separate int_wrapper.cpp file +bool int_wrapper::our_trace_flag = true; +unsigned int_wrapper::our_object_counter = 0; + +boost::python::indexing::iterator_pair get_array_plain() +{ + static int array[] = { 8, 6, 4, 2, 1, 3, 5, 7, 0 }; + + return boost::python::indexing::iterator_pair + (boost::python::indexing::begin(array) + , boost::python::indexing::end(array)); +} + +boost::python::indexing::iterator_pair get_array_wrap() +{ + static int_wrapper array[] = { + int_wrapper(8), int_wrapper(6), int_wrapper(4), int_wrapper(2) + , int_wrapper(1), int_wrapper(3), int_wrapper(5) + , int_wrapper(7), int_wrapper(0) }; + + return boost::python::indexing::iterator_pair + (boost::python::indexing::begin(array) + , boost::python::indexing::end(array)); +} + +std::string repr (int_wrapper const &i) +{ + std::stringstream temp; + temp << i; + return temp.str(); +} + +BOOST_PYTHON_MODULE(test_array_ext) +{ + boost::python::implicitly_convertible (); + + boost::python::def ("setTrace", &int_wrapper::setTrace); + + boost::python::class_("int_wrapper", boost::python::init()) + .def ("increment", &int_wrapper::increment) + .def ("__repr__", repr) + .def ("__cmp__", compare) + ; + + typedef boost::python::indexing::iterator_pair Container1; + + boost::python::class_ + ("Array", boost::python::init()) + .def (boost::python::indexing::container_suite()); + + boost::python::def ("get_array_plain", get_array_plain); + + typedef boost::python::indexing::iterator_pair Container2; + + // reference_existing_object is safe in this case, because the array + // is static, and we never manually destroy any array elements. There + // is also no point in using return_internal_reference to extend the + // life of the iterator_pair object, since it has no influence on the + // lifetimes of the array elements. + boost::python::class_ + ("Array_ref", boost::python::init()) + .def (boost::python::indexing::container_suite + ::with_policies(boost::python::return_value_policy + ())); + + boost::python::def ("get_array_wrap", get_array_wrap); +} diff --git a/test/test_array_ref.py b/test/test_array_ref.py new file mode 100644 index 00000000..a314f548 --- /dev/null +++ b/test/test_array_ref.py @@ -0,0 +1,62 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_array_ref.py +# +# Test the array container with return_internal_reference +# policies. This is a dangerous container - see the container suite +# documentation on using policies for details. +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/15 rmg File creation from test_vector_ref.py and test_array.py +# +# $Id$ +# + +'''>>> from test_array_ext import * +>>> element_type = int_wrapper +>>> def increment(wrapper, change = 1): +... wrapper.increment (change) +... +>>> setTrace(False) +>>> v = get_array_wrap () +>>> ref = v[0] +>>> print ref, v[0] +8 8 +>>> increment (v[0]) # Mutate object in container +>>> print ref, v[0] # Check reference refers to same object +9 9 +>>> for x in v: +... increment(x) # Check iterator provides by-ref access +... +>>> print ref, v[0] # Check mutation happened in container element +10 10 +>>> print [ x for x in v ] # Check other elements mutated as well +[10, 7, 5, 3, 2, 4, 6, 8, 1] +>>> v[:] = [ 8, 6, 4, 2, 1, 3, 5, 7, 0 ] # Return array to original state +>>> #### NOTE: test_array_common gets included after this point #### +''' + +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__': + from test_array_common import common_doctest_string + __doc__ += common_doctest_string + print 'running...' + import sys + status = run()[0] + if (status == 0): print "Done." + sys.exit(status) diff --git a/test/test_deque_ext.cpp b/test/test_deque_ext.cpp new file mode 100755 index 00000000..b6d7df58 --- /dev/null +++ b/test/test_deque_ext.cpp @@ -0,0 +1,77 @@ +// -*- mode:c++ -*- +// +// Module test_deque_ext.cpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) +// +// History +// ======= +// 2003/10/15 rmg File creation from testlinear.cpp +// +// $Id$ +// + +#include "int_wrapper.hpp" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +// More messiness from not having a separate int_wrapper.cpp file +bool int_wrapper::our_trace_flag = true; +unsigned int_wrapper::our_object_counter = 0; + +std::string repr (int_wrapper const &i) +{ + std::stringstream temp; + temp << i; + return temp.str(); +} + +BOOST_PYTHON_MODULE(test_deque_ext) +{ + boost::python::implicitly_convertible (); + + boost::python::def ("setTrace", &int_wrapper::setTrace); + + boost::python::class_("int_wrapper", boost::python::init()) + .def ("increment", &int_wrapper::increment) + .def ("__repr__", repr) + .def ("__cmp__", compare) + ; + + typedef std::deque Container1; + + boost::python::class_("Deque") + .def (boost::python::indexing::container_suite()) + ; + + typedef std::deque Container2; + + // Returning internal references to elements of a deque is + // dangerous - the references can be invalidated by inserts or + // deletes! + boost::python::class_("Deque_ref") + .def (boost::python::indexing::container_suite + ::with_policies (boost::python::return_internal_reference<>())); + + typedef boost::python::indexing::container_proxy< std::deque > + Container3; + + boost::python::class_("Deque_proxy") + .def (boost::python::indexing::container_suite()) + ; +} diff --git a/test/test_deque_plain.py b/test/test_deque_plain.py new file mode 100644 index 00000000..c91de33b --- /dev/null +++ b/test/test_deque_plain.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_deque_plain.py +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/15 rmg File creation from test_vector_plain.py +# +# $Id$ +# + +'''>>> from test_deque_ext import * +>>> element_type = int +>>> v = Deque() +>>> v[:] = (6, 7, 8, 5, 4, 8, 3, 1, 2) # Slice replace (tuple) +>>> print [ x for x in v ] +[6, 7, 8, 5, 4, 8, 3, 1, 2] +>>> #### NOTE: test_vector_common gets included after this point #### +''' + +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__': + from test_vector_common import common_doctest_string + __doc__ += common_doctest_string + print 'running...' + import sys + status = run()[0] + if (status == 0): print "Done." + sys.exit(status) diff --git a/test/test_deque_proxy.py b/test/test_deque_proxy.py new file mode 100644 index 00000000..7d979624 --- /dev/null +++ b/test/test_deque_proxy.py @@ -0,0 +1,46 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_deque_proxy.py +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/15 rmg File creation from test_vector_proxy.py +# +# $Id$ +# + +'''>>> from test_deque_ext import * +>>> element_type = int_wrapper +>>> def increment(wrapper, change = 1): +... wrapper.increment (change) +... +>>> setTrace(False) +>>> v = Deque_proxy() +>>> #### NOTE: test_python_ref, test_vector_common included after this #### +''' + +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__': + import test_python_ref_common # Checks for python reference semantics + import test_vector_common + __doc__ += test_python_ref_common.common_doctest_string + __doc__ += test_vector_common.common_doctest_string + print 'running...' + import sys + status = run()[0] + if (status == 0): print "Done." + sys.exit(status) diff --git a/test/test_deque_ref.py b/test/test_deque_ref.py new file mode 100644 index 00000000..ecc999c9 --- /dev/null +++ b/test/test_deque_ref.py @@ -0,0 +1,63 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_deque_ref.py +# +# Test the deque container with return_internal_reference +# policies. This is a dangerous container - see the container suite +# documentation on using policies for details. +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/15 rmg File creation from test_vector_ref.py +# +# $Id$ +# + +'''>>> from test_deque_ext import * +>>> element_type = int_wrapper +>>> def increment(wrapper, change = 1): +... wrapper.increment (change) +... +>>> setTrace(False) +>>> v = Deque_ref() +>>> v.append (3) +>>> ref = v[0] +>>> print ref, v[0] +3 3 +>>> increment(v[0]) # Mutate object in container +>>> print ref, v[0] # Check reference refers to same object +4 4 +>>> for x in v: +... increment(x) # Check iterator provides by-ref access +... +>>> print ref, v[0] # Check mutation happened in container element +5 5 +>>> # DO NOT try insert and delete, since the element reference +>>> # would be invalidated by those operations. +>>> del ref # Avoid dangling reference during subsequent tests +>>> #### NOTE: test_vector_common gets included after this point #### +''' + +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__': + from test_vector_common import common_doctest_string + __doc__ += common_doctest_string + print 'running...' + import sys + status = run()[0] + if (status == 0): print "Done." + sys.exit(status) diff --git a/test/test_list_ext.cpp b/test/test_list_ext.cpp new file mode 100755 index 00000000..3620a729 --- /dev/null +++ b/test/test_list_ext.cpp @@ -0,0 +1,60 @@ +// -*- mode:c++ -*- +// +// Module test_list_ext.cpp +// +// Copyright (c) 2003 Raoul M. Gough +// +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) +// +// History +// ======= +// 2003/10/15 rmg File creation from testlinear.cpp +// +// $Id$ +// + +#include "int_wrapper.hpp" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +// More messiness from not having a separate int_wrapper.cpp file +bool int_wrapper::our_trace_flag = true; +unsigned int_wrapper::our_object_counter = 0; + +std::string repr (int_wrapper const &i) +{ + std::stringstream temp; + temp << i; + return temp.str(); +} + +BOOST_PYTHON_MODULE(test_list_ext) +{ + boost::python::implicitly_convertible (); + + boost::python::def ("setTrace", &int_wrapper::setTrace); + + boost::python::class_("int_wrapper", boost::python::init()) + .def ("increment", &int_wrapper::increment) + .def ("__repr__", repr) + .def ("__cmp__", compare) + ; + + typedef std::list Container1; + + boost::python::class_("List") + .def (boost::python::indexing::container_suite()); +} diff --git a/test/test_list_plain.py b/test/test_list_plain.py index 41964c8b..eb5751fe 100644 --- a/test/test_list_plain.py +++ b/test/test_list_plain.py @@ -16,7 +16,7 @@ # $Id$ # -'''>>> from testlinear import * +'''>>> from test_list_ext import * >>> setTrace(0) >>> l = List() >>> assert not 0 in l # Search in empty list @@ -40,7 +40,7 @@ >>> print len(l) # Length 3 >>> for x in l: -... x.increment() # Check value semantics +... x.increment(1) # Check value semantics ... >>> print [ x for x in l ] # Container should be unchanged [1, 2, 3] diff --git a/test/test_python_list.py b/test/test_python_list.py index 02da81a9..2072c3e7 100644 --- a/test/test_python_list.py +++ b/test/test_python_list.py @@ -17,6 +17,20 @@ # '''>>> v = [] +>>> # Provide a mutable int-like object (same as int_wrapper) +>>> class element_type: +... def __init__(self, val = 0): +... self.val = val +... def increment(self, incr): +... self.val += incr +... def __repr__(self): +... return repr(self.val) +... def __cmp__(self, other): +... return self.val.__cmp__(other.val) +... +>>> def increment(element, change = 1): +... element.increment (change) +... ''' def run(args = None): @@ -28,8 +42,10 @@ def run(args = None): return doctest.testmod(sys.modules.get(__name__)) if __name__ == '__main__': - from test_vector_common import common_doctest_string - __doc__ += common_doctest_string + import test_python_ref_common # Checks for python reference semantics + import test_vector_common + __doc__ += test_python_ref_common.common_doctest_string + __doc__ += test_vector_common.common_doctest_string print 'running...' import sys status = run()[0] diff --git a/test/test_python_ref_common.py b/test/test_python_ref_common.py new file mode 100644 index 00000000..860efb2c --- /dev/null +++ b/test/test_python_ref_common.py @@ -0,0 +1,102 @@ +#!/usr/bin/python +# -*- mode:python -*- +# +# Python module test_python_refs_common.py +# +# Copyright (c) 2003 Raoul M. Gough +# +# Use, modification and distribution is subject to the Boost Software +# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) +# +# History +# ======= +# 2003/10/15 rmg File creation +# +# $Id$ +# + +'''>>> print len(v) # Check container starts off empty +0 +>>> v.extend ([element_type(x) for x in [6, 5, 4, 3]]) # Add elements +>>> print [ x for x in v ] +[6, 5, 4, 3] +>>> for x in v: +... increment(x) # Check iterator provides by-ref access +... +>>> print [ x for x in v ] # Check mutation happened in container +[7, 6, 5, 4] +>>> v0 = v[0] # Reference to first element +>>> v3 = v[3] # Reference to last element +>>> print v0, v[0], v3 # Check reference values +7 7 4 +>>> increment(v0) # Increment one of the referenced elements +>>> print v0, v[0], v3 # Check reference to same object +8 8 4 +>>> v[:0] = [element_type(3)] # Insert before any referenced elements +>>> print [ x for x in v ] # Check whole contents +[3, 8, 6, 5, 4] +>>> print v0, v[1], v3 # Check references to original elements +8 8 4 +>>> increment(v[1]) # Increment element in container +>>> print v0, v[1], v3 # Check reference to same object +9 9 4 +>>> del v[1] # Delete element from container +>>> print v0, v[1], v3 # Check old element value copied +9 6 4 +>>> print [ x for x in v ] # Check container contents +[3, 6, 5, 4] +>>> v0 = v[0] # Get new reference to first element +>>> print v0, v[0] # Check matching +3 3 +>>> v[0] = element_type(9) # Overwrite first element +>>> print v0, v[0] # Check old value copied +3 9 +>>> v_slice1 = v[1:3] # Slice for v[1] and v[2] +>>> v_slice2 = v[1:3] # Same slice again +>>> print v_slice1, v_slice2, v[1], v[2] +[6, 5] [6, 5] 6 5 +>>> increment(v[1]) # Check all refer to same v[1] +>>> print v_slice1, v_slice2, v[1], v[2] +[7, 5] [7, 5] 7 5 +>>> increment(v_slice1[1]) # Check all refer to same v[2] +>>> print v_slice1, v_slice2, v[1], v[2] +[7, 6] [7, 6] 7 6 +>>> v[2:2] = [element_type(10)] # Insert within slice range +>>> print v_slice1, v_slice2, v[1], v[2], v[3] +[7, 6] [7, 6] 7 10 6 +>>> v_slice1[1] = element_type(9) # Replace one reference +>>> print v_slice1, v_slice2, v[1], v[2], v[3] # Check no side-effects +[7, 9] [7, 6] 7 10 6 +>>> del v[1:4] # Remove whole slice +>>> print v_slice1, v_slice2, v[1] # Check reference copies +[7, 9] [7, 6] 4 +>>> increment(v_slice1[0]) # Mutate shared object +>>> print v_slice1, v_slice2, v[1] # Check reference to same object +[8, 9] [8, 6] 4 +>>> v.extend ([element_type(x) for x in [8, 7, 6, 5, 4, 3, -1]]) # New, incl -1 +>>> print [ x for x in v ] +[9, 4, 8, 7, 6, 5, 4, 3, -1] +>>> least_element = v[len(v)-1] # Get proxy for min element +>>> print least_element +-1 +>>> v.sort() # Sort min element to front +>>> print [ x for x in v ] +[-1, 3, 4, 4, 5, 6, 7, 8, 9] +>>> print least_element, v[0] # Check values match +-1 -1 +''' + +# It would be nice if sorting the list did not detach any existing +# proxies, but this is probably not possible to guarantee with the +# current implementation. The overload of iter_swap is sufficient with +# some standard libraries, but not others. The following test works +# only on MSVC so far. + +# +# >>> increment(v[0]) # Mutate value in container +# >>> print least_element, v[0] # Verify proxy still attached +# 0 0 +# + +common_doctest_string = __doc__ diff --git a/test/test_vector_common.py b/test/test_vector_common.py index 29866ba1..977a1964 100644 --- a/test/test_vector_common.py +++ b/test/test_vector_common.py @@ -24,16 +24,16 @@ >>> print [ x for x in v ] # Iterate over empty container [] >>> try: -... print v.index (2) # Search in empty container +... print v.index (element_type(2)) # Search in empty container ... except ValueError, e: ... print "Got expected exception" ... Got expected exception ->>> print v.count (2) # Search in empty container +>>> print v.count (element_type(2)) # Search in empty container 0 >>> print len(v) # Length of empty container 0 ->>> v.extend ([1, 3, 5, 2, 4, 6]) # Try extend with Python list +>>> v.extend ([ element_type(x) for x in [1, 3, 5, 2, 4, 6]]) # Extend via list >>> print len(v) # Length of non-empty container 6 >>> print [ x for x in v ] # Iteration @@ -44,23 +44,23 @@ Got expected exception >>> v.sort() # Sort >>> print [ x for x in v ] [1, 2, 3, 4, 5, 6] ->>> v[:] = [3, 4] # Remove dependencies on prior results ->>> v.insert (0, 2) # Insert at start +>>> v[:] = [element_type(3), element_type(4)] # Remove dep. on prior results +>>> v.insert (0, element_type(2)) # Insert at start >>> print [ x for x in v ] [2, 3, 4] ->>> v.insert (len(v), 5) # Insert at end +>>> v.insert (len(v), element_type(5)) # Insert at end >>> print [ x for x in v ] [2, 3, 4, 5] ->>> v.insert (999, 6) # Insert at end (out of bounds) +>>> v.insert (999, element_type(6)) # Insert at end (out of bounds) >>> print [ x for x in v ] [2, 3, 4, 5, 6] ->>> v.insert (-1, 1) # Insert at beginning (-ve) +>>> v.insert (-1, element_type(1)) # Insert at beginning (-ve) >>> print [ x for x in v ] [1, 2, 3, 4, 5, 6] ->>> v.append (7) # Append +>>> v.append (element_type(7)) # Append >>> print [ x for x in v ] [1, 2, 3, 4, 5, 6, 7] ->>> v.extend ([3,8,9,10]) # Extend +>>> v.extend ([element_type(x) for x in [3,8,9,10]]) # Extend >>> print [ x for x in v ] [1, 2, 3, 4, 5, 6, 7, 3, 8, 9, 10] >>> del v[2] # Single element delete @@ -87,13 +87,14 @@ Got expected exception ... print "Got expected exception" ... Got expected exception ->>> v.insert (len(v) + 1, 0) # Insert at end via out of range +>>> v.insert (len(v) + 1, element_type(0)) # Insert at end via out of range >>> print [ x for x in v ] [1, 2, 4, 5, 6, 9, 10, 8, 0] ->>> v.insert (-1, 7) # Insert at beginning via negative +>>> v.insert (-1, element_type(7)) # Insert at beginning via negative >>> print [ x for x in v ] [7, 1, 2, 4, 5, 6, 9, 10, 8, 0] ->>> v[:] = [8, 6, 4, 2, 1, 3, 5, 7, 0] # Prepare for common array tests +>>> # Prepare for common array tests +>>> v[:] = [element_type(x) for x in [8, 6, 4, 2, 1, 3, 5, 7, 0]] ''' import test_array_common diff --git a/test/testlinear.cpp b/test/test_vector_ext.cpp similarity index 61% rename from test/testlinear.cpp rename to test/test_vector_ext.cpp index 2663cbee..094e10b8 100755 --- a/test/testlinear.cpp +++ b/test/test_vector_ext.cpp @@ -1,6 +1,6 @@ // -*- mode:c++ -*- // -// Module testlinear.cpp +// Module test_vector_ext.cpp // // Copyright (c) 2003 Raoul M. Gough // @@ -12,6 +12,7 @@ // ======= // 2003/ 9/ 8 rmg File creation as testsuite.cpp // 2003/ 9/29 rmg Renamed testlinear.cpp to allow division into parts +// 2003/10/15 rmg Renamed test_vector_ext.cpp for further division // // $Id$ // @@ -22,7 +23,6 @@ #include #include -#include #include #include #include @@ -36,18 +36,6 @@ bool int_wrapper::our_trace_flag = true; unsigned int_wrapper::our_object_counter = 0; -boost::python::indexing::iterator_pair getArray() -{ - static int_wrapper array[] = { - int_wrapper(8), int_wrapper(6), int_wrapper(4), int_wrapper(2) - , int_wrapper(1), int_wrapper(3), int_wrapper(5) - , int_wrapper(7), int_wrapper(0) }; - - return boost::python::indexing::iterator_pair - (boost::python::indexing::begin(array) - , boost::python::indexing::end(array)); -} - std::string repr (int_wrapper const &i) { std::stringstream temp; @@ -55,13 +43,13 @@ std::string repr (int_wrapper const &i) return temp.str(); } -BOOST_PYTHON_MODULE(testlinear) +BOOST_PYTHON_MODULE(test_vector_ext) { boost::python::implicitly_convertible (); boost::python::def ("setTrace", &int_wrapper::setTrace); - boost::python::class_ ("int_wrapper", boost::python::init()) + boost::python::class_("int_wrapper", boost::python::init()) .def ("increment", &int_wrapper::increment) .def ("__repr__", repr) .def ("__cmp__", compare) @@ -74,34 +62,21 @@ BOOST_PYTHON_MODULE(testlinear) .def ("reserve", &Container1::reserve) ; - typedef std::list Container2; - - boost::python::class_("List") - .def (boost::python::indexing::container_suite()); - - typedef boost::python::indexing::iterator_pair Container3; - - boost::python::class_ - ("Array", boost::python::init()) - .def (boost::python::indexing::container_suite()); - - boost::python::def ("getArray", getArray); - - typedef std::vector Container4; + typedef std::vector Container2; // Returning internal references to elements of a vector is - // dangerous! The references can be invalidated by inserts or + // dangerous - the references can be invalidated by inserts or // deletes! - boost::python::class_("Vector_ref") - .def (boost::python::indexing::container_suite + boost::python::class_("Vector_ref") + .def (boost::python::indexing::container_suite ::with_policies (boost::python::return_internal_reference<>())); typedef boost::python::indexing::container_proxy< std::vector > - Container5; + Container3; - boost::python::class_("Vector_proxy") - .def (boost::python::indexing::container_suite()) - .def ("reserve", &Container5::reserve) + boost::python::class_("Vector_proxy") + .def (boost::python::indexing::container_suite()) + .def ("reserve", &Container3::reserve) ; /* The no-partial-specialization version for vector diff --git a/test/test_vector_plain.py b/test/test_vector_plain.py index 06553cc0..42379af1 100644 --- a/test/test_vector_plain.py +++ b/test/test_vector_plain.py @@ -16,11 +16,13 @@ # $Id$ # -'''>>> from testlinear import * +'''>>> from test_vector_ext import * +>>> element_type = int >>> v = Vector() >>> v[:] = (6, 7, 8, 5, 4, 8, 3, 1, 2) # Slice replace (tuple) >>> print [ x for x in v ] [6, 7, 8, 5, 4, 8, 3, 1, 2] +>>> #### NOTE: test_vector_common gets included after this point #### ''' def run(args = None): diff --git a/test/test_vector_proxy.py b/test/test_vector_proxy.py index 988e425f..7dd369d5 100644 --- a/test/test_vector_proxy.py +++ b/test/test_vector_proxy.py @@ -16,90 +16,16 @@ # $Id$ # -'''>>> from testlinear import * +'''>>> from test_vector_ext import * +>>> element_type = int_wrapper +>>> def increment(wrapper, change = 1): +... wrapper.increment (change) +... >>> setTrace(False) >>> v = Vector_proxy() ->>> v.extend ([6, 5, 4, 3]) ->>> print [ x for x in v ] -[6, 5, 4, 3] ->>> for x in v: -... x.increment() # Check iterator provides by-ref access -... ->>> print [ x for x in v ] # Check mutation happened in container -[7, 6, 5, 4] ->>> v0 = v[0] # Reference to first element ->>> v3 = v[3] # Reference to last element ->>> print v0, v[0], v3 # Check reference values -7 7 4 ->>> v0.increment() # Increment one of the referenced elements ->>> print v0, v[0], v3 # Check reference to same object -8 8 4 ->>> v[:0] = [3] # Insert before any referenced elements ->>> print [ x for x in v ] # Check whole contents -[3, 8, 6, 5, 4] ->>> print v0, v[1], v3 # Check references to original elements -8 8 4 ->>> v[1].increment() # Increment element in container ->>> print v0, v[1], v3 # Check reference to same object -9 9 4 ->>> del v[1] # Delete element from container ->>> print v0, v[1], v3 # Check old element value copied -9 6 4 ->>> print [ x for x in v ] # Check container contents -[3, 6, 5, 4] ->>> v0 = v[0] # Get new reference to first element ->>> print v0, v[0] # Check matching -3 3 ->>> v[0] = 9 # Overwrite first element ->>> print v0, v[0] # Check old value copied -3 9 ->>> v_slice1 = v[1:3] # Slice for v[1] and v[2] ->>> v_slice2 = v[1:3] # Same slice again ->>> print v_slice1, v_slice2, v[1], v[2] -[6, 5] [6, 5] 6 5 ->>> v[1].increment() # Check all refer to same v[1] ->>> print v_slice1, v_slice2, v[1], v[2] -[7, 5] [7, 5] 7 5 ->>> v_slice1[1].increment() # Check all refer to same v[2] ->>> print v_slice1, v_slice2, v[1], v[2] -[7, 6] [7, 6] 7 6 ->>> v[2:2] = [10] # Insert within slice range ->>> print v_slice1, v_slice2, v[1], v[2], v[3] -[7, 6] [7, 6] 7 10 6 ->>> v_slice1[1] = 9 # Replace one reference ->>> print v_slice1, v_slice2, v[1], v[2], v[3] # Check no side-effects -[7, 9] [7, 6] 7 10 6 ->>> del v[1:4] # Remove whole slice ->>> print v_slice1, v_slice2, v[1] # Check reference copies -[7, 9] [7, 6] 4 ->>> v_slice1[0].increment() # Mutate shared object ->>> print v_slice1, v_slice2, v[1] # Check reference to same object -[8, 9] [8, 6] 4 ->>> v.extend ([8, 7, 6, 5, 4, 3, -1]) # Add new values, including -1 ->>> print [ x for x in v ] -[9, 4, 8, 7, 6, 5, 4, 3, -1] ->>> least_element = v[len(v)-1] # Get proxy for min element ->>> print least_element --1 ->>> v.sort() # Sort min element to front ->>> print [ x for x in v ] -[-1, 3, 4, 4, 5, 6, 7, 8, 9] ->>> print least_element, v[0] # Check values match --1 -1 +>>> #### NOTE: test_python_ref, test_vector_common included after this #### ''' -# It would be nice if sorting the list did not detach any existing -# proxies, but this is probably not possible to guarantee with the -# current implementation. The overload of iter_swap is sufficient with -# some standard libraries, but not others. The following test works -# only on MSVC so far. - -# -# >>> v[0].increment() # Mutate value in container -# >>> print least_element, v[0] # Verify proxy still attached -# 0 0 -# - def run(args = None): import sys import doctest @@ -109,8 +35,10 @@ def run(args = None): return doctest.testmod(sys.modules.get(__name__)) if __name__ == '__main__': - from test_vector_common import common_doctest_string - __doc__ += common_doctest_string + import test_python_ref_common # Checks for python reference semantics + import test_vector_common + __doc__ += test_python_ref_common.common_doctest_string + __doc__ += test_vector_common.common_doctest_string print 'running...' import sys status = run()[0] diff --git a/test/test_vector_ref.py b/test/test_vector_ref.py index 5fb911ba..7fb3ada7 100644 --- a/test/test_vector_ref.py +++ b/test/test_vector_ref.py @@ -20,24 +20,29 @@ # $Id$ # -'''>>> from testlinear import * +'''>>> from test_vector_ext import * +>>> element_type = int_wrapper +>>> def increment(wrapper, change = 1): +... wrapper.increment (change) +... >>> setTrace(False) >>> v = Vector_ref() ->>> v.append (3) +>>> v.append (element_type(3)) >>> ref = v[0] >>> print ref, v[0] 3 3 ->>> v[0].increment() # Mutate object in container +>>> increment(v[0]) # Mutate object in container >>> print ref, v[0] # Check reference refers to same object 4 4 >>> for x in v: -... x.increment() # Check iterator provides by-ref access +... increment(x) # Check iterator provides by-ref access ... >>> print ref, v[0] # Check mutation happened in container element 5 5 >>> # DO NOT try insert and delete, since the element reference >>> # would be invalidated by those operations. >>> del ref # Avoid dangling reference during subsequent tests +>>> #### NOTE: test_vector_common gets included after this point #### ''' def run(args = None):