changeset: 94535:e55f955659bc branch: 2.7 user: Serhiy Storchaka date: Fri Feb 06 08:56:33 2015 +0200 files: Lib/test/test_marshal.py Misc/NEWS Modules/_testcapimodule.c description: Issue #23392: Added tests for marshal C API that works with FILE*. diff -r cee39701b280 -r e55f955659bc Lib/test/test_marshal.py --- a/Lib/test/test_marshal.py Fri Feb 06 08:36:14 2015 +0200 +++ b/Lib/test/test_marshal.py Fri Feb 06 08:56:33 2015 +0200 @@ -6,6 +6,11 @@ import unittest import os +try: + import _testcapi +except ImportError: + _testcapi = None + class IntTestCase(unittest.TestCase): def test_ints(self): # Test the full range of Python ints. @@ -316,6 +321,65 @@ self.check_unmarshallable(bytearray(size)) +@test_support.cpython_only +@unittest.skipUnless(_testcapi, 'requires _testcapi') +class CAPI_TestCase(unittest.TestCase): + + def test_write_long_to_file(self): + for v in range(marshal.version + 1): + _testcapi.pymarshal_write_long_to_file(0x12345678, test_support.TESTFN, v) + with open(test_support.TESTFN, 'rb') as f: + data = f.read() + test_support.unlink(test_support.TESTFN) + self.assertEqual(data, b'\x78\x56\x34\x12') + + def test_write_object_to_file(self): + obj = ('\u20ac', b'abc', 123, 45.6, 7+8j, 'long line '*1000) + for v in range(marshal.version + 1): + _testcapi.pymarshal_write_object_to_file(obj, test_support.TESTFN, v) + with open(test_support.TESTFN, 'rb') as f: + data = f.read() + test_support.unlink(test_support.TESTFN) + self.assertEqual(marshal.loads(data), obj) + + def test_read_short_from_file(self): + with open(test_support.TESTFN, 'wb') as f: + f.write(b'\x34\x12xxxx') + r, p = _testcapi.pymarshal_read_short_from_file(test_support.TESTFN) + test_support.unlink(test_support.TESTFN) + self.assertEqual(r, 0x1234) + self.assertEqual(p, 2) + + def test_read_long_from_file(self): + with open(test_support.TESTFN, 'wb') as f: + f.write(b'\x78\x56\x34\x12xxxx') + r, p = _testcapi.pymarshal_read_long_from_file(test_support.TESTFN) + test_support.unlink(test_support.TESTFN) + self.assertEqual(r, 0x12345678) + self.assertEqual(p, 4) + + def test_read_last_object_from_file(self): + obj = ('\u20ac', b'abc', 123, 45.6, 7+8j) + for v in range(marshal.version + 1): + data = marshal.dumps(obj, v) + with open(test_support.TESTFN, 'wb') as f: + f.write(data + b'xxxx') + r, p = _testcapi.pymarshal_read_last_object_from_file(test_support.TESTFN) + test_support.unlink(test_support.TESTFN) + self.assertEqual(r, obj) + + def test_read_object_from_file(self): + obj = ('\u20ac', b'abc', 123, 45.6, 7+8j) + for v in range(marshal.version + 1): + data = marshal.dumps(obj, v) + with open(test_support.TESTFN, 'wb') as f: + f.write(data + b'xxxx') + r, p = _testcapi.pymarshal_read_object_from_file(test_support.TESTFN) + test_support.unlink(test_support.TESTFN) + self.assertEqual(r, obj) + self.assertEqual(p, len(data)) + + def test_main(): test_support.run_unittest(IntTestCase, FloatTestCase, @@ -325,6 +389,7 @@ ExceptionTestCase, BugsTestCase, LargeValuesTestCase, + CAPI_TestCase, ) if __name__ == "__main__": diff -r cee39701b280 -r e55f955659bc Misc/NEWS --- a/Misc/NEWS Fri Feb 06 08:36:14 2015 +0200 +++ b/Misc/NEWS Fri Feb 06 08:56:33 2015 +0200 @@ -98,6 +98,8 @@ Tests ----- +- Issue #23392: Added tests for marshal C API that works with FILE*. + - Issue #18982: Add tests for CLI of the calendar module. - Issue #19949: The test_xpickle test now tests compatibility with installed diff -r cee39701b280 -r e55f955659bc Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Fri Feb 06 08:36:14 2015 +0200 +++ b/Modules/_testcapimodule.c Fri Feb 06 08:56:33 2015 +0200 @@ -9,6 +9,7 @@ #include #include "structmember.h" #include "datetime.h" +#include "marshal.h" #ifdef WITH_THREAD #include "pythread.h" @@ -1875,6 +1876,159 @@ } #endif /* WITH_THREAD */ +/* marshal */ + +static PyObject* +pymarshal_write_long_to_file(PyObject* self, PyObject *args) +{ + long value; + char *filename; + int version; + FILE *fp; + + if (!PyArg_ParseTuple(args, "lsi:pymarshal_write_long_to_file", + &value, &filename, &version)) + return NULL; + + fp = fopen(filename, "wb"); + if (fp == NULL) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + PyMarshal_WriteLongToFile(value, fp, version); + + fclose(fp); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_NONE; +} + +static PyObject* +pymarshal_write_object_to_file(PyObject* self, PyObject *args) +{ + PyObject *obj; + char *filename; + int version; + FILE *fp; + + if (!PyArg_ParseTuple(args, "Osi:pymarshal_write_object_to_file", + &obj, &filename, &version)) + return NULL; + + fp = fopen(filename, "wb"); + if (fp == NULL) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + PyMarshal_WriteObjectToFile(obj, fp, version); + + fclose(fp); + if (PyErr_Occurred()) + return NULL; + Py_RETURN_NONE; +} + +static PyObject* +pymarshal_read_short_from_file(PyObject* self, PyObject *args) +{ + int value; + long pos; + char *filename; + FILE *fp; + + if (!PyArg_ParseTuple(args, "s:pymarshal_read_short_from_file", &filename)) + return NULL; + + fp = fopen(filename, "rb"); + if (fp == NULL) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + value = PyMarshal_ReadShortFromFile(fp); + pos = ftell(fp); + + fclose(fp); + if (PyErr_Occurred()) + return NULL; + return Py_BuildValue("il", value, pos); +} + +static PyObject* +pymarshal_read_long_from_file(PyObject* self, PyObject *args) +{ + long value, pos; + char *filename; + FILE *fp; + + if (!PyArg_ParseTuple(args, "s:pymarshal_read_long_from_file", &filename)) + return NULL; + + fp = fopen(filename, "rb"); + if (fp == NULL) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + value = PyMarshal_ReadLongFromFile(fp); + pos = ftell(fp); + + fclose(fp); + if (PyErr_Occurred()) + return NULL; + return Py_BuildValue("ll", value, pos); +} + +static PyObject* +pymarshal_read_last_object_from_file(PyObject* self, PyObject *args) +{ + PyObject *obj; + long pos; + char *filename; + FILE *fp; + + if (!PyArg_ParseTuple(args, "s:pymarshal_read_last_object_from_file", &filename)) + return NULL; + + fp = fopen(filename, "rb"); + if (fp == NULL) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + obj = PyMarshal_ReadLastObjectFromFile(fp); + pos = ftell(fp); + + fclose(fp); + return Py_BuildValue("Nl", obj, pos); +} + +static PyObject* +pymarshal_read_object_from_file(PyObject* self, PyObject *args) +{ + PyObject *obj; + long pos; + char *filename; + FILE *fp; + + if (!PyArg_ParseTuple(args, "s:pymarshal_read_object_from_file", &filename)) + return NULL; + + fp = fopen(filename, "rb"); + if (fp == NULL) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + + obj = PyMarshal_ReadObjectFromFile(fp); + pos = ftell(fp); + + fclose(fp); + return Py_BuildValue("Nl", obj, pos); +} + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, @@ -1940,6 +2094,18 @@ {"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_O, PyDoc_STR("set_error_class(error_class) -> None")}, #endif + {"pymarshal_write_long_to_file", + pymarshal_write_long_to_file, METH_VARARGS}, + {"pymarshal_write_object_to_file", + pymarshal_write_object_to_file, METH_VARARGS}, + {"pymarshal_read_short_from_file", + pymarshal_read_short_from_file, METH_VARARGS}, + {"pymarshal_read_long_from_file", + pymarshal_read_long_from_file, METH_VARARGS}, + {"pymarshal_read_last_object_from_file", + pymarshal_read_last_object_from_file, METH_VARARGS}, + {"pymarshal_read_object_from_file", + pymarshal_read_object_from_file, METH_VARARGS}, {NULL, NULL} /* sentinel */ };