Commit 4797dbff authored by Serhiy Storchaka's avatar Serhiy Storchaka

Issue #23392: Added tests for marshal C API that works with FILE*.

parent 680362fa
......@@ -6,6 +6,11 @@ import sys
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 @@ class LargeValuesTestCase(unittest.TestCase):
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 @@ def test_main():
ExceptionTestCase,
BugsTestCase,
LargeValuesTestCase,
CAPI_TestCase,
)
if __name__ == "__main__":
......
......@@ -98,6 +98,8 @@ Tools/Demos
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
......
......@@ -9,6 +9,7 @@
#include <float.h>
#include "structmember.h"
#include "datetime.h"
#include "marshal.h"
#ifdef WITH_THREAD
#include "pythread.h"
......@@ -1875,6 +1876,159 @@ exit:
}
#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 @@ static PyMethodDef TestMethods[] = {
{"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 */
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment