]> git.samba.org - metze/samba/wip.git/commitdiff
pidl: Fix our python reference handling
authorAndrew Bartlett <abartlet@samba.org>
Tue, 16 Feb 2016 01:06:28 +0000 (14:06 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 8 Mar 2016 00:58:26 +0000 (01:58 +0100)
The new talloc.BaseObject allow us to hold a talloc context per
python object (there may be many referring to the same C object)
and the talloc context that the actual object pointer is under.

Another advantage is that talloc.BaseObject(), has less of
an ABI surface.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
pidl/lib/Parse/Pidl/Samba4/Python.pm
python/samba/tests/dcerpc/array.py [new file with mode: 0644]
python/samba/tests/dcerpc/rpc_talloc.py
source4/librpc/rpc/pyrpc.c

index f2cb5387751dc0a4acfc708ef6e15835c06d1b75..29fb6e0008469d2ecabe64a5943cfce3534bcb15 100644 (file)
@@ -376,15 +376,16 @@ sub PythonStruct($$$$$$)
        }
        $self->pidl(".tp_methods = $py_methods,");
        $self->pidl(".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,");
-       $self->pidl(".tp_basicsize = sizeof(pytalloc_Object),");
        $self->pidl(".tp_new = py_$name\_new,");
        $self->deindent;
        $self->pidl("};");
 
        $self->pidl("");
 
-       my $talloc_typename = $self->import_type_variable("talloc", "Object");
-       $self->register_module_prereadycode(["$name\_Type.tp_base = $talloc_typename;", ""]);
+       my $talloc_typename = $self->import_type_variable("talloc", "BaseObject");
+       $self->register_module_prereadycode(["$name\_Type.tp_base = $talloc_typename;",
+                                            "$name\_Type.tp_basicsize = pytalloc_BaseObject_size();",
+                                            ""]);
 
        return "&$typeobject";
 }
@@ -810,7 +811,6 @@ sub Interface($$$)
                $self->indent;
                $self->pidl("PyObject_HEAD_INIT(NULL) 0,");
                $self->pidl(".tp_name = \"$basename.$interface->{NAME}\",");
-               $self->pidl(".tp_basicsize = sizeof(pytalloc_Object),");
                $self->pidl(".tp_doc = $docstring,");
                $self->pidl(".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,");
                $self->pidl(".tp_new = syntax_$interface->{NAME}_new,");
@@ -821,7 +821,9 @@ sub Interface($$$)
 
                $self->register_module_typeobject("abstract_syntax", "&$syntax_typename");
                my $ndr_typename = $self->import_type_variable("samba.dcerpc.misc", "ndr_syntax_id");
-               $self->register_module_prereadycode(["$syntax_typename.tp_base = $ndr_typename;", ""]);
+               $self->register_module_prereadycode(["$syntax_typename.tp_base = $ndr_typename;",
+                                                    "$syntax_typename.tp_basicsize = pytalloc_BaseObject_size();",
+                                                    ""]);
        }
 
        $self->pidl_hdr("\n");
diff --git a/python/samba/tests/dcerpc/array.py b/python/samba/tests/dcerpc/array.py
new file mode 100644 (file)
index 0000000..80c53c6
--- /dev/null
@@ -0,0 +1,171 @@
+# Unix SMB/CIFS implementation.
+# Copyright (C) Andrew Bartlett <abartlet@samba.org> 2016
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+"""Tests for array handling in PIDL generated bindings samba.dcerpc.*"""
+
+from samba.dcerpc import drsblobs
+import samba.tests
+from samba.ndr import ndr_unpack, ndr_pack
+import talloc
+import gc
+
+class ArrayTests(samba.tests.TestCase):
+
+    def setUp(self):
+        super(ArrayTests, self).setUp()
+        talloc.enable_null_tracking()
+        self.startup_blocks = talloc.total_blocks()
+
+    def tearDown(self):
+        super(ArrayTests, self).tearDown()
+        self.assertEqual(talloc.total_blocks(), self.startup_blocks)
+        talloc.report_full()
+
+    def test_array_from_python(self):
+        rmd = drsblobs.replPropertyMetaDataBlob()
+
+        rmd.version = 1
+        rmd.ctr = drsblobs.replPropertyMetaDataCtr1()
+        rmd.ctr.count = 3
+
+        rmd1 = drsblobs.replPropertyMetaData1()
+        rmd1.attid = 1
+        rmd1.version = 2
+
+        rmd2 = drsblobs.replPropertyMetaData1()
+        rmd2.attid = 2
+        rmd2.version = 2
+
+        rmd3 = drsblobs.replPropertyMetaData1()
+        rmd3.attid = 3
+        rmd3.version = 2
+
+        rmd.ctr.array = [rmd1, rmd2, rmd3]
+        gc.collect()
+
+        self.assertIsNotNone(rmd)
+        self.assertEqual(rmd.version, 1)
+        self.assertIsNotNone(rmd.ctr)
+        self.assertEqual(rmd.ctr.count, 3)
+        self.assertEqual(len(rmd.ctr.array), rmd.ctr.count)
+        self.assertIsNotNone(rmd.ctr.array[0])
+        self.assertEqual(rmd.ctr.array[0].attid, 1)
+
+    def test_array_with_exception(self):
+        try:
+            rmd = drsblobs.replPropertyMetaDataBlob()
+
+            rmd.version = 1
+            rmd.ctr = drsblobs.replPropertyMetaDataCtr1()
+            rmd.ctr.count = 3
+
+            rmd1 = drsblobs.replPropertyMetaData1()
+            rmd1.attid = 1
+            rmd1.version = 2
+
+            rmd2 = drsblobs.replPropertyMetaData1()
+            rmd2.attid = 2
+            rmd2.version = 2
+
+            rmd3 = drsblobs.replPropertyMetaData1()
+            rmd3.attid = 3
+            rmd3.version = 2
+
+            rmd.ctr.array = [rmd1, rmd2, rmd3]
+
+            gc.collect()
+
+            self.assertIsNotNone(rmd)
+            self.assertEqual(rmd.version, 1)
+            self.assertIsNotNone(rmd.ctr)
+            self.assertEqual(rmd.ctr.count, 3)
+            self.assertEqual(len(rmd.ctr.array), rmd.ctr.count)
+            self.assertIsNotNone(rmd.ctr.array[0])
+            self.assertEqual(rmd.ctr.array[0].attid, 1)
+
+            raise Exception()
+        except:
+            pass
+
+    def test_array_from_python_function(self):
+        def get_rmd():
+            rmd = drsblobs.replPropertyMetaDataBlob()
+
+            rmd.version = 1
+            rmd.ctr = drsblobs.replPropertyMetaDataCtr1()
+            rmd.ctr.count = 3
+
+            rmd1 = drsblobs.replPropertyMetaData1()
+            rmd1.attid = 1
+            rmd1.version = 2
+
+            rmd2 = drsblobs.replPropertyMetaData1()
+            rmd2.attid = 2
+            rmd2.version = 2
+
+            rmd3 = drsblobs.replPropertyMetaData1()
+            rmd3.attid = 3
+            rmd3.version = 2
+
+            rmd.ctr.array = [rmd1, rmd2, rmd3]
+            return rmd
+
+        rmd = get_rmd()
+        gc.collect()
+        self.assertIsNotNone(rmd)
+        self.assertEqual(rmd.version, 1)
+        self.assertIsNotNone(rmd.ctr)
+        self.assertEqual(rmd.ctr.count, 3)
+        self.assertEqual(len(rmd.ctr.array), rmd.ctr.count)
+        self.assertIsNotNone(rmd.ctr.array[0])
+        self.assertEqual(rmd.ctr.array[0].attid, 1)
+
+    def test_array_from_ndr(self):
+        rmd = drsblobs.replPropertyMetaDataBlob()
+
+        rmd.version = 1
+        rmd.ctr = drsblobs.replPropertyMetaDataCtr1()
+        rmd.ctr.count = 3
+
+        rmd1 = drsblobs.replPropertyMetaData1()
+        rmd1.attid = 1
+        rmd1.version = 2
+
+        rmd2 = drsblobs.replPropertyMetaData1()
+        rmd2.attid = 2
+        rmd2.version = 2
+
+        rmd3 = drsblobs.replPropertyMetaData1()
+        rmd3.attid = 3
+        rmd3.version = 2
+
+        rmd.ctr.array = [rmd1, rmd2, rmd3]
+
+        packed = ndr_pack(rmd)
+        gc.collect()
+
+        rmd_unpacked = ndr_unpack(drsblobs.replPropertyMetaDataBlob, packed)
+        self.assertIsNotNone(rmd_unpacked)
+        self.assertEqual(rmd_unpacked.version, 1)
+        self.assertIsNotNone(rmd_unpacked.ctr)
+        self.assertEqual(rmd_unpacked.ctr.count, 3)
+        self.assertEqual(len(rmd_unpacked.ctr.array), rmd_unpacked.ctr.count)
+        self.assertIsNotNone(rmd_unpacked.ctr.array[0])
+        self.assertEqual(rmd_unpacked.ctr.array[0].attid, 1)
+
+        self.assertEqual(rmd.ctr.array[0].attid,
+                         rmd_unpacked.ctr.array[0].attid)
index b1e2741d7de9bd44eec229d4bcd02d286ed8ba6d..191e70c97021c4415b3df8376d35c293f8a9c304 100644 (file)
@@ -51,25 +51,27 @@ class TallocTests(samba.tests.TestCase):
         '''get a list of attributes for RODC replication'''
         partial_attribute_set = drsuapi.DsPartialAttributeSet()
 
