Issue #23392: Added tests for marshal C API that works with FILE*.
This commit is contained in:
parent
17d337bc7a
commit
b51813403f
|
@ -7,6 +7,11 @@ import unittest
|
||||||
import os
|
import os
|
||||||
import types
|
import types
|
||||||
|
|
||||||
|
try:
|
||||||
|
import _testcapi
|
||||||
|
except ImportError:
|
||||||
|
_testcapi = None
|
||||||
|
|
||||||
class HelperMixin:
|
class HelperMixin:
|
||||||
def helper(self, sample, *extra):
|
def helper(self, sample, *extra):
|
||||||
new = marshal.loads(marshal.dumps(sample, *extra))
|
new = marshal.loads(marshal.dumps(sample, *extra))
|
||||||
|
@ -434,18 +439,88 @@ class InterningTestCase(unittest.TestCase, HelperMixin):
|
||||||
s2 = sys.intern(s)
|
s2 = sys.intern(s)
|
||||||
self.assertNotEqual(id(s2), id(s))
|
self.assertNotEqual(id(s2), id(s))
|
||||||
|
|
||||||
|
@support.cpython_only
|
||||||
|
@unittest.skipUnless(_testcapi, 'requires _testcapi')
|
||||||
|
class CAPI_TestCase(unittest.TestCase, HelperMixin):
|
||||||
|
|
||||||
|
def test_write_long_to_file(self):
|
||||||
|
for v in range(marshal.version + 1):
|
||||||
|
_testcapi.pymarshal_write_long_to_file(0x12345678, support.TESTFN, v)
|
||||||
|
with open(support.TESTFN, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
support.unlink(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, support.TESTFN, v)
|
||||||
|
with open(support.TESTFN, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
support.unlink(support.TESTFN)
|
||||||
|
self.assertEqual(marshal.loads(data), obj)
|
||||||
|
|
||||||
|
def test_read_short_from_file(self):
|
||||||
|
with open(support.TESTFN, 'wb') as f:
|
||||||
|
f.write(b'\x34\x12xxxx')
|
||||||
|
r, p = _testcapi.pymarshal_read_short_from_file(support.TESTFN)
|
||||||
|
support.unlink(support.TESTFN)
|
||||||
|
self.assertEqual(r, 0x1234)
|
||||||
|
self.assertEqual(p, 2)
|
||||||
|
|
||||||
|
with open(support.TESTFN, 'wb') as f:
|
||||||
|
f.write(b'\x12')
|
||||||
|
with self.assertRaises(EOFError):
|
||||||
|
_testcapi.pymarshal_read_short_from_file(support.TESTFN)
|
||||||
|
support.unlink(support.TESTFN)
|
||||||
|
|
||||||
|
def test_read_long_from_file(self):
|
||||||
|
with open(support.TESTFN, 'wb') as f:
|
||||||
|
f.write(b'\x78\x56\x34\x12xxxx')
|
||||||
|
r, p = _testcapi.pymarshal_read_long_from_file(support.TESTFN)
|
||||||
|
support.unlink(support.TESTFN)
|
||||||
|
self.assertEqual(r, 0x12345678)
|
||||||
|
self.assertEqual(p, 4)
|
||||||
|
|
||||||
|
with open(support.TESTFN, 'wb') as f:
|
||||||
|
f.write(b'\x56\x34\x12')
|
||||||
|
with self.assertRaises(EOFError):
|
||||||
|
_testcapi.pymarshal_read_long_from_file(support.TESTFN)
|
||||||
|
support.unlink(support.TESTFN)
|
||||||
|
|
||||||
|
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(support.TESTFN, 'wb') as f:
|
||||||
|
f.write(data + b'xxxx')
|
||||||
|
r, p = _testcapi.pymarshal_read_last_object_from_file(support.TESTFN)
|
||||||
|
support.unlink(support.TESTFN)
|
||||||
|
self.assertEqual(r, obj)
|
||||||
|
|
||||||
|
with open(support.TESTFN, 'wb') as f:
|
||||||
|
f.write(data[:1])
|
||||||
|
with self.assertRaises(EOFError):
|
||||||
|
_testcapi.pymarshal_read_last_object_from_file(support.TESTFN)
|
||||||
|
support.unlink(support.TESTFN)
|
||||||
|
|
||||||
|
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(support.TESTFN, 'wb') as f:
|
||||||
|
f.write(data + b'xxxx')
|
||||||
|
r, p = _testcapi.pymarshal_read_object_from_file(support.TESTFN)
|
||||||
|
support.unlink(support.TESTFN)
|
||||||
|
self.assertEqual(r, obj)
|
||||||
|
self.assertEqual(p, len(data))
|
||||||
|
|
||||||
|
with open(support.TESTFN, 'wb') as f:
|
||||||
|
f.write(data[:1])
|
||||||
|
with self.assertRaises(EOFError):
|
||||||
|
_testcapi.pymarshal_read_object_from_file(support.TESTFN)
|
||||||
|
support.unlink(support.TESTFN)
|
||||||
|
|
||||||
def test_main():
|
|
||||||
support.run_unittest(IntTestCase,
|
|
||||||
FloatTestCase,
|
|
||||||
StringTestCase,
|
|
||||||
CodeTestCase,
|
|
||||||
ContainerTestCase,
|
|
||||||
ExceptionTestCase,
|
|
||||||
BufferTestCase,
|
|
||||||
BugsTestCase,
|
|
||||||
LargeValuesTestCase,
|
|
||||||
)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_main()
|
unittest.main()
|
||||||
|
|
|
@ -326,6 +326,8 @@ IDLE
|
||||||
Tests
|
Tests
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
- Issue #23392: Added tests for marshal C API that works with FILE*.
|
||||||
|
|
||||||
- Issue #18982: Add tests for CLI of the calendar module.
|
- Issue #18982: Add tests for CLI of the calendar module.
|
||||||
|
|
||||||
- Issue #19548: Added some additional checks to test_codecs to ensure that
|
- Issue #19548: Added some additional checks to test_codecs to ensure that
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
#include "datetime.h"
|
#include "datetime.h"
|
||||||
|
#include "marshal.h"
|
||||||
|
|
||||||
#ifdef WITH_THREAD
|
#ifdef WITH_THREAD
|
||||||
#include "pythread.h"
|
#include "pythread.h"
|
||||||
|
@ -3050,6 +3051,159 @@ exit:
|
||||||
}
|
}
|
||||||
#endif /* WITH_THREAD */
|
#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[] = {
|
static PyMethodDef TestMethods[] = {
|
||||||
{"raise_exception", raise_exception, METH_VARARGS},
|
{"raise_exception", raise_exception, METH_VARARGS},
|
||||||
|
@ -3190,6 +3344,18 @@ static PyMethodDef TestMethods[] = {
|
||||||
{"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_O,
|
{"call_in_temporary_c_thread", call_in_temporary_c_thread, METH_O,
|
||||||
PyDoc_STR("set_error_class(error_class) -> None")},
|
PyDoc_STR("set_error_class(error_class) -> None")},
|
||||||
#endif
|
#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 */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue