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,
|
enabled=True,
|
||||||
realname='talloc.so')
|
realname='talloc.so')
|
||||||
|
|
||||||
|
bld.SAMBA_PYTHON('test_pytalloc',
|
||||||
|
'test_pytalloc.c',
|
||||||
|
deps='pytalloc',
|
||||||
|
enabled=True,
|
||||||
|
realname='_test_pytalloc.so',
|
||||||
|
install=False)
|
||||||
|
|
||||||
def test(ctx):
|
def test(ctx):
|
||||||
'''run talloc testsuite'''
|
'''run talloc testsuite'''
|
||||||
import Utils, samba_utils
|
import Utils, samba_utils
|
||||||
|
env = samba_utils.LOAD_ENVIRONMENT()
|
||||||
cmd = os.path.join(Utils.g_module.blddir, 'talloc_testsuite')
|
cmd = os.path.join(Utils.g_module.blddir, 'talloc_testsuite')
|
||||||
ret = samba_utils.RUN_COMMAND(cmd)
|
ret = samba_utils.RUN_COMMAND(cmd)
|
||||||
print("testsuite returned %d" % ret)
|
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():
|
def dist():
|
||||||
'''makes a tarball for distribution'''
|
'''makes a tarball for distribution'''
|
||||||
|
Reference in New Issue
Block a user