-        # we expect one block for the object, and one for the structure
-        self.check_blocks(partial_attribute_set, 2)
+        # we expect one block for the object
+        self.check_blocks(partial_attribute_set, 1)
 
         attids = [1, 2, 3]
         partial_attribute_set.version = 1
         partial_attribute_set.attids     = attids
         partial_attribute_set.num_attids = len(attids)
 
-        # we expect one block object, a structure, an ARRAY, and a
+        # we expect one block for the object, a structure, and a
         # reference to the array
-        self.check_blocks(partial_attribute_set, 3)
+        self.check_blocks(partial_attribute_set, 2)
 
         return partial_attribute_set
 
     def pas_test(self):
         pas = self.get_rodc_partial_attribute_set()
-        self.check_blocks(pas, 3)
+        self.check_blocks(pas, 2)
         req8 = drsuapi.DsGetNCChangesRequest8()
-        self.check_blocks(req8, 2)
+        self.check_blocks(req8, 1)
+
+        # We expect the pas and req8, plus one block for each python object
         self.check_blocks(None, 5)
         req8.partial_attribute_set = pas
         if req8.partial_attribute_set.attids[1] != 2:
index f1bfc88787112fbaa3f0e88e8f20747676028239..948cad212f6e3d402926146e15ee2196625dfb67 100644 (file)
@@ -342,7 +342,6 @@ static PyObject *py_transfer_syntax_ndr_new(PyTypeObject *type, PyObject *args,
 static PyTypeObject py_transfer_syntax_ndr_SyntaxType = {
        PyObject_HEAD_INIT(NULL) 0,
        .tp_name = "base.transfer_syntax_ndr",
-       .tp_basicsize = sizeof(pytalloc_Object),
        .tp_doc = "transfer_syntax_ndr()\n",
        .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
        .tp_new = py_transfer_syntax_ndr_new,
@@ -356,7 +355,6 @@ static PyObject *py_transfer_syntax_ndr64_new(PyTypeObject *type, PyObject *args
 static PyTypeObject py_transfer_syntax_ndr64_SyntaxType = {
        PyObject_HEAD_INIT(NULL) 0,
        .tp_name = "base.transfer_syntax_ndr64",
-       .tp_basicsize = sizeof(pytalloc_Object),
        .tp_doc = "transfer_syntax_ndr64()\n",
        .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
        .tp_new = py_transfer_syntax_ndr64_new,
@@ -395,7 +393,6 @@ static PyObject *py_bind_time_features_syntax_new(PyTypeObject *type, PyObject *
 static PyTypeObject py_bind_time_features_syntax_SyntaxType = {
        PyObject_HEAD_INIT(NULL) 0,
        .tp_name = "base.bind_time_features_syntax",
-       .tp_basicsize = sizeof(pytalloc_Object),
        .tp_doc = "bind_time_features_syntax(features)\n",
        .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
        .tp_new = py_bind_time_features_syntax_new,
@@ -415,8 +412,11 @@ void initbase(void)
                return;
 
        py_transfer_syntax_ndr_SyntaxType.tp_base = ndr_syntax_id_Type;
+       py_transfer_syntax_ndr_SyntaxType.tp_basicsize = pytalloc_BaseObject_size();
        py_transfer_syntax_ndr64_SyntaxType.tp_base = ndr_syntax_id_Type;
+       py_transfer_syntax_ndr64_SyntaxType.tp_basicsize = pytalloc_BaseObject_size();
        py_bind_time_features_syntax_SyntaxType.tp_base = ndr_syntax_id_Type;
+       py_bind_time_features_syntax_SyntaxType.tp_basicsize = pytalloc_BaseObject_size();
 
        if (PyType_Ready(&dcerpc_InterfaceType) < 0)
                return;