mirror of
https://github.com/samba-team/samba.git
synced 2025-08-03 04:22:09 +03:00
pytalloc: Add tests
Add tests for pytalloc. Since talloc objects can't be created from Python, a C extension with helpers is added. Signed-off-by: Petr Viktorin <pviktori@redhat.com> Reviewed-by: Andreas Schneider <asn@samba.org> Reviewed-by: Jelmer Vernooij <jelmer@samba.org>
This commit is contained in:
committed by
Jelmer Vernooij
parent
50311c7606
commit
8ac21ec4aa
128
lib/talloc/test_pytalloc.c
Normal file
128
lib/talloc/test_pytalloc.c
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
Samba Unix SMB/CIFS implementation.
|
||||
|
||||
C utilities for the pytalloc test suite.
|
||||
Provides the "_test_pytalloc" Python module.
|
||||
|
||||
NOTE: Please read talloc_guide.txt for full documentation
|
||||
|
||||
Copyright (C) Petr Viktorin 2015
|
||||
|
||||
** NOTE! The following LGPL license applies to the talloc
|
||||
** library. This does NOT imply that all of Samba is released
|
||||
** under the LGPL
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include <talloc.h>
|
||||
#include <pytalloc.h>
|
||||
|
||||
static PyObject *testpytalloc_new(PyTypeObject *mod)
|
||||
{
|
||||
char *obj = talloc_strdup(NULL, "This is a test string");;
|
||||
return pytalloc_steal(pytalloc_GetObjectType(), obj);
|
||||
}
|
||||
|
||||
static PyObject *testpytalloc_get_object_type(PyObject *mod) {
|
||||
PyObject *type = (PyObject *)pytalloc_GetObjectType();
|
||||
Py_INCREF(type);
|
||||
return type;
|
||||
}
|
||||
|
||||
static PyObject *testpytalloc_reference(PyObject *mod, PyObject *args) {
|
||||
pytalloc_Object *source = NULL;
|
||||
void *ptr;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O!", pytalloc_GetObjectType(), &source))
|
||||
return NULL;
|
||||
|
||||
ptr = source->ptr;
|
||||
return pytalloc_reference_ex(pytalloc_GetObjectType(), ptr, ptr);
|
||||
}
|
||||
|
||||
static PyMethodDef test_talloc_methods[] = {
|
||||
{ "new", (PyCFunction)testpytalloc_new, METH_NOARGS,
|
||||
"create a talloc Object with a testing string"},
|
||||
{ "get_object_type", (PyCFunction)testpytalloc_get_object_type, METH_NOARGS,
|
||||
"call pytalloc_GetObjectType"},
|
||||
{ "reference", (PyCFunction)testpytalloc_reference, METH_VARARGS,
|
||||
"call pytalloc_reference_ex"},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static PyTypeObject DObject_Type;
|
||||
|
||||
static int dobject_destructor(void *ptr)
|
||||
{
|
||||
PyObject *destructor_func = *talloc_get_type(ptr, PyObject*);
|
||||
PyObject *ret;
|
||||
ret = PyObject_CallObject(destructor_func, NULL);
|
||||
Py_DECREF(destructor_func);
|
||||
if (ret == NULL) {
|
||||
PyErr_Print();
|
||||
} else {
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *dobject_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
PyObject *destructor_func = NULL;
|
||||
PyObject **obj;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O", &destructor_func))
|
||||
return NULL;
|
||||
Py_INCREF(destructor_func);
|
||||
|
||||
obj = talloc(NULL, PyObject*);
|
||||
*obj = destructor_func;
|
||||
|
||||
talloc_set_destructor((void*)obj, dobject_destructor);
|
||||
return pytalloc_steal(&DObject_Type, obj);
|
||||
}
|
||||
|
||||
static PyTypeObject DObject_Type = {
|
||||
.tp_name = "_test_pytalloc.DObject",
|
||||
.tp_basicsize = sizeof(pytalloc_Object),
|
||||
.tp_methods = NULL,
|
||||
.tp_new = dobject_new,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT,
|
||||
.tp_doc = "test talloc object that calls a function when underlying data is freed\n",
|
||||
};
|
||||
|
||||
#define MODULE_DOC "Test utility module for pytalloc"
|
||||
|
||||
void init_test_pytalloc(void);
|
||||
void init_test_pytalloc(void)
|
||||
{
|
||||
PyObject *m;
|
||||
|
||||
DObject_Type.tp_base = pytalloc_GetObjectType();
|
||||
if (PyType_Ready(&DObject_Type) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
m = Py_InitModule3("_test_pytalloc", test_talloc_methods, MODULE_DOC);
|
||||
|
||||
if (m == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
Py_INCREF(&DObject_Type);
|
||||
Py_INCREF(DObject_Type.tp_base);
|
||||
PyModule_AddObject(m, "DObject", (PyObject *)&DObject_Type);
|
||||
}
|
114
lib/talloc/test_pytalloc.py
Normal file
114
lib/talloc/test_pytalloc.py
Normal file
@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python
|
||||
# Simple tests for the talloc python bindings.
|
||||
# Copyright (C) 2015 Petr Viktorin <pviktori@redhat.com>
|
||||
|
||||
import unittest
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
import gc
|
||||
|
||||
import talloc
|
||||
import _test_pytalloc
|
||||
|
||||
def dummy_func():
|
||||
pass
|
||||
|
||||
|
||||
class TallocTests(unittest.TestCase):
|
||||
|
||||
def test_report_full(self):
|
||||
# report_full is hardcoded to print to stdout, so use a subprocess
|
||||
process = subprocess.Popen([
|
||||
sys.executable, '-c',
|
||||
"""if True:
|
||||
import talloc, _test_pytalloc
|
||||
obj = _test_pytalloc.new()
|
||||
talloc.report_full(obj)
|
||||
"""
|
||||
], stdout=subprocess.PIPE)
|
||||
output, stderr = process.communicate()
|
||||
output = str(output)
|
||||
self.assertTrue("full talloc report on 'talloc.Object" in output)
|
||||
self.assertTrue("This is a test string" in output)
|
||||
|
||||
def test_totalblocks(self):
|
||||
obj = _test_pytalloc.new()
|
||||
# Two blocks: the string, and the name
|
||||
self.assertEqual(talloc.total_blocks(obj), 2)
|
||||
|
||||
def test_repr(self):
|
||||
obj = _test_pytalloc.new()
|
||||
prefix = '<talloc.Object talloc object at'
|
||||
self.assertTrue(repr(obj).startswith(prefix))
|
||||
self.assertEqual(repr(obj), str(obj))
|
||||
|
||||
def test_destructor(self):
|
||||
# Check correct lifetime of the talloc'd data
|
||||
lst = []
|
||||
obj = _test_pytalloc.DObject(lambda: lst.append('dead'))
|
||||
self.assertEqual(lst, [])
|
||||
del obj
|
||||
gc.collect()
|
||||
self.assertEqual(lst, ['dead'])
|
||||
|
||||
|
||||
class TallocComparisonTests(unittest.TestCase):
|
||||
|
||||
def test_compare_same(self):
|
||||
obj1 = _test_pytalloc.new()
|
||||
self.assertTrue(obj1 == obj1)
|
||||
self.assertFalse(obj1 != obj1)
|
||||
self.assertTrue(obj1 <= obj1)
|
||||
self.assertFalse(obj1 < obj1)
|
||||
self.assertTrue(obj1 >= obj1)
|
||||
self.assertFalse(obj1 > obj1)
|
||||
|
||||
def test_compare_different(self):
|
||||
# object comparison is consistent
|
||||
obj1, obj2 = sorted([
|
||||
_test_pytalloc.new(),
|
||||
_test_pytalloc.new()])
|
||||
self.assertFalse(obj1 == obj2)
|
||||
self.assertTrue(obj1 != obj2)
|
||||
self.assertTrue(obj1 <= obj2)
|
||||
self.assertTrue(obj1 < obj2)
|
||||
self.assertFalse(obj1 >= obj2)
|
||||
self.assertFalse(obj1 > obj2)
|
||||
|
||||
def test_compare_different_types(self):
|
||||
# object comparison falls back to comparing types
|
||||
if talloc.Object < _test_pytalloc.DObject:
|
||||
obj1 = _test_pytalloc.new()
|
||||
obj2 = _test_pytalloc.DObject(dummy_func)
|
||||
else:
|
||||
obj2 = _test_pytalloc.new()
|
||||
obj1 = _test_pytalloc.DObject(dummy_func)
|
||||
self.assertFalse(obj1 == obj2)
|
||||
self.assertTrue(obj1 != obj2)
|
||||
self.assertTrue(obj1 <= obj2)
|
||||
self.assertTrue(obj1 < obj2)
|
||||
self.assertFalse(obj1 >= obj2)
|
||||
self.assertFalse(obj1 > obj2)
|
||||
|
||||
|
||||
class TallocUtilTests(unittest.TestCase):
|
||||
|
||||
def test_get_type(self):
|
||||
self.assertTrue(talloc.Object is _test_pytalloc.get_object_type())
|
||||
|
||||
def test_refrence(self):
|
||||
# Check correct lifetime of the talloc'd data with multiple references
|
||||
lst = []
|
||||
obj = _test_pytalloc.DObject(lambda: lst.append('dead'))
|
||||
ref = _test_pytalloc.reference(obj)
|
||||
del obj
|
||||
gc.collect()
|
||||
self.assertEqual(lst, [])
|
||||
del ref
|
||||
gc.collect()
|
||||
self.assertEqual(lst, ['dead'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.TestProgram()
|
@ -136,13 +136,30 @@ def build(bld):
|
||||
enabled=True,
|
||||
realname='talloc.so')
|
||||
|
||||
bld.SAMBA_PYTHON('test_pytalloc',
|
||||
'test_pytalloc.c',
|
||||
deps='pytalloc',
|
||||
enabled=True,
|
||||
realname='_test_pytalloc.so',
|
||||
install=False)
|
||||
|
||||
def test(ctx):
|
||||
'''run talloc testsuite'''
|
||||
import Utils, samba_utils
|
||||
env = samba_utils.LOAD_ENVIRONMENT()
|
||||
cmd = os.path.join(Utils.g_module.blddir, 'talloc_testsuite')
|
||||
ret = samba_utils.RUN_COMMAND(cmd)
|
||||
print("testsuite returned %d" % ret)
|
||||
sys.exit(ret)
|
||||
if 'USING_SYSTEM_PYTALLOC_UTIL' not in env.defines and not env.disable_python:
|
||||
cmd = "PYTHONPATH=%s %s test_pytalloc.py" % (
|
||||
os.path.join(Utils.g_module.blddir, 'python'),
|
||||
env['PYTHON'],
|
||||
)
|
||||
pyret = samba_utils.RUN_COMMAND(cmd)
|
||||
else:
|
||||
pyret = 0
|
||||
print("python testsuite returned %d" % pyret)
|
||||
sys.exit(ret or pyret)
|
||||
|
||||
def dist():
|
||||
'''makes a tarball for distribution'''
|
||||
|
Reference in New Issue
Block a user