Import Upstream version 2.7.18
This commit is contained in:
216
Lib/ctypes/test/__init__.py
Normal file
216
Lib/ctypes/test/__init__.py
Normal file
@@ -0,0 +1,216 @@
|
||||
import os, sys, unittest, getopt, time
|
||||
|
||||
use_resources = []
|
||||
|
||||
import ctypes
|
||||
ctypes_symbols = dir(ctypes)
|
||||
|
||||
def need_symbol(name):
|
||||
return unittest.skipUnless(name in ctypes_symbols,
|
||||
'{!r} is required'.format(name))
|
||||
|
||||
|
||||
class ResourceDenied(unittest.SkipTest):
|
||||
"""Test skipped because it requested a disallowed resource.
|
||||
|
||||
This is raised when a test calls requires() for a resource that
|
||||
has not be enabled. Resources are defined by test modules.
|
||||
"""
|
||||
|
||||
def is_resource_enabled(resource):
|
||||
"""Test whether a resource is enabled.
|
||||
|
||||
If the caller's module is __main__ then automatically return True."""
|
||||
if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
|
||||
return True
|
||||
result = use_resources is not None and \
|
||||
(resource in use_resources or "*" in use_resources)
|
||||
if not result:
|
||||
_unavail[resource] = None
|
||||
return result
|
||||
|
||||
_unavail = {}
|
||||
def requires(resource, msg=None):
|
||||
"""Raise ResourceDenied if the specified resource is not available.
|
||||
|
||||
If the caller's module is __main__ then automatically return True."""
|
||||
# see if the caller's module is __main__ - if so, treat as if
|
||||
# the resource was set
|
||||
if sys._getframe().f_back.f_globals.get("__name__") == "__main__":
|
||||
return
|
||||
if not is_resource_enabled(resource):
|
||||
if msg is None:
|
||||
msg = "Use of the `%s' resource not enabled" % resource
|
||||
raise ResourceDenied(msg)
|
||||
|
||||
def find_package_modules(package, mask):
|
||||
import fnmatch
|
||||
if (hasattr(package, "__loader__") and
|
||||
hasattr(package.__loader__, '_files')):
|
||||
path = package.__name__.replace(".", os.path.sep)
|
||||
mask = os.path.join(path, mask)
|
||||
for fnm in package.__loader__._files.iterkeys():
|
||||
if fnmatch.fnmatchcase(fnm, mask):
|
||||
yield os.path.splitext(fnm)[0].replace(os.path.sep, ".")
|
||||
else:
|
||||
path = package.__path__[0]
|
||||
for fnm in os.listdir(path):
|
||||
if fnmatch.fnmatchcase(fnm, mask):
|
||||
yield "%s.%s" % (package.__name__, os.path.splitext(fnm)[0])
|
||||
|
||||
def get_tests(package, mask, verbosity, exclude=()):
|
||||
"""Return a list of skipped test modules, and a list of test cases."""
|
||||
tests = []
|
||||
skipped = []
|
||||
for modname in find_package_modules(package, mask):
|
||||
if modname.split(".")[-1] in exclude:
|
||||
skipped.append(modname)
|
||||
if verbosity > 1:
|
||||
print >> sys.stderr, "Skipped %s: excluded" % modname
|
||||
continue
|
||||
try:
|
||||
mod = __import__(modname, globals(), locals(), ['*'])
|
||||
except (ResourceDenied, unittest.SkipTest) as detail:
|
||||
skipped.append(modname)
|
||||
if verbosity > 1:
|
||||
print >> sys.stderr, "Skipped %s: %s" % (modname, detail)
|
||||
continue
|
||||
for name in dir(mod):
|
||||
if name.startswith("_"):
|
||||
continue
|
||||
o = getattr(mod, name)
|
||||
if type(o) is type(unittest.TestCase) and issubclass(o, unittest.TestCase):
|
||||
tests.append(o)
|
||||
return skipped, tests
|
||||
|
||||
def usage():
|
||||
print __doc__
|
||||
return 1
|
||||
|
||||
def test_with_refcounts(runner, verbosity, testcase):
|
||||
"""Run testcase several times, tracking reference counts."""
|
||||
import gc
|
||||
import ctypes
|
||||
ptc = ctypes._pointer_type_cache.copy()
|
||||
cfc = ctypes._c_functype_cache.copy()
|
||||
wfc = ctypes._win_functype_cache.copy()
|
||||
|
||||
# when searching for refcount leaks, we have to manually reset any
|
||||
# caches that ctypes has.
|
||||
def cleanup():
|
||||
ctypes._pointer_type_cache = ptc.copy()
|
||||
ctypes._c_functype_cache = cfc.copy()
|
||||
ctypes._win_functype_cache = wfc.copy()
|
||||
gc.collect()
|
||||
|
||||
test = unittest.makeSuite(testcase)
|
||||
for i in range(5):
|
||||
rc = sys.gettotalrefcount()
|
||||
runner.run(test)
|
||||
cleanup()
|
||||
COUNT = 5
|
||||
refcounts = [None] * COUNT
|
||||
for i in range(COUNT):
|
||||
rc = sys.gettotalrefcount()
|
||||
runner.run(test)
|
||||
cleanup()
|
||||
refcounts[i] = sys.gettotalrefcount() - rc
|
||||
if filter(None, refcounts):
|
||||
print "%s leaks:\n\t" % testcase, refcounts
|
||||
elif verbosity:
|
||||
print "%s: ok." % testcase
|
||||
|
||||
class TestRunner(unittest.TextTestRunner):
|
||||
def run(self, test, skipped):
|
||||
"Run the given test case or test suite."
|
||||
# Same as unittest.TextTestRunner.run, except that it reports
|
||||
# skipped tests.
|
||||
result = self._makeResult()
|
||||
startTime = time.time()
|
||||
test(result)
|
||||
stopTime = time.time()
|
||||
timeTaken = stopTime - startTime
|
||||
result.printErrors()
|
||||
self.stream.writeln(result.separator2)
|
||||
run = result.testsRun
|
||||
if _unavail: #skipped:
|
||||
requested = _unavail.keys()
|
||||
requested.sort()
|
||||
self.stream.writeln("Ran %d test%s in %.3fs (%s module%s skipped)" %
|
||||
(run, run != 1 and "s" or "", timeTaken,
|
||||
len(skipped),
|
||||
len(skipped) != 1 and "s" or ""))
|
||||
self.stream.writeln("Unavailable resources: %s" % ", ".join(requested))
|
||||
else:
|
||||
self.stream.writeln("Ran %d test%s in %.3fs" %
|
||||
(run, run != 1 and "s" or "", timeTaken))
|
||||
self.stream.writeln()
|
||||
if not result.wasSuccessful():
|
||||
self.stream.write("FAILED (")
|
||||
failed, errored = map(len, (result.failures, result.errors))
|
||||
if failed:
|
||||
self.stream.write("failures=%d" % failed)
|
||||
if errored:
|
||||
if failed: self.stream.write(", ")
|
||||
self.stream.write("errors=%d" % errored)
|
||||
self.stream.writeln(")")
|
||||
else:
|
||||
self.stream.writeln("OK")
|
||||
return result
|
||||
|
||||
|
||||
def main(*packages):
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], "rqvu:x:")
|
||||
except getopt.error:
|
||||
return usage()
|
||||
|
||||
verbosity = 1
|
||||
search_leaks = False
|
||||
exclude = []
|
||||
for flag, value in opts:
|
||||
if flag == "-q":
|
||||
verbosity -= 1
|
||||
elif flag == "-v":
|
||||
verbosity += 1
|
||||
elif flag == "-r":
|
||||
try:
|
||||
sys.gettotalrefcount
|
||||
except AttributeError:
|
||||
print >> sys.stderr, "-r flag requires Python debug build"
|
||||
return -1
|
||||
search_leaks = True
|
||||
elif flag == "-u":
|
||||
use_resources.extend(value.split(","))
|
||||
elif flag == "-x":
|
||||
exclude.extend(value.split(","))
|
||||
|
||||
mask = "test_*.py"
|
||||
if args:
|
||||
mask = args[0]
|
||||
|
||||
for package in packages:
|
||||
run_tests(package, mask, verbosity, search_leaks, exclude)
|
||||
|
||||
|
||||
def run_tests(package, mask, verbosity, search_leaks, exclude):
|
||||
skipped, testcases = get_tests(package, mask, verbosity, exclude)
|
||||
runner = TestRunner(verbosity=verbosity)
|
||||
|
||||
suites = [unittest.makeSuite(o) for o in testcases]
|
||||
suite = unittest.TestSuite(suites)
|
||||
result = runner.run(suite, skipped)
|
||||
|
||||
if search_leaks:
|
||||
# hunt for refcount leaks
|
||||
runner = BasicTestRunner()
|
||||
for t in testcases:
|
||||
test_with_refcounts(runner, verbosity, t)
|
||||
|
||||
return bool(result.errors)
|
||||
|
||||
class BasicTestRunner:
|
||||
def run(self, test):
|
||||
result = unittest.TestResult()
|
||||
test(result)
|
||||
return result
|
||||
19
Lib/ctypes/test/runtests.py
Normal file
19
Lib/ctypes/test/runtests.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""Usage: runtests.py [-q] [-r] [-v] [-u resources] [mask]
|
||||
|
||||
Run all tests found in this directory, and print a summary of the results.
|
||||
Command line flags:
|
||||
-q quiet mode: don't print anything while the tests are running
|
||||
-r run tests repeatedly, look for refcount leaks
|
||||
-u<resources>
|
||||
Add resources to the lits of allowed resources. '*' allows all
|
||||
resources.
|
||||
-v verbose mode: print the test currently executed
|
||||
-x<test1[,test2...]>
|
||||
Exclude specified tests.
|
||||
mask mask to select filenames containing testcases, wildcards allowed
|
||||
"""
|
||||
import sys
|
||||
import ctypes.test
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(ctypes.test.main(ctypes.test))
|
||||
73
Lib/ctypes/test/test_anon.py
Normal file
73
Lib/ctypes/test/test_anon.py
Normal file
@@ -0,0 +1,73 @@
|
||||
import unittest
|
||||
from test.support import cpython_only
|
||||
from ctypes import *
|
||||
|
||||
class AnonTest(unittest.TestCase):
|
||||
|
||||
def test_anon(self):
|
||||
class ANON(Union):
|
||||
_fields_ = [("a", c_int),
|
||||
("b", c_int)]
|
||||
|
||||
class Y(Structure):
|
||||
_fields_ = [("x", c_int),
|
||||
("_", ANON),
|
||||
("y", c_int)]
|
||||
_anonymous_ = ["_"]
|
||||
|
||||
self.assertEqual(Y.a.offset, sizeof(c_int))
|
||||
self.assertEqual(Y.b.offset, sizeof(c_int))
|
||||
|
||||
self.assertEqual(ANON.a.offset, 0)
|
||||
self.assertEqual(ANON.b.offset, 0)
|
||||
|
||||
def test_anon_nonseq(self):
|
||||
# TypeError: _anonymous_ must be a sequence
|
||||
self.assertRaises(TypeError,
|
||||
lambda: type(Structure)("Name",
|
||||
(Structure,),
|
||||
{"_fields_": [], "_anonymous_": 42}))
|
||||
|
||||
def test_anon_nonmember(self):
|
||||
# AttributeError: type object 'Name' has no attribute 'x'
|
||||
self.assertRaises(AttributeError,
|
||||
lambda: type(Structure)("Name",
|
||||
(Structure,),
|
||||
{"_fields_": [],
|
||||
"_anonymous_": ["x"]}))
|
||||
|
||||
@cpython_only
|
||||
def test_issue31490(self):
|
||||
# There shouldn't be an assertion failure in case the class has an
|
||||
# attribute whose name is specified in _anonymous_ but not in _fields_.
|
||||
|
||||
# AttributeError: 'x' is specified in _anonymous_ but not in _fields_
|
||||
with self.assertRaises(AttributeError):
|
||||
class Name(Structure):
|
||||
_fields_ = []
|
||||
_anonymous_ = ["x"]
|
||||
x = 42
|
||||
|
||||
def test_nested(self):
|
||||
class ANON_S(Structure):
|
||||
_fields_ = [("a", c_int)]
|
||||
|
||||
class ANON_U(Union):
|
||||
_fields_ = [("_", ANON_S),
|
||||
("b", c_int)]
|
||||
_anonymous_ = ["_"]
|
||||
|
||||
class Y(Structure):
|
||||
_fields_ = [("x", c_int),
|
||||
("_", ANON_U),
|
||||
("y", c_int)]
|
||||
_anonymous_ = ["_"]
|
||||
|
||||
self.assertEqual(Y.x.offset, 0)
|
||||
self.assertEqual(Y.a.offset, sizeof(c_int))
|
||||
self.assertEqual(Y.b.offset, sizeof(c_int))
|
||||
self.assertEqual(Y._.offset, sizeof(c_int))
|
||||
self.assertEqual(Y.y.offset, sizeof(c_int) * 2)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
64
Lib/ctypes/test/test_array_in_pointer.py
Normal file
64
Lib/ctypes/test/test_array_in_pointer.py
Normal file
@@ -0,0 +1,64 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
from binascii import hexlify
|
||||
import re
|
||||
|
||||
def dump(obj):
|
||||
# helper function to dump memory contents in hex, with a hyphen
|
||||
# between the bytes.
|
||||
h = hexlify(memoryview(obj))
|
||||
return re.sub(r"(..)", r"\1-", h)[:-1]
|
||||
|
||||
|
||||
class Value(Structure):
|
||||
_fields_ = [("val", c_byte)]
|
||||
|
||||
class Container(Structure):
|
||||
_fields_ = [("pvalues", POINTER(Value))]
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test(self):
|
||||
# create an array of 4 values
|
||||
val_array = (Value * 4)()
|
||||
|
||||
# create a container, which holds a pointer to the pvalues array.
|
||||
c = Container()
|
||||
c.pvalues = val_array
|
||||
|
||||
# memory contains 4 NUL bytes now, that's correct
|
||||
self.assertEqual("00-00-00-00", dump(val_array))
|
||||
|
||||
# set the values of the array through the pointer:
|
||||
for i in range(4):
|
||||
c.pvalues[i].val = i + 1
|
||||
|
||||
values = [c.pvalues[i].val for i in range(4)]
|
||||
|
||||
# These are the expected results: here s the bug!
|
||||
self.assertEqual(
|
||||
(values, dump(val_array)),
|
||||
([1, 2, 3, 4], "01-02-03-04")
|
||||
)
|
||||
|
||||
def test_2(self):
|
||||
|
||||
val_array = (Value * 4)()
|
||||
|
||||
# memory contains 4 NUL bytes now, that's correct
|
||||
self.assertEqual("00-00-00-00", dump(val_array))
|
||||
|
||||
ptr = cast(val_array, POINTER(Value))
|
||||
# set the values of the array through the pointer:
|
||||
for i in range(4):
|
||||
ptr[i].val = i + 1
|
||||
|
||||
values = [ptr[i].val for i in range(4)]
|
||||
|
||||
# These are the expected results: here s the bug!
|
||||
self.assertEqual(
|
||||
(values, dump(val_array)),
|
||||
([1, 2, 3, 4], "01-02-03-04")
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
164
Lib/ctypes/test/test_arrays.py
Normal file
164
Lib/ctypes/test/test_arrays.py
Normal file
@@ -0,0 +1,164 @@
|
||||
import unittest
|
||||
from test.support import precisionbigmemtest, _2G
|
||||
import sys
|
||||
from ctypes import *
|
||||
|
||||
from ctypes.test import need_symbol
|
||||
|
||||
formats = "bBhHiIlLqQfd"
|
||||
|
||||
formats = c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint, \
|
||||
c_long, c_ulonglong, c_float, c_double, c_longdouble
|
||||
|
||||
class ArrayTestCase(unittest.TestCase):
|
||||
def test_simple(self):
|
||||
# create classes holding simple numeric types, and check
|
||||
# various properties.
|
||||
|
||||
init = range(15, 25)
|
||||
|
||||
for fmt in formats:
|
||||
alen = len(init)
|
||||
int_array = ARRAY(fmt, alen)
|
||||
|
||||
ia = int_array(*init)
|
||||
# length of instance ok?
|
||||
self.assertEqual(len(ia), alen)
|
||||
|
||||
# slot values ok?
|
||||
values = [ia[i] for i in range(alen)]
|
||||
self.assertEqual(values, init)
|
||||
|
||||
# out-of-bounds accesses should be caught
|
||||
with self.assertRaises(IndexError): ia[alen]
|
||||
with self.assertRaises(IndexError): ia[-alen-1]
|
||||
|
||||
# change the items
|
||||
from operator import setitem
|
||||
new_values = range(42, 42+alen)
|
||||
[setitem(ia, n, new_values[n]) for n in range(alen)]
|
||||
values = [ia[i] for i in range(alen)]
|
||||
self.assertEqual(values, new_values)
|
||||
|
||||
# are the items initialized to 0?
|
||||
ia = int_array()
|
||||
values = [ia[i] for i in range(alen)]
|
||||
self.assertEqual(values, [0] * alen)
|
||||
|
||||
# Too many initializers should be caught
|
||||
self.assertRaises(IndexError, int_array, *range(alen*2))
|
||||
|
||||
CharArray = ARRAY(c_char, 3)
|
||||
|
||||
ca = CharArray("a", "b", "c")
|
||||
|
||||
# Should this work? It doesn't:
|
||||
# CharArray("abc")
|
||||
self.assertRaises(TypeError, CharArray, "abc")
|
||||
|
||||
self.assertEqual(ca[0], "a")
|
||||
self.assertEqual(ca[1], "b")
|
||||
self.assertEqual(ca[2], "c")
|
||||
self.assertEqual(ca[-3], "a")
|
||||
self.assertEqual(ca[-2], "b")
|
||||
self.assertEqual(ca[-1], "c")
|
||||
|
||||
self.assertEqual(len(ca), 3)
|
||||
|
||||
# slicing is now supported, but not extended slicing (3-argument)!
|
||||
from operator import getslice, delitem
|
||||
self.assertRaises(TypeError, getslice, ca, 0, 1, -1)
|
||||
|
||||
# cannot delete items
|
||||
self.assertRaises(TypeError, delitem, ca, 0)
|
||||
|
||||
def test_numeric_arrays(self):
|
||||
|
||||
alen = 5
|
||||
|
||||
numarray = ARRAY(c_int, alen)
|
||||
|
||||
na = numarray()
|
||||
values = [na[i] for i in range(alen)]
|
||||
self.assertEqual(values, [0] * alen)
|
||||
|
||||
na = numarray(*[c_int()] * alen)
|
||||
values = [na[i] for i in range(alen)]
|
||||
self.assertEqual(values, [0]*alen)
|
||||
|
||||
na = numarray(1, 2, 3, 4, 5)
|
||||
values = [i for i in na]
|
||||
self.assertEqual(values, [1, 2, 3, 4, 5])
|
||||
|
||||
na = numarray(*map(c_int, (1, 2, 3, 4, 5)))
|
||||
values = [i for i in na]
|
||||
self.assertEqual(values, [1, 2, 3, 4, 5])
|
||||
|
||||
def test_classcache(self):
|
||||
self.assertIsNot(ARRAY(c_int, 3), ARRAY(c_int, 4))
|
||||
self.assertIs(ARRAY(c_int, 3), ARRAY(c_int, 3))
|
||||
|
||||
def test_from_address(self):
|
||||
# Failed with 0.9.8, reported by JUrner
|
||||
p = create_string_buffer("foo")
|
||||
sz = (c_char * 3).from_address(addressof(p))
|
||||
self.assertEqual(sz[:], "foo")
|
||||
self.assertEqual(sz[::], "foo")
|
||||
self.assertEqual(sz[::-1], "oof")
|
||||
self.assertEqual(sz[::3], "f")
|
||||
self.assertEqual(sz[1:4:2], "o")
|
||||
self.assertEqual(sz.value, "foo")
|
||||
|
||||
@need_symbol('create_unicode_buffer')
|
||||
def test_from_addressW(self):
|
||||
p = create_unicode_buffer("foo")
|
||||
sz = (c_wchar * 3).from_address(addressof(p))
|
||||
self.assertEqual(sz[:], "foo")
|
||||
self.assertEqual(sz[::], "foo")
|
||||
self.assertEqual(sz[::-1], "oof")
|
||||
self.assertEqual(sz[::3], "f")
|
||||
self.assertEqual(sz[1:4:2], "o")
|
||||
self.assertEqual(sz.value, "foo")
|
||||
|
||||
def test_cache(self):
|
||||
# Array types are cached internally in the _ctypes extension,
|
||||
# in a WeakValueDictionary. Make sure the array type is
|
||||
# removed from the cache when the itemtype goes away. This
|
||||
# test will not fail, but will show a leak in the testsuite.
|
||||
|
||||
# Create a new type:
|
||||
class my_int(c_int):
|
||||
pass
|
||||
# Create a new array type based on it:
|
||||
t1 = my_int * 1
|
||||
t2 = my_int * 1
|
||||
self.assertIs(t1, t2)
|
||||
|
||||
def test_empty_element_struct(self):
|
||||
class EmptyStruct(Structure):
|
||||
_fields_ = []
|
||||
|
||||
obj = (EmptyStruct * 2)() # bpo37188: Floating point exception
|
||||
self.assertEqual(sizeof(obj), 0)
|
||||
|
||||
def test_empty_element_array(self):
|
||||
class EmptyArray(Array):
|
||||
_type_ = c_int
|
||||
_length_ = 0
|
||||
|
||||
obj = (EmptyArray * 2)() # bpo37188: Floating point exception
|
||||
self.assertEqual(sizeof(obj), 0)
|
||||
|
||||
def test_bpo36504_signed_int_overflow(self):
|
||||
# The overflow check in PyCArrayType_new() could cause signed integer
|
||||
# overflow.
|
||||
with self.assertRaises(OverflowError):
|
||||
c_char * sys.maxsize * 2
|
||||
|
||||
@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
|
||||
@precisionbigmemtest(size=_2G, memuse=1, dry_run=False)
|
||||
def test_large_array(self, size):
|
||||
a = c_char * size
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
226
Lib/ctypes/test/test_as_parameter.py
Normal file
226
Lib/ctypes/test/test_as_parameter.py
Normal file
@@ -0,0 +1,226 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
import _ctypes_test
|
||||
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
|
||||
try:
|
||||
CALLBACK_FUNCTYPE = WINFUNCTYPE
|
||||
except NameError:
|
||||
# fake to enable this test on Linux
|
||||
CALLBACK_FUNCTYPE = CFUNCTYPE
|
||||
|
||||
class POINT(Structure):
|
||||
_fields_ = [("x", c_int), ("y", c_int)]
|
||||
|
||||
class BasicWrapTestCase(unittest.TestCase):
|
||||
def wrap(self, param):
|
||||
return param
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
def test_wchar_parm(self):
|
||||
f = dll._testfunc_i_bhilfd
|
||||
f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double]
|
||||
result = f(self.wrap(1), self.wrap(u"x"), self.wrap(3), self.wrap(4), self.wrap(5.0), self.wrap(6.0))
|
||||
self.assertEqual(result, 139)
|
||||
self.assertIs(type(result), int)
|
||||
|
||||
def test_pointers(self):
|
||||
f = dll._testfunc_p_p
|
||||
f.restype = POINTER(c_int)
|
||||
f.argtypes = [POINTER(c_int)]
|
||||
|
||||
# This only works if the value c_int(42) passed to the
|
||||
# function is still alive while the pointer (the result) is
|
||||
# used.
|
||||
|
||||
v = c_int(42)
|
||||
|
||||
self.assertEqual(pointer(v).contents.value, 42)
|
||||
result = f(self.wrap(pointer(v)))
|
||||
self.assertEqual(type(result), POINTER(c_int))
|
||||
self.assertEqual(result.contents.value, 42)
|
||||
|
||||
# This on works...
|
||||
result = f(self.wrap(pointer(v)))
|
||||
self.assertEqual(result.contents.value, v.value)
|
||||
|
||||
p = pointer(c_int(99))
|
||||
result = f(self.wrap(p))
|
||||
self.assertEqual(result.contents.value, 99)
|
||||
|
||||
def test_shorts(self):
|
||||
f = dll._testfunc_callback_i_if
|
||||
|
||||
args = []
|
||||
expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048,
|
||||
1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
|
||||
|
||||
def callback(v):
|
||||
args.append(v)
|
||||
return v
|
||||
|
||||
CallBack = CFUNCTYPE(c_int, c_int)
|
||||
|
||||
cb = CallBack(callback)
|
||||
f(self.wrap(2**18), self.wrap(cb))
|
||||
self.assertEqual(args, expected)
|
||||
|
||||
################################################################
|
||||
|
||||
def test_callbacks(self):
|
||||
f = dll._testfunc_callback_i_if
|
||||
f.restype = c_int
|
||||
f.argtypes = None
|
||||
|
||||
MyCallback = CFUNCTYPE(c_int, c_int)
|
||||
|
||||
def callback(value):
|
||||
#print "called back with", value
|
||||
return value
|
||||
|
||||
cb = MyCallback(callback)
|
||||
|
||||
result = f(self.wrap(-10), self.wrap(cb))
|
||||
self.assertEqual(result, -18)
|
||||
|
||||
# test with prototype
|
||||
f.argtypes = [c_int, MyCallback]
|
||||
cb = MyCallback(callback)
|
||||
|
||||
result = f(self.wrap(-10), self.wrap(cb))
|
||||
self.assertEqual(result, -18)
|
||||
|
||||
result = f(self.wrap(-10), self.wrap(cb))
|
||||
self.assertEqual(result, -18)
|
||||
|
||||
AnotherCallback = CALLBACK_FUNCTYPE(c_int, c_int, c_int, c_int, c_int)
|
||||
|
||||
# check that the prototype works: we call f with wrong
|
||||
# argument types
|
||||
cb = AnotherCallback(callback)
|
||||
self.assertRaises(ArgumentError, f, self.wrap(-10), self.wrap(cb))
|
||||
|
||||
def test_callbacks_2(self):
|
||||
# Can also use simple datatypes as argument type specifiers
|
||||
# for the callback function.
|
||||
# In this case the call receives an instance of that type
|
||||
f = dll._testfunc_callback_i_if
|
||||
f.restype = c_int
|
||||
|
||||
MyCallback = CFUNCTYPE(c_int, c_int)
|
||||
|
||||
f.argtypes = [c_int, MyCallback]
|
||||
|
||||
def callback(value):
|
||||
#print "called back with", value
|
||||
self.assertEqual(type(value), int)
|
||||
return value
|
||||
|
||||
cb = MyCallback(callback)
|
||||
result = f(self.wrap(-10), self.wrap(cb))
|
||||
self.assertEqual(result, -18)
|
||||
|
||||
def test_longlong_callbacks(self):
|
||||
|
||||
f = dll._testfunc_callback_q_qf
|
||||
f.restype = c_longlong
|
||||
|
||||
MyCallback = CFUNCTYPE(c_longlong, c_longlong)
|
||||
|
||||
f.argtypes = [c_longlong, MyCallback]
|
||||
|
||||
def callback(value):
|
||||
self.assertIsInstance(value, (int, long))
|
||||
return value & 0x7FFFFFFF
|
||||
|
||||
cb = MyCallback(callback)
|
||||
|
||||
self.assertEqual(13577625587, int(f(self.wrap(1000000000000), self.wrap(cb))))
|
||||
|
||||
def test_byval(self):
|
||||
# without prototype
|
||||
ptin = POINT(1, 2)
|
||||
ptout = POINT()
|
||||
# EXPORT int _testfunc_byval(point in, point *pout)
|
||||
result = dll._testfunc_byval(ptin, byref(ptout))
|
||||
got = result, ptout.x, ptout.y
|
||||
expected = 3, 1, 2
|
||||
self.assertEqual(got, expected)
|
||||
|
||||
# with prototype
|
||||
ptin = POINT(101, 102)
|
||||
ptout = POINT()
|
||||
dll._testfunc_byval.argtypes = (POINT, POINTER(POINT))
|
||||
dll._testfunc_byval.restype = c_int
|
||||
result = dll._testfunc_byval(self.wrap(ptin), byref(ptout))
|
||||
got = result, ptout.x, ptout.y
|
||||
expected = 203, 101, 102
|
||||
self.assertEqual(got, expected)
|
||||
|
||||
def test_struct_return_2H(self):
|
||||
class S2H(Structure):
|
||||
_fields_ = [("x", c_short),
|
||||
("y", c_short)]
|
||||
dll.ret_2h_func.restype = S2H
|
||||
dll.ret_2h_func.argtypes = [S2H]
|
||||
inp = S2H(99, 88)
|
||||
s2h = dll.ret_2h_func(self.wrap(inp))
|
||||
self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
|
||||
|
||||
def test_struct_return_8H(self):
|
||||
class S8I(Structure):
|
||||
_fields_ = [("a", c_int),
|
||||
("b", c_int),
|
||||
("c", c_int),
|
||||
("d", c_int),
|
||||
("e", c_int),
|
||||
("f", c_int),
|
||||
("g", c_int),
|
||||
("h", c_int)]
|
||||
dll.ret_8i_func.restype = S8I
|
||||
dll.ret_8i_func.argtypes = [S8I]
|
||||
inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
|
||||
s8i = dll.ret_8i_func(self.wrap(inp))
|
||||
self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
|
||||
(9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
|
||||
|
||||
def test_recursive_as_param(self):
|
||||
from ctypes import c_int
|
||||
|
||||
class A(object):
|
||||
pass
|
||||
|
||||
a = A()
|
||||
a._as_parameter_ = a
|
||||
with self.assertRaises(RuntimeError):
|
||||
c_int.from_param(a)
|
||||
|
||||
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class AsParamWrapper(object):
|
||||
def __init__(self, param):
|
||||
self._as_parameter_ = param
|
||||
|
||||
class AsParamWrapperTestCase(BasicWrapTestCase):
|
||||
wrap = AsParamWrapper
|
||||
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class AsParamPropertyWrapper(object):
|
||||
def __init__(self, param):
|
||||
self._param = param
|
||||
|
||||
def getParameter(self):
|
||||
return self._param
|
||||
_as_parameter_ = property(getParameter)
|
||||
|
||||
class AsParamPropertyWrapperTestCase(BasicWrapTestCase):
|
||||
wrap = AsParamPropertyWrapper
|
||||
|
||||
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
291
Lib/ctypes/test/test_bitfields.py
Normal file
291
Lib/ctypes/test/test_bitfields.py
Normal file
@@ -0,0 +1,291 @@
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
import unittest
|
||||
import os
|
||||
|
||||
import ctypes
|
||||
import _ctypes_test
|
||||
|
||||
class BITS(Structure):
|
||||
_fields_ = [("A", c_int, 1),
|
||||
("B", c_int, 2),
|
||||
("C", c_int, 3),
|
||||
("D", c_int, 4),
|
||||
("E", c_int, 5),
|
||||
("F", c_int, 6),
|
||||
("G", c_int, 7),
|
||||
("H", c_int, 8),
|
||||
("I", c_int, 9),
|
||||
|
||||
("M", c_short, 1),
|
||||
("N", c_short, 2),
|
||||
("O", c_short, 3),
|
||||
("P", c_short, 4),
|
||||
("Q", c_short, 5),
|
||||
("R", c_short, 6),
|
||||
("S", c_short, 7)]
|
||||
|
||||
func = CDLL(_ctypes_test.__file__).unpack_bitfields
|
||||
func.argtypes = POINTER(BITS), c_char
|
||||
|
||||
##for n in "ABCDEFGHIMNOPQRS":
|
||||
## print n, hex(getattr(BITS, n).size), getattr(BITS, n).offset
|
||||
|
||||
class C_Test(unittest.TestCase):
|
||||
|
||||
def test_ints(self):
|
||||
for i in range(512):
|
||||
for name in "ABCDEFGHI":
|
||||
b = BITS()
|
||||
setattr(b, name, i)
|
||||
self.assertEqual((name, i, getattr(b, name)), (name, i, func(byref(b), name)))
|
||||
|
||||
def test_shorts(self):
|
||||
for i in range(256):
|
||||
for name in "MNOPQRS":
|
||||
b = BITS()
|
||||
setattr(b, name, i)
|
||||
self.assertEqual((name, i, getattr(b, name)), (name, i, func(byref(b), name)))
|
||||
|
||||
signed_int_types = (c_byte, c_short, c_int, c_long, c_longlong)
|
||||
unsigned_int_types = (c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong)
|
||||
int_types = unsigned_int_types + signed_int_types
|
||||
|
||||
class BitFieldTest(unittest.TestCase):
|
||||
|
||||
def test_longlong(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_longlong, 1),
|
||||
("b", c_longlong, 62),
|
||||
("c", c_longlong, 1)]
|
||||
|
||||
self.assertEqual(sizeof(X), sizeof(c_longlong))
|
||||
x = X()
|
||||
x.a, x.b, x.c = -1, 7, -1
|
||||
self.assertEqual((x.a, x.b, x.c), (-1, 7, -1))
|
||||
|
||||
def test_ulonglong(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_ulonglong, 1),
|
||||
("b", c_ulonglong, 62),
|
||||
("c", c_ulonglong, 1)]
|
||||
|
||||
self.assertEqual(sizeof(X), sizeof(c_longlong))
|
||||
x = X()
|
||||
self.assertEqual((x.a, x.b, x.c), (0, 0, 0))
|
||||
x.a, x.b, x.c = 7, 7, 7
|
||||
self.assertEqual((x.a, x.b, x.c), (1, 7, 1))
|
||||
|
||||
def test_signed(self):
|
||||
for c_typ in signed_int_types:
|
||||
class X(Structure):
|
||||
_fields_ = [("dummy", c_typ),
|
||||
("a", c_typ, 3),
|
||||
("b", c_typ, 3),
|
||||
("c", c_typ, 1)]
|
||||
self.assertEqual(sizeof(X), sizeof(c_typ)*2)
|
||||
|
||||
x = X()
|
||||
self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 0, 0))
|
||||
x.a = -1
|
||||
self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, -1, 0, 0))
|
||||
x.a, x.b = 0, -1
|
||||
self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, -1, 0))
|
||||
|
||||
|
||||
def test_unsigned(self):
|
||||
for c_typ in unsigned_int_types:
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_typ, 3),
|
||||
("b", c_typ, 3),
|
||||
("c", c_typ, 1)]
|
||||
self.assertEqual(sizeof(X), sizeof(c_typ))
|
||||
|
||||
x = X()
|
||||
self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 0, 0))
|
||||
x.a = -1
|
||||
self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 7, 0, 0))
|
||||
x.a, x.b = 0, -1
|
||||
self.assertEqual((c_typ, x.a, x.b, x.c), (c_typ, 0, 7, 0))
|
||||
|
||||
|
||||
def fail_fields(self, *fields):
|
||||
return self.get_except(type(Structure), "X", (),
|
||||
{"_fields_": fields})
|
||||
|
||||
def test_nonint_types(self):
|
||||
# bit fields are not allowed on non-integer types.
|
||||
result = self.fail_fields(("a", c_char_p, 1))
|
||||
self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char_p'))
|
||||
|
||||
result = self.fail_fields(("a", c_void_p, 1))
|
||||
self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_void_p'))
|
||||
|
||||
if c_int != c_long:
|
||||
result = self.fail_fields(("a", POINTER(c_int), 1))
|
||||
self.assertEqual(result, (TypeError, 'bit fields not allowed for type LP_c_int'))
|
||||
|
||||
result = self.fail_fields(("a", c_char, 1))
|
||||
self.assertEqual(result, (TypeError, 'bit fields not allowed for type c_char'))
|
||||
|
||||
class Dummy(Structure):
|
||||
_fields_ = []
|
||||
|
||||
result = self.fail_fields(("a", Dummy, 1))
|
||||
self.assertEqual(result, (TypeError, 'bit fields not allowed for type Dummy'))
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
def test_c_wchar(self):
|
||||
result = self.fail_fields(("a", c_wchar, 1))
|
||||
self.assertEqual(result,
|
||||
(TypeError, 'bit fields not allowed for type c_wchar'))
|
||||
|
||||
def test_single_bitfield_size(self):
|
||||
for c_typ in int_types:
|
||||
result = self.fail_fields(("a", c_typ, -1))
|
||||
self.assertEqual(result, (ValueError, 'number of bits invalid for bit field'))
|
||||
|
||||
result = self.fail_fields(("a", c_typ, 0))
|
||||
self.assertEqual(result, (ValueError, 'number of bits invalid for bit field'))
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_typ, 1)]
|
||||
self.assertEqual(sizeof(X), sizeof(c_typ))
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_typ, sizeof(c_typ)*8)]
|
||||
self.assertEqual(sizeof(X), sizeof(c_typ))
|
||||
|
||||
result = self.fail_fields(("a", c_typ, sizeof(c_typ)*8 + 1))
|
||||
self.assertEqual(result, (ValueError, 'number of bits invalid for bit field'))
|
||||
|
||||
def test_multi_bitfields_size(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_short, 1),
|
||||
("b", c_short, 14),
|
||||
("c", c_short, 1)]
|
||||
self.assertEqual(sizeof(X), sizeof(c_short))
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_short, 1),
|
||||
("a1", c_short),
|
||||
("b", c_short, 14),
|
||||
("c", c_short, 1)]
|
||||
self.assertEqual(sizeof(X), sizeof(c_short)*3)
|
||||
self.assertEqual(X.a.offset, 0)
|
||||
self.assertEqual(X.a1.offset, sizeof(c_short))
|
||||
self.assertEqual(X.b.offset, sizeof(c_short)*2)
|
||||
self.assertEqual(X.c.offset, sizeof(c_short)*2)
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_short, 3),
|
||||
("b", c_short, 14),
|
||||
("c", c_short, 14)]
|
||||
self.assertEqual(sizeof(X), sizeof(c_short)*3)
|
||||
self.assertEqual(X.a.offset, sizeof(c_short)*0)
|
||||
self.assertEqual(X.b.offset, sizeof(c_short)*1)
|
||||
self.assertEqual(X.c.offset, sizeof(c_short)*2)
|
||||
|
||||
|
||||
def get_except(self, func, *args, **kw):
|
||||
try:
|
||||
func(*args, **kw)
|
||||
except Exception, detail:
|
||||
return detail.__class__, str(detail)
|
||||
|
||||
def test_mixed_1(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_byte, 4),
|
||||
("b", c_int, 4)]
|
||||
if os.name in ("nt", "ce"):
|
||||
self.assertEqual(sizeof(X), sizeof(c_int)*2)
|
||||
else:
|
||||
self.assertEqual(sizeof(X), sizeof(c_int))
|
||||
|
||||
def test_mixed_2(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_byte, 4),
|
||||
("b", c_int, 32)]
|
||||
self.assertEqual(sizeof(X), alignment(c_int)+sizeof(c_int))
|
||||
|
||||
def test_mixed_3(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_byte, 4),
|
||||
("b", c_ubyte, 4)]
|
||||
self.assertEqual(sizeof(X), sizeof(c_byte))
|
||||
|
||||
def test_mixed_4(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_short, 4),
|
||||
("b", c_short, 4),
|
||||
("c", c_int, 24),
|
||||
("d", c_short, 4),
|
||||
("e", c_short, 4),
|
||||
("f", c_int, 24)]
|
||||
# MSVC does NOT combine c_short and c_int into one field, GCC
|
||||
# does (unless GCC is run with '-mms-bitfields' which
|
||||
# produces code compatible with MSVC).
|
||||
if os.name in ("nt", "ce"):
|
||||
self.assertEqual(sizeof(X), sizeof(c_int) * 4)
|
||||
else:
|
||||
self.assertEqual(sizeof(X), sizeof(c_int) * 2)
|
||||
|
||||
def test_anon_bitfields(self):
|
||||
# anonymous bit-fields gave a strange error message
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_byte, 4),
|
||||
("b", c_ubyte, 4)]
|
||||
class Y(Structure):
|
||||
_anonymous_ = ["_"]
|
||||
_fields_ = [("_", X)]
|
||||
|
||||
@need_symbol('c_uint32')
|
||||
def test_uint32(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_uint32, 32)]
|
||||
x = X()
|
||||
x.a = 10
|
||||
self.assertEqual(x.a, 10)
|
||||
x.a = 0xFDCBA987
|
||||
self.assertEqual(x.a, 0xFDCBA987)
|
||||
|
||||
@need_symbol('c_uint64')
|
||||
def test_uint64(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_uint64, 64)]
|
||||
x = X()
|
||||
x.a = 10
|
||||
self.assertEqual(x.a, 10)
|
||||
x.a = 0xFEDCBA9876543211
|
||||
self.assertEqual(x.a, 0xFEDCBA9876543211)
|
||||
|
||||
@need_symbol('c_uint32')
|
||||
def test_uint32_swap_little_endian(self):
|
||||
# Issue #23319
|
||||
class Little(LittleEndianStructure):
|
||||
_fields_ = [("a", c_uint32, 24),
|
||||
("b", c_uint32, 4),
|
||||
("c", c_uint32, 4)]
|
||||
b = bytearray(4)
|
||||
x = Little.from_buffer(b)
|
||||
x.a = 0xabcdef
|
||||
x.b = 1
|
||||
x.c = 2
|
||||
self.assertEqual(b, b'\xef\xcd\xab\x21')
|
||||
|
||||
@need_symbol('c_uint32')
|
||||
def test_uint32_swap_big_endian(self):
|
||||
# Issue #23319
|
||||
class Big(BigEndianStructure):
|
||||
_fields_ = [("a", c_uint32, 24),
|
||||
("b", c_uint32, 4),
|
||||
("c", c_uint32, 4)]
|
||||
b = bytearray(4)
|
||||
x = Big.from_buffer(b)
|
||||
x.a = 0xabcdef
|
||||
x.b = 1
|
||||
x.c = 2
|
||||
self.assertEqual(b, b'\xab\xcd\xef\x12')
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
72
Lib/ctypes/test/test_buffers.py
Normal file
72
Lib/ctypes/test/test_buffers.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
import unittest
|
||||
|
||||
class StringBufferTestCase(unittest.TestCase):
|
||||
|
||||
def test_buffer(self):
|
||||
b = create_string_buffer(32)
|
||||
self.assertEqual(len(b), 32)
|
||||
self.assertEqual(sizeof(b), 32 * sizeof(c_char))
|
||||
self.assertIs(type(b[0]), str)
|
||||
|
||||
b = create_string_buffer("abc")
|
||||
self.assertEqual(len(b), 4) # trailing nul char
|
||||
self.assertEqual(sizeof(b), 4 * sizeof(c_char))
|
||||
self.assertIs(type(b[0]), str)
|
||||
self.assertEqual(b[0], "a")
|
||||
self.assertEqual(b[:], "abc\0")
|
||||
self.assertEqual(b[::], "abc\0")
|
||||
self.assertEqual(b[::-1], "\0cba")
|
||||
self.assertEqual(b[::2], "ac")
|
||||
self.assertEqual(b[::5], "a")
|
||||
|
||||
def test_buffer_interface(self):
|
||||
self.assertEqual(len(bytearray(create_string_buffer(0))), 0)
|
||||
self.assertEqual(len(bytearray(create_string_buffer(1))), 1)
|
||||
|
||||
def test_string_conversion(self):
|
||||
b = create_string_buffer(u"abc")
|
||||
self.assertEqual(len(b), 4) # trailing nul char
|
||||
self.assertEqual(sizeof(b), 4 * sizeof(c_char))
|
||||
self.assertTrue(type(b[0]) is str)
|
||||
self.assertEqual(b[0], "a")
|
||||
self.assertEqual(b[:], "abc\0")
|
||||
self.assertEqual(b[::], "abc\0")
|
||||
self.assertEqual(b[::-1], "\0cba")
|
||||
self.assertEqual(b[::2], "ac")
|
||||
self.assertEqual(b[::5], "a")
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
def test_unicode_buffer(self):
|
||||
b = create_unicode_buffer(32)
|
||||
self.assertEqual(len(b), 32)
|
||||
self.assertEqual(sizeof(b), 32 * sizeof(c_wchar))
|
||||
self.assertIs(type(b[0]), unicode)
|
||||
|
||||
b = create_unicode_buffer(u"abc")
|
||||
self.assertEqual(len(b), 4) # trailing nul char
|
||||
self.assertEqual(sizeof(b), 4 * sizeof(c_wchar))
|
||||
self.assertIs(type(b[0]), unicode)
|
||||
self.assertEqual(b[0], u"a")
|
||||
self.assertEqual(b[:], "abc\0")
|
||||
self.assertEqual(b[::], "abc\0")
|
||||
self.assertEqual(b[::-1], "\0cba")
|
||||
self.assertEqual(b[::2], "ac")
|
||||
self.assertEqual(b[::5], "a")
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
def test_unicode_conversion(self):
|
||||
b = create_unicode_buffer("abc")
|
||||
self.assertEqual(len(b), 4) # trailing nul char
|
||||
self.assertEqual(sizeof(b), 4 * sizeof(c_wchar))
|
||||
self.assertIs(type(b[0]), unicode)
|
||||
self.assertEqual(b[0], u"a")
|
||||
self.assertEqual(b[:], "abc\0")
|
||||
self.assertEqual(b[::], "abc\0")
|
||||
self.assertEqual(b[::-1], "\0cba")
|
||||
self.assertEqual(b[::2], "ac")
|
||||
self.assertEqual(b[::5], "a")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
295
Lib/ctypes/test/test_byteswap.py
Normal file
295
Lib/ctypes/test/test_byteswap.py
Normal file
@@ -0,0 +1,295 @@
|
||||
import sys, unittest, struct, math, ctypes
|
||||
from binascii import hexlify
|
||||
|
||||
from ctypes import *
|
||||
|
||||
def bin(s):
|
||||
return hexlify(memoryview(s)).upper()
|
||||
|
||||
# Each *simple* type that supports different byte orders has an
|
||||
# __ctype_be__ attribute that specifies the same type in BIG ENDIAN
|
||||
# byte order, and a __ctype_le__ attribute that is the same type in
|
||||
# LITTLE ENDIAN byte order.
|
||||
#
|
||||
# For Structures and Unions, these types are created on demand.
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
@unittest.skip('test disabled')
|
||||
def test_X(self):
|
||||
print >> sys.stderr, sys.byteorder
|
||||
for i in range(32):
|
||||
bits = BITS()
|
||||
setattr(bits, "i%s" % i, 1)
|
||||
dump(bits)
|
||||
|
||||
def test_endian_short(self):
|
||||
if sys.byteorder == "little":
|
||||
self.assertIs(c_short.__ctype_le__, c_short)
|
||||
self.assertIs(c_short.__ctype_be__.__ctype_le__, c_short)
|
||||
else:
|
||||
self.assertIs(c_short.__ctype_be__, c_short)
|
||||
self.assertIs(c_short.__ctype_le__.__ctype_be__, c_short)
|
||||
s = c_short.__ctype_be__(0x1234)
|
||||
self.assertEqual(bin(struct.pack(">h", 0x1234)), "1234")
|
||||
self.assertEqual(bin(s), "1234")
|
||||
self.assertEqual(s.value, 0x1234)
|
||||
|
||||
s = c_short.__ctype_le__(0x1234)
|
||||
self.assertEqual(bin(struct.pack("<h", 0x1234)), "3412")
|
||||
self.assertEqual(bin(s), "3412")
|
||||
self.assertEqual(s.value, 0x1234)
|
||||
|
||||
s = c_ushort.__ctype_be__(0x1234)
|
||||
self.assertEqual(bin(struct.pack(">h", 0x1234)), "1234")
|
||||
self.assertEqual(bin(s), "1234")
|
||||
self.assertEqual(s.value, 0x1234)
|
||||
|
||||
s = c_ushort.__ctype_le__(0x1234)
|
||||
self.assertEqual(bin(struct.pack("<h", 0x1234)), "3412")
|
||||
self.assertEqual(bin(s), "3412")
|
||||
self.assertEqual(s.value, 0x1234)
|
||||
|
||||
def test_endian_int(self):
|
||||
if sys.byteorder == "little":
|
||||
self.assertIs(c_int.__ctype_le__, c_int)
|
||||
self.assertIs(c_int.__ctype_be__.__ctype_le__, c_int)
|
||||
else:
|
||||
self.assertIs(c_int.__ctype_be__, c_int)
|
||||
self.assertIs(c_int.__ctype_le__.__ctype_be__, c_int)
|
||||
|
||||
s = c_int.__ctype_be__(0x12345678)
|
||||
self.assertEqual(bin(struct.pack(">i", 0x12345678)), "12345678")
|
||||
self.assertEqual(bin(s), "12345678")
|
||||
self.assertEqual(s.value, 0x12345678)
|
||||
|
||||
s = c_int.__ctype_le__(0x12345678)
|
||||
self.assertEqual(bin(struct.pack("<i", 0x12345678)), "78563412")
|
||||
self.assertEqual(bin(s), "78563412")
|
||||
self.assertEqual(s.value, 0x12345678)
|
||||
|
||||
s = c_uint.__ctype_be__(0x12345678)
|
||||
self.assertEqual(bin(struct.pack(">I", 0x12345678)), "12345678")
|
||||
self.assertEqual(bin(s), "12345678")
|
||||
self.assertEqual(s.value, 0x12345678)
|
||||
|
||||
s = c_uint.__ctype_le__(0x12345678)
|
||||
self.assertEqual(bin(struct.pack("<I", 0x12345678)), "78563412")
|
||||
self.assertEqual(bin(s), "78563412")
|
||||
self.assertEqual(s.value, 0x12345678)
|
||||
|
||||
def test_endian_longlong(self):
|
||||
if sys.byteorder == "little":
|
||||
self.assertIs(c_longlong.__ctype_le__, c_longlong)
|
||||
self.assertIs(c_longlong.__ctype_be__.__ctype_le__, c_longlong)
|
||||
else:
|
||||
self.assertIs(c_longlong.__ctype_be__, c_longlong)
|
||||
self.assertIs(c_longlong.__ctype_le__.__ctype_be__, c_longlong)
|
||||
|
||||
s = c_longlong.__ctype_be__(0x1234567890ABCDEF)
|
||||
self.assertEqual(bin(struct.pack(">q", 0x1234567890ABCDEF)), "1234567890ABCDEF")
|
||||
self.assertEqual(bin(s), "1234567890ABCDEF")
|
||||
self.assertEqual(s.value, 0x1234567890ABCDEF)
|
||||
|
||||
s = c_longlong.__ctype_le__(0x1234567890ABCDEF)
|
||||
self.assertEqual(bin(struct.pack("<q", 0x1234567890ABCDEF)), "EFCDAB9078563412")
|
||||
self.assertEqual(bin(s), "EFCDAB9078563412")
|
||||
self.assertEqual(s.value, 0x1234567890ABCDEF)
|
||||
|
||||
s = c_ulonglong.__ctype_be__(0x1234567890ABCDEF)
|
||||
self.assertEqual(bin(struct.pack(">Q", 0x1234567890ABCDEF)), "1234567890ABCDEF")
|
||||
self.assertEqual(bin(s), "1234567890ABCDEF")
|
||||
self.assertEqual(s.value, 0x1234567890ABCDEF)
|
||||
|
||||
s = c_ulonglong.__ctype_le__(0x1234567890ABCDEF)
|
||||
self.assertEqual(bin(struct.pack("<Q", 0x1234567890ABCDEF)), "EFCDAB9078563412")
|
||||
self.assertEqual(bin(s), "EFCDAB9078563412")
|
||||
self.assertEqual(s.value, 0x1234567890ABCDEF)
|
||||
|
||||
def test_endian_float(self):
|
||||
if sys.byteorder == "little":
|
||||
self.assertIs(c_float.__ctype_le__, c_float)
|
||||
self.assertIs(c_float.__ctype_be__.__ctype_le__, c_float)
|
||||
else:
|
||||
self.assertIs(c_float.__ctype_be__, c_float)
|
||||
self.assertIs(c_float.__ctype_le__.__ctype_be__, c_float)
|
||||
s = c_float(math.pi)
|
||||
self.assertEqual(bin(struct.pack("f", math.pi)), bin(s))
|
||||
# Hm, what's the precision of a float compared to a double?
|
||||
self.assertAlmostEqual(s.value, math.pi, 6)
|
||||
s = c_float.__ctype_le__(math.pi)
|
||||
self.assertAlmostEqual(s.value, math.pi, 6)
|
||||
self.assertEqual(bin(struct.pack("<f", math.pi)), bin(s))
|
||||
s = c_float.__ctype_be__(math.pi)
|
||||
self.assertAlmostEqual(s.value, math.pi, 6)
|
||||
self.assertEqual(bin(struct.pack(">f", math.pi)), bin(s))
|
||||
|
||||
def test_endian_double(self):
|
||||
if sys.byteorder == "little":
|
||||
self.assertIs(c_double.__ctype_le__, c_double)
|
||||
self.assertIs(c_double.__ctype_be__.__ctype_le__, c_double)
|
||||
else:
|
||||
self.assertIs(c_double.__ctype_be__, c_double)
|
||||
self.assertIs(c_double.__ctype_le__.__ctype_be__, c_double)
|
||||
s = c_double(math.pi)
|
||||
self.assertEqual(s.value, math.pi)
|
||||
self.assertEqual(bin(struct.pack("d", math.pi)), bin(s))
|
||||
s = c_double.__ctype_le__(math.pi)
|
||||
self.assertEqual(s.value, math.pi)
|
||||
self.assertEqual(bin(struct.pack("<d", math.pi)), bin(s))
|
||||
s = c_double.__ctype_be__(math.pi)
|
||||
self.assertEqual(s.value, math.pi)
|
||||
self.assertEqual(bin(struct.pack(">d", math.pi)), bin(s))
|
||||
|
||||
def test_endian_other(self):
|
||||
self.assertIs(c_byte.__ctype_le__, c_byte)
|
||||
self.assertIs(c_byte.__ctype_be__, c_byte)
|
||||
|
||||
self.assertIs(c_ubyte.__ctype_le__, c_ubyte)
|
||||
self.assertIs(c_ubyte.__ctype_be__, c_ubyte)
|
||||
|
||||
self.assertIs(c_char.__ctype_le__, c_char)
|
||||
self.assertIs(c_char.__ctype_be__, c_char)
|
||||
|
||||
def test_struct_fields_1(self):
|
||||
if sys.byteorder == "little":
|
||||
base = BigEndianStructure
|
||||
else:
|
||||
base = LittleEndianStructure
|
||||
|
||||
class T(base):
|
||||
pass
|
||||
_fields_ = [("a", c_ubyte),
|
||||
("b", c_byte),
|
||||
("c", c_short),
|
||||
("d", c_ushort),
|
||||
("e", c_int),
|
||||
("f", c_uint),
|
||||
("g", c_long),
|
||||
("h", c_ulong),
|
||||
("i", c_longlong),
|
||||
("k", c_ulonglong),
|
||||
("l", c_float),
|
||||
("m", c_double),
|
||||
("n", c_char),
|
||||
|
||||
("b1", c_byte, 3),
|
||||
("b2", c_byte, 3),
|
||||
("b3", c_byte, 2),
|
||||
("a", c_int * 3 * 3 * 3)]
|
||||
T._fields_ = _fields_
|
||||
|
||||
# these fields do not support different byte order:
|
||||
for typ in c_wchar, c_void_p, POINTER(c_int):
|
||||
_fields_.append(("x", typ))
|
||||
class T(base):
|
||||
pass
|
||||
self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)])
|
||||
|
||||
def test_struct_struct(self):
|
||||
# nested structures with different byteorders
|
||||
|
||||
# create nested structures with given byteorders and set memory to data
|
||||
|
||||
for nested, data in (
|
||||
(BigEndianStructure, b'\0\0\0\1\0\0\0\2'),
|
||||
(LittleEndianStructure, b'\1\0\0\0\2\0\0\0'),
|
||||
):
|
||||
for parent in (
|
||||
BigEndianStructure,
|
||||
LittleEndianStructure,
|
||||
Structure,
|
||||
):
|
||||
class NestedStructure(nested):
|
||||
_fields_ = [("x", c_uint32),
|
||||
("y", c_uint32)]
|
||||
|
||||
class TestStructure(parent):
|
||||
_fields_ = [("point", NestedStructure)]
|
||||
|
||||
self.assertEqual(len(data), sizeof(TestStructure))
|
||||
ptr = POINTER(TestStructure)
|
||||
s = cast(data, ptr)[0]
|
||||
del ctypes._pointer_type_cache[TestStructure]
|
||||
self.assertEqual(s.point.x, 1)
|
||||
self.assertEqual(s.point.y, 2)
|
||||
|
||||
def test_struct_fields_2(self):
|
||||
# standard packing in struct uses no alignment.
|
||||
# So, we have to align using pad bytes.
|
||||
#
|
||||
# Unaligned accesses will crash Python (on those platforms that
|
||||
# don't allow it, like sparc solaris).
|
||||
if sys.byteorder == "little":
|
||||
base = BigEndianStructure
|
||||
fmt = ">bxhid"
|
||||
else:
|
||||
base = LittleEndianStructure
|
||||
fmt = "<bxhid"
|
||||
|
||||
class S(base):
|
||||
_fields_ = [("b", c_byte),
|
||||
("h", c_short),
|
||||
("i", c_int),
|
||||
("d", c_double)]
|
||||
|
||||
s1 = S(0x12, 0x1234, 0x12345678, 3.14)
|
||||
s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
|
||||
self.assertEqual(bin(s1), bin(s2))
|
||||
|
||||
def test_unaligned_nonnative_struct_fields(self):
|
||||
if sys.byteorder == "little":
|
||||
base = BigEndianStructure
|
||||
fmt = ">b h xi xd"
|
||||
else:
|
||||
base = LittleEndianStructure
|
||||
fmt = "<b h xi xd"
|
||||
|
||||
class S(base):
|
||||
_pack_ = 1
|
||||
_fields_ = [("b", c_byte),
|
||||
|
||||
("h", c_short),
|
||||
|
||||
("_1", c_byte),
|
||||
("i", c_int),
|
||||
|
||||
("_2", c_byte),
|
||||
("d", c_double)]
|
||||
|
||||
s1 = S()
|
||||
s1.b = 0x12
|
||||
s1.h = 0x1234
|
||||
s1.i = 0x12345678
|
||||
s1.d = 3.14
|
||||
s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
|
||||
self.assertEqual(bin(s1), bin(s2))
|
||||
|
||||
def test_unaligned_native_struct_fields(self):
|
||||
if sys.byteorder == "little":
|
||||
fmt = "<b h xi xd"
|
||||
else:
|
||||
base = LittleEndianStructure
|
||||
fmt = ">b h xi xd"
|
||||
|
||||
class S(Structure):
|
||||
_pack_ = 1
|
||||
_fields_ = [("b", c_byte),
|
||||
|
||||
("h", c_short),
|
||||
|
||||
("_1", c_byte),
|
||||
("i", c_int),
|
||||
|
||||
("_2", c_byte),
|
||||
("d", c_double)]
|
||||
|
||||
s1 = S()
|
||||
s1.b = 0x12
|
||||
s1.h = 0x1234
|
||||
s1.i = 0x12345678
|
||||
s1.d = 3.14
|
||||
s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
|
||||
self.assertEqual(bin(s1), bin(s2))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
299
Lib/ctypes/test/test_callbacks.py
Normal file
299
Lib/ctypes/test/test_callbacks.py
Normal file
@@ -0,0 +1,299 @@
|
||||
import functools
|
||||
import unittest
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
import _ctypes_test
|
||||
|
||||
class Callbacks(unittest.TestCase):
|
||||
functype = CFUNCTYPE
|
||||
|
||||
## def tearDown(self):
|
||||
## import gc
|
||||
## gc.collect()
|
||||
|
||||
def callback(self, *args):
|
||||
self.got_args = args
|
||||
return args[-1]
|
||||
|
||||
def check_type(self, typ, arg):
|
||||
PROTO = self.functype.im_func(typ, typ)
|
||||
result = PROTO(self.callback)(arg)
|
||||
if typ == c_float:
|
||||
self.assertAlmostEqual(result, arg, places=5)
|
||||
else:
|
||||
self.assertEqual(self.got_args, (arg,))
|
||||
self.assertEqual(result, arg)
|
||||
|
||||
PROTO = self.functype.im_func(typ, c_byte, typ)
|
||||
result = PROTO(self.callback)(-3, arg)
|
||||
if typ == c_float:
|
||||
self.assertAlmostEqual(result, arg, places=5)
|
||||
else:
|
||||
self.assertEqual(self.got_args, (-3, arg))
|
||||
self.assertEqual(result, arg)
|
||||
|
||||
################
|
||||
|
||||
def test_byte(self):
|
||||
self.check_type(c_byte, 42)
|
||||
self.check_type(c_byte, -42)
|
||||
|
||||
def test_ubyte(self):
|
||||
self.check_type(c_ubyte, 42)
|
||||
|
||||
def test_short(self):
|
||||
self.check_type(c_short, 42)
|
||||
self.check_type(c_short, -42)
|
||||
|
||||
def test_ushort(self):
|
||||
self.check_type(c_ushort, 42)
|
||||
|
||||
def test_int(self):
|
||||
self.check_type(c_int, 42)
|
||||
self.check_type(c_int, -42)
|
||||
|
||||
def test_uint(self):
|
||||
self.check_type(c_uint, 42)
|
||||
|
||||
def test_long(self):
|
||||
self.check_type(c_long, 42)
|
||||
self.check_type(c_long, -42)
|
||||
|
||||
def test_ulong(self):
|
||||
self.check_type(c_ulong, 42)
|
||||
|
||||
def test_longlong(self):
|
||||
# test some 64-bit values, positive and negative
|
||||
self.check_type(c_longlong, 5948291757245277467)
|
||||
self.check_type(c_longlong, -5229388909784190580)
|
||||
self.check_type(c_longlong, 42)
|
||||
self.check_type(c_longlong, -42)
|
||||
|
||||
def test_ulonglong(self):
|
||||
# test some 64-bit values, with and without msb set.
|
||||
self.check_type(c_ulonglong, 10955412242170339782)
|
||||
self.check_type(c_ulonglong, 3665885499841167458)
|
||||
self.check_type(c_ulonglong, 42)
|
||||
|
||||
def test_float(self):
|
||||
# only almost equal: double -> float -> double
|
||||
import math
|
||||
self.check_type(c_float, math.e)
|
||||
self.check_type(c_float, -math.e)
|
||||
|
||||
def test_double(self):
|
||||
self.check_type(c_double, 3.14)
|
||||
self.check_type(c_double, -3.14)
|
||||
|
||||
def test_longdouble(self):
|
||||
self.check_type(c_longdouble, 3.14)
|
||||
self.check_type(c_longdouble, -3.14)
|
||||
|
||||
def test_char(self):
|
||||
self.check_type(c_char, "x")
|
||||
self.check_type(c_char, "a")
|
||||
|
||||
# disabled: would now (correctly) raise a RuntimeWarning about
|
||||
# a memory leak. A callback function cannot return a non-integral
|
||||
# C type without causing a memory leak.
|
||||
@unittest.skip('test disabled')
|
||||
def test_char_p(self):
|
||||
self.check_type(c_char_p, "abc")
|
||||
self.check_type(c_char_p, "def")
|
||||
|
||||
def test_pyobject(self):
|
||||
o = ()
|
||||
from sys import getrefcount as grc
|
||||
for o in (), [], object():
|
||||
initial = grc(o)
|
||||
# This call leaks a reference to 'o'...
|
||||
self.check_type(py_object, o)
|
||||
before = grc(o)
|
||||
# ...but this call doesn't leak any more. Where is the refcount?
|
||||
self.check_type(py_object, o)
|
||||
after = grc(o)
|
||||
self.assertEqual((after, o), (before, o))
|
||||
|
||||
def test_unsupported_restype_1(self):
|
||||
# Only "fundamental" result types are supported for callback
|
||||
# functions, the type must have a non-NULL stgdict->setfunc.
|
||||
# POINTER(c_double), for example, is not supported.
|
||||
|
||||
prototype = self.functype.im_func(POINTER(c_double))
|
||||
# The type is checked when the prototype is called
|
||||
self.assertRaises(TypeError, prototype, lambda: None)
|
||||
|
||||
def test_unsupported_restype_2(self):
|
||||
prototype = self.functype.im_func(object)
|
||||
self.assertRaises(TypeError, prototype, lambda: None)
|
||||
|
||||
def test_issue_7959(self):
|
||||
proto = self.functype.im_func(None)
|
||||
|
||||
class X(object):
|
||||
def func(self): pass
|
||||
def __init__(self):
|
||||
self.v = proto(self.func)
|
||||
|
||||
import gc
|
||||
for i in range(32):
|
||||
X()
|
||||
gc.collect()
|
||||
live = [x for x in gc.get_objects()
|
||||
if isinstance(x, X)]
|
||||
self.assertEqual(len(live), 0)
|
||||
|
||||
def test_issue12483(self):
|
||||
import gc
|
||||
class Nasty:
|
||||
def __del__(self):
|
||||
gc.collect()
|
||||
CFUNCTYPE(None)(lambda x=Nasty(): None)
|
||||
|
||||
|
||||
@need_symbol('WINFUNCTYPE')
|
||||
class StdcallCallbacks(Callbacks):
|
||||
try:
|
||||
functype = WINFUNCTYPE
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
################################################################
|
||||
|
||||
class SampleCallbacksTestCase(unittest.TestCase):
|
||||
|
||||
def test_integrate(self):
|
||||
# Derived from some then non-working code, posted by David Foster
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
|
||||
# The function prototype called by 'integrate': double func(double);
|
||||
CALLBACK = CFUNCTYPE(c_double, c_double)
|
||||
|
||||
# The integrate function itself, exposed from the _ctypes_test dll
|
||||
integrate = dll.integrate
|
||||
integrate.argtypes = (c_double, c_double, CALLBACK, c_long)
|
||||
integrate.restype = c_double
|
||||
|
||||
def func(x):
|
||||
return x**2
|
||||
|
||||
result = integrate(0.0, 1.0, CALLBACK(func), 10)
|
||||
diff = abs(result - 1./3.)
|
||||
|
||||
self.assertLess(diff, 0.01, "%s not less than 0.01" % diff)
|
||||
|
||||
def test_issue_8959_a(self):
|
||||
from ctypes.util import find_library
|
||||
libc_path = find_library("c")
|
||||
if not libc_path:
|
||||
self.skipTest('could not find libc')
|
||||
libc = CDLL(libc_path)
|
||||
|
||||
@CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
|
||||
def cmp_func(a, b):
|
||||
return a[0] - b[0]
|
||||
|
||||
array = (c_int * 5)(5, 1, 99, 7, 33)
|
||||
|
||||
libc.qsort(array, len(array), sizeof(c_int), cmp_func)
|
||||
self.assertEqual(array[:], [1, 5, 7, 33, 99])
|
||||
|
||||
@need_symbol('WINFUNCTYPE')
|
||||
def test_issue_8959_b(self):
|
||||
from ctypes.wintypes import BOOL, HWND, LPARAM
|
||||
global windowCount
|
||||
windowCount = 0
|
||||
|
||||
@WINFUNCTYPE(BOOL, HWND, LPARAM)
|
||||
def EnumWindowsCallbackFunc(hwnd, lParam):
|
||||
global windowCount
|
||||
windowCount += 1
|
||||
return True #Allow windows to keep enumerating
|
||||
|
||||
windll.user32.EnumWindows(EnumWindowsCallbackFunc, 0)
|
||||
|
||||
def test_callback_register_int(self):
|
||||
# Issue #8275: buggy handling of callback args under Win64
|
||||
# NOTE: should be run on release builds as well
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
CALLBACK = CFUNCTYPE(c_int, c_int, c_int, c_int, c_int, c_int)
|
||||
# All this function does is call the callback with its args squared
|
||||
func = dll._testfunc_cbk_reg_int
|
||||
func.argtypes = (c_int, c_int, c_int, c_int, c_int, CALLBACK)
|
||||
func.restype = c_int
|
||||
|
||||
def callback(a, b, c, d, e):
|
||||
return a + b + c + d + e
|
||||
|
||||
result = func(2, 3, 4, 5, 6, CALLBACK(callback))
|
||||
self.assertEqual(result, callback(2*2, 3*3, 4*4, 5*5, 6*6))
|
||||
|
||||
def test_callback_register_double(self):
|
||||
# Issue #8275: buggy handling of callback args under Win64
|
||||
# NOTE: should be run on release builds as well
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
CALLBACK = CFUNCTYPE(c_double, c_double, c_double, c_double,
|
||||
c_double, c_double)
|
||||
# All this function does is call the callback with its args squared
|
||||
func = dll._testfunc_cbk_reg_double
|
||||
func.argtypes = (c_double, c_double, c_double,
|
||||
c_double, c_double, CALLBACK)
|
||||
func.restype = c_double
|
||||
|
||||
def callback(a, b, c, d, e):
|
||||
return a + b + c + d + e
|
||||
|
||||
result = func(1.1, 2.2, 3.3, 4.4, 5.5, CALLBACK(callback))
|
||||
self.assertEqual(result,
|
||||
callback(1.1*1.1, 2.2*2.2, 3.3*3.3, 4.4*4.4, 5.5*5.5))
|
||||
|
||||
def test_callback_large_struct(self):
|
||||
class Check: pass
|
||||
|
||||
# This should mirror the structure in Modules/_ctypes/_ctypes_test.c
|
||||
class X(Structure):
|
||||
_fields_ = [
|
||||
('first', c_ulong),
|
||||
('second', c_ulong),
|
||||
('third', c_ulong),
|
||||
]
|
||||
|
||||
def callback(check, s):
|
||||
check.first = s.first
|
||||
check.second = s.second
|
||||
check.third = s.third
|
||||
# See issue #29565.
|
||||
# The structure should be passed by value, so
|
||||
# any changes to it should not be reflected in
|
||||
# the value passed
|
||||
s.first = s.second = s.third = 0x0badf00d
|
||||
|
||||
check = Check()
|
||||
s = X()
|
||||
s.first = 0xdeadbeef
|
||||
s.second = 0xcafebabe
|
||||
s.third = 0x0bad1dea
|
||||
|
||||
CALLBACK = CFUNCTYPE(None, X)
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
func = dll._testfunc_cbk_large_struct
|
||||
func.argtypes = (X, CALLBACK)
|
||||
func.restype = None
|
||||
# the function just calls the callback with the passed structure
|
||||
func(s, CALLBACK(functools.partial(callback, check)))
|
||||
self.assertEqual(check.first, s.first)
|
||||
self.assertEqual(check.second, s.second)
|
||||
self.assertEqual(check.third, s.third)
|
||||
self.assertEqual(check.first, 0xdeadbeef)
|
||||
self.assertEqual(check.second, 0xcafebabe)
|
||||
self.assertEqual(check.third, 0x0bad1dea)
|
||||
# See issue #29565.
|
||||
# Ensure that the original struct is unchanged.
|
||||
self.assertEqual(s.first, check.first)
|
||||
self.assertEqual(s.second, check.second)
|
||||
self.assertEqual(s.third, check.third)
|
||||
|
||||
################################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
86
Lib/ctypes/test/test_cast.py
Normal file
86
Lib/ctypes/test/test_cast.py
Normal file
@@ -0,0 +1,86 @@
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
import unittest
|
||||
import sys
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def test_array2pointer(self):
|
||||
array = (c_int * 3)(42, 17, 2)
|
||||
|
||||
# casting an array to a pointer works.
|
||||
ptr = cast(array, POINTER(c_int))
|
||||
self.assertEqual([ptr[i] for i in range(3)], [42, 17, 2])
|
||||
|
||||
if 2*sizeof(c_short) == sizeof(c_int):
|
||||
ptr = cast(array, POINTER(c_short))
|
||||
if sys.byteorder == "little":
|
||||
self.assertEqual([ptr[i] for i in range(6)],
|
||||
[42, 0, 17, 0, 2, 0])
|
||||
else:
|
||||
self.assertEqual([ptr[i] for i in range(6)],
|
||||
[0, 42, 0, 17, 0, 2])
|
||||
|
||||
def test_address2pointer(self):
|
||||
array = (c_int * 3)(42, 17, 2)
|
||||
|
||||
address = addressof(array)
|
||||
ptr = cast(c_void_p(address), POINTER(c_int))
|
||||
self.assertEqual([ptr[i] for i in range(3)], [42, 17, 2])
|
||||
|
||||
ptr = cast(address, POINTER(c_int))
|
||||
self.assertEqual([ptr[i] for i in range(3)], [42, 17, 2])
|
||||
|
||||
def test_p2a_objects(self):
|
||||
array = (c_char_p * 5)()
|
||||
self.assertEqual(array._objects, None)
|
||||
array[0] = "foo bar"
|
||||
self.assertEqual(array._objects, {'0': "foo bar"})
|
||||
|
||||
p = cast(array, POINTER(c_char_p))
|
||||
# array and p share a common _objects attribute
|
||||
self.assertIs(p._objects, array._objects)
|
||||
self.assertEqual(array._objects, {'0': "foo bar", id(array): array})
|
||||
p[0] = "spam spam"
|
||||
self.assertEqual(p._objects, {'0': "spam spam", id(array): array})
|
||||
self.assertIs(array._objects, p._objects)
|
||||
p[1] = "foo bar"
|
||||
self.assertEqual(p._objects, {'1': 'foo bar', '0': "spam spam", id(array): array})
|
||||
self.assertIs(array._objects, p._objects)
|
||||
|
||||
def test_other(self):
|
||||
p = cast((c_int * 4)(1, 2, 3, 4), POINTER(c_int))
|
||||
self.assertEqual(p[:4], [1,2, 3, 4])
|
||||
self.assertEqual(p[:4:], [1, 2, 3, 4])
|
||||
self.assertEqual(p[3:-1:-1], [4, 3, 2, 1])
|
||||
self.assertEqual(p[:4:3], [1, 4])
|
||||
c_int()
|
||||
self.assertEqual(p[:4], [1, 2, 3, 4])
|
||||
self.assertEqual(p[:4:], [1, 2, 3, 4])
|
||||
self.assertEqual(p[3:-1:-1], [4, 3, 2, 1])
|
||||
self.assertEqual(p[:4:3], [1, 4])
|
||||
p[2] = 96
|
||||
self.assertEqual(p[:4], [1, 2, 96, 4])
|
||||
self.assertEqual(p[:4:], [1, 2, 96, 4])
|
||||
self.assertEqual(p[3:-1:-1], [4, 96, 2, 1])
|
||||
self.assertEqual(p[:4:3], [1, 4])
|
||||
c_int()
|
||||
self.assertEqual(p[:4], [1, 2, 96, 4])
|
||||
self.assertEqual(p[:4:], [1, 2, 96, 4])
|
||||
self.assertEqual(p[3:-1:-1], [4, 96, 2, 1])
|
||||
self.assertEqual(p[:4:3], [1, 4])
|
||||
|
||||
def test_char_p(self):
|
||||
# This didn't work: bad argument to internal function
|
||||
s = c_char_p("hiho")
|
||||
self.assertEqual(cast(cast(s, c_void_p), c_char_p).value,
|
||||
"hiho")
|
||||
|
||||
@need_symbol('c_wchar_p')
|
||||
def test_wchar_p(self):
|
||||
s = c_wchar_p("hiho")
|
||||
self.assertEqual(cast(cast(s, c_void_p), c_wchar_p).value,
|
||||
"hiho")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
212
Lib/ctypes/test/test_cfuncs.py
Normal file
212
Lib/ctypes/test/test_cfuncs.py
Normal file
@@ -0,0 +1,212 @@
|
||||
# A lot of failures in these tests on Mac OS X.
|
||||
# Byte order related?
|
||||
|
||||
import unittest
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
|
||||
import _ctypes_test
|
||||
|
||||
class CFunctions(unittest.TestCase):
|
||||
_dll = CDLL(_ctypes_test.__file__)
|
||||
|
||||
def S(self):
|
||||
return c_longlong.in_dll(self._dll, "last_tf_arg_s").value
|
||||
def U(self):
|
||||
return c_ulonglong.in_dll(self._dll, "last_tf_arg_u").value
|
||||
|
||||
def test_byte(self):
|
||||
self._dll.tf_b.restype = c_byte
|
||||
self._dll.tf_b.argtypes = (c_byte,)
|
||||
self.assertEqual(self._dll.tf_b(-126), -42)
|
||||
self.assertEqual(self.S(), -126)
|
||||
|
||||
def test_byte_plus(self):
|
||||
self._dll.tf_bb.restype = c_byte
|
||||
self._dll.tf_bb.argtypes = (c_byte, c_byte)
|
||||
self.assertEqual(self._dll.tf_bb(0, -126), -42)
|
||||
self.assertEqual(self.S(), -126)
|
||||
|
||||
def test_ubyte(self):
|
||||
self._dll.tf_B.restype = c_ubyte
|
||||
self._dll.tf_B.argtypes = (c_ubyte,)
|
||||
self.assertEqual(self._dll.tf_B(255), 85)
|
||||
self.assertEqual(self.U(), 255)
|
||||
|
||||
def test_ubyte_plus(self):
|
||||
self._dll.tf_bB.restype = c_ubyte
|
||||
self._dll.tf_bB.argtypes = (c_byte, c_ubyte)
|
||||
self.assertEqual(self._dll.tf_bB(0, 255), 85)
|
||||
self.assertEqual(self.U(), 255)
|
||||
|
||||
def test_short(self):
|
||||
self._dll.tf_h.restype = c_short
|
||||
self._dll.tf_h.argtypes = (c_short,)
|
||||
self.assertEqual(self._dll.tf_h(-32766), -10922)
|
||||
self.assertEqual(self.S(), -32766)
|
||||
|
||||
def test_short_plus(self):
|
||||
self._dll.tf_bh.restype = c_short
|
||||
self._dll.tf_bh.argtypes = (c_byte, c_short)
|
||||
self.assertEqual(self._dll.tf_bh(0, -32766), -10922)
|
||||
self.assertEqual(self.S(), -32766)
|
||||
|
||||
def test_ushort(self):
|
||||
self._dll.tf_H.restype = c_ushort
|
||||
self._dll.tf_H.argtypes = (c_ushort,)
|
||||
self.assertEqual(self._dll.tf_H(65535), 21845)
|
||||
self.assertEqual(self.U(), 65535)
|
||||
|
||||
def test_ushort_plus(self):
|
||||
self._dll.tf_bH.restype = c_ushort
|
||||
self._dll.tf_bH.argtypes = (c_byte, c_ushort)
|
||||
self.assertEqual(self._dll.tf_bH(0, 65535), 21845)
|
||||
self.assertEqual(self.U(), 65535)
|
||||
|
||||
def test_int(self):
|
||||
self._dll.tf_i.restype = c_int
|
||||
self._dll.tf_i.argtypes = (c_int,)
|
||||
self.assertEqual(self._dll.tf_i(-2147483646), -715827882)
|
||||
self.assertEqual(self.S(), -2147483646)
|
||||
|
||||
def test_int_plus(self):
|
||||
self._dll.tf_bi.restype = c_int
|
||||
self._dll.tf_bi.argtypes = (c_byte, c_int)
|
||||
self.assertEqual(self._dll.tf_bi(0, -2147483646), -715827882)
|
||||
self.assertEqual(self.S(), -2147483646)
|
||||
|
||||
def test_uint(self):
|
||||
self._dll.tf_I.restype = c_uint
|
||||
self._dll.tf_I.argtypes = (c_uint,)
|
||||
self.assertEqual(self._dll.tf_I(4294967295), 1431655765)
|
||||
self.assertEqual(self.U(), 4294967295)
|
||||
|
||||
def test_uint_plus(self):
|
||||
self._dll.tf_bI.restype = c_uint
|
||||
self._dll.tf_bI.argtypes = (c_byte, c_uint)
|
||||
self.assertEqual(self._dll.tf_bI(0, 4294967295), 1431655765)
|
||||
self.assertEqual(self.U(), 4294967295)
|
||||
|
||||
def test_long(self):
|
||||
self._dll.tf_l.restype = c_long
|
||||
self._dll.tf_l.argtypes = (c_long,)
|
||||
self.assertEqual(self._dll.tf_l(-2147483646), -715827882)
|
||||
self.assertEqual(self.S(), -2147483646)
|
||||
|
||||
def test_long_plus(self):
|
||||
self._dll.tf_bl.restype = c_long
|
||||
self._dll.tf_bl.argtypes = (c_byte, c_long)
|
||||
self.assertEqual(self._dll.tf_bl(0, -2147483646), -715827882)
|
||||
self.assertEqual(self.S(), -2147483646)
|
||||
|
||||
def test_ulong(self):
|
||||
self._dll.tf_L.restype = c_ulong
|
||||
self._dll.tf_L.argtypes = (c_ulong,)
|
||||
self.assertEqual(self._dll.tf_L(4294967295), 1431655765)
|
||||
self.assertEqual(self.U(), 4294967295)
|
||||
|
||||
def test_ulong_plus(self):
|
||||
self._dll.tf_bL.restype = c_ulong
|
||||
self._dll.tf_bL.argtypes = (c_char, c_ulong)
|
||||
self.assertEqual(self._dll.tf_bL(' ', 4294967295), 1431655765)
|
||||
self.assertEqual(self.U(), 4294967295)
|
||||
|
||||
def test_longlong(self):
|
||||
self._dll.tf_q.restype = c_longlong
|
||||
self._dll.tf_q.argtypes = (c_longlong, )
|
||||
self.assertEqual(self._dll.tf_q(-9223372036854775806), -3074457345618258602)
|
||||
self.assertEqual(self.S(), -9223372036854775806)
|
||||
|
||||
def test_longlong_plus(self):
|
||||
self._dll.tf_bq.restype = c_longlong
|
||||
self._dll.tf_bq.argtypes = (c_byte, c_longlong)
|
||||
self.assertEqual(self._dll.tf_bq(0, -9223372036854775806), -3074457345618258602)
|
||||
self.assertEqual(self.S(), -9223372036854775806)
|
||||
|
||||
def test_ulonglong(self):
|
||||
self._dll.tf_Q.restype = c_ulonglong
|
||||
self._dll.tf_Q.argtypes = (c_ulonglong, )
|
||||
self.assertEqual(self._dll.tf_Q(18446744073709551615), 6148914691236517205)
|
||||
self.assertEqual(self.U(), 18446744073709551615)
|
||||
|
||||
def test_ulonglong_plus(self):
|
||||
self._dll.tf_bQ.restype = c_ulonglong
|
||||
self._dll.tf_bQ.argtypes = (c_byte, c_ulonglong)
|
||||
self.assertEqual(self._dll.tf_bQ(0, 18446744073709551615), 6148914691236517205)
|
||||
self.assertEqual(self.U(), 18446744073709551615)
|
||||
|
||||
def test_float(self):
|
||||
self._dll.tf_f.restype = c_float
|
||||
self._dll.tf_f.argtypes = (c_float,)
|
||||
self.assertEqual(self._dll.tf_f(-42.), -14.)
|
||||
self.assertEqual(self.S(), -42)
|
||||
|
||||
def test_float_plus(self):
|
||||
self._dll.tf_bf.restype = c_float
|
||||
self._dll.tf_bf.argtypes = (c_byte, c_float)
|
||||
self.assertEqual(self._dll.tf_bf(0, -42.), -14.)
|
||||
self.assertEqual(self.S(), -42)
|
||||
|
||||
def test_double(self):
|
||||
self._dll.tf_d.restype = c_double
|
||||
self._dll.tf_d.argtypes = (c_double,)
|
||||
self.assertEqual(self._dll.tf_d(42.), 14.)
|
||||
self.assertEqual(self.S(), 42)
|
||||
|
||||
def test_double_plus(self):
|
||||
self._dll.tf_bd.restype = c_double
|
||||
self._dll.tf_bd.argtypes = (c_byte, c_double)
|
||||
self.assertEqual(self._dll.tf_bd(0, 42.), 14.)
|
||||
self.assertEqual(self.S(), 42)
|
||||
|
||||
def test_longdouble(self):
|
||||
self._dll.tf_D.restype = c_longdouble
|
||||
self._dll.tf_D.argtypes = (c_longdouble,)
|
||||
self.assertEqual(self._dll.tf_D(42.), 14.)
|
||||
self.assertEqual(self.S(), 42)
|
||||
|
||||
def test_longdouble_plus(self):
|
||||
self._dll.tf_bD.restype = c_longdouble
|
||||
self._dll.tf_bD.argtypes = (c_byte, c_longdouble)
|
||||
self.assertEqual(self._dll.tf_bD(0, 42.), 14.)
|
||||
self.assertEqual(self.S(), 42)
|
||||
|
||||
def test_callwithresult(self):
|
||||
def process_result(result):
|
||||
return result * 2
|
||||
self._dll.tf_i.restype = process_result
|
||||
self._dll.tf_i.argtypes = (c_int,)
|
||||
self.assertEqual(self._dll.tf_i(42), 28)
|
||||
self.assertEqual(self.S(), 42)
|
||||
self.assertEqual(self._dll.tf_i(-42), -28)
|
||||
self.assertEqual(self.S(), -42)
|
||||
|
||||
def test_void(self):
|
||||
self._dll.tv_i.restype = None
|
||||
self._dll.tv_i.argtypes = (c_int,)
|
||||
self.assertEqual(self._dll.tv_i(42), None)
|
||||
self.assertEqual(self.S(), 42)
|
||||
self.assertEqual(self._dll.tv_i(-42), None)
|
||||
self.assertEqual(self.S(), -42)
|
||||
|
||||
# The following repeats the above tests with stdcall functions (where
|
||||
# they are available)
|
||||
try:
|
||||
WinDLL
|
||||
except NameError:
|
||||
def stdcall_dll(*_): pass
|
||||
else:
|
||||
class stdcall_dll(WinDLL):
|
||||
def __getattr__(self, name):
|
||||
if name[:2] == '__' and name[-2:] == '__':
|
||||
raise AttributeError(name)
|
||||
func = self._FuncPtr(("s_" + name, self))
|
||||
setattr(self, name, func)
|
||||
return func
|
||||
|
||||
@need_symbol('WinDLL')
|
||||
class stdcallCFunctions(CFunctions):
|
||||
_dll = stdcall_dll(_ctypes_test.__file__)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
36
Lib/ctypes/test/test_checkretval.py
Normal file
36
Lib/ctypes/test/test_checkretval.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import unittest
|
||||
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
|
||||
class CHECKED(c_int):
|
||||
def _check_retval_(value):
|
||||
# Receives a CHECKED instance.
|
||||
return str(value.value)
|
||||
_check_retval_ = staticmethod(_check_retval_)
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def test_checkretval(self):
|
||||
|
||||
import _ctypes_test
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
self.assertEqual(42, dll._testfunc_p_p(42))
|
||||
|
||||
dll._testfunc_p_p.restype = CHECKED
|
||||
self.assertEqual("42", dll._testfunc_p_p(42))
|
||||
|
||||
dll._testfunc_p_p.restype = None
|
||||
self.assertEqual(None, dll._testfunc_p_p(42))
|
||||
|
||||
del dll._testfunc_p_p.restype
|
||||
self.assertEqual(42, dll._testfunc_p_p(42))
|
||||
|
||||
@need_symbol('oledll')
|
||||
def test_oledll(self):
|
||||
self.assertRaises(WindowsError,
|
||||
oledll.oleaut32.CreateTypeLib2,
|
||||
0, None, None)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
21
Lib/ctypes/test/test_delattr.py
Normal file
21
Lib/ctypes/test/test_delattr.py
Normal file
@@ -0,0 +1,21 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("foo", c_int)]
|
||||
|
||||
class TestCase(unittest.TestCase):
|
||||
def test_simple(self):
|
||||
self.assertRaises(TypeError,
|
||||
delattr, c_int(42), "value")
|
||||
|
||||
def test_chararray(self):
|
||||
self.assertRaises(TypeError,
|
||||
delattr, (c_char * 5)(), "value")
|
||||
|
||||
def test_struct(self):
|
||||
self.assertRaises(TypeError,
|
||||
delattr, X(), "foo")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
80
Lib/ctypes/test/test_errno.py
Normal file
80
Lib/ctypes/test/test_errno.py
Normal file
@@ -0,0 +1,80 @@
|
||||
import unittest, os, errno
|
||||
from ctypes import *
|
||||
from ctypes.util import find_library
|
||||
from test import test_support
|
||||
try:
|
||||
import threading
|
||||
except ImportError:
|
||||
threading = None
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test_open(self):
|
||||
libc_name = find_library("c")
|
||||
if libc_name is None:
|
||||
raise unittest.SkipTest("Unable to find C library")
|
||||
libc = CDLL(libc_name, use_errno=True)
|
||||
if os.name == "nt":
|
||||
libc_open = libc._open
|
||||
else:
|
||||
libc_open = libc.open
|
||||
|
||||
libc_open.argtypes = c_char_p, c_int
|
||||
|
||||
self.assertEqual(libc_open("", 0), -1)
|
||||
self.assertEqual(get_errno(), errno.ENOENT)
|
||||
|
||||
self.assertEqual(set_errno(32), errno.ENOENT)
|
||||
self.assertEqual(get_errno(), 32)
|
||||
|
||||
if threading:
|
||||
def _worker():
|
||||
set_errno(0)
|
||||
|
||||
libc = CDLL(libc_name, use_errno=False)
|
||||
if os.name == "nt":
|
||||
libc_open = libc._open
|
||||
else:
|
||||
libc_open = libc.open
|
||||
libc_open.argtypes = c_char_p, c_int
|
||||
self.assertEqual(libc_open("", 0), -1)
|
||||
self.assertEqual(get_errno(), 0)
|
||||
|
||||
t = threading.Thread(target=_worker)
|
||||
t.start()
|
||||
t.join()
|
||||
|
||||
self.assertEqual(get_errno(), 32)
|
||||
set_errno(0)
|
||||
|
||||
@unittest.skipUnless(os.name == "nt", 'Test specific to Windows')
|
||||
def test_GetLastError(self):
|
||||
dll = WinDLL("kernel32", use_last_error=True)
|
||||
GetModuleHandle = dll.GetModuleHandleA
|
||||
GetModuleHandle.argtypes = [c_wchar_p]
|
||||
|
||||
self.assertEqual(0, GetModuleHandle("foo"))
|
||||
self.assertEqual(get_last_error(), 126)
|
||||
|
||||
self.assertEqual(set_last_error(32), 126)
|
||||
self.assertEqual(get_last_error(), 32)
|
||||
|
||||
def _worker():
|
||||
set_last_error(0)
|
||||
|
||||
dll = WinDLL("kernel32", use_last_error=False)
|
||||
GetModuleHandle = dll.GetModuleHandleW
|
||||
GetModuleHandle.argtypes = [c_wchar_p]
|
||||
GetModuleHandle("bar")
|
||||
|
||||
self.assertEqual(get_last_error(), 0)
|
||||
|
||||
t = threading.Thread(target=_worker)
|
||||
t.start()
|
||||
t.join()
|
||||
|
||||
self.assertEqual(get_last_error(), 32)
|
||||
|
||||
set_last_error(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
75
Lib/ctypes/test/test_find.py
Normal file
75
Lib/ctypes/test/test_find.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import unittest
|
||||
import os.path
|
||||
import sys
|
||||
from test import test_support
|
||||
from ctypes import *
|
||||
from ctypes.util import find_library
|
||||
from ctypes.test import is_resource_enabled
|
||||
|
||||
if sys.platform == "win32":
|
||||
lib_gl = find_library("OpenGL32")
|
||||
lib_glu = find_library("Glu32")
|
||||
lib_gle = None
|
||||
elif sys.platform == "darwin":
|
||||
lib_gl = lib_glu = find_library("OpenGL")
|
||||
lib_gle = None
|
||||
else:
|
||||
lib_gl = find_library("GL")
|
||||
lib_glu = find_library("GLU")
|
||||
lib_gle = find_library("gle")
|
||||
|
||||
## print, for debugging
|
||||
if is_resource_enabled("printing"):
|
||||
if lib_gl or lib_glu or lib_gle:
|
||||
print "OpenGL libraries:"
|
||||
for item in (("GL", lib_gl),
|
||||
("GLU", lib_glu),
|
||||
("gle", lib_gle)):
|
||||
print "\t", item
|
||||
|
||||
|
||||
# On some systems, loading the OpenGL libraries needs the RTLD_GLOBAL mode.
|
||||
class Test_OpenGL_libs(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.gl = self.glu = self.gle = None
|
||||
if lib_gl:
|
||||
try:
|
||||
self.gl = CDLL(lib_gl, mode=RTLD_GLOBAL)
|
||||
except OSError:
|
||||
pass
|
||||
if lib_glu:
|
||||
try:
|
||||
self.glu = CDLL(lib_glu, RTLD_GLOBAL)
|
||||
except OSError:
|
||||
pass
|
||||
if lib_gle:
|
||||
try:
|
||||
self.gle = CDLL(lib_gle)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def tearDown(self):
|
||||
self.gl = self.glu = self.gle = None
|
||||
|
||||
@unittest.skipUnless(lib_gl, 'lib_gl not available')
|
||||
def test_gl(self):
|
||||
if self.gl:
|
||||
self.gl.glClearIndex
|
||||
|
||||
@unittest.skipUnless(lib_glu, 'lib_glu not available')
|
||||
def test_glu(self):
|
||||
if self.glu:
|
||||
self.glu.gluBeginCurve
|
||||
|
||||
@unittest.skipUnless(lib_gle, 'lib_gle not available')
|
||||
def test_gle(self):
|
||||
if self.gle:
|
||||
self.gle.gleGetJoinStyle
|
||||
|
||||
def test_shell_injection(self):
|
||||
result = find_library('; echo Hello shell > ' + test_support.TESTFN)
|
||||
self.assertFalse(os.path.lexists(test_support.TESTFN))
|
||||
self.assertIsNone(result)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
98
Lib/ctypes/test/test_frombuffer.py
Normal file
98
Lib/ctypes/test/test_frombuffer.py
Normal file
@@ -0,0 +1,98 @@
|
||||
from ctypes import *
|
||||
import array
|
||||
import gc
|
||||
import unittest
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("c_int", c_int)]
|
||||
init_called = False
|
||||
def __init__(self):
|
||||
self._init_called = True
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
def test_fom_buffer(self):
|
||||
a = array.array("i", range(16))
|
||||
x = (c_int * 16).from_buffer(a)
|
||||
|
||||
y = X.from_buffer(a)
|
||||
self.assertEqual(y.c_int, a[0])
|
||||
self.assertFalse(y.init_called)
|
||||
|
||||
self.assertEqual(x[:], a.tolist())
|
||||
|
||||
a[0], a[-1] = 200, -200
|
||||
self.assertEqual(x[:], a.tolist())
|
||||
|
||||
self.assertIn(a, x._objects.values())
|
||||
|
||||
self.assertRaises(ValueError,
|
||||
c_int.from_buffer, a, -1)
|
||||
|
||||
expected = x[:]
|
||||
del a; gc.collect(); gc.collect(); gc.collect()
|
||||
self.assertEqual(x[:], expected)
|
||||
|
||||
self.assertRaises(TypeError,
|
||||
(c_char * 16).from_buffer, "a" * 16)
|
||||
|
||||
def test_fom_buffer_with_offset(self):
|
||||
a = array.array("i", range(16))
|
||||
x = (c_int * 15).from_buffer(a, sizeof(c_int))
|
||||
|
||||
self.assertEqual(x[:], a.tolist()[1:])
|
||||
self.assertRaises(ValueError, lambda: (c_int * 16).from_buffer(a, sizeof(c_int)))
|
||||
self.assertRaises(ValueError, lambda: (c_int * 1).from_buffer(a, 16 * sizeof(c_int)))
|
||||
|
||||
def test_from_buffer_copy(self):
|
||||
a = array.array("i", range(16))
|
||||
x = (c_int * 16).from_buffer_copy(a)
|
||||
|
||||
y = X.from_buffer_copy(a)
|
||||
self.assertEqual(y.c_int, a[0])
|
||||
self.assertFalse(y.init_called)
|
||||
|
||||
self.assertEqual(x[:], range(16))
|
||||
|
||||
a[0], a[-1] = 200, -200
|
||||
self.assertEqual(x[:], range(16))
|
||||
|
||||
self.assertEqual(x._objects, None)
|
||||
|
||||
self.assertRaises(ValueError,
|
||||
c_int.from_buffer, a, -1)
|
||||
|
||||
del a; gc.collect(); gc.collect(); gc.collect()
|
||||
self.assertEqual(x[:], range(16))
|
||||
|
||||
x = (c_char * 16).from_buffer_copy("a" * 16)
|
||||
self.assertEqual(x[:], "a" * 16)
|
||||
|
||||
def test_fom_buffer_copy_with_offset(self):
|
||||
a = array.array("i", range(16))
|
||||
x = (c_int * 15).from_buffer_copy(a, sizeof(c_int))
|
||||
|
||||
self.assertEqual(x[:], a.tolist()[1:])
|
||||
self.assertRaises(ValueError,
|
||||
(c_int * 16).from_buffer_copy, a, sizeof(c_int))
|
||||
self.assertRaises(ValueError,
|
||||
(c_int * 1).from_buffer_copy, a, 16 * sizeof(c_int))
|
||||
|
||||
def test_abstract(self):
|
||||
from ctypes import _Pointer, _SimpleCData, _CFuncPtr
|
||||
|
||||
self.assertRaises(TypeError, Array.from_buffer, bytearray(10))
|
||||
self.assertRaises(TypeError, Structure.from_buffer, bytearray(10))
|
||||
self.assertRaises(TypeError, Union.from_buffer, bytearray(10))
|
||||
self.assertRaises(TypeError, _CFuncPtr.from_buffer, bytearray(10))
|
||||
self.assertRaises(TypeError, _Pointer.from_buffer, bytearray(10))
|
||||
self.assertRaises(TypeError, _SimpleCData.from_buffer, bytearray(10))
|
||||
|
||||
self.assertRaises(TypeError, Array.from_buffer_copy, b"123")
|
||||
self.assertRaises(TypeError, Structure.from_buffer_copy, b"123")
|
||||
self.assertRaises(TypeError, Union.from_buffer_copy, b"123")
|
||||
self.assertRaises(TypeError, _CFuncPtr.from_buffer_copy, b"123")
|
||||
self.assertRaises(TypeError, _Pointer.from_buffer_copy, b"123")
|
||||
self.assertRaises(TypeError, _SimpleCData.from_buffer_copy, b"123")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
132
Lib/ctypes/test/test_funcptr.py
Normal file
132
Lib/ctypes/test/test_funcptr.py
Normal file
@@ -0,0 +1,132 @@
|
||||
import os, unittest
|
||||
from ctypes import *
|
||||
|
||||
try:
|
||||
WINFUNCTYPE
|
||||
except NameError:
|
||||
# fake to enable this test on Linux
|
||||
WINFUNCTYPE = CFUNCTYPE
|
||||
|
||||
import _ctypes_test
|
||||
lib = CDLL(_ctypes_test.__file__)
|
||||
|
||||
class CFuncPtrTestCase(unittest.TestCase):
|
||||
def test_basic(self):
|
||||
X = WINFUNCTYPE(c_int, c_int, c_int)
|
||||
|
||||
def func(*args):
|
||||
return len(args)
|
||||
|
||||
x = X(func)
|
||||
self.assertEqual(x.restype, c_int)
|
||||
self.assertEqual(x.argtypes, (c_int, c_int))
|
||||
self.assertEqual(sizeof(x), sizeof(c_voidp))
|
||||
self.assertEqual(sizeof(X), sizeof(c_voidp))
|
||||
|
||||
def test_first(self):
|
||||
StdCallback = WINFUNCTYPE(c_int, c_int, c_int)
|
||||
CdeclCallback = CFUNCTYPE(c_int, c_int, c_int)
|
||||
|
||||
def func(a, b):
|
||||
return a + b
|
||||
|
||||
s = StdCallback(func)
|
||||
c = CdeclCallback(func)
|
||||
|
||||
self.assertEqual(s(1, 2), 3)
|
||||
self.assertEqual(c(1, 2), 3)
|
||||
# The following no longer raises a TypeError - it is now
|
||||
# possible, as in C, to call cdecl functions with more parameters.
|
||||
#self.assertRaises(TypeError, c, 1, 2, 3)
|
||||
self.assertEqual(c(1, 2, 3, 4, 5, 6), 3)
|
||||
if not WINFUNCTYPE is CFUNCTYPE and os.name != "ce":
|
||||
self.assertRaises(TypeError, s, 1, 2, 3)
|
||||
|
||||
def test_structures(self):
|
||||
WNDPROC = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int)
|
||||
|
||||
def wndproc(hwnd, msg, wParam, lParam):
|
||||
return hwnd + msg + wParam + lParam
|
||||
|
||||
HINSTANCE = c_int
|
||||
HICON = c_int
|
||||
HCURSOR = c_int
|
||||
LPCTSTR = c_char_p
|
||||
|
||||
class WNDCLASS(Structure):
|
||||
_fields_ = [("style", c_uint),
|
||||
("lpfnWndProc", WNDPROC),
|
||||
("cbClsExtra", c_int),
|
||||
("cbWndExtra", c_int),
|
||||
("hInstance", HINSTANCE),
|
||||
("hIcon", HICON),
|
||||
("hCursor", HCURSOR),
|
||||
("lpszMenuName", LPCTSTR),
|
||||
("lpszClassName", LPCTSTR)]
|
||||
|
||||
wndclass = WNDCLASS()
|
||||
wndclass.lpfnWndProc = WNDPROC(wndproc)
|
||||
|
||||
WNDPROC_2 = WINFUNCTYPE(c_long, c_int, c_int, c_int, c_int)
|
||||
|
||||
# This is no longer true, now that WINFUNCTYPE caches created types internally.
|
||||
## # CFuncPtr subclasses are compared by identity, so this raises a TypeError:
|
||||
## self.assertRaises(TypeError, setattr, wndclass,
|
||||
## "lpfnWndProc", WNDPROC_2(wndproc))
|
||||
# instead:
|
||||
|
||||
self.assertIs(WNDPROC, WNDPROC_2)
|
||||
# 'wndclass.lpfnWndProc' leaks 94 references. Why?
|
||||
self.assertEqual(wndclass.lpfnWndProc(1, 2, 3, 4), 10)
|
||||
|
||||
|
||||
f = wndclass.lpfnWndProc
|
||||
|
||||
del wndclass
|
||||
del wndproc
|
||||
|
||||
self.assertEqual(f(10, 11, 12, 13), 46)
|
||||
|
||||
def test_dllfunctions(self):
|
||||
|
||||
def NoNullHandle(value):
|
||||
if not value:
|
||||
raise WinError()
|
||||
return value
|
||||
|
||||
strchr = lib.my_strchr
|
||||
strchr.restype = c_char_p
|
||||
strchr.argtypes = (c_char_p, c_char)
|
||||
self.assertEqual(strchr("abcdefghi", "b"), "bcdefghi")
|
||||
self.assertEqual(strchr("abcdefghi", "x"), None)
|
||||
|
||||
|
||||
strtok = lib.my_strtok
|
||||
strtok.restype = c_char_p
|
||||
# Neither of this does work: strtok changes the buffer it is passed
|
||||
## strtok.argtypes = (c_char_p, c_char_p)
|
||||
## strtok.argtypes = (c_string, c_char_p)
|
||||
|
||||
def c_string(init):
|
||||
size = len(init) + 1
|
||||
return (c_char*size)(*init)
|
||||
|
||||
s = "a\nb\nc"
|
||||
b = c_string(s)
|
||||
|
||||
## b = (c_char * (len(s)+1))()
|
||||
## b.value = s
|
||||
|
||||
## b = c_string(s)
|
||||
self.assertEqual(strtok(b, "\n"), "a")
|
||||
self.assertEqual(strtok(None, "\n"), "b")
|
||||
self.assertEqual(strtok(None, "\n"), "c")
|
||||
self.assertEqual(strtok(None, "\n"), None)
|
||||
|
||||
def test_abstract(self):
|
||||
from ctypes import _CFuncPtr
|
||||
|
||||
self.assertRaises(TypeError, _CFuncPtr, 13, "name", 42, "iid")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
402
Lib/ctypes/test/test_functions.py
Normal file
402
Lib/ctypes/test/test_functions.py
Normal file
@@ -0,0 +1,402 @@
|
||||
"""
|
||||
Here is probably the place to write the docs, since the test-cases
|
||||
show how the type behave.
|
||||
|
||||
Later...
|
||||
"""
|
||||
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
import sys, unittest
|
||||
|
||||
try:
|
||||
WINFUNCTYPE
|
||||
except NameError:
|
||||
# fake to enable this test on Linux
|
||||
WINFUNCTYPE = CFUNCTYPE
|
||||
|
||||
import _ctypes_test
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
if sys.platform == "win32":
|
||||
windll = WinDLL(_ctypes_test.__file__)
|
||||
|
||||
class POINT(Structure):
|
||||
_fields_ = [("x", c_int), ("y", c_int)]
|
||||
class RECT(Structure):
|
||||
_fields_ = [("left", c_int), ("top", c_int),
|
||||
("right", c_int), ("bottom", c_int)]
|
||||
class FunctionTestCase(unittest.TestCase):
|
||||
|
||||
def test_mro(self):
|
||||
# in Python 2.3, this raises TypeError: MRO conflict among bases classes,
|
||||
# in Python 2.2 it works.
|
||||
#
|
||||
# But in early versions of _ctypes.c, the result of tp_new
|
||||
# wasn't checked, and it even crashed Python.
|
||||
# Found by Greg Chapman.
|
||||
|
||||
try:
|
||||
class X(object, Array):
|
||||
_length_ = 5
|
||||
_type_ = "i"
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
|
||||
from _ctypes import _Pointer
|
||||
try:
|
||||
class X(object, _Pointer):
|
||||
pass
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
from _ctypes import _SimpleCData
|
||||
try:
|
||||
class X(object, _SimpleCData):
|
||||
_type_ = "i"
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
class X(object, Structure):
|
||||
_fields_ = []
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
def test_wchar_parm(self):
|
||||
f = dll._testfunc_i_bhilfd
|
||||
f.argtypes = [c_byte, c_wchar, c_int, c_long, c_float, c_double]
|
||||
result = f(1, u"x", 3, 4, 5.0, 6.0)
|
||||
self.assertEqual(result, 139)
|
||||
self.assertEqual(type(result), int)
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
def test_wchar_result(self):
|
||||
f = dll._testfunc_i_bhilfd
|
||||
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
|
||||
f.restype = c_wchar
|
||||
result = f(0, 0, 0, 0, 0, 0)
|
||||
self.assertEqual(result, u'\x00')
|
||||
|
||||
def test_voidresult(self):
|
||||
f = dll._testfunc_v
|
||||
f.restype = None
|
||||
f.argtypes = [c_int, c_int, POINTER(c_int)]
|
||||
result = c_int()
|
||||
self.assertEqual(None, f(1, 2, byref(result)))
|
||||
self.assertEqual(result.value, 3)
|
||||
|
||||
def test_intresult(self):
|
||||
f = dll._testfunc_i_bhilfd
|
||||
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
|
||||
f.restype = c_int
|
||||
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||
self.assertEqual(result, 21)
|
||||
self.assertEqual(type(result), int)
|
||||
|
||||
result = f(-1, -2, -3, -4, -5.0, -6.0)
|
||||
self.assertEqual(result, -21)
|
||||
self.assertEqual(type(result), int)
|
||||
|
||||
# If we declare the function to return a short,
|
||||
# is the high part split off?
|
||||
f.restype = c_short
|
||||
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||
self.assertEqual(result, 21)
|
||||
self.assertEqual(type(result), int)
|
||||
|
||||
result = f(1, 2, 3, 0x10004, 5.0, 6.0)
|
||||
self.assertEqual(result, 21)
|
||||
self.assertEqual(type(result), int)
|
||||
|
||||
# You cannot assign character format codes as restype any longer
|
||||
self.assertRaises(TypeError, setattr, f, "restype", "i")
|
||||
|
||||
def test_floatresult(self):
|
||||
f = dll._testfunc_f_bhilfd
|
||||
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
|
||||
f.restype = c_float
|
||||
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||
self.assertEqual(result, 21)
|
||||
self.assertEqual(type(result), float)
|
||||
|
||||
result = f(-1, -2, -3, -4, -5.0, -6.0)
|
||||
self.assertEqual(result, -21)
|
||||
self.assertEqual(type(result), float)
|
||||
|
||||
def test_doubleresult(self):
|
||||
f = dll._testfunc_d_bhilfd
|
||||
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
|
||||
f.restype = c_double
|
||||
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||
self.assertEqual(result, 21)
|
||||
self.assertEqual(type(result), float)
|
||||
|
||||
result = f(-1, -2, -3, -4, -5.0, -6.0)
|
||||
self.assertEqual(result, -21)
|
||||
self.assertEqual(type(result), float)
|
||||
|
||||
def test_longdoubleresult(self):
|
||||
f = dll._testfunc_D_bhilfD
|
||||
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_longdouble]
|
||||
f.restype = c_longdouble
|
||||
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||
self.assertEqual(result, 21)
|
||||
self.assertEqual(type(result), float)
|
||||
|
||||
result = f(-1, -2, -3, -4, -5.0, -6.0)
|
||||
self.assertEqual(result, -21)
|
||||
self.assertEqual(type(result), float)
|
||||
|
||||
@need_symbol('c_longlong')
|
||||
def test_longlongresult(self):
|
||||
f = dll._testfunc_q_bhilfd
|
||||
f.restype = c_longlong
|
||||
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]
|
||||
result = f(1, 2, 3, 4, 5.0, 6.0)
|
||||
self.assertEqual(result, 21)
|
||||
|
||||
f = dll._testfunc_q_bhilfdq
|
||||
f.restype = c_longlong
|
||||
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double, c_longlong]
|
||||
result = f(1, 2, 3, 4, 5.0, 6.0, 21)
|
||||
self.assertEqual(result, 42)
|
||||
|
||||
def test_stringresult(self):
|
||||
f = dll._testfunc_p_p
|
||||
f.argtypes = None
|
||||
f.restype = c_char_p
|
||||
result = f("123")
|
||||
self.assertEqual(result, "123")
|
||||
|
||||
result = f(None)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
def test_pointers(self):
|
||||
f = dll._testfunc_p_p
|
||||
f.restype = POINTER(c_int)
|
||||
f.argtypes = [POINTER(c_int)]
|
||||
|
||||
# This only works if the value c_int(42) passed to the
|
||||
# function is still alive while the pointer (the result) is
|
||||
# used.
|
||||
|
||||
v = c_int(42)
|
||||
|
||||
self.assertEqual(pointer(v).contents.value, 42)
|
||||
result = f(pointer(v))
|
||||
self.assertEqual(type(result), POINTER(c_int))
|
||||
self.assertEqual(result.contents.value, 42)
|
||||
|
||||
# This on works...
|
||||
result = f(pointer(v))
|
||||
self.assertEqual(result.contents.value, v.value)
|
||||
|
||||
p = pointer(c_int(99))
|
||||
result = f(p)
|
||||
self.assertEqual(result.contents.value, 99)
|
||||
|
||||
arg = byref(v)
|
||||
result = f(arg)
|
||||
self.assertNotEqual(result.contents, v.value)
|
||||
|
||||
self.assertRaises(ArgumentError, f, byref(c_short(22)))
|
||||
|
||||
# It is dangerous, however, because you don't control the lifetime
|
||||
# of the pointer:
|
||||
result = f(byref(c_int(99)))
|
||||
self.assertNotEqual(result.contents, 99)
|
||||
|
||||
def test_errors(self):
|
||||
f = dll._testfunc_p_p
|
||||
f.restype = c_int
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("y", c_int)]
|
||||
|
||||
self.assertRaises(TypeError, f, X()) #cannot convert parameter
|
||||
|
||||
################################################################
|
||||
def test_shorts(self):
|
||||
f = dll._testfunc_callback_i_if
|
||||
|
||||
args = []
|
||||
expected = [262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048,
|
||||
1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1]
|
||||
|
||||
def callback(v):
|
||||
args.append(v)
|
||||
return v
|
||||
|
||||
CallBack = CFUNCTYPE(c_int, c_int)
|
||||
|
||||
cb = CallBack(callback)
|
||||
f(2**18, cb)
|
||||
self.assertEqual(args, expected)
|
||||
|
||||
################################################################
|
||||
|
||||
|
||||
def test_callbacks(self):
|
||||
f = dll._testfunc_callback_i_if
|
||||
f.restype = c_int
|
||||
f.argtypes = None
|
||||
|
||||
MyCallback = CFUNCTYPE(c_int, c_int)
|
||||
|
||||
def callback(value):
|
||||
#print "called back with", value
|
||||
return value
|
||||
|
||||
cb = MyCallback(callback)
|
||||
result = f(-10, cb)
|
||||
self.assertEqual(result, -18)
|
||||
|
||||
# test with prototype
|
||||
f.argtypes = [c_int, MyCallback]
|
||||
cb = MyCallback(callback)
|
||||
result = f(-10, cb)
|
||||
self.assertEqual(result, -18)
|
||||
|
||||
AnotherCallback = WINFUNCTYPE(c_int, c_int, c_int, c_int, c_int)
|
||||
|
||||
# check that the prototype works: we call f with wrong
|
||||
# argument types
|
||||
cb = AnotherCallback(callback)
|
||||
self.assertRaises(ArgumentError, f, -10, cb)
|
||||
|
||||
|
||||
def test_callbacks_2(self):
|
||||
# Can also use simple datatypes as argument type specifiers
|
||||
# for the callback function.
|
||||
# In this case the call receives an instance of that type
|
||||
f = dll._testfunc_callback_i_if
|
||||
f.restype = c_int
|
||||
|
||||
MyCallback = CFUNCTYPE(c_int, c_int)
|
||||
|
||||
f.argtypes = [c_int, MyCallback]
|
||||
|
||||
def callback(value):
|
||||
#print "called back with", value
|
||||
self.assertEqual(type(value), int)
|
||||
return value
|
||||
|
||||
cb = MyCallback(callback)
|
||||
result = f(-10, cb)
|
||||
self.assertEqual(result, -18)
|
||||
|
||||
@need_symbol('c_longlong')
|
||||
def test_longlong_callbacks(self):
|
||||
|
||||
f = dll._testfunc_callback_q_qf
|
||||
f.restype = c_longlong
|
||||
|
||||
MyCallback = CFUNCTYPE(c_longlong, c_longlong)
|
||||
|
||||
f.argtypes = [c_longlong, MyCallback]
|
||||
|
||||
def callback(value):
|
||||
self.assertIsInstance(value, (int, long))
|
||||
return value & 0x7FFFFFFF
|
||||
|
||||
cb = MyCallback(callback)
|
||||
|
||||
self.assertEqual(13577625587, f(1000000000000, cb))
|
||||
|
||||
def test_errors(self):
|
||||
self.assertRaises(AttributeError, getattr, dll, "_xxx_yyy")
|
||||
self.assertRaises(ValueError, c_int.in_dll, dll, "_xxx_yyy")
|
||||
|
||||
def test_byval(self):
|
||||
|
||||
# without prototype
|
||||
ptin = POINT(1, 2)
|
||||
ptout = POINT()
|
||||
# EXPORT int _testfunc_byval(point in, point *pout)
|
||||
result = dll._testfunc_byval(ptin, byref(ptout))
|
||||
got = result, ptout.x, ptout.y
|
||||
expected = 3, 1, 2
|
||||
self.assertEqual(got, expected)
|
||||
|
||||
# with prototype
|
||||
ptin = POINT(101, 102)
|
||||
ptout = POINT()
|
||||
dll._testfunc_byval.argtypes = (POINT, POINTER(POINT))
|
||||
dll._testfunc_byval.restype = c_int
|
||||
result = dll._testfunc_byval(ptin, byref(ptout))
|
||||
got = result, ptout.x, ptout.y
|
||||
expected = 203, 101, 102
|
||||
self.assertEqual(got, expected)
|
||||
|
||||
def test_struct_return_2H(self):
|
||||
class S2H(Structure):
|
||||
_fields_ = [("x", c_short),
|
||||
("y", c_short)]
|
||||
dll.ret_2h_func.restype = S2H
|
||||
dll.ret_2h_func.argtypes = [S2H]
|
||||
inp = S2H(99, 88)
|
||||
s2h = dll.ret_2h_func(inp)
|
||||
self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
|
||||
|
||||
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||||
def test_struct_return_2H_stdcall(self):
|
||||
class S2H(Structure):
|
||||
_fields_ = [("x", c_short),
|
||||
("y", c_short)]
|
||||
|
||||
windll.s_ret_2h_func.restype = S2H
|
||||
windll.s_ret_2h_func.argtypes = [S2H]
|
||||
s2h = windll.s_ret_2h_func(S2H(99, 88))
|
||||
self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
|
||||
|
||||
def test_struct_return_8H(self):
|
||||
class S8I(Structure):
|
||||
_fields_ = [("a", c_int),
|
||||
("b", c_int),
|
||||
("c", c_int),
|
||||
("d", c_int),
|
||||
("e", c_int),
|
||||
("f", c_int),
|
||||
("g", c_int),
|
||||
("h", c_int)]
|
||||
dll.ret_8i_func.restype = S8I
|
||||
dll.ret_8i_func.argtypes = [S8I]
|
||||
inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
|
||||
s8i = dll.ret_8i_func(inp)
|
||||
self.assertEqual((s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
|
||||
(9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
|
||||
|
||||
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||||
def test_struct_return_8H_stdcall(self):
|
||||
class S8I(Structure):
|
||||
_fields_ = [("a", c_int),
|
||||
("b", c_int),
|
||||
("c", c_int),
|
||||
("d", c_int),
|
||||
("e", c_int),
|
||||
("f", c_int),
|
||||
("g", c_int),
|
||||
("h", c_int)]
|
||||
windll.s_ret_8i_func.restype = S8I
|
||||
windll.s_ret_8i_func.argtypes = [S8I]
|
||||
inp = S8I(9, 8, 7, 6, 5, 4, 3, 2)
|
||||
s8i = windll.s_ret_8i_func(inp)
|
||||
self.assertEqual(
|
||||
(s8i.a, s8i.b, s8i.c, s8i.d, s8i.e, s8i.f, s8i.g, s8i.h),
|
||||
(9*2, 8*3, 7*4, 6*5, 5*6, 4*7, 3*8, 2*9))
|
||||
|
||||
def test_sf1651235(self):
|
||||
# see http://www.python.org/sf/1651235
|
||||
|
||||
proto = CFUNCTYPE(c_int, RECT, POINT)
|
||||
def callback(*args):
|
||||
return 0
|
||||
|
||||
callback = proto(callback)
|
||||
self.assertRaises(ArgumentError, lambda: callback((1, 2, 3, 4), POINT()))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
42
Lib/ctypes/test/test_incomplete.py
Normal file
42
Lib/ctypes/test/test_incomplete.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
|
||||
################################################################
|
||||
#
|
||||
# The incomplete pointer example from the tutorial
|
||||
#
|
||||
|
||||
class MyTestCase(unittest.TestCase):
|
||||
|
||||
def test_incomplete_example(self):
|
||||
lpcell = POINTER("cell")
|
||||
class cell(Structure):
|
||||
_fields_ = [("name", c_char_p),
|
||||
("next", lpcell)]
|
||||
|
||||
SetPointerType(lpcell, cell)
|
||||
|
||||
c1 = cell()
|
||||
c1.name = "foo"
|
||||
c2 = cell()
|
||||
c2.name = "bar"
|
||||
|
||||
c1.next = pointer(c2)
|
||||
c2.next = pointer(c1)
|
||||
|
||||
p = c1
|
||||
|
||||
result = []
|
||||
for i in range(8):
|
||||
result.append(p.name)
|
||||
p = p.next[0]
|
||||
self.assertEqual(result, ["foo", "bar"] * 4)
|
||||
|
||||
# to not leak references, we must clean _pointer_type_cache
|
||||
from ctypes import _pointer_type_cache
|
||||
del _pointer_type_cache[cell]
|
||||
|
||||
################################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
40
Lib/ctypes/test/test_init.py
Normal file
40
Lib/ctypes/test/test_init.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from ctypes import *
|
||||
import unittest
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_int),
|
||||
("b", c_int)]
|
||||
new_was_called = False
|
||||
|
||||
def __new__(cls):
|
||||
result = super(X, cls).__new__(cls)
|
||||
result.new_was_called = True
|
||||
return result
|
||||
|
||||
def __init__(self):
|
||||
self.a = 9
|
||||
self.b = 12
|
||||
|
||||
class Y(Structure):
|
||||
_fields_ = [("x", X)]
|
||||
|
||||
|
||||
class InitTest(unittest.TestCase):
|
||||
def test_get(self):
|
||||
# make sure the only accessing a nested structure
|
||||
# doesn't call the structure's __new__ and __init__
|
||||
y = Y()
|
||||
self.assertEqual((y.x.a, y.x.b), (0, 0))
|
||||
self.assertEqual(y.x.new_was_called, False)
|
||||
|
||||
# But explicitly creating an X structure calls __new__ and __init__, of course.
|
||||
x = X()
|
||||
self.assertEqual((x.a, x.b), (9, 12))
|
||||
self.assertEqual(x.new_was_called, True)
|
||||
|
||||
y.x = x
|
||||
self.assertEqual((y.x.a, y.x.b), (9, 12))
|
||||
self.assertEqual(y.x.new_was_called, False)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
103
Lib/ctypes/test/test_internals.py
Normal file
103
Lib/ctypes/test/test_internals.py
Normal file
@@ -0,0 +1,103 @@
|
||||
# This tests the internal _objects attribute
|
||||
import unittest
|
||||
from ctypes import *
|
||||
from sys import getrefcount as grc
|
||||
|
||||
# XXX This test must be reviewed for correctness!!!
|
||||
|
||||
"""
|
||||
ctypes' types are container types.
|
||||
|
||||
They have an internal memory block, which only consists of some bytes,
|
||||
but it has to keep references to other objects as well. This is not
|
||||
really needed for trivial C types like int or char, but it is important
|
||||
for aggregate types like strings or pointers in particular.
|
||||
|
||||
What about pointers?
|
||||
|
||||
"""
|
||||
|
||||
class ObjectsTestCase(unittest.TestCase):
|
||||
def assertSame(self, a, b):
|
||||
self.assertEqual(id(a), id(b))
|
||||
|
||||
def test_ints(self):
|
||||
i = 42000123
|
||||
refcnt = grc(i)
|
||||
ci = c_int(i)
|
||||
self.assertEqual(refcnt, grc(i))
|
||||
self.assertEqual(ci._objects, None)
|
||||
|
||||
def test_c_char_p(self):
|
||||
s = "Hello, World"
|
||||
refcnt = grc(s)
|
||||
cs = c_char_p(s)
|
||||
self.assertEqual(refcnt + 1, grc(s))
|
||||
self.assertSame(cs._objects, s)
|
||||
|
||||
def test_simple_struct(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_int), ("b", c_int)]
|
||||
|
||||
a = 421234
|
||||
b = 421235
|
||||
x = X()
|
||||
self.assertEqual(x._objects, None)
|
||||
x.a = a
|
||||
x.b = b
|
||||
self.assertEqual(x._objects, None)
|
||||
|
||||
def test_embedded_structs(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_int), ("b", c_int)]
|
||||
|
||||
class Y(Structure):
|
||||
_fields_ = [("x", X), ("y", X)]
|
||||
|
||||
y = Y()
|
||||
self.assertEqual(y._objects, None)
|
||||
|
||||
x1, x2 = X(), X()
|
||||
y.x, y.y = x1, x2
|
||||
self.assertEqual(y._objects, {"0": {}, "1": {}})
|
||||
x1.a, x2.b = 42, 93
|
||||
self.assertEqual(y._objects, {"0": {}, "1": {}})
|
||||
|
||||
def test_xxx(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_char_p), ("b", c_char_p)]
|
||||
|
||||
class Y(Structure):
|
||||
_fields_ = [("x", X), ("y", X)]
|
||||
|
||||
s1 = "Hello, World"
|
||||
s2 = "Hallo, Welt"
|
||||
|
||||
x = X()
|
||||
x.a = s1
|
||||
x.b = s2
|
||||
self.assertEqual(x._objects, {"0": s1, "1": s2})
|
||||
|
||||
y = Y()
|
||||
y.x = x
|
||||
self.assertEqual(y._objects, {"0": {"0": s1, "1": s2}})
|
||||
## x = y.x
|
||||
## del y
|
||||
## print x._b_base_._objects
|
||||
|
||||
def test_ptr_struct(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("data", POINTER(c_int))]
|
||||
|
||||
A = c_int*4
|
||||
a = A(11, 22, 33, 44)
|
||||
self.assertEqual(a._objects, None)
|
||||
|
||||
x = X()
|
||||
x.data = a
|
||||
##XXX print x._objects
|
||||
##XXX print x.data[0]
|
||||
##XXX print x.data._objects
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
153
Lib/ctypes/test/test_keeprefs.py
Normal file
153
Lib/ctypes/test/test_keeprefs.py
Normal file
@@ -0,0 +1,153 @@
|
||||
from ctypes import *
|
||||
import unittest
|
||||
|
||||
class SimpleTestCase(unittest.TestCase):
|
||||
def test_cint(self):
|
||||
x = c_int()
|
||||
self.assertEqual(x._objects, None)
|
||||
x.value = 42
|
||||
self.assertEqual(x._objects, None)
|
||||
x = c_int(99)
|
||||
self.assertEqual(x._objects, None)
|
||||
|
||||
def test_ccharp(self):
|
||||
x = c_char_p()
|
||||
self.assertEqual(x._objects, None)
|
||||
x.value = "abc"
|
||||
self.assertEqual(x._objects, "abc")
|
||||
x = c_char_p("spam")
|
||||
self.assertEqual(x._objects, "spam")
|
||||
|
||||
class StructureTestCase(unittest.TestCase):
|
||||
def test_cint_struct(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_int),
|
||||
("b", c_int)]
|
||||
|
||||
x = X()
|
||||
self.assertEqual(x._objects, None)
|
||||
x.a = 42
|
||||
x.b = 99
|
||||
self.assertEqual(x._objects, None)
|
||||
|
||||
def test_ccharp_struct(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_char_p),
|
||||
("b", c_char_p)]
|
||||
x = X()
|
||||
self.assertEqual(x._objects, None)
|
||||
|
||||
x.a = "spam"
|
||||
x.b = "foo"
|
||||
self.assertEqual(x._objects, {"0": "spam", "1": "foo"})
|
||||
|
||||
def test_struct_struct(self):
|
||||
class POINT(Structure):
|
||||
_fields_ = [("x", c_int), ("y", c_int)]
|
||||
class RECT(Structure):
|
||||
_fields_ = [("ul", POINT), ("lr", POINT)]
|
||||
|
||||
r = RECT()
|
||||
r.ul.x = 0
|
||||
r.ul.y = 1
|
||||
r.lr.x = 2
|
||||
r.lr.y = 3
|
||||
self.assertEqual(r._objects, None)
|
||||
|
||||
r = RECT()
|
||||
pt = POINT(1, 2)
|
||||
r.ul = pt
|
||||
self.assertEqual(r._objects, {'0': {}})
|
||||
r.ul.x = 22
|
||||
r.ul.y = 44
|
||||
self.assertEqual(r._objects, {'0': {}})
|
||||
r.lr = POINT()
|
||||
self.assertEqual(r._objects, {'0': {}, '1': {}})
|
||||
|
||||
class ArrayTestCase(unittest.TestCase):
|
||||
def test_cint_array(self):
|
||||
INTARR = c_int * 3
|
||||
|
||||
ia = INTARR()
|
||||
self.assertEqual(ia._objects, None)
|
||||
ia[0] = 1
|
||||
ia[1] = 2
|
||||
ia[2] = 3
|
||||
self.assertEqual(ia._objects, None)
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("x", c_int),
|
||||
("a", INTARR)]
|
||||
|
||||
x = X()
|
||||
x.x = 1000
|
||||
x.a[0] = 42
|
||||
x.a[1] = 96
|
||||
self.assertEqual(x._objects, None)
|
||||
x.a = ia
|
||||
self.assertEqual(x._objects, {'1': {}})
|
||||
|
||||
class PointerTestCase(unittest.TestCase):
|
||||
def test_p_cint(self):
|
||||
i = c_int(42)
|
||||
x = pointer(i)
|
||||
self.assertEqual(x._objects, {'1': i})
|
||||
|
||||
class DeletePointerTestCase(unittest.TestCase):
|
||||
@unittest.skip('test disabled')
|
||||
def test_X(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("p", POINTER(c_char_p))]
|
||||
x = X()
|
||||
i = c_char_p("abc def")
|
||||
from sys import getrefcount as grc
|
||||
print "2?", grc(i)
|
||||
x.p = pointer(i)
|
||||
print "3?", grc(i)
|
||||
for i in range(320):
|
||||
c_int(99)
|
||||
x.p[0]
|
||||
print x.p[0]
|
||||
## del x
|
||||
## print "2?", grc(i)
|
||||
## del i
|
||||
import gc
|
||||
gc.collect()
|
||||
for i in range(320):
|
||||
c_int(99)
|
||||
x.p[0]
|
||||
print x.p[0]
|
||||
print x.p.contents
|
||||
## print x._objects
|
||||
|
||||
x.p[0] = "spam spam"
|
||||
## print x.p[0]
|
||||
print "+" * 42
|
||||
print x._objects
|
||||
|
||||
class PointerToStructure(unittest.TestCase):
|
||||
def test(self):
|
||||
class POINT(Structure):
|
||||
_fields_ = [("x", c_int), ("y", c_int)]
|
||||
class RECT(Structure):
|
||||
_fields_ = [("a", POINTER(POINT)),
|
||||
("b", POINTER(POINT))]
|
||||
r = RECT()
|
||||
p1 = POINT(1, 2)
|
||||
|
||||
r.a = pointer(p1)
|
||||
r.b = pointer(p1)
|
||||
## from pprint import pprint as pp
|
||||
## pp(p1._objects)
|
||||
## pp(r._objects)
|
||||
|
||||
r.a[0].x = 42
|
||||
r.a[0].y = 99
|
||||
|
||||
# to avoid leaking when tests are run several times
|
||||
# clean up the types left in the cache.
|
||||
from ctypes import _pointer_type_cache
|
||||
del _pointer_type_cache[POINT]
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
29
Lib/ctypes/test/test_libc.py
Normal file
29
Lib/ctypes/test/test_libc.py
Normal file
@@ -0,0 +1,29 @@
|
||||
import unittest
|
||||
|
||||
from ctypes import *
|
||||
import _ctypes_test
|
||||
|
||||
lib = CDLL(_ctypes_test.__file__)
|
||||
|
||||
class LibTest(unittest.TestCase):
|
||||
def test_sqrt(self):
|
||||
lib.my_sqrt.argtypes = c_double,
|
||||
lib.my_sqrt.restype = c_double
|
||||
self.assertEqual(lib.my_sqrt(4.0), 2.0)
|
||||
import math
|
||||
self.assertEqual(lib.my_sqrt(2.0), math.sqrt(2.0))
|
||||
|
||||
def test_qsort(self):
|
||||
comparefunc = CFUNCTYPE(c_int, POINTER(c_char), POINTER(c_char))
|
||||
lib.my_qsort.argtypes = c_void_p, c_size_t, c_size_t, comparefunc
|
||||
lib.my_qsort.restype = None
|
||||
|
||||
def sort(a, b):
|
||||
return cmp(a[0], b[0])
|
||||
|
||||
chars = create_string_buffer("spam, spam, and spam")
|
||||
lib.my_qsort(chars, len(chars)-1, sizeof(c_char), comparefunc(sort))
|
||||
self.assertEqual(chars.raw, " ,,aaaadmmmnpppsss\x00")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
121
Lib/ctypes/test/test_loading.py
Normal file
121
Lib/ctypes/test/test_loading.py
Normal file
@@ -0,0 +1,121 @@
|
||||
from ctypes import *
|
||||
import sys, unittest
|
||||
import os
|
||||
from ctypes.util import find_library
|
||||
from ctypes.test import is_resource_enabled
|
||||
import test.test_support as support
|
||||
|
||||
libc_name = None
|
||||
if os.name == "nt":
|
||||
libc_name = find_library("c")
|
||||
elif os.name == "ce":
|
||||
libc_name = "coredll"
|
||||
elif sys.platform == "cygwin":
|
||||
libc_name = "cygwin1.dll"
|
||||
else:
|
||||
libc_name = find_library("c")
|
||||
|
||||
if is_resource_enabled("printing"):
|
||||
print "libc_name is", libc_name
|
||||
|
||||
class LoaderTest(unittest.TestCase):
|
||||
|
||||
unknowndll = "xxrandomnamexx"
|
||||
|
||||
@unittest.skipUnless(libc_name is not None, 'could not find libc')
|
||||
def test_load(self):
|
||||
CDLL(libc_name)
|
||||
CDLL(os.path.basename(libc_name))
|
||||
self.assertRaises(OSError, CDLL, self.unknowndll)
|
||||
|
||||
@support.requires_unicode
|
||||
@unittest.skipUnless(libc_name is not None, 'could not find libc')
|
||||
def test_load_unicode(self):
|
||||
CDLL(unicode(libc_name))
|
||||
self.assertRaises(OSError, CDLL, unicode(self.unknowndll))
|
||||
|
||||
@unittest.skipUnless(libc_name is not None, 'could not find libc')
|
||||
@unittest.skipUnless(libc_name is not None and
|
||||
os.path.basename(libc_name) == "libc.so.6",
|
||||
'wrong libc path for test')
|
||||
def test_load_version(self):
|
||||
cdll.LoadLibrary("libc.so.6")
|
||||
# linux uses version, libc 9 should not exist
|
||||
self.assertRaises(OSError, cdll.LoadLibrary, "libc.so.9")
|
||||
self.assertRaises(OSError, cdll.LoadLibrary, self.unknowndll)
|
||||
|
||||
def test_find(self):
|
||||
for name in ("c", "m"):
|
||||
lib = find_library(name)
|
||||
if lib:
|
||||
cdll.LoadLibrary(lib)
|
||||
CDLL(lib)
|
||||
|
||||
@unittest.skipUnless(os.name in ("nt", "ce"),
|
||||
'test specific to Windows (NT/CE)')
|
||||
def test_load_library(self):
|
||||
self.assertIsNotNone(libc_name)
|
||||
if is_resource_enabled("printing"):
|
||||
print find_library("kernel32")
|
||||
print find_library("user32")
|
||||
|
||||
if os.name == "nt":
|
||||
windll.kernel32.GetModuleHandleW
|
||||
windll["kernel32"].GetModuleHandleW
|
||||
windll.LoadLibrary("kernel32").GetModuleHandleW
|
||||
WinDLL("kernel32").GetModuleHandleW
|
||||
elif os.name == "ce":
|
||||
windll.coredll.GetModuleHandleW
|
||||
windll["coredll"].GetModuleHandleW
|
||||
windll.LoadLibrary("coredll").GetModuleHandleW
|
||||
WinDLL("coredll").GetModuleHandleW
|
||||
|
||||
@unittest.skipUnless(os.name in ("nt", "ce"),
|
||||
'test specific to Windows (NT/CE)')
|
||||
def test_load_ordinal_functions(self):
|
||||
import _ctypes_test
|
||||
dll = WinDLL(_ctypes_test.__file__)
|
||||
# We load the same function both via ordinal and name
|
||||
func_ord = dll[2]
|
||||
func_name = dll.GetString
|
||||
# addressof gets the address where the function pointer is stored
|
||||
a_ord = addressof(func_ord)
|
||||
a_name = addressof(func_name)
|
||||
f_ord_addr = c_void_p.from_address(a_ord).value
|
||||
f_name_addr = c_void_p.from_address(a_name).value
|
||||
self.assertEqual(hex(f_ord_addr), hex(f_name_addr))
|
||||
|
||||
self.assertRaises(AttributeError, dll.__getitem__, 1234)
|
||||
|
||||
@unittest.skipUnless(os.name == "nt", 'Windows-specific test')
|
||||
def test_1703286_A(self):
|
||||
from _ctypes import LoadLibrary, FreeLibrary
|
||||
# On winXP 64-bit, advapi32 loads at an address that does
|
||||
# NOT fit into a 32-bit integer. FreeLibrary must be able
|
||||
# to accept this address.
|
||||
|
||||
# These are tests for http://www.python.org/sf/1703286
|
||||
handle = LoadLibrary("advapi32")
|
||||
FreeLibrary(handle)
|
||||
|
||||
@unittest.skipUnless(os.name == "nt", 'Windows-specific test')
|
||||
def test_1703286_B(self):
|
||||
# Since on winXP 64-bit advapi32 loads like described
|
||||
# above, the (arbitrarily selected) CloseEventLog function
|
||||
# also has a high address. 'call_function' should accept
|
||||
# addresses so large.
|
||||
from _ctypes import call_function
|
||||
advapi32 = windll.advapi32
|
||||
# Calling CloseEventLog with a NULL argument should fail,
|
||||
# but the call should not segfault or so.
|
||||
self.assertEqual(0, advapi32.CloseEventLog(None))
|
||||
windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p
|
||||
windll.kernel32.GetProcAddress.restype = c_void_p
|
||||
proc = windll.kernel32.GetProcAddress(advapi32._handle,
|
||||
"CloseEventLog")
|
||||
self.assertTrue(proc)
|
||||
# This is the real test: call the function via 'call_function'
|
||||
self.assertEqual(0, call_function(proc, (None,)))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
65
Lib/ctypes/test/test_macholib.py
Normal file
65
Lib/ctypes/test/test_macholib.py
Normal file
@@ -0,0 +1,65 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
# Bob Ippolito:
|
||||
"""
|
||||
Ok.. the code to find the filename for __getattr__ should look
|
||||
something like:
|
||||
|
||||
import os
|
||||
from macholib.dyld import dyld_find
|
||||
|
||||
def find_lib(name):
|
||||
possible = ['lib'+name+'.dylib', name+'.dylib',
|
||||
name+'.framework/'+name]
|
||||
for dylib in possible:
|
||||
try:
|
||||
return os.path.realpath(dyld_find(dylib))
|
||||
except ValueError:
|
||||
pass
|
||||
raise ValueError, "%s not found" % (name,)
|
||||
|
||||
It'll have output like this:
|
||||
|
||||
>>> find_lib('pthread')
|
||||
'/usr/lib/libSystem.B.dylib'
|
||||
>>> find_lib('z')
|
||||
'/usr/lib/libz.1.dylib'
|
||||
>>> find_lib('IOKit')
|
||||
'/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit'
|
||||
|
||||
-bob
|
||||
|
||||
"""
|
||||
|
||||
from ctypes.macholib.dyld import dyld_find
|
||||
|
||||
def find_lib(name):
|
||||
possible = ['lib'+name+'.dylib', name+'.dylib', name+'.framework/'+name]
|
||||
for dylib in possible:
|
||||
try:
|
||||
return os.path.realpath(dyld_find(dylib))
|
||||
except ValueError:
|
||||
pass
|
||||
raise ValueError("%s not found" % (name,))
|
||||
|
||||
class MachOTest(unittest.TestCase):
|
||||
@unittest.skipUnless(sys.platform == "darwin", 'OSX-specific test')
|
||||
def test_find(self):
|
||||
|
||||
self.assertEqual(find_lib('pthread'),
|
||||
'/usr/lib/libSystem.B.dylib')
|
||||
|
||||
result = find_lib('z')
|
||||
# Issue #21093: dyld default search path includes $HOME/lib and
|
||||
# /usr/local/lib before /usr/lib, which caused test failures if
|
||||
# a local copy of libz exists in one of them. Now ignore the head
|
||||
# of the path.
|
||||
self.assertRegexpMatches(result, r".*/lib/libz\..*.*\.dylib")
|
||||
|
||||
self.assertEqual(find_lib('IOKit'),
|
||||
'/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit')
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
77
Lib/ctypes/test/test_memfunctions.py
Normal file
77
Lib/ctypes/test/test_memfunctions.py
Normal file
@@ -0,0 +1,77 @@
|
||||
import sys
|
||||
import unittest
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
|
||||
class MemFunctionsTest(unittest.TestCase):
|
||||
@unittest.skip('test disabled')
|
||||
def test_overflow(self):
|
||||
# string_at and wstring_at must use the Python calling
|
||||
# convention (which acquires the GIL and checks the Python
|
||||
# error flag). Provoke an error and catch it; see also issue
|
||||
# #3554: <http://bugs.python.org/issue3554>
|
||||
self.assertRaises((OverflowError, MemoryError, SystemError),
|
||||
lambda: wstring_at(u"foo", sys.maxint - 1))
|
||||
self.assertRaises((OverflowError, MemoryError, SystemError),
|
||||
lambda: string_at("foo", sys.maxint - 1))
|
||||
|
||||
def test_memmove(self):
|
||||
# large buffers apparently increase the chance that the memory
|
||||
# is allocated in high address space.
|
||||
a = create_string_buffer(1000000)
|
||||
p = "Hello, World"
|
||||
result = memmove(a, p, len(p))
|
||||
self.assertEqual(a.value, "Hello, World")
|
||||
|
||||
self.assertEqual(string_at(result), "Hello, World")
|
||||
self.assertEqual(string_at(result, 5), "Hello")
|
||||
self.assertEqual(string_at(result, 16), "Hello, World\0\0\0\0")
|
||||
self.assertEqual(string_at(result, 0), "")
|
||||
|
||||
def test_memset(self):
|
||||
a = create_string_buffer(1000000)
|
||||
result = memset(a, ord('x'), 16)
|
||||
self.assertEqual(a.value, "xxxxxxxxxxxxxxxx")
|
||||
|
||||
self.assertEqual(string_at(result), "xxxxxxxxxxxxxxxx")
|
||||
self.assertEqual(string_at(a), "xxxxxxxxxxxxxxxx")
|
||||
self.assertEqual(string_at(a, 20), "xxxxxxxxxxxxxxxx\0\0\0\0")
|
||||
|
||||
def test_cast(self):
|
||||
a = (c_ubyte * 32)(*map(ord, "abcdef"))
|
||||
self.assertEqual(cast(a, c_char_p).value, "abcdef")
|
||||
self.assertEqual(cast(a, POINTER(c_byte))[:7],
|
||||
[97, 98, 99, 100, 101, 102, 0])
|
||||
self.assertEqual(cast(a, POINTER(c_byte))[:7:],
|
||||
[97, 98, 99, 100, 101, 102, 0])
|
||||
self.assertEqual(cast(a, POINTER(c_byte))[6:-1:-1],
|
||||
[0, 102, 101, 100, 99, 98, 97])
|
||||
self.assertEqual(cast(a, POINTER(c_byte))[:7:2],
|
||||
[97, 99, 101, 0])
|
||||
self.assertEqual(cast(a, POINTER(c_byte))[:7:7],
|
||||
[97])
|
||||
|
||||
def test_string_at(self):
|
||||
s = string_at("foo bar")
|
||||
# XXX The following may be wrong, depending on how Python
|
||||
# manages string instances
|
||||
self.assertEqual(2, sys.getrefcount(s))
|
||||
self.assertTrue(s, "foo bar")
|
||||
|
||||
self.assertEqual(string_at("foo bar", 8), "foo bar\0")
|
||||
self.assertEqual(string_at("foo bar", 3), "foo")
|
||||
|
||||
@need_symbol('create_unicode_buffer')
|
||||
def test_wstring_at(self):
|
||||
p = create_unicode_buffer("Hello, World")
|
||||
a = create_unicode_buffer(1000000)
|
||||
result = memmove(a, p, len(p) * sizeof(c_wchar))
|
||||
self.assertEqual(a.value, "Hello, World")
|
||||
|
||||
self.assertEqual(wstring_at(a), "Hello, World")
|
||||
self.assertEqual(wstring_at(a, 5), "Hello")
|
||||
self.assertEqual(wstring_at(a, 16), "Hello, World\0\0\0\0")
|
||||
self.assertEqual(wstring_at(a, 0), "")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
289
Lib/ctypes/test/test_numbers.py
Normal file
289
Lib/ctypes/test/test_numbers.py
Normal file
@@ -0,0 +1,289 @@
|
||||
from ctypes import *
|
||||
import unittest
|
||||
import struct
|
||||
|
||||
def valid_ranges(*types):
|
||||
# given a sequence of numeric types, collect their _type_
|
||||
# attribute, which is a single format character compatible with
|
||||
# the struct module, use the struct module to calculate the
|
||||
# minimum and maximum value allowed for this format.
|
||||
# Returns a list of (min, max) values.
|
||||
result = []
|
||||
for t in types:
|
||||
fmt = t._type_
|
||||
size = struct.calcsize(fmt)
|
||||
a = struct.unpack(fmt, ("\x00"*32)[:size])[0]
|
||||
b = struct.unpack(fmt, ("\xFF"*32)[:size])[0]
|
||||
c = struct.unpack(fmt, ("\x7F"+"\x00"*32)[:size])[0]
|
||||
d = struct.unpack(fmt, ("\x80"+"\xFF"*32)[:size])[0]
|
||||
result.append((min(a, b, c, d), max(a, b, c, d)))
|
||||
return result
|
||||
|
||||
ArgType = type(byref(c_int(0)))
|
||||
|
||||
unsigned_types = [c_ubyte, c_ushort, c_uint, c_ulong]
|
||||
signed_types = [c_byte, c_short, c_int, c_long, c_longlong]
|
||||
|
||||
bool_types = []
|
||||
|
||||
float_types = [c_double, c_float]
|
||||
|
||||
try:
|
||||
c_ulonglong
|
||||
c_longlong
|
||||
except NameError:
|
||||
pass
|
||||
else:
|
||||
unsigned_types.append(c_ulonglong)
|
||||
signed_types.append(c_longlong)
|
||||
|
||||
try:
|
||||
c_bool
|
||||
except NameError:
|
||||
pass
|
||||
else:
|
||||
bool_types.append(c_bool)
|
||||
|
||||
unsigned_ranges = valid_ranges(*unsigned_types)
|
||||
signed_ranges = valid_ranges(*signed_types)
|
||||
bool_values = [True, False, 0, 1, -1, 5000, 'test', [], [1]]
|
||||
|
||||
################################################################
|
||||
|
||||
class NumberTestCase(unittest.TestCase):
|
||||
|
||||
def test_default_init(self):
|
||||
# default values are set to zero
|
||||
for t in signed_types + unsigned_types + float_types:
|
||||
self.assertEqual(t().value, 0)
|
||||
|
||||
def test_unsigned_values(self):
|
||||
# the value given to the constructor is available
|
||||
# as the 'value' attribute
|
||||
for t, (l, h) in zip(unsigned_types, unsigned_ranges):
|
||||
self.assertEqual(t(l).value, l)
|
||||
self.assertEqual(t(h).value, h)
|
||||
|
||||
def test_signed_values(self):
|
||||
# see above
|
||||
for t, (l, h) in zip(signed_types, signed_ranges):
|
||||
self.assertEqual(t(l).value, l)
|
||||
self.assertEqual(t(h).value, h)
|
||||
|
||||
def test_bool_values(self):
|
||||
from operator import truth
|
||||
for t, v in zip(bool_types, bool_values):
|
||||
self.assertEqual(t(v).value, truth(v))
|
||||
|
||||
def test_typeerror(self):
|
||||
# Only numbers are allowed in the constructor,
|
||||
# otherwise TypeError is raised
|
||||
for t in signed_types + unsigned_types + float_types:
|
||||
self.assertRaises(TypeError, t, "")
|
||||
self.assertRaises(TypeError, t, None)
|
||||
|
||||
@unittest.skip('test disabled')
|
||||
def test_valid_ranges(self):
|
||||
# invalid values of the correct type
|
||||
# raise ValueError (not OverflowError)
|
||||
for t, (l, h) in zip(unsigned_types, unsigned_ranges):
|
||||
self.assertRaises(ValueError, t, l-1)
|
||||
self.assertRaises(ValueError, t, h+1)
|
||||
|
||||
def test_from_param(self):
|
||||
# the from_param class method attribute always
|
||||
# returns PyCArgObject instances
|
||||
for t in signed_types + unsigned_types + float_types:
|
||||
self.assertEqual(ArgType, type(t.from_param(0)))
|
||||
|
||||
def test_byref(self):
|
||||
# calling byref returns also a PyCArgObject instance
|
||||
for t in signed_types + unsigned_types + float_types + bool_types:
|
||||
parm = byref(t())
|
||||
self.assertEqual(ArgType, type(parm))
|
||||
|
||||
|
||||
def test_floats(self):
|
||||
# c_float and c_double can be created from
|
||||
# Python int, long and float
|
||||
class FloatLike(object):
|
||||
def __float__(self):
|
||||
return 2.0
|
||||
f = FloatLike()
|
||||
for t in float_types:
|
||||
self.assertEqual(t(2.0).value, 2.0)
|
||||
self.assertEqual(t(2).value, 2.0)
|
||||
self.assertEqual(t(2L).value, 2.0)
|
||||
self.assertEqual(t(f).value, 2.0)
|
||||
|
||||
def test_integers(self):
|
||||
class FloatLike(object):
|
||||
def __float__(self):
|
||||
return 2.0
|
||||
f = FloatLike()
|
||||
class IntLike(object):
|
||||
def __int__(self):
|
||||
return 2
|
||||
i = IntLike()
|
||||
# integers cannot be constructed from floats,
|
||||
# but from integer-like objects
|
||||
for t in signed_types + unsigned_types:
|
||||
self.assertRaises(TypeError, t, 3.14)
|
||||
self.assertRaises(TypeError, t, f)
|
||||
self.assertEqual(t(i).value, 2)
|
||||
|
||||
def test_sizes(self):
|
||||
for t in signed_types + unsigned_types + float_types + bool_types:
|
||||
try:
|
||||
size = struct.calcsize(t._type_)
|
||||
except struct.error:
|
||||
continue
|
||||
# sizeof of the type...
|
||||
self.assertEqual(sizeof(t), size)
|
||||
# and sizeof of an instance
|
||||
self.assertEqual(sizeof(t()), size)
|
||||
|
||||
def test_alignments(self):
|
||||
for t in signed_types + unsigned_types + float_types:
|
||||
code = t._type_ # the typecode
|
||||
align = struct.calcsize("c%c" % code) - struct.calcsize(code)
|
||||
|
||||
# alignment of the type...
|
||||
self.assertEqual((code, alignment(t)),
|
||||
(code, align))
|
||||
# and alignment of an instance
|
||||
self.assertEqual((code, alignment(t())),
|
||||
(code, align))
|
||||
|
||||
def test_int_from_address(self):
|
||||
from array import array
|
||||
for t in signed_types + unsigned_types:
|
||||
# the array module doesn't support all format codes
|
||||
# (no 'q' or 'Q')
|
||||
try:
|
||||
array(t._type_)
|
||||
except ValueError:
|
||||
continue
|
||||
a = array(t._type_, [100])
|
||||
|
||||
# v now is an integer at an 'external' memory location
|
||||
v = t.from_address(a.buffer_info()[0])
|
||||
self.assertEqual(v.value, a[0])
|
||||
self.assertEqual(type(v), t)
|
||||
|
||||
# changing the value at the memory location changes v's value also
|
||||
a[0] = 42
|
||||
self.assertEqual(v.value, a[0])
|
||||
|
||||
|
||||
def test_float_from_address(self):
|
||||
from array import array
|
||||
for t in float_types:
|
||||
a = array(t._type_, [3.14])
|
||||
v = t.from_address(a.buffer_info()[0])
|
||||
self.assertEqual(v.value, a[0])
|
||||
self.assertIs(type(v), t)
|
||||
a[0] = 2.3456e17
|
||||
self.assertEqual(v.value, a[0])
|
||||
self.assertIs(type(v), t)
|
||||
|
||||
def test_char_from_address(self):
|
||||
from ctypes import c_char
|
||||
from array import array
|
||||
|
||||
a = array('c', 'x')
|
||||
v = c_char.from_address(a.buffer_info()[0])
|
||||
self.assertEqual(v.value, a[0])
|
||||
self.assertIs(type(v), c_char)
|
||||
|
||||
a[0] = '?'
|
||||
self.assertEqual(v.value, a[0])
|
||||
|
||||
# array does not support c_bool / 't'
|
||||
@unittest.skip('test disabled')
|
||||
def test_bool_from_address(self):
|
||||
from ctypes import c_bool
|
||||
from array import array
|
||||
a = array(c_bool._type_, [True])
|
||||
v = t.from_address(a.buffer_info()[0])
|
||||
self.assertEqual(v.value, a[0])
|
||||
self.assertEqual(type(v) is t)
|
||||
a[0] = False
|
||||
self.assertEqual(v.value, a[0])
|
||||
self.assertEqual(type(v) is t)
|
||||
|
||||
def test_init(self):
|
||||
# c_int() can be initialized from Python's int, and c_int.
|
||||
# Not from c_long or so, which seems strange, abc should
|
||||
# probably be changed:
|
||||
self.assertRaises(TypeError, c_int, c_long(42))
|
||||
|
||||
def test_float_overflow(self):
|
||||
import sys
|
||||
big_int = int(sys.float_info.max) * 2
|
||||
for t in float_types + [c_longdouble]:
|
||||
self.assertRaises(OverflowError, t, big_int)
|
||||
if (hasattr(t, "__ctype_be__")):
|
||||
self.assertRaises(OverflowError, t.__ctype_be__, big_int)
|
||||
if (hasattr(t, "__ctype_le__")):
|
||||
self.assertRaises(OverflowError, t.__ctype_le__, big_int)
|
||||
|
||||
@unittest.skip('test disabled')
|
||||
def test_perf(self):
|
||||
check_perf()
|
||||
|
||||
from ctypes import _SimpleCData
|
||||
class c_int_S(_SimpleCData):
|
||||
_type_ = "i"
|
||||
__slots__ = []
|
||||
|
||||
def run_test(rep, msg, func, arg=None):
|
||||
## items = [None] * rep
|
||||
items = range(rep)
|
||||
from time import clock
|
||||
if arg is not None:
|
||||
start = clock()
|
||||
for i in items:
|
||||
func(arg); func(arg); func(arg); func(arg); func(arg)
|
||||
stop = clock()
|
||||
else:
|
||||
start = clock()
|
||||
for i in items:
|
||||
func(); func(); func(); func(); func()
|
||||
stop = clock()
|
||||
print "%15s: %.2f us" % (msg, ((stop-start)*1e6/5/rep))
|
||||
|
||||
def check_perf():
|
||||
# Construct 5 objects
|
||||
from ctypes import c_int
|
||||
|
||||
REP = 200000
|
||||
|
||||
run_test(REP, "int()", int)
|
||||
run_test(REP, "int(999)", int)
|
||||
run_test(REP, "c_int()", c_int)
|
||||
run_test(REP, "c_int(999)", c_int)
|
||||
run_test(REP, "c_int_S()", c_int_S)
|
||||
run_test(REP, "c_int_S(999)", c_int_S)
|
||||
|
||||
# Python 2.3 -OO, win2k, P4 700 MHz:
|
||||
#
|
||||
# int(): 0.87 us
|
||||
# int(999): 0.87 us
|
||||
# c_int(): 3.35 us
|
||||
# c_int(999): 3.34 us
|
||||
# c_int_S(): 3.23 us
|
||||
# c_int_S(999): 3.24 us
|
||||
|
||||
# Python 2.2 -OO, win2k, P4 700 MHz:
|
||||
#
|
||||
# int(): 0.89 us
|
||||
# int(999): 0.89 us
|
||||
# c_int(): 9.99 us
|
||||
# c_int(999): 10.02 us
|
||||
# c_int_S(): 9.87 us
|
||||
# c_int_S(999): 9.85 us
|
||||
|
||||
if __name__ == '__main__':
|
||||
## check_perf()
|
||||
unittest.main()
|
||||
67
Lib/ctypes/test/test_objects.py
Normal file
67
Lib/ctypes/test/test_objects.py
Normal file
@@ -0,0 +1,67 @@
|
||||
r'''
|
||||
This tests the '_objects' attribute of ctypes instances. '_objects'
|
||||
holds references to objects that must be kept alive as long as the
|
||||
ctypes instance, to make sure that the memory buffer is valid.
|
||||
|
||||
WARNING: The '_objects' attribute is exposed ONLY for debugging ctypes itself,
|
||||
it MUST NEVER BE MODIFIED!
|
||||
|
||||
'_objects' is initialized to a dictionary on first use, before that it
|
||||
is None.
|
||||
|
||||
Here is an array of string pointers:
|
||||
|
||||
>>> from ctypes import *
|
||||
>>> array = (c_char_p * 5)()
|
||||
>>> print array._objects
|
||||
None
|
||||
>>>
|
||||
|
||||
The memory block stores pointers to strings, and the strings itself
|
||||
assigned from Python must be kept.
|
||||
|
||||
>>> array[4] = 'foo bar'
|
||||
>>> array._objects
|
||||
{'4': 'foo bar'}
|
||||
>>> array[4]
|
||||
'foo bar'
|
||||
>>>
|
||||
|
||||
It gets more complicated when the ctypes instance itself is contained
|
||||
in a 'base' object.
|
||||
|
||||
>>> class X(Structure):
|
||||
... _fields_ = [("x", c_int), ("y", c_int), ("array", c_char_p * 5)]
|
||||
...
|
||||
>>> x = X()
|
||||
>>> print x._objects
|
||||
None
|
||||
>>>
|
||||
|
||||
The'array' attribute of the 'x' object shares part of the memory buffer
|
||||
of 'x' ('_b_base_' is either None, or the root object owning the memory block):
|
||||
|
||||
>>> print x.array._b_base_ # doctest: +ELLIPSIS
|
||||
<ctypes.test.test_objects.X object at 0x...>
|
||||
>>>
|
||||
|
||||
>>> x.array[0] = 'spam spam spam'
|
||||
>>> x._objects
|
||||
{'0:2': 'spam spam spam'}
|
||||
>>> x.array._b_base_._objects
|
||||
{'0:2': 'spam spam spam'}
|
||||
>>>
|
||||
|
||||
'''
|
||||
|
||||
import unittest, doctest, sys
|
||||
|
||||
import ctypes.test.test_objects
|
||||
|
||||
class TestCase(unittest.TestCase):
|
||||
def test(self):
|
||||
failures, tests = doctest.testmod(ctypes.test.test_objects)
|
||||
self.assertFalse(failures, 'doctests failed, see output above')
|
||||
|
||||
if __name__ == '__main__':
|
||||
doctest.testmod(ctypes.test.test_objects)
|
||||
212
Lib/ctypes/test/test_parameters.py
Normal file
212
Lib/ctypes/test/test_parameters.py
Normal file
@@ -0,0 +1,212 @@
|
||||
import unittest, sys
|
||||
from ctypes.test import need_symbol
|
||||
import test.support
|
||||
|
||||
class SimpleTypesTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
import ctypes
|
||||
try:
|
||||
from _ctypes import set_conversion_mode
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
self.prev_conv_mode = set_conversion_mode("ascii", "strict")
|
||||
|
||||
def tearDown(self):
|
||||
try:
|
||||
from _ctypes import set_conversion_mode
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
set_conversion_mode(*self.prev_conv_mode)
|
||||
|
||||
|
||||
def test_subclasses(self):
|
||||
from ctypes import c_void_p, c_char_p
|
||||
# ctypes 0.9.5 and before did overwrite from_param in SimpleType_new
|
||||
class CVOIDP(c_void_p):
|
||||
def from_param(cls, value):
|
||||
return value * 2
|
||||
from_param = classmethod(from_param)
|
||||
|
||||
class CCHARP(c_char_p):
|
||||
def from_param(cls, value):
|
||||
return value * 4
|
||||
from_param = classmethod(from_param)
|
||||
|
||||
self.assertEqual(CVOIDP.from_param("abc"), "abcabc")
|
||||
self.assertEqual(CCHARP.from_param("abc"), "abcabcabcabc")
|
||||
|
||||
@need_symbol('c_wchar_p')
|
||||
def test_subclasses_c_wchar_p(self):
|
||||
from ctypes import c_wchar_p
|
||||
|
||||
class CWCHARP(c_wchar_p):
|
||||
def from_param(cls, value):
|
||||
return value * 3
|
||||
from_param = classmethod(from_param)
|
||||
|
||||
self.assertEqual(CWCHARP.from_param("abc"), "abcabcabc")
|
||||
|
||||
# XXX Replace by c_char_p tests
|
||||
def test_cstrings(self):
|
||||
from ctypes import c_char_p, byref
|
||||
|
||||
# c_char_p.from_param on a Python String packs the string
|
||||
# into a cparam object
|
||||
s = "123"
|
||||
self.assertIs(c_char_p.from_param(s)._obj, s)
|
||||
|
||||
# new in 0.9.1: convert (encode) unicode to ascii
|
||||
self.assertEqual(c_char_p.from_param(u"123")._obj, "123")
|
||||
self.assertRaises(UnicodeEncodeError, c_char_p.from_param, u"123\377")
|
||||
|
||||
self.assertRaises(TypeError, c_char_p.from_param, 42)
|
||||
|
||||
# calling c_char_p.from_param with a c_char_p instance
|
||||
# returns the argument itself:
|
||||
a = c_char_p("123")
|
||||
self.assertIs(c_char_p.from_param(a), a)
|
||||
|
||||
@need_symbol('c_wchar_p')
|
||||
def test_cw_strings(self):
|
||||
from ctypes import byref, c_wchar_p
|
||||
s = u"123"
|
||||
if sys.platform == "win32":
|
||||
self.assertTrue(c_wchar_p.from_param(s)._obj is s)
|
||||
self.assertRaises(TypeError, c_wchar_p.from_param, 42)
|
||||
|
||||
# new in 0.9.1: convert (decode) ascii to unicode
|
||||
self.assertEqual(c_wchar_p.from_param("123")._obj, u"123")
|
||||
self.assertRaises(UnicodeDecodeError, c_wchar_p.from_param, "123\377")
|
||||
|
||||
pa = c_wchar_p.from_param(c_wchar_p(u"123"))
|
||||
self.assertEqual(type(pa), c_wchar_p)
|
||||
|
||||
def test_int_pointers(self):
|
||||
from ctypes import c_short, c_uint, c_int, c_long, POINTER, pointer
|
||||
LPINT = POINTER(c_int)
|
||||
|
||||
## p = pointer(c_int(42))
|
||||
## x = LPINT.from_param(p)
|
||||
x = LPINT.from_param(pointer(c_int(42)))
|
||||
self.assertEqual(x.contents.value, 42)
|
||||
self.assertEqual(LPINT(c_int(42)).contents.value, 42)
|
||||
|
||||
self.assertEqual(LPINT.from_param(None), None)
|
||||
|
||||
if c_int != c_long:
|
||||
self.assertRaises(TypeError, LPINT.from_param, pointer(c_long(42)))
|
||||
self.assertRaises(TypeError, LPINT.from_param, pointer(c_uint(42)))
|
||||
self.assertRaises(TypeError, LPINT.from_param, pointer(c_short(42)))
|
||||
|
||||
def test_byref_pointer(self):
|
||||
# The from_param class method of POINTER(typ) classes accepts what is
|
||||
# returned by byref(obj), it type(obj) == typ
|
||||
from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
|
||||
LPINT = POINTER(c_int)
|
||||
|
||||
LPINT.from_param(byref(c_int(42)))
|
||||
|
||||
self.assertRaises(TypeError, LPINT.from_param, byref(c_short(22)))
|
||||
if c_int != c_long:
|
||||
self.assertRaises(TypeError, LPINT.from_param, byref(c_long(22)))
|
||||
self.assertRaises(TypeError, LPINT.from_param, byref(c_uint(22)))
|
||||
|
||||
def test_byref_pointerpointer(self):
|
||||
# See above
|
||||
from ctypes import c_short, c_uint, c_int, c_long, pointer, POINTER, byref
|
||||
|
||||
LPLPINT = POINTER(POINTER(c_int))
|
||||
LPLPINT.from_param(byref(pointer(c_int(42))))
|
||||
|
||||
self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_short(22))))
|
||||
if c_int != c_long:
|
||||
self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_long(22))))
|
||||
self.assertRaises(TypeError, LPLPINT.from_param, byref(pointer(c_uint(22))))
|
||||
|
||||
def test_array_pointers(self):
|
||||
from ctypes import c_short, c_uint, c_int, c_long, POINTER
|
||||
INTARRAY = c_int * 3
|
||||
ia = INTARRAY()
|
||||
self.assertEqual(len(ia), 3)
|
||||
self.assertEqual([ia[i] for i in range(3)], [0, 0, 0])
|
||||
|
||||
# Pointers are only compatible with arrays containing items of
|
||||
# the same type!
|
||||
LPINT = POINTER(c_int)
|
||||
LPINT.from_param((c_int*3)())
|
||||
self.assertRaises(TypeError, LPINT.from_param, c_short*3)
|
||||
self.assertRaises(TypeError, LPINT.from_param, c_long*3)
|
||||
self.assertRaises(TypeError, LPINT.from_param, c_uint*3)
|
||||
|
||||
def test_noctypes_argtype(self):
|
||||
import _ctypes_test
|
||||
from ctypes import CDLL, c_void_p, ArgumentError
|
||||
|
||||
func = CDLL(_ctypes_test.__file__)._testfunc_p_p
|
||||
func.restype = c_void_p
|
||||
# TypeError: has no from_param method
|
||||
self.assertRaises(TypeError, setattr, func, "argtypes", (object,))
|
||||
|
||||
class Adapter(object):
|
||||
def from_param(cls, obj):
|
||||
return None
|
||||
|
||||
func.argtypes = (Adapter(),)
|
||||
self.assertEqual(func(None), None)
|
||||
self.assertEqual(func(object()), None)
|
||||
|
||||
class Adapter(object):
|
||||
def from_param(cls, obj):
|
||||
return obj
|
||||
|
||||
func.argtypes = (Adapter(),)
|
||||
# don't know how to convert parameter 1
|
||||
self.assertRaises(ArgumentError, func, object())
|
||||
self.assertEqual(func(c_void_p(42)), 42)
|
||||
|
||||
class Adapter(object):
|
||||
def from_param(cls, obj):
|
||||
raise ValueError(obj)
|
||||
|
||||
func.argtypes = (Adapter(),)
|
||||
# ArgumentError: argument 1: ValueError: 99
|
||||
self.assertRaises(ArgumentError, func, 99)
|
||||
|
||||
def test_abstract(self):
|
||||
from ctypes import (Array, Structure, Union, _Pointer,
|
||||
_SimpleCData, _CFuncPtr)
|
||||
|
||||
self.assertRaises(TypeError, Array.from_param, 42)
|
||||
self.assertRaises(TypeError, Structure.from_param, 42)
|
||||
self.assertRaises(TypeError, Union.from_param, 42)
|
||||
self.assertRaises(TypeError, _CFuncPtr.from_param, 42)
|
||||
self.assertRaises(TypeError, _Pointer.from_param, 42)
|
||||
self.assertRaises(TypeError, _SimpleCData.from_param, 42)
|
||||
|
||||
@test.support.cpython_only
|
||||
def test_issue31311(self):
|
||||
# __setstate__ should neither raise a SystemError nor crash in case
|
||||
# of a bad __dict__.
|
||||
from ctypes import Structure
|
||||
|
||||
class BadStruct(Structure):
|
||||
@property
|
||||
def __dict__(self):
|
||||
pass
|
||||
with self.assertRaises(TypeError):
|
||||
BadStruct().__setstate__({}, b'foo')
|
||||
|
||||
class WorseStruct(Structure):
|
||||
@property
|
||||
def __dict__(self):
|
||||
1/0.0
|
||||
with self.assertRaises(ZeroDivisionError):
|
||||
WorseStruct().__setstate__({}, b'foo')
|
||||
|
||||
################################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
230
Lib/ctypes/test/test_pep3118.py
Normal file
230
Lib/ctypes/test/test_pep3118.py
Normal file
@@ -0,0 +1,230 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
import re, sys
|
||||
|
||||
if sys.byteorder == "little":
|
||||
THIS_ENDIAN = "<"
|
||||
OTHER_ENDIAN = ">"
|
||||
else:
|
||||
THIS_ENDIAN = ">"
|
||||
OTHER_ENDIAN = "<"
|
||||
|
||||
def normalize(format):
|
||||
# Remove current endian specifier and white space from a format
|
||||
# string
|
||||
if format is None:
|
||||
return ""
|
||||
format = format.replace(OTHER_ENDIAN, THIS_ENDIAN)
|
||||
return re.sub(r"\s", "", format)
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def test_native_types(self):
|
||||
for tp, fmt, shape, itemtp in native_types:
|
||||
ob = tp()
|
||||
v = memoryview(ob)
|
||||
try:
|
||||
self.assertEqual(normalize(v.format), normalize(fmt))
|
||||
if shape is not None:
|
||||
self.assertEqual(len(v), shape[0])
|
||||
else:
|
||||
self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob))
|
||||
self.assertEqual(v.itemsize, sizeof(itemtp))
|
||||
self.assertEqual(v.shape, shape)
|
||||
# ctypes object always have a non-strided memory block
|
||||
self.assertEqual(v.strides, None)
|
||||
# they are always read/write
|
||||
self.assertFalse(v.readonly)
|
||||
|
||||
if v.shape:
|
||||
n = 1
|
||||
for dim in v.shape:
|
||||
n = n * dim
|
||||
self.assertEqual(n * v.itemsize, len(v.tobytes()))
|
||||
except:
|
||||
# so that we can see the failing type
|
||||
print(tp)
|
||||
raise
|
||||
|
||||
def test_endian_types(self):
|
||||
for tp, fmt, shape, itemtp in endian_types:
|
||||
ob = tp()
|
||||
v = memoryview(ob)
|
||||
try:
|
||||
self.assertEqual(v.format, fmt)
|
||||
if shape is not None:
|
||||
self.assertEqual(len(v), shape[0])
|
||||
else:
|
||||
self.assertEqual(len(v) * sizeof(itemtp), sizeof(ob))
|
||||
self.assertEqual(v.itemsize, sizeof(itemtp))
|
||||
self.assertEqual(v.shape, shape)
|
||||
# ctypes object always have a non-strided memory block
|
||||
self.assertEqual(v.strides, None)
|
||||
# they are always read/write
|
||||
self.assertFalse(v.readonly)
|
||||
|
||||
if v.shape:
|
||||
n = 1
|
||||
for dim in v.shape:
|
||||
n = n * dim
|
||||
self.assertEqual(n, len(v))
|
||||
except:
|
||||
# so that we can see the failing type
|
||||
print(tp)
|
||||
raise
|
||||
|
||||
# define some structure classes
|
||||
|
||||
class Point(Structure):
|
||||
_fields_ = [("x", c_long), ("y", c_long)]
|
||||
|
||||
class PackedPoint(Structure):
|
||||
_pack_ = 2
|
||||
_fields_ = [("x", c_long), ("y", c_long)]
|
||||
|
||||
class Point2(Structure):
|
||||
pass
|
||||
Point2._fields_ = [("x", c_long), ("y", c_long)]
|
||||
|
||||
class EmptyStruct(Structure):
|
||||
_fields_ = []
|
||||
|
||||
class aUnion(Union):
|
||||
_fields_ = [("a", c_int)]
|
||||
|
||||
class StructWithArrays(Structure):
|
||||
_fields_ = [("x", c_long * 3 * 2), ("y", Point * 4)]
|
||||
|
||||
|
||||
class Incomplete(Structure):
|
||||
pass
|
||||
|
||||
class Complete(Structure):
|
||||
pass
|
||||
PComplete = POINTER(Complete)
|
||||
Complete._fields_ = [("a", c_long)]
|
||||
|
||||
################################################################
|
||||
#
|
||||
# This table contains format strings as they look on little endian
|
||||
# machines. The test replaces '<' with '>' on big endian machines.
|
||||
#
|
||||
|
||||
# Platform-specific type codes
|
||||
s_bool = {1: '?', 2: 'H', 4: 'L', 8: 'Q'}[sizeof(c_bool)]
|
||||
s_short = {2: 'h', 4: 'l', 8: 'q'}[sizeof(c_short)]
|
||||
s_ushort = {2: 'H', 4: 'L', 8: 'Q'}[sizeof(c_ushort)]
|
||||
s_int = {2: 'h', 4: 'i', 8: 'q'}[sizeof(c_int)]
|
||||
s_uint = {2: 'H', 4: 'I', 8: 'Q'}[sizeof(c_uint)]
|
||||
s_long = {4: 'l', 8: 'q'}[sizeof(c_long)]
|
||||
s_ulong = {4: 'L', 8: 'Q'}[sizeof(c_ulong)]
|
||||
s_longlong = "q"
|
||||
s_ulonglong = "Q"
|
||||
s_float = "f"
|
||||
s_double = "d"
|
||||
s_longdouble = "g"
|
||||
|
||||
# Alias definitions in ctypes/__init__.py
|
||||
if c_int is c_long:
|
||||
s_int = s_long
|
||||
if c_uint is c_ulong:
|
||||
s_uint = s_ulong
|
||||
if c_longlong is c_long:
|
||||
s_longlong = s_long
|
||||
if c_ulonglong is c_ulong:
|
||||
s_ulonglong = s_ulong
|
||||
if c_longdouble is c_double:
|
||||
s_longdouble = s_double
|
||||
|
||||
|
||||
native_types = [
|
||||
# type format shape calc itemsize
|
||||
|
||||
## simple types
|
||||
|
||||
(c_char, "<c", None, c_char),
|
||||
(c_byte, "<b", None, c_byte),
|
||||
(c_ubyte, "<B", None, c_ubyte),
|
||||
(c_short, "<" + s_short, None, c_short),
|
||||
(c_ushort, "<" + s_ushort, None, c_ushort),
|
||||
|
||||
(c_int, "<" + s_int, None, c_int),
|
||||
(c_uint, "<" + s_uint, None, c_uint),
|
||||
|
||||
(c_long, "<" + s_long, None, c_long),
|
||||
(c_ulong, "<" + s_ulong, None, c_ulong),
|
||||
|
||||
(c_longlong, "<" + s_longlong, None, c_longlong),
|
||||
(c_ulonglong, "<" + s_ulonglong, None, c_ulonglong),
|
||||
|
||||
(c_float, "<f", None, c_float),
|
||||
(c_double, "<d", None, c_double),
|
||||
|
||||
(c_longdouble, "<" + s_longdouble, None, c_longdouble),
|
||||
|
||||
(c_bool, "<" + s_bool, None, c_bool),
|
||||
(py_object, "<O", None, py_object),
|
||||
|
||||
## pointers
|
||||
|
||||
(POINTER(c_byte), "&<b", None, POINTER(c_byte)),
|
||||
(POINTER(POINTER(c_long)), "&&<" + s_long, None, POINTER(POINTER(c_long))),
|
||||
|
||||
## arrays and pointers
|
||||
|
||||
(c_double * 4, "<d", (4,), c_double),
|
||||
(c_float * 4 * 3 * 2, "<f", (2,3,4), c_float),
|
||||
(POINTER(c_short) * 2, "&<" + s_short, (2,), POINTER(c_short)),
|
||||
(POINTER(c_short) * 2 * 3, "&<" + s_short, (3,2,), POINTER(c_short)),
|
||||
(POINTER(c_short * 2), "&(2)<" + s_short, None, POINTER(c_short)),
|
||||
|
||||
## structures and unions
|
||||
|
||||
(Point, "T{<l:x:<l:y:}".replace('l', s_long), None, Point),
|
||||
# packed structures do not implement the pep
|
||||
(PackedPoint, "B", None, PackedPoint),
|
||||
(Point2, "T{<l:x:<l:y:}".replace('l', s_long), None, Point2),
|
||||
(EmptyStruct, "T{}", None, EmptyStruct),
|
||||
# the pep does't support unions
|
||||
(aUnion, "B", None, aUnion),
|
||||
# structure with sub-arrays
|
||||
(StructWithArrays, "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}".replace('l', s_long), None, StructWithArrays),
|
||||
(StructWithArrays * 3, "T{(2,3)<l:x:(4)T{<l:x:<l:y:}:y:}".replace('l', s_long), (3,), StructWithArrays),
|
||||
|
||||
## pointer to incomplete structure
|
||||
(Incomplete, "B", None, Incomplete),
|
||||
(POINTER(Incomplete), "&B", None, POINTER(Incomplete)),
|
||||
|
||||
# 'Complete' is a structure that starts incomplete, but is completed after the
|
||||
# pointer type to it has been created.
|
||||
(Complete, "T{<l:a:}".replace('l', s_long), None, Complete),
|
||||
# Unfortunately the pointer format string is not fixed...
|
||||
(POINTER(Complete), "&B", None, POINTER(Complete)),
|
||||
|
||||
## other
|
||||
|
||||
# function signatures are not implemented
|
||||
(CFUNCTYPE(None), "X{}", None, CFUNCTYPE(None)),
|
||||
|
||||
]
|
||||
|
||||
class BEPoint(BigEndianStructure):
|
||||
_fields_ = [("x", c_long), ("y", c_long)]
|
||||
|
||||
class LEPoint(LittleEndianStructure):
|
||||
_fields_ = [("x", c_long), ("y", c_long)]
|
||||
|
||||
################################################################
|
||||
#
|
||||
# This table contains format strings as they really look, on both big
|
||||
# and little endian machines.
|
||||
#
|
||||
endian_types = [
|
||||
(BEPoint, "T{>l:x:>l:y:}".replace('l', s_long), None, BEPoint),
|
||||
(LEPoint, "T{<l:x:<l:y:}".replace('l', s_long), None, LEPoint),
|
||||
(POINTER(BEPoint), "&T{>l:x:>l:y:}".replace('l', s_long), None, POINTER(BEPoint)),
|
||||
(POINTER(LEPoint), "&T{<l:x:<l:y:}".replace('l', s_long), None, POINTER(LEPoint)),
|
||||
]
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
81
Lib/ctypes/test/test_pickling.py
Normal file
81
Lib/ctypes/test/test_pickling.py
Normal file
@@ -0,0 +1,81 @@
|
||||
import unittest
|
||||
import pickle
|
||||
from ctypes import *
|
||||
import _ctypes_test
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_int), ("b", c_double)]
|
||||
init_called = 0
|
||||
def __init__(self, *args, **kw):
|
||||
X.init_called += 1
|
||||
self.x = 42
|
||||
|
||||
class Y(X):
|
||||
_fields_ = [("str", c_char_p)]
|
||||
|
||||
class PickleTest:
|
||||
def dumps(self, item):
|
||||
return pickle.dumps(item, self.proto)
|
||||
|
||||
def loads(self, item):
|
||||
return pickle.loads(item)
|
||||
|
||||
def test_simple(self):
|
||||
for src in [
|
||||
c_int(42),
|
||||
c_double(3.14),
|
||||
]:
|
||||
dst = self.loads(self.dumps(src))
|
||||
self.assertEqual(src.__dict__, dst.__dict__)
|
||||
self.assertEqual(memoryview(src).tobytes(),
|
||||
memoryview(dst).tobytes())
|
||||
|
||||
def test_struct(self):
|
||||
X.init_called = 0
|
||||
|
||||
x = X()
|
||||
x.a = 42
|
||||
self.assertEqual(X.init_called, 1)
|
||||
|
||||
y = self.loads(self.dumps(x))
|
||||
|
||||
# loads must NOT call __init__
|
||||
self.assertEqual(X.init_called, 1)
|
||||
|
||||
# ctypes instances are identical when the instance __dict__
|
||||
# and the memory buffer are identical
|
||||
self.assertEqual(y.__dict__, x.__dict__)
|
||||
self.assertEqual(memoryview(y).tobytes(),
|
||||
memoryview(x).tobytes())
|
||||
|
||||
def test_unpickable(self):
|
||||
# ctypes objects that are pointers or contain pointers are
|
||||
# unpickable.
|
||||
self.assertRaises(ValueError, lambda: self.dumps(Y()))
|
||||
|
||||
prototype = CFUNCTYPE(c_int)
|
||||
|
||||
for item in [
|
||||
c_char_p(),
|
||||
c_wchar_p(),
|
||||
c_void_p(),
|
||||
pointer(c_int(42)),
|
||||
dll._testfunc_p_p,
|
||||
prototype(lambda: 42),
|
||||
]:
|
||||
self.assertRaises(ValueError, lambda: self.dumps(item))
|
||||
|
||||
def test_wchar(self):
|
||||
self.dumps(c_char(b"x"))
|
||||
# Issue 5049
|
||||
self.dumps(c_wchar(u"x"))
|
||||
|
||||
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
|
||||
name = 'PickleTest_%s' % proto
|
||||
globals()[name] = type(name,
|
||||
(PickleTest, unittest.TestCase),
|
||||
{'proto': proto})
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
220
Lib/ctypes/test/test_pointers.py
Normal file
220
Lib/ctypes/test/test_pointers.py
Normal file
@@ -0,0 +1,220 @@
|
||||
import unittest, sys
|
||||
|
||||
from ctypes import *
|
||||
import _ctypes_test
|
||||
|
||||
ctype_types = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
|
||||
c_long, c_ulong, c_longlong, c_ulonglong, c_double, c_float]
|
||||
python_types = [int, int, int, int, int, long,
|
||||
int, long, long, long, float, float]
|
||||
|
||||
class PointersTestCase(unittest.TestCase):
|
||||
|
||||
def test_pointer_crash(self):
|
||||
|
||||
class A(POINTER(c_ulong)):
|
||||
pass
|
||||
|
||||
POINTER(c_ulong)(c_ulong(22))
|
||||
# Pointer can't set contents: has no _type_
|
||||
self.assertRaises(TypeError, A, c_ulong(33))
|
||||
|
||||
def test_pass_pointers(self):
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
func = dll._testfunc_p_p
|
||||
func.restype = c_long
|
||||
|
||||
i = c_int(12345678)
|
||||
## func.argtypes = (POINTER(c_int),)
|
||||
address = func(byref(i))
|
||||
self.assertEqual(c_int.from_address(address).value, 12345678)
|
||||
|
||||
func.restype = POINTER(c_int)
|
||||
res = func(pointer(i))
|
||||
self.assertEqual(res.contents.value, 12345678)
|
||||
self.assertEqual(res[0], 12345678)
|
||||
|
||||
def test_change_pointers(self):
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
func = dll._testfunc_p_p
|
||||
|
||||
i = c_int(87654)
|
||||
func.restype = POINTER(c_int)
|
||||
func.argtypes = (POINTER(c_int),)
|
||||
|
||||
res = func(pointer(i))
|
||||
self.assertEqual(res[0], 87654)
|
||||
self.assertEqual(res.contents.value, 87654)
|
||||
|
||||
# C code: *res = 54345
|
||||
res[0] = 54345
|
||||
self.assertEqual(i.value, 54345)
|
||||
|
||||
# C code:
|
||||
# int x = 12321;
|
||||
# res = &x
|
||||
x = c_int(12321)
|
||||
res.contents = x
|
||||
self.assertEqual(i.value, 54345)
|
||||
|
||||
x.value = -99
|
||||
self.assertEqual(res.contents.value, -99)
|
||||
|
||||
def test_callbacks_with_pointers(self):
|
||||
# a function type receiving a pointer
|
||||
PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int))
|
||||
|
||||
self.result = []
|
||||
|
||||
def func(arg):
|
||||
for i in range(10):
|
||||
## print arg[i],
|
||||
self.result.append(arg[i])
|
||||
## print
|
||||
return 0
|
||||
callback = PROTOTYPE(func)
|
||||
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
# This function expects a function pointer,
|
||||
# and calls this with an integer pointer as parameter.
|
||||
# The int pointer points to a table containing the numbers 1..10
|
||||
doit = dll._testfunc_callback_with_pointer
|
||||
|
||||
## i = c_int(42)
|
||||
## callback(byref(i))
|
||||
## self.assertEqual(i.value, 84)
|
||||
|
||||
doit(callback)
|
||||
## print self.result
|
||||
doit(callback)
|
||||
## print self.result
|
||||
|
||||
def test_basics(self):
|
||||
from operator import delitem
|
||||
for ct, pt in zip(ctype_types, python_types):
|
||||
i = ct(42)
|
||||
p = pointer(i)
|
||||
## print type(p.contents), ct
|
||||
self.assertIs(type(p.contents), ct)
|
||||
# p.contents is the same as p[0]
|
||||
## print p.contents
|
||||
## self.assertEqual(p.contents, 42)
|
||||
## self.assertEqual(p[0], 42)
|
||||
|
||||
self.assertRaises(TypeError, delitem, p, 0)
|
||||
|
||||
def test_from_address(self):
|
||||
from array import array
|
||||
a = array('i', [100, 200, 300, 400, 500])
|
||||
addr = a.buffer_info()[0]
|
||||
|
||||
p = POINTER(POINTER(c_int))
|
||||
## print dir(p)
|
||||
## print p.from_address
|
||||
## print p.from_address(addr)[0][0]
|
||||
|
||||
def test_other(self):
|
||||
class Table(Structure):
|
||||
_fields_ = [("a", c_int),
|
||||
("b", c_int),
|
||||
("c", c_int)]
|
||||
|
||||
pt = pointer(Table(1, 2, 3))
|
||||
|
||||
self.assertEqual(pt.contents.a, 1)
|
||||
self.assertEqual(pt.contents.b, 2)
|
||||
self.assertEqual(pt.contents.c, 3)
|
||||
|
||||
pt.contents.c = 33
|
||||
|
||||
from ctypes import _pointer_type_cache
|
||||
del _pointer_type_cache[Table]
|
||||
|
||||
def test_basic(self):
|
||||
p = pointer(c_int(42))
|
||||
# Although a pointer can be indexed, it has no length
|
||||
self.assertRaises(TypeError, len, p)
|
||||
self.assertEqual(p[0], 42)
|
||||
self.assertEqual(p[0:1], [42])
|
||||
self.assertEqual(p.contents.value, 42)
|
||||
|
||||
def test_charpp(self):
|
||||
"""Test that a character pointer-to-pointer is correctly passed"""
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
func = dll._testfunc_c_p_p
|
||||
func.restype = c_char_p
|
||||
argv = (c_char_p * 2)()
|
||||
argc = c_int( 2 )
|
||||
argv[0] = 'hello'
|
||||
argv[1] = 'world'
|
||||
result = func( byref(argc), argv )
|
||||
assert result == 'world', result
|
||||
|
||||
def test_bug_1467852(self):
|
||||
# http://sourceforge.net/tracker/?func=detail&atid=532154&aid=1467852&group_id=71702
|
||||
x = c_int(5)
|
||||
dummy = []
|
||||
for i in range(32000):
|
||||
dummy.append(c_int(i))
|
||||
y = c_int(6)
|
||||
p = pointer(x)
|
||||
pp = pointer(p)
|
||||
q = pointer(y)
|
||||
pp[0] = q # <==
|
||||
self.assertEqual(p[0], 6)
|
||||
def test_c_void_p(self):
|
||||
# http://sourceforge.net/tracker/?func=detail&aid=1518190&group_id=5470&atid=105470
|
||||
if sizeof(c_void_p) == 4:
|
||||
self.assertEqual(c_void_p(0xFFFFFFFFL).value,
|
||||
c_void_p(-1).value)
|
||||
self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFL).value,
|
||||
c_void_p(-1).value)
|
||||
elif sizeof(c_void_p) == 8:
|
||||
self.assertEqual(c_void_p(0xFFFFFFFFL).value,
|
||||
0xFFFFFFFFL)
|
||||
self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFL).value,
|
||||
c_void_p(-1).value)
|
||||
self.assertEqual(c_void_p(0xFFFFFFFFFFFFFFFFFFFFFFFFL).value,
|
||||
c_void_p(-1).value)
|
||||
|
||||
self.assertRaises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted
|
||||
self.assertRaises(TypeError, c_void_p, object()) # nor other objects
|
||||
|
||||
def test_pointers_bool(self):
|
||||
# NULL pointers have a boolean False value, non-NULL pointers True.
|
||||
self.assertEqual(bool(POINTER(c_int)()), False)
|
||||
self.assertEqual(bool(pointer(c_int())), True)
|
||||
|
||||
self.assertEqual(bool(CFUNCTYPE(None)(0)), False)
|
||||
self.assertEqual(bool(CFUNCTYPE(None)(42)), True)
|
||||
|
||||
# COM methods are boolean True:
|
||||
if sys.platform == "win32":
|
||||
mth = WINFUNCTYPE(None)(42, "name", (), None)
|
||||
self.assertEqual(bool(mth), True)
|
||||
|
||||
def test_pointer_type_name(self):
|
||||
LargeNamedType = type('T' * 2 ** 25, (Structure,), {})
|
||||
self.assertTrue(POINTER(LargeNamedType))
|
||||
|
||||
# to not leak references, we must clean _pointer_type_cache
|
||||
from ctypes import _pointer_type_cache
|
||||
del _pointer_type_cache[LargeNamedType]
|
||||
|
||||
def test_pointer_type_str_name(self):
|
||||
large_string = 'T' * 2 ** 25
|
||||
P = POINTER(large_string)
|
||||
self.assertTrue(P)
|
||||
|
||||
# to not leak references, we must clean _pointer_type_cache
|
||||
from ctypes import _pointer_type_cache
|
||||
del _pointer_type_cache[id(P)]
|
||||
|
||||
def test_abstract(self):
|
||||
from ctypes import _Pointer
|
||||
|
||||
self.assertRaises(TypeError, _Pointer.set_type, 42)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
219
Lib/ctypes/test/test_prototypes.py
Normal file
219
Lib/ctypes/test/test_prototypes.py
Normal file
@@ -0,0 +1,219 @@
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
import unittest
|
||||
|
||||
# IMPORTANT INFO:
|
||||
#
|
||||
# Consider this call:
|
||||
# func.restype = c_char_p
|
||||
# func(c_char_p("123"))
|
||||
# It returns
|
||||
# "123"
|
||||
#
|
||||
# WHY IS THIS SO?
|
||||
#
|
||||
# argument tuple (c_char_p("123"), ) is destroyed after the function
|
||||
# func is called, but NOT before the result is actually built.
|
||||
#
|
||||
# If the arglist would be destroyed BEFORE the result has been built,
|
||||
# the c_char_p("123") object would already have a zero refcount,
|
||||
# and the pointer passed to (and returned by) the function would
|
||||
# probably point to deallocated space.
|
||||
#
|
||||
# In this case, there would have to be an additional reference to the argument...
|
||||
|
||||
import _ctypes_test
|
||||
testdll = CDLL(_ctypes_test.__file__)
|
||||
|
||||
# Return machine address `a` as a (possibly long) non-negative integer.
|
||||
# Starting with Python 2.5, id(anything) is always non-negative, and
|
||||
# the ctypes addressof() inherits that via PyLong_FromVoidPtr().
|
||||
def positive_address(a):
|
||||
if a >= 0:
|
||||
return a
|
||||
# View the bits in `a` as unsigned instead.
|
||||
import struct
|
||||
num_bits = struct.calcsize("P") * 8 # num bits in native machine address
|
||||
a += 1L << num_bits
|
||||
assert a >= 0
|
||||
return a
|
||||
|
||||
def c_wbuffer(init):
|
||||
n = len(init) + 1
|
||||
return (c_wchar * n)(*init)
|
||||
|
||||
class CharPointersTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
func = testdll._testfunc_p_p
|
||||
func.restype = c_long
|
||||
func.argtypes = None
|
||||
|
||||
def test_paramflags(self):
|
||||
# function returns c_void_p result,
|
||||
# and has a required parameter named 'input'
|
||||
prototype = CFUNCTYPE(c_void_p, c_void_p)
|
||||
func = prototype(("_testfunc_p_p", testdll),
|
||||
((1, "input"),))
|
||||
|
||||
try:
|
||||
func()
|
||||
except TypeError, details:
|
||||
self.assertEqual(str(details), "required argument 'input' missing")
|
||||
else:
|
||||
self.fail("TypeError not raised")
|
||||
|
||||
self.assertEqual(func(None), None)
|
||||
self.assertEqual(func(input=None), None)
|
||||
|
||||
|
||||
def test_int_pointer_arg(self):
|
||||
func = testdll._testfunc_p_p
|
||||
func.restype = c_long
|
||||
self.assertEqual(0, func(0))
|
||||
|
||||
ci = c_int(0)
|
||||
|
||||
func.argtypes = POINTER(c_int),
|
||||
self.assertEqual(positive_address(addressof(ci)),
|
||||
positive_address(func(byref(ci))))
|
||||
|
||||
func.argtypes = c_char_p,
|
||||
self.assertRaises(ArgumentError, func, byref(ci))
|
||||
|
||||
func.argtypes = POINTER(c_short),
|
||||
self.assertRaises(ArgumentError, func, byref(ci))
|
||||
|
||||
func.argtypes = POINTER(c_double),
|
||||
self.assertRaises(ArgumentError, func, byref(ci))
|
||||
|
||||
def test_POINTER_c_char_arg(self):
|
||||
func = testdll._testfunc_p_p
|
||||
func.restype = c_char_p
|
||||
func.argtypes = POINTER(c_char),
|
||||
|
||||
self.assertEqual(None, func(None))
|
||||
self.assertEqual("123", func("123"))
|
||||
self.assertEqual(None, func(c_char_p(None)))
|
||||
self.assertEqual("123", func(c_char_p("123")))
|
||||
|
||||
self.assertEqual("123", func(c_buffer("123")))
|
||||
ca = c_char("a")
|
||||
self.assertEqual("a", func(pointer(ca))[0])
|
||||
self.assertEqual("a", func(byref(ca))[0])
|
||||
|
||||
def test_c_char_p_arg(self):
|
||||
func = testdll._testfunc_p_p
|
||||
func.restype = c_char_p
|
||||
func.argtypes = c_char_p,
|
||||
|
||||
self.assertEqual(None, func(None))
|
||||
self.assertEqual("123", func("123"))
|
||||
self.assertEqual(None, func(c_char_p(None)))
|
||||
self.assertEqual("123", func(c_char_p("123")))
|
||||
|
||||
self.assertEqual("123", func(c_buffer("123")))
|
||||
ca = c_char("a")
|
||||
self.assertEqual("a", func(pointer(ca))[0])
|
||||
self.assertEqual("a", func(byref(ca))[0])
|
||||
|
||||
def test_c_void_p_arg(self):
|
||||
func = testdll._testfunc_p_p
|
||||
func.restype = c_char_p
|
||||
func.argtypes = c_void_p,
|
||||
|
||||
self.assertEqual(None, func(None))
|
||||
self.assertEqual("123", func("123"))
|
||||
self.assertEqual("123", func(c_char_p("123")))
|
||||
self.assertEqual(None, func(c_char_p(None)))
|
||||
|
||||
self.assertEqual("123", func(c_buffer("123")))
|
||||
ca = c_char("a")
|
||||
self.assertEqual("a", func(pointer(ca))[0])
|
||||
self.assertEqual("a", func(byref(ca))[0])
|
||||
|
||||
func(byref(c_int()))
|
||||
func(pointer(c_int()))
|
||||
func((c_int * 3)())
|
||||
|
||||
@need_symbol('c_wchar_p')
|
||||
def test_c_void_p_arg_with_c_wchar_p(self):
|
||||
func = testdll._testfunc_p_p
|
||||
func.restype = c_wchar_p
|
||||
func.argtypes = c_void_p,
|
||||
|
||||
self.assertEqual(None, func(c_wchar_p(None)))
|
||||
self.assertEqual(u"123", func(c_wchar_p(u"123")))
|
||||
|
||||
def test_instance(self):
|
||||
func = testdll._testfunc_p_p
|
||||
func.restype = c_void_p
|
||||
|
||||
class X:
|
||||
_as_parameter_ = None
|
||||
|
||||
func.argtypes = c_void_p,
|
||||
self.assertEqual(None, func(X()))
|
||||
|
||||
func.argtypes = None
|
||||
self.assertEqual(None, func(X()))
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
class WCharPointersTestCase(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
func = testdll._testfunc_p_p
|
||||
func.restype = c_int
|
||||
func.argtypes = None
|
||||
|
||||
|
||||
def test_POINTER_c_wchar_arg(self):
|
||||
func = testdll._testfunc_p_p
|
||||
func.restype = c_wchar_p
|
||||
func.argtypes = POINTER(c_wchar),
|
||||
|
||||
self.assertEqual(None, func(None))
|
||||
self.assertEqual(u"123", func(u"123"))
|
||||
self.assertEqual(None, func(c_wchar_p(None)))
|
||||
self.assertEqual(u"123", func(c_wchar_p(u"123")))
|
||||
|
||||
self.assertEqual(u"123", func(c_wbuffer(u"123")))
|
||||
ca = c_wchar("a")
|
||||
self.assertEqual(u"a", func(pointer(ca))[0])
|
||||
self.assertEqual(u"a", func(byref(ca))[0])
|
||||
|
||||
def test_c_wchar_p_arg(self):
|
||||
func = testdll._testfunc_p_p
|
||||
func.restype = c_wchar_p
|
||||
func.argtypes = c_wchar_p,
|
||||
|
||||
c_wchar_p.from_param(u"123")
|
||||
|
||||
self.assertEqual(None, func(None))
|
||||
self.assertEqual("123", func(u"123"))
|
||||
self.assertEqual(None, func(c_wchar_p(None)))
|
||||
self.assertEqual("123", func(c_wchar_p("123")))
|
||||
|
||||
# XXX Currently, these raise TypeErrors, although they shouldn't:
|
||||
self.assertEqual("123", func(c_wbuffer("123")))
|
||||
ca = c_wchar("a")
|
||||
self.assertEqual("a", func(pointer(ca))[0])
|
||||
self.assertEqual("a", func(byref(ca))[0])
|
||||
|
||||
class ArrayTest(unittest.TestCase):
|
||||
def test(self):
|
||||
func = testdll._testfunc_ai8
|
||||
func.restype = POINTER(c_int)
|
||||
func.argtypes = c_int * 8,
|
||||
|
||||
func((c_int * 8)(1, 2, 3, 4, 5, 6, 7, 8))
|
||||
|
||||
# This did crash before:
|
||||
|
||||
def func(): pass
|
||||
CFUNCTYPE(None, c_int * 3)(func)
|
||||
|
||||
################################################################
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
90
Lib/ctypes/test/test_python_api.py
Normal file
90
Lib/ctypes/test/test_python_api.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from ctypes import *
|
||||
import unittest, sys
|
||||
from ctypes.test import requires
|
||||
|
||||
################################################################
|
||||
# This section should be moved into ctypes\__init__.py, when it's ready.
|
||||
|
||||
from _ctypes import PyObj_FromPtr
|
||||
|
||||
################################################################
|
||||
|
||||
from sys import getrefcount as grc
|
||||
if sys.version_info > (2, 4):
|
||||
c_py_ssize_t = c_size_t
|
||||
else:
|
||||
c_py_ssize_t = c_int
|
||||
|
||||
class PythonAPITestCase(unittest.TestCase):
|
||||
|
||||
def test_PyString_FromStringAndSize(self):
|
||||
PyString_FromStringAndSize = pythonapi.PyString_FromStringAndSize
|
||||
|
||||
PyString_FromStringAndSize.restype = py_object
|
||||
PyString_FromStringAndSize.argtypes = c_char_p, c_py_ssize_t
|
||||
|
||||
self.assertEqual(PyString_FromStringAndSize("abcdefghi", 3), "abc")
|
||||
|
||||
def test_PyString_FromString(self):
|
||||
pythonapi.PyString_FromString.restype = py_object
|
||||
pythonapi.PyString_FromString.argtypes = (c_char_p,)
|
||||
|
||||
s = "abc"
|
||||
refcnt = grc(s)
|
||||
pyob = pythonapi.PyString_FromString(s)
|
||||
self.assertEqual(grc(s), refcnt)
|
||||
self.assertEqual(s, pyob)
|
||||
del pyob
|
||||
self.assertEqual(grc(s), refcnt)
|
||||
|
||||
# This test is unreliable, because it is possible that code in
|
||||
# unittest changes the refcount of the '42' integer. So, it
|
||||
# is disabled by default.
|
||||
def test_PyInt_Long(self):
|
||||
requires("refcount")
|
||||
ref42 = grc(42)
|
||||
pythonapi.PyInt_FromLong.restype = py_object
|
||||
self.assertEqual(pythonapi.PyInt_FromLong(42), 42)
|
||||
|
||||
self.assertEqual(grc(42), ref42)
|
||||
|
||||
pythonapi.PyInt_AsLong.argtypes = (py_object,)
|
||||
pythonapi.PyInt_AsLong.restype = c_long
|
||||
|
||||
res = pythonapi.PyInt_AsLong(42)
|
||||
self.assertEqual(grc(res), ref42 + 1)
|
||||
del res
|
||||
self.assertEqual(grc(42), ref42)
|
||||
|
||||
def test_PyObj_FromPtr(self):
|
||||
s = "abc def ghi jkl"
|
||||
ref = grc(s)
|
||||
# id(python-object) is the address
|
||||
pyobj = PyObj_FromPtr(id(s))
|
||||
self.assertIs(s, pyobj)
|
||||
|
||||
self.assertEqual(grc(s), ref + 1)
|
||||
del pyobj
|
||||
self.assertEqual(grc(s), ref)
|
||||
|
||||
def test_PyOS_snprintf(self):
|
||||
PyOS_snprintf = pythonapi.PyOS_snprintf
|
||||
PyOS_snprintf.argtypes = POINTER(c_char), c_size_t, c_char_p
|
||||
|
||||
buf = c_buffer(256)
|
||||
PyOS_snprintf(buf, sizeof(buf), "Hello from %s", "ctypes")
|
||||
self.assertEqual(buf.value, "Hello from ctypes")
|
||||
|
||||
PyOS_snprintf(buf, sizeof(buf), "Hello from %s", "ctypes", 1, 2, 3)
|
||||
self.assertEqual(buf.value, "Hello from ctypes")
|
||||
|
||||
# not enough arguments
|
||||
self.assertRaises(TypeError, PyOS_snprintf, buf)
|
||||
|
||||
def test_pyobject_repr(self):
|
||||
self.assertEqual(repr(py_object()), "py_object(<NULL>)")
|
||||
self.assertEqual(repr(py_object(42)), "py_object(42)")
|
||||
self.assertEqual(repr(py_object(object)), "py_object(%r)" % object)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
74
Lib/ctypes/test/test_random_things.py
Normal file
74
Lib/ctypes/test/test_random_things.py
Normal file
@@ -0,0 +1,74 @@
|
||||
from ctypes import *
|
||||
import unittest, sys
|
||||
|
||||
def callback_func(arg):
|
||||
42 // arg
|
||||
raise ValueError(arg)
|
||||
|
||||
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||||
class call_function_TestCase(unittest.TestCase):
|
||||
# _ctypes.call_function is deprecated and private, but used by
|
||||
# Gary Bishp's readline module. If we have it, we must test it as well.
|
||||
|
||||
def test(self):
|
||||
from _ctypes import call_function
|
||||
windll.kernel32.LoadLibraryA.restype = c_void_p
|
||||
windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p
|
||||
windll.kernel32.GetProcAddress.restype = c_void_p
|
||||
|
||||
hdll = windll.kernel32.LoadLibraryA("kernel32")
|
||||
funcaddr = windll.kernel32.GetProcAddress(hdll, "GetModuleHandleA")
|
||||
|
||||
self.assertEqual(call_function(funcaddr, (None,)),
|
||||
windll.kernel32.GetModuleHandleA(None))
|
||||
|
||||
class CallbackTracbackTestCase(unittest.TestCase):
|
||||
# When an exception is raised in a ctypes callback function, the C
|
||||
# code prints a traceback.
|
||||
#
|
||||
# This test makes sure the exception types *and* the exception
|
||||
# value is printed correctly.
|
||||
#
|
||||
# Changed in 0.9.3: No longer is '(in callback)' prepended to the
|
||||
# error message - instead an additional frame for the C code is
|
||||
# created, then a full traceback printed. When SystemExit is
|
||||
# raised in a callback function, the interpreter exits.
|
||||
|
||||
def capture_stderr(self, func, *args, **kw):
|
||||
# helper - call function 'func', and return the captured stderr
|
||||
import StringIO
|
||||
old_stderr = sys.stderr
|
||||
logger = sys.stderr = StringIO.StringIO()
|
||||
try:
|
||||
func(*args, **kw)
|
||||
finally:
|
||||
sys.stderr = old_stderr
|
||||
return logger.getvalue()
|
||||
|
||||
def test_ValueError(self):
|
||||
cb = CFUNCTYPE(c_int, c_int)(callback_func)
|
||||
out = self.capture_stderr(cb, 42)
|
||||
self.assertEqual(out.splitlines()[-1],
|
||||
"ValueError: 42")
|
||||
|
||||
def test_IntegerDivisionError(self):
|
||||
cb = CFUNCTYPE(c_int, c_int)(callback_func)
|
||||
out = self.capture_stderr(cb, 0)
|
||||
self.assertEqual(out.splitlines()[-1][:19],
|
||||
"ZeroDivisionError: ")
|
||||
|
||||
def test_FloatDivisionError(self):
|
||||
cb = CFUNCTYPE(c_int, c_double)(callback_func)
|
||||
out = self.capture_stderr(cb, 0.0)
|
||||
self.assertEqual(out.splitlines()[-1][:19],
|
||||
"ZeroDivisionError: ")
|
||||
|
||||
def test_TypeErrorDivisionError(self):
|
||||
cb = CFUNCTYPE(c_int, c_char_p)(callback_func)
|
||||
out = self.capture_stderr(cb, "spam")
|
||||
self.assertEqual(out.splitlines()[-1],
|
||||
"TypeError: "
|
||||
"unsupported operand type(s) for //: 'int' and 'str'")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
98
Lib/ctypes/test/test_refcounts.py
Normal file
98
Lib/ctypes/test/test_refcounts.py
Normal file
@@ -0,0 +1,98 @@
|
||||
import unittest
|
||||
import ctypes
|
||||
import gc
|
||||
|
||||
MyCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)
|
||||
OtherCallback = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_ulonglong)
|
||||
|
||||
import _ctypes_test
|
||||
dll = ctypes.CDLL(_ctypes_test.__file__)
|
||||
|
||||
class RefcountTestCase(unittest.TestCase):
|
||||
|
||||
def test_1(self):
|
||||
from sys import getrefcount as grc
|
||||
|
||||
f = dll._testfunc_callback_i_if
|
||||
f.restype = ctypes.c_int
|
||||
f.argtypes = [ctypes.c_int, MyCallback]
|
||||
|
||||
def callback(value):
|
||||
#print "called back with", value
|
||||
return value
|
||||
|
||||
self.assertEqual(grc(callback), 2)
|
||||
cb = MyCallback(callback)
|
||||
|
||||
self.assertGreater(grc(callback), 2)
|
||||
result = f(-10, cb)
|
||||
self.assertEqual(result, -18)
|
||||
cb = None
|
||||
|
||||
gc.collect()
|
||||
|
||||
self.assertEqual(grc(callback), 2)
|
||||
|
||||
|
||||
def test_refcount(self):
|
||||
from sys import getrefcount as grc
|
||||
def func(*args):
|
||||
pass
|
||||
# this is the standard refcount for func
|
||||
self.assertEqual(grc(func), 2)
|
||||
|
||||
# the CFuncPtr instance holds at least one refcount on func:
|
||||
f = OtherCallback(func)
|
||||
self.assertGreater(grc(func), 2)
|
||||
|
||||
# and may release it again
|
||||
del f
|
||||
self.assertGreaterEqual(grc(func), 2)
|
||||
|
||||
# but now it must be gone
|
||||
gc.collect()
|
||||
self.assertEqual(grc(func), 2)
|
||||
|
||||
class X(ctypes.Structure):
|
||||
_fields_ = [("a", OtherCallback)]
|
||||
x = X()
|
||||
x.a = OtherCallback(func)
|
||||
|
||||
# the CFuncPtr instance holds at least one refcount on func:
|
||||
self.assertGreater(grc(func), 2)
|
||||
|
||||
# and may release it again
|
||||
del x
|
||||
self.assertGreaterEqual(grc(func), 2)
|
||||
|
||||
# and now it must be gone again
|
||||
gc.collect()
|
||||
self.assertEqual(grc(func), 2)
|
||||
|
||||
f = OtherCallback(func)
|
||||
|
||||
# the CFuncPtr instance holds at least one refcount on func:
|
||||
self.assertGreater(grc(func), 2)
|
||||
|
||||
# create a cycle
|
||||
f.cycle = f
|
||||
|
||||
del f
|
||||
gc.collect()
|
||||
self.assertEqual(grc(func), 2)
|
||||
|
||||
class AnotherLeak(unittest.TestCase):
|
||||
def test_callback(self):
|
||||
import sys
|
||||
|
||||
proto = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int)
|
||||
def func(a, b):
|
||||
return a * b * 2
|
||||
f = proto(func)
|
||||
|
||||
a = sys.getrefcount(ctypes.c_int)
|
||||
f(1, 2)
|
||||
self.assertEqual(sys.getrefcount(ctypes.c_int), a)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
29
Lib/ctypes/test/test_repr.py
Normal file
29
Lib/ctypes/test/test_repr.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from ctypes import *
|
||||
import unittest
|
||||
|
||||
subclasses = []
|
||||
for base in [c_byte, c_short, c_int, c_long, c_longlong,
|
||||
c_ubyte, c_ushort, c_uint, c_ulong, c_ulonglong,
|
||||
c_float, c_double, c_longdouble, c_bool]:
|
||||
class X(base):
|
||||
pass
|
||||
subclasses.append(X)
|
||||
|
||||
class X(c_char):
|
||||
pass
|
||||
|
||||
# This test checks if the __repr__ is correct for subclasses of simple types
|
||||
|
||||
class ReprTest(unittest.TestCase):
|
||||
def test_numbers(self):
|
||||
for typ in subclasses:
|
||||
base = typ.__bases__[0]
|
||||
self.assertTrue(repr(base(42)).startswith(base.__name__))
|
||||
self.assertEqual("<X object at", repr(typ(42))[:12])
|
||||
|
||||
def test_char(self):
|
||||
self.assertEqual("c_char('x')", repr(c_char('x')))
|
||||
self.assertEqual("<X object at", repr(X('x'))[:12])
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
65
Lib/ctypes/test/test_returnfuncptrs.py
Normal file
65
Lib/ctypes/test/test_returnfuncptrs.py
Normal file
@@ -0,0 +1,65 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
import os
|
||||
|
||||
import _ctypes_test
|
||||
|
||||
class ReturnFuncPtrTestCase(unittest.TestCase):
|
||||
|
||||
def test_with_prototype(self):
|
||||
# The _ctypes_test shared lib/dll exports quite some functions for testing.
|
||||
# The get_strchr function returns a *pointer* to the C strchr function.
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
get_strchr = dll.get_strchr
|
||||
get_strchr.restype = CFUNCTYPE(c_char_p, c_char_p, c_char)
|
||||
strchr = get_strchr()
|
||||
self.assertEqual(strchr("abcdef", "b"), "bcdef")
|
||||
self.assertEqual(strchr("abcdef", "x"), None)
|
||||
self.assertRaises(ArgumentError, strchr, "abcdef", 3)
|
||||
self.assertRaises(TypeError, strchr, "abcdef")
|
||||
|
||||
def test_without_prototype(self):
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
get_strchr = dll.get_strchr
|
||||
# the default 'c_int' would not work on systems where sizeof(int) != sizeof(void *)
|
||||
get_strchr.restype = c_void_p
|
||||
addr = get_strchr()
|
||||
# _CFuncPtr instances are now callable with an integer argument
|
||||
# which denotes a function address:
|
||||
strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(addr)
|
||||
self.assertTrue(strchr("abcdef", "b"), "bcdef")
|
||||
self.assertEqual(strchr("abcdef", "x"), None)
|
||||
self.assertRaises(ArgumentError, strchr, "abcdef", 3)
|
||||
self.assertRaises(TypeError, strchr, "abcdef")
|
||||
|
||||
def test_from_dll(self):
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
# _CFuncPtr instances are now callable with a tuple argument
|
||||
# which denotes a function name and a dll:
|
||||
strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(("my_strchr", dll))
|
||||
self.assertTrue(strchr(b"abcdef", b"b"), "bcdef")
|
||||
self.assertEqual(strchr(b"abcdef", b"x"), None)
|
||||
self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0)
|
||||
self.assertRaises(TypeError, strchr, b"abcdef")
|
||||
|
||||
# Issue 6083: Reference counting bug
|
||||
def test_from_dll_refcount(self):
|
||||
class BadSequence(tuple):
|
||||
def __getitem__(self, key):
|
||||
if key == 0:
|
||||
return "my_strchr"
|
||||
if key == 1:
|
||||
return CDLL(_ctypes_test.__file__)
|
||||
raise IndexError
|
||||
|
||||
# _CFuncPtr instances are now callable with a tuple argument
|
||||
# which denotes a function name and a dll:
|
||||
strchr = CFUNCTYPE(c_char_p, c_char_p, c_char)(
|
||||
BadSequence(("my_strchr", CDLL(_ctypes_test.__file__))))
|
||||
self.assertTrue(strchr(b"abcdef", b"b"), "bcdef")
|
||||
self.assertEqual(strchr(b"abcdef", b"x"), None)
|
||||
self.assertRaises(ArgumentError, strchr, b"abcdef", 3.0)
|
||||
self.assertRaises(TypeError, strchr, b"abcdef")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
57
Lib/ctypes/test/test_simplesubclasses.py
Normal file
57
Lib/ctypes/test/test_simplesubclasses.py
Normal file
@@ -0,0 +1,57 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
|
||||
class MyInt(c_int):
|
||||
def __cmp__(self, other):
|
||||
if type(other) != MyInt:
|
||||
return -1
|
||||
return cmp(self.value, other.value)
|
||||
def __hash__(self): # Silence Py3k warning
|
||||
return hash(self.value)
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
def test_compare(self):
|
||||
self.assertEqual(MyInt(3), MyInt(3))
|
||||
self.assertNotEqual(MyInt(42), MyInt(43))
|
||||
|
||||
def test_ignore_retval(self):
|
||||
# Test if the return value of a callback is ignored
|
||||
# if restype is None
|
||||
proto = CFUNCTYPE(None)
|
||||
def func():
|
||||
return (1, "abc", None)
|
||||
|
||||
cb = proto(func)
|
||||
self.assertEqual(None, cb())
|
||||
|
||||
|
||||
def test_int_callback(self):
|
||||
args = []
|
||||
def func(arg):
|
||||
args.append(arg)
|
||||
return arg
|
||||
|
||||
cb = CFUNCTYPE(None, MyInt)(func)
|
||||
|
||||
self.assertEqual(None, cb(42))
|
||||
self.assertEqual(type(args[-1]), MyInt)
|
||||
|
||||
cb = CFUNCTYPE(c_int, c_int)(func)
|
||||
|
||||
self.assertEqual(42, cb(42))
|
||||
self.assertEqual(type(args[-1]), int)
|
||||
|
||||
def test_int_struct(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("x", MyInt)]
|
||||
|
||||
self.assertEqual(X().x, MyInt())
|
||||
|
||||
s = X()
|
||||
s.x = MyInt(42)
|
||||
|
||||
self.assertEqual(s.x, MyInt(42))
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
34
Lib/ctypes/test/test_sizes.py
Normal file
34
Lib/ctypes/test/test_sizes.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# Test specifically-sized containers.
|
||||
|
||||
from ctypes import *
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
|
||||
class SizesTestCase(unittest.TestCase):
|
||||
def test_8(self):
|
||||
self.assertEqual(1, sizeof(c_int8))
|
||||
self.assertEqual(1, sizeof(c_uint8))
|
||||
|
||||
def test_16(self):
|
||||
self.assertEqual(2, sizeof(c_int16))
|
||||
self.assertEqual(2, sizeof(c_uint16))
|
||||
|
||||
def test_32(self):
|
||||
self.assertEqual(4, sizeof(c_int32))
|
||||
self.assertEqual(4, sizeof(c_uint32))
|
||||
|
||||
def test_64(self):
|
||||
self.assertEqual(8, sizeof(c_int64))
|
||||
self.assertEqual(8, sizeof(c_uint64))
|
||||
|
||||
def test_size_t(self):
|
||||
self.assertEqual(sizeof(c_void_p), sizeof(c_size_t))
|
||||
|
||||
def test_ssize_t(self):
|
||||
self.assertEqual(sizeof(c_void_p), sizeof(c_ssize_t))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
175
Lib/ctypes/test/test_slicing.py
Normal file
175
Lib/ctypes/test/test_slicing.py
Normal file
@@ -0,0 +1,175 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
|
||||
import _ctypes_test
|
||||
|
||||
class SlicesTestCase(unittest.TestCase):
|
||||
def test_getslice_cint(self):
|
||||
a = (c_int * 100)(*xrange(1100, 1200))
|
||||
b = range(1100, 1200)
|
||||
self.assertEqual(a[0:2], b[0:2])
|
||||
self.assertEqual(a[0:2:], b[0:2:])
|
||||
self.assertEqual(len(a), len(b))
|
||||
self.assertEqual(a[5:7], b[5:7])
|
||||
self.assertEqual(a[5:7:], b[5:7:])
|
||||
self.assertEqual(a[-1], b[-1])
|
||||
self.assertEqual(a[:], b[:])
|
||||
self.assertEqual(a[::], b[::])
|
||||
self.assertEqual(a[10::-1], b[10::-1])
|
||||
self.assertEqual(a[30:20:-1], b[30:20:-1])
|
||||
self.assertEqual(a[:12:6], b[:12:6])
|
||||
self.assertEqual(a[2:6:4], b[2:6:4])
|
||||
|
||||
a[0:5] = range(5, 10)
|
||||
self.assertEqual(a[0:5], range(5, 10))
|
||||
self.assertEqual(a[0:5:], range(5, 10))
|
||||
self.assertEqual(a[4::-1], range(9, 4, -1))
|
||||
|
||||
def test_setslice_cint(self):
|
||||
a = (c_int * 100)(*xrange(1100, 1200))
|
||||
b = range(1100, 1200)
|
||||
|
||||
a[32:47] = range(32, 47)
|
||||
self.assertEqual(a[32:47], range(32, 47))
|
||||
a[32:47] = range(132, 147)
|
||||
self.assertEqual(a[32:47:], range(132, 147))
|
||||
a[46:31:-1] = range(232, 247)
|
||||
self.assertEqual(a[32:47:1], range(246, 231, -1))
|
||||
|
||||
a[32:47] = range(1132, 1147)
|
||||
self.assertEqual(a[:], b)
|
||||
a[32:47:7] = range(3)
|
||||
b[32:47:7] = range(3)
|
||||
self.assertEqual(a[:], b)
|
||||
a[33::-3] = range(12)
|
||||
b[33::-3] = range(12)
|
||||
self.assertEqual(a[:], b)
|
||||
|
||||
from operator import setslice, setitem
|
||||
|
||||
# TypeError: int expected instead of str instance
|
||||
self.assertRaises(TypeError, setslice, a, 0, 5, "abcde")
|
||||
self.assertRaises(TypeError, setitem, a, slice(0, 5), "abcde")
|
||||
# TypeError: int expected instead of str instance
|
||||
self.assertRaises(TypeError, setslice, a, 0, 5, ["a", "b", "c", "d", "e"])
|
||||
self.assertRaises(TypeError, setitem, a, slice(0, 5),
|
||||
["a", "b", "c", "d", "e"])
|
||||
# TypeError: int expected instead of float instance
|
||||
self.assertRaises(TypeError, setslice, a, 0, 5, [1, 2, 3, 4, 3.14])
|
||||
self.assertRaises(TypeError, setitem, a, slice(0, 5),
|
||||
[1, 2, 3, 4, 3.14])
|
||||
# ValueError: Can only assign sequence of same size
|
||||
self.assertRaises(ValueError, setslice, a, 0, 5, range(32))
|
||||
self.assertRaises(ValueError, setitem, a, slice(0, 5), range(32))
|
||||
|
||||
def test_char_ptr(self):
|
||||
s = "abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
dll.my_strdup.restype = POINTER(c_char)
|
||||
dll.my_free.restype = None
|
||||
res = dll.my_strdup(s)
|
||||
self.assertEqual(res[:len(s)], s)
|
||||
self.assertEqual(res[:3], s[:3])
|
||||
self.assertEqual(res[:len(s):], s)
|
||||
self.assertEqual(res[len(s)-1:-1:-1], s[::-1])
|
||||
self.assertEqual(res[len(s)-1:5:-7], s[:5:-7])
|
||||
self.assertEqual(res[0:-1:-1], s[0::-1])
|
||||
|
||||
import operator
|
||||
self.assertRaises(ValueError, operator.getitem,
|
||||
res, slice(None, None, None))
|
||||
self.assertRaises(ValueError, operator.getitem,
|
||||
res, slice(0, None, None))
|
||||
self.assertRaises(ValueError, operator.getitem,
|
||||
res, slice(None, 5, -1))
|
||||
self.assertRaises(ValueError, operator.getitem,
|
||||
res, slice(-5, None, None))
|
||||
|
||||
self.assertRaises(TypeError, operator.setslice,
|
||||
res, 0, 5, u"abcde")
|
||||
self.assertRaises(TypeError, operator.setitem,
|
||||
res, slice(0, 5), u"abcde")
|
||||
dll.my_free(res)
|
||||
|
||||
dll.my_strdup.restype = POINTER(c_byte)
|
||||
res = dll.my_strdup(s)
|
||||
self.assertEqual(res[:len(s)], range(ord("a"), ord("z")+1))
|
||||
self.assertEqual(res[:len(s):], range(ord("a"), ord("z")+1))
|
||||
dll.my_free(res)
|
||||
|
||||
def test_char_ptr_with_free(self):
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
s = "abcdefghijklmnopqrstuvwxyz"
|
||||
|
||||
class allocated_c_char_p(c_char_p):
|
||||
pass
|
||||
|
||||
dll.my_free.restype = None
|
||||
def errcheck(result, func, args):
|
||||
retval = result.value
|
||||
dll.my_free(result)
|
||||
return retval
|
||||
|
||||
dll.my_strdup.restype = allocated_c_char_p
|
||||
dll.my_strdup.errcheck = errcheck
|
||||
try:
|
||||
res = dll.my_strdup(s)
|
||||
self.assertEqual(res, s)
|
||||
finally:
|
||||
del dll.my_strdup.errcheck
|
||||
|
||||
|
||||
def test_char_array(self):
|
||||
s = "abcdefghijklmnopqrstuvwxyz\0"
|
||||
|
||||
p = (c_char * 27)(*s)
|
||||
self.assertEqual(p[:], s)
|
||||
self.assertEqual(p[::], s)
|
||||
self.assertEqual(p[::-1], s[::-1])
|
||||
self.assertEqual(p[5::-2], s[5::-2])
|
||||
self.assertEqual(p[2:5:-3], s[2:5:-3])
|
||||
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
def test_wchar_ptr(self):
|
||||
s = u"abcdefghijklmnopqrstuvwxyz\0"
|
||||
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
dll.my_wcsdup.restype = POINTER(c_wchar)
|
||||
dll.my_wcsdup.argtypes = POINTER(c_wchar),
|
||||
dll.my_free.restype = None
|
||||
res = dll.my_wcsdup(s)
|
||||
self.assertEqual(res[:len(s)], s)
|
||||
self.assertEqual(res[:len(s):], s)
|
||||
self.assertEqual(res[len(s)-1:-1:-1], s[::-1])
|
||||
self.assertEqual(res[len(s)-1:5:-7], s[:5:-7])
|
||||
|
||||
import operator
|
||||
self.assertRaises(TypeError, operator.setslice,
|
||||
res, 0, 5, u"abcde")
|
||||
self.assertRaises(TypeError, operator.setitem,
|
||||
res, slice(0, 5), u"abcde")
|
||||
dll.my_free(res)
|
||||
|
||||
if sizeof(c_wchar) == sizeof(c_short):
|
||||
dll.my_wcsdup.restype = POINTER(c_short)
|
||||
elif sizeof(c_wchar) == sizeof(c_int):
|
||||
dll.my_wcsdup.restype = POINTER(c_int)
|
||||
elif sizeof(c_wchar) == sizeof(c_long):
|
||||
dll.my_wcsdup.restype = POINTER(c_long)
|
||||
else:
|
||||
self.skipTest('Pointers to c_wchar are not supported')
|
||||
res = dll.my_wcsdup(s)
|
||||
tmpl = range(ord("a"), ord("z")+1)
|
||||
self.assertEqual(res[:len(s)-1], tmpl)
|
||||
self.assertEqual(res[:len(s)-1:], tmpl)
|
||||
self.assertEqual(res[len(s)-2:-1:-1], tmpl[::-1])
|
||||
self.assertEqual(res[len(s)-2:5:-7], tmpl[:5:-7])
|
||||
dll.my_free(res)
|
||||
|
||||
################################################################
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
75
Lib/ctypes/test/test_stringptr.py
Normal file
75
Lib/ctypes/test/test_stringptr.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
|
||||
import _ctypes_test
|
||||
|
||||
lib = CDLL(_ctypes_test.__file__)
|
||||
|
||||
class StringPtrTestCase(unittest.TestCase):
|
||||
|
||||
def test__POINTER_c_char(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("str", POINTER(c_char))]
|
||||
x = X()
|
||||
|
||||
# NULL pointer access
|
||||
self.assertRaises(ValueError, getattr, x.str, "contents")
|
||||
b = c_buffer("Hello, World")
|
||||
from sys import getrefcount as grc
|
||||
self.assertEqual(grc(b), 2)
|
||||
x.str = b
|
||||
self.assertEqual(grc(b), 3)
|
||||
|
||||
# POINTER(c_char) and Python string is NOT compatible
|
||||
# POINTER(c_char) and c_buffer() is compatible
|
||||
for i in range(len(b)):
|
||||
self.assertEqual(b[i], x.str[i])
|
||||
|
||||
self.assertRaises(TypeError, setattr, x, "str", "Hello, World")
|
||||
|
||||
def test__c_char_p(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("str", c_char_p)]
|
||||
x = X()
|
||||
|
||||
# c_char_p and Python string is compatible
|
||||
# c_char_p and c_buffer is NOT compatible
|
||||
self.assertEqual(x.str, None)
|
||||
x.str = "Hello, World"
|
||||
self.assertEqual(x.str, "Hello, World")
|
||||
b = c_buffer("Hello, World")
|
||||
self.assertRaises(TypeError, setattr, x, "str", b)
|
||||
|
||||
|
||||
def test_functions(self):
|
||||
strchr = lib.my_strchr
|
||||
strchr.restype = c_char_p
|
||||
|
||||
# c_char_p and Python string is compatible
|
||||
# c_char_p and c_buffer are now compatible
|
||||
strchr.argtypes = c_char_p, c_char
|
||||
self.assertEqual(strchr("abcdef", "c"), "cdef")
|
||||
self.assertEqual(strchr(c_buffer("abcdef"), "c"), "cdef")
|
||||
|
||||
# POINTER(c_char) and Python string is NOT compatible
|
||||
# POINTER(c_char) and c_buffer() is compatible
|
||||
strchr.argtypes = POINTER(c_char), c_char
|
||||
buf = c_buffer("abcdef")
|
||||
self.assertEqual(strchr(buf, "c"), "cdef")
|
||||
self.assertEqual(strchr("abcdef", "c"), "cdef")
|
||||
|
||||
# XXX These calls are dangerous, because the first argument
|
||||
# to strchr is no longer valid after the function returns!
|
||||
# So we must keep a reference to buf separately
|
||||
|
||||
strchr.restype = POINTER(c_char)
|
||||
buf = c_buffer("abcdef")
|
||||
r = strchr(buf, "c")
|
||||
x = r[0], r[1], r[2], r[3], r[4]
|
||||
self.assertEqual(x, ("c", "d", "e", "f", "\000"))
|
||||
del buf
|
||||
# x1 will NOT be the same as x, usually:
|
||||
x1 = r[0], r[1], r[2], r[3], r[4]
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
232
Lib/ctypes/test/test_strings.py
Normal file
232
Lib/ctypes/test/test_strings.py
Normal file
@@ -0,0 +1,232 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
from test import test_support
|
||||
|
||||
class StringArrayTestCase(unittest.TestCase):
|
||||
def test(self):
|
||||
BUF = c_char * 4
|
||||
|
||||
buf = BUF("a", "b", "c")
|
||||
self.assertEqual(buf.value, "abc")
|
||||
self.assertEqual(buf.raw, "abc\000")
|
||||
|
||||
buf.value = "ABCD"
|
||||
self.assertEqual(buf.value, "ABCD")
|
||||
self.assertEqual(buf.raw, "ABCD")
|
||||
|
||||
buf.value = "x"
|
||||
self.assertEqual(buf.value, "x")
|
||||
self.assertEqual(buf.raw, "x\000CD")
|
||||
|
||||
buf[1] = "Z"
|
||||
self.assertEqual(buf.value, "xZCD")
|
||||
self.assertEqual(buf.raw, "xZCD")
|
||||
|
||||
self.assertRaises(ValueError, setattr, buf, "value", "aaaaaaaa")
|
||||
self.assertRaises(TypeError, setattr, buf, "value", 42)
|
||||
|
||||
def test_c_buffer_value(self, memoryview=memoryview):
|
||||
buf = c_buffer(32)
|
||||
|
||||
buf.value = "Hello, World"
|
||||
self.assertEqual(buf.value, "Hello, World")
|
||||
|
||||
self.assertRaises(TypeError, setattr, buf, "value", memoryview("Hello, World"))
|
||||
self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc"))
|
||||
self.assertRaises(ValueError, setattr, buf, "raw", memoryview("x" * 100))
|
||||
|
||||
def test_c_buffer_raw(self, memoryview=memoryview):
|
||||
buf = c_buffer(32)
|
||||
|
||||
buf.raw = memoryview("Hello, World")
|
||||
self.assertEqual(buf.value, "Hello, World")
|
||||
self.assertRaises(TypeError, setattr, buf, "value", memoryview("abc"))
|
||||
self.assertRaises(ValueError, setattr, buf, "raw", memoryview("x" * 100))
|
||||
|
||||
def test_c_buffer_deprecated(self):
|
||||
# Compatibility with 2.x
|
||||
with test_support.check_py3k_warnings():
|
||||
self.test_c_buffer_value(buffer)
|
||||
self.test_c_buffer_raw(buffer)
|
||||
|
||||
def test_param_1(self):
|
||||
BUF = c_char * 4
|
||||
buf = BUF()
|
||||
## print c_char_p.from_param(buf)
|
||||
|
||||
def test_param_2(self):
|
||||
BUF = c_char * 4
|
||||
buf = BUF()
|
||||
## print BUF.from_param(c_char_p("python"))
|
||||
## print BUF.from_param(BUF(*"pyth"))
|
||||
|
||||
def test_del_segfault(self):
|
||||
BUF = c_char * 4
|
||||
buf = BUF()
|
||||
with self.assertRaises(AttributeError):
|
||||
del buf.raw
|
||||
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
class WStringArrayTestCase(unittest.TestCase):
|
||||
def test(self):
|
||||
BUF = c_wchar * 4
|
||||
|
||||
buf = BUF(u"a", u"b", u"c")
|
||||
self.assertEqual(buf.value, u"abc")
|
||||
|
||||
buf.value = u"ABCD"
|
||||
self.assertEqual(buf.value, u"ABCD")
|
||||
|
||||
buf.value = u"x"
|
||||
self.assertEqual(buf.value, u"x")
|
||||
|
||||
buf[1] = u"Z"
|
||||
self.assertEqual(buf.value, u"xZCD")
|
||||
|
||||
class StringTestCase(unittest.TestCase):
|
||||
@unittest.skip('test disabled')
|
||||
def test_basic_strings(self):
|
||||
cs = c_string("abcdef")
|
||||
|
||||
# Cannot call len on a c_string any longer
|
||||
self.assertRaises(TypeError, len, cs)
|
||||
self.assertEqual(sizeof(cs), 7)
|
||||
|
||||
# The value property is the string up to the first terminating NUL.
|
||||
self.assertEqual(cs.value, "abcdef")
|
||||
self.assertEqual(c_string("abc\000def").value, "abc")
|
||||
|
||||
# The raw property is the total buffer contents:
|
||||
self.assertEqual(cs.raw, "abcdef\000")
|
||||
self.assertEqual(c_string("abc\000def").raw, "abc\000def\000")
|
||||
|
||||
# We can change the value:
|
||||
cs.value = "ab"
|
||||
self.assertEqual(cs.value, "ab")
|
||||
self.assertEqual(cs.raw, "ab\000\000\000\000\000")
|
||||
|
||||
cs.raw = "XY"
|
||||
self.assertEqual(cs.value, "XY")
|
||||
self.assertEqual(cs.raw, "XY\000\000\000\000\000")
|
||||
|
||||
self.assertRaises(TypeError, c_string, u"123")
|
||||
|
||||
@unittest.skip('test disabled')
|
||||
def test_sized_strings(self):
|
||||
|
||||
# New in releases later than 0.4.0:
|
||||
self.assertRaises(TypeError, c_string, None)
|
||||
|
||||
# New in releases later than 0.4.0:
|
||||
# c_string(number) returns an empty string of size number
|
||||
self.assertEqual(len(c_string(32).raw), 32)
|
||||
self.assertRaises(ValueError, c_string, -1)
|
||||
self.assertRaises(ValueError, c_string, 0)
|
||||
|
||||
# These tests fail, because it is no longer initialized
|
||||
## self.assertEqual(c_string(2).value, "")
|
||||
## self.assertEqual(c_string(2).raw, "\000\000")
|
||||
self.assertEqual(c_string(2).raw[-1], "\000")
|
||||
self.assertEqual(len(c_string(2).raw), 2)
|
||||
|
||||
@unittest.skip('test disabled')
|
||||
def test_initialized_strings(self):
|
||||
|
||||
self.assertEqual(c_string("ab", 4).raw[:2], "ab")
|
||||
self.assertEqual(c_string("ab", 4).raw[:2:], "ab")
|
||||
self.assertEqual(c_string("ab", 4).raw[:2:-1], "ba")
|
||||
self.assertEqual(c_string("ab", 4).raw[:2:2], "a")
|
||||
self.assertEqual(c_string("ab", 4).raw[-1], "\000")
|
||||
self.assertEqual(c_string("ab", 2).raw, "a\000")
|
||||
|
||||
@unittest.skip('test disabled')
|
||||
def test_toolong(self):
|
||||
cs = c_string("abcdef")
|
||||
# Much too long string:
|
||||
self.assertRaises(ValueError, setattr, cs, "value", "123456789012345")
|
||||
|
||||
# One char too long values:
|
||||
self.assertRaises(ValueError, setattr, cs, "value", "1234567")
|
||||
|
||||
@unittest.skip('test disabled')
|
||||
def test_perf(self):
|
||||
check_perf()
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
class WStringTestCase(unittest.TestCase):
|
||||
def test_wchar(self):
|
||||
c_wchar(u"x")
|
||||
repr(byref(c_wchar(u"x")))
|
||||
c_wchar("x")
|
||||
|
||||
|
||||
@unittest.skip('test disabled')
|
||||
def test_basic_wstrings(self):
|
||||
cs = c_wstring(u"abcdef")
|
||||
|
||||
# XXX This behaviour is about to change:
|
||||
# len returns the size of the internal buffer in bytes.
|
||||
# This includes the terminating NUL character.
|
||||
self.assertEqual(sizeof(cs), 14)
|
||||
|
||||
# The value property is the string up to the first terminating NUL.
|
||||
self.assertEqual(cs.value, u"abcdef")
|
||||
self.assertEqual(c_wstring(u"abc\000def").value, u"abc")
|
||||
|
||||
self.assertEqual(c_wstring(u"abc\000def").value, u"abc")
|
||||
|
||||
# The raw property is the total buffer contents:
|
||||
self.assertEqual(cs.raw, u"abcdef\000")
|
||||
self.assertEqual(c_wstring(u"abc\000def").raw, u"abc\000def\000")
|
||||
|
||||
# We can change the value:
|
||||
cs.value = u"ab"
|
||||
self.assertEqual(cs.value, u"ab")
|
||||
self.assertEqual(cs.raw, u"ab\000\000\000\000\000")
|
||||
|
||||
self.assertRaises(TypeError, c_wstring, "123")
|
||||
self.assertRaises(ValueError, c_wstring, 0)
|
||||
|
||||
@unittest.skip('test disabled')
|
||||
def test_toolong(self):
|
||||
cs = c_wstring(u"abcdef")
|
||||
# Much too long string:
|
||||
self.assertRaises(ValueError, setattr, cs, "value", u"123456789012345")
|
||||
|
||||
# One char too long values:
|
||||
self.assertRaises(ValueError, setattr, cs, "value", u"1234567")
|
||||
|
||||
|
||||
def run_test(rep, msg, func, arg):
|
||||
items = range(rep)
|
||||
from time import clock
|
||||
start = clock()
|
||||
for i in items:
|
||||
func(arg); func(arg); func(arg); func(arg); func(arg)
|
||||
stop = clock()
|
||||
print "%20s: %.2f us" % (msg, ((stop-start)*1e6/5/rep))
|
||||
|
||||
def check_perf():
|
||||
# Construct 5 objects
|
||||
|
||||
REP = 200000
|
||||
|
||||
run_test(REP, "c_string(None)", c_string, None)
|
||||
run_test(REP, "c_string('abc')", c_string, 'abc')
|
||||
|
||||
# Python 2.3 -OO, win2k, P4 700 MHz:
|
||||
#
|
||||
# c_string(None): 1.75 us
|
||||
# c_string('abc'): 2.74 us
|
||||
|
||||
# Python 2.2 -OO, win2k, P4 700 MHz:
|
||||
#
|
||||
# c_string(None): 2.95 us
|
||||
# c_string('abc'): 3.67 us
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
## check_perf()
|
||||
unittest.main()
|
||||
74
Lib/ctypes/test/test_struct_fields.py
Normal file
74
Lib/ctypes/test/test_struct_fields.py
Normal file
@@ -0,0 +1,74 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
|
||||
class StructFieldsTestCase(unittest.TestCase):
|
||||
# Structure/Union classes must get 'finalized' sooner or
|
||||
# later, when one of these things happen:
|
||||
#
|
||||
# 1. _fields_ is set.
|
||||
# 2. An instance is created.
|
||||
# 3. The type is used as field of another Structure/Union.
|
||||
# 4. The type is subclassed
|
||||
#
|
||||
# When they are finalized, assigning _fields_ is no longer allowed.
|
||||
|
||||
def test_1_A(self):
|
||||
class X(Structure):
|
||||
pass
|
||||
self.assertEqual(sizeof(X), 0) # not finalized
|
||||
X._fields_ = [] # finalized
|
||||
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||
|
||||
def test_1_B(self):
|
||||
class X(Structure):
|
||||
_fields_ = [] # finalized
|
||||
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||
|
||||
def test_2(self):
|
||||
class X(Structure):
|
||||
pass
|
||||
X()
|
||||
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||
|
||||
def test_3(self):
|
||||
class X(Structure):
|
||||
pass
|
||||
class Y(Structure):
|
||||
_fields_ = [("x", X)] # finalizes X
|
||||
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||
|
||||
def test_4(self):
|
||||
class X(Structure):
|
||||
pass
|
||||
class Y(X):
|
||||
pass
|
||||
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||
Y._fields_ = []
|
||||
self.assertRaises(AttributeError, setattr, X, "_fields_", [])
|
||||
|
||||
# __set__ and __get__ should raise a TypeError in case their self
|
||||
# argument is not a ctype instance.
|
||||
def test___set__(self):
|
||||
class MyCStruct(Structure):
|
||||
_fields_ = (("field", c_int),)
|
||||
self.assertRaises(TypeError,
|
||||
MyCStruct.field.__set__, 'wrong type self', 42)
|
||||
|
||||
class MyCUnion(Union):
|
||||
_fields_ = (("field", c_int),)
|
||||
self.assertRaises(TypeError,
|
||||
MyCUnion.field.__set__, 'wrong type self', 42)
|
||||
|
||||
def test___get__(self):
|
||||
class MyCStruct(Structure):
|
||||
_fields_ = (("field", c_int),)
|
||||
self.assertRaises(TypeError,
|
||||
MyCStruct.field.__get__, 'wrong type self', 42)
|
||||
|
||||
class MyCUnion(Union):
|
||||
_fields_ = (("field", c_int),)
|
||||
self.assertRaises(TypeError,
|
||||
MyCUnion.field.__get__, 'wrong type self', 42)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
498
Lib/ctypes/test/test_structures.py
Normal file
498
Lib/ctypes/test/test_structures.py
Normal file
@@ -0,0 +1,498 @@
|
||||
import unittest
|
||||
from ctypes import *
|
||||
from ctypes.test import need_symbol
|
||||
from struct import calcsize
|
||||
import _testcapi
|
||||
import _ctypes_test
|
||||
|
||||
class SubclassesTest(unittest.TestCase):
|
||||
def test_subclass(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_int)]
|
||||
|
||||
class Y(X):
|
||||
_fields_ = [("b", c_int)]
|
||||
|
||||
class Z(X):
|
||||
pass
|
||||
|
||||
self.assertEqual(sizeof(X), sizeof(c_int))
|
||||
self.assertEqual(sizeof(Y), sizeof(c_int)*2)
|
||||
self.assertEqual(sizeof(Z), sizeof(c_int))
|
||||
self.assertEqual(X._fields_, [("a", c_int)])
|
||||
self.assertEqual(Y._fields_, [("b", c_int)])
|
||||
self.assertEqual(Z._fields_, [("a", c_int)])
|
||||
|
||||
def test_subclass_delayed(self):
|
||||
class X(Structure):
|
||||
pass
|
||||
self.assertEqual(sizeof(X), 0)
|
||||
X._fields_ = [("a", c_int)]
|
||||
|
||||
class Y(X):
|
||||
pass
|
||||
self.assertEqual(sizeof(Y), sizeof(X))
|
||||
Y._fields_ = [("b", c_int)]
|
||||
|
||||
class Z(X):
|
||||
pass
|
||||
|
||||
self.assertEqual(sizeof(X), sizeof(c_int))
|
||||
self.assertEqual(sizeof(Y), sizeof(c_int)*2)
|
||||
self.assertEqual(sizeof(Z), sizeof(c_int))
|
||||
self.assertEqual(X._fields_, [("a", c_int)])
|
||||
self.assertEqual(Y._fields_, [("b", c_int)])
|
||||
self.assertEqual(Z._fields_, [("a", c_int)])
|
||||
|
||||
class StructureTestCase(unittest.TestCase):
|
||||
formats = {"c": c_char,
|
||||
"b": c_byte,
|
||||
"B": c_ubyte,
|
||||
"h": c_short,
|
||||
"H": c_ushort,
|
||||
"i": c_int,
|
||||
"I": c_uint,
|
||||
"l": c_long,
|
||||
"L": c_ulong,
|
||||
"q": c_longlong,
|
||||
"Q": c_ulonglong,
|
||||
"f": c_float,
|
||||
"d": c_double,
|
||||
}
|
||||
|
||||
def test_simple_structs(self):
|
||||
for code, tp in self.formats.items():
|
||||
class X(Structure):
|
||||
_fields_ = [("x", c_char),
|
||||
("y", tp)]
|
||||
self.assertEqual((sizeof(X), code),
|
||||
(calcsize("c%c0%c" % (code, code)), code))
|
||||
|
||||
def test_unions(self):
|
||||
for code, tp in self.formats.items():
|
||||
class X(Union):
|
||||
_fields_ = [("x", c_char),
|
||||
("y", tp)]
|
||||
self.assertEqual((sizeof(X), code),
|
||||
(calcsize("%c" % (code)), code))
|
||||
|
||||
def test_struct_alignment(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("x", c_char * 3)]
|
||||
self.assertEqual(alignment(X), calcsize("s"))
|
||||
self.assertEqual(sizeof(X), calcsize("3s"))
|
||||
|
||||
class Y(Structure):
|
||||
_fields_ = [("x", c_char * 3),
|
||||
("y", c_int)]
|
||||
self.assertEqual(alignment(Y), alignment(c_int))
|
||||
self.assertEqual(sizeof(Y), calcsize("3si"))
|
||||
|
||||
class SI(Structure):
|
||||
_fields_ = [("a", X),
|
||||
("b", Y)]
|
||||
self.assertEqual(alignment(SI), max(alignment(Y), alignment(X)))
|
||||
self.assertEqual(sizeof(SI), calcsize("3s0i 3si 0i"))
|
||||
|
||||
class IS(Structure):
|
||||
_fields_ = [("b", Y),
|
||||
("a", X)]
|
||||
|
||||
self.assertEqual(alignment(SI), max(alignment(X), alignment(Y)))
|
||||
self.assertEqual(sizeof(IS), calcsize("3si 3s 0i"))
|
||||
|
||||
class XX(Structure):
|
||||
_fields_ = [("a", X),
|
||||
("b", X)]
|
||||
self.assertEqual(alignment(XX), alignment(X))
|
||||
self.assertEqual(sizeof(XX), calcsize("3s 3s 0s"))
|
||||
|
||||
def test_empty(self):
|
||||
# I had problems with these
|
||||
#
|
||||
# Although these are pathological cases: Empty Structures!
|
||||
class X(Structure):
|
||||
_fields_ = []
|
||||
|
||||
class Y(Union):
|
||||
_fields_ = []
|
||||
|
||||
# Is this really the correct alignment, or should it be 0?
|
||||
self.assertTrue(alignment(X) == alignment(Y) == 1)
|
||||
self.assertTrue(sizeof(X) == sizeof(Y) == 0)
|
||||
|
||||
class XX(Structure):
|
||||
_fields_ = [("a", X),
|
||||
("b", X)]
|
||||
|
||||
self.assertEqual(alignment(XX), 1)
|
||||
self.assertEqual(sizeof(XX), 0)
|
||||
|
||||
def test_fields(self):
|
||||
# test the offset and size attributes of Structure/Unoin fields.
|
||||
class X(Structure):
|
||||
_fields_ = [("x", c_int),
|
||||
("y", c_char)]
|
||||
|
||||
self.assertEqual(X.x.offset, 0)
|
||||
self.assertEqual(X.x.size, sizeof(c_int))
|
||||
|
||||
self.assertEqual(X.y.offset, sizeof(c_int))
|
||||
self.assertEqual(X.y.size, sizeof(c_char))
|
||||
|
||||
# readonly
|
||||
self.assertRaises((TypeError, AttributeError), setattr, X.x, "offset", 92)
|
||||
self.assertRaises((TypeError, AttributeError), setattr, X.x, "size", 92)
|
||||
|
||||
class X(Union):
|
||||
_fields_ = [("x", c_int),
|
||||
("y", c_char)]
|
||||
|
||||
self.assertEqual(X.x.offset, 0)
|
||||
self.assertEqual(X.x.size, sizeof(c_int))
|
||||
|
||||
self.assertEqual(X.y.offset, 0)
|
||||
self.assertEqual(X.y.size, sizeof(c_char))
|
||||
|
||||
# readonly
|
||||
self.assertRaises((TypeError, AttributeError), setattr, X.x, "offset", 92)
|
||||
self.assertRaises((TypeError, AttributeError), setattr, X.x, "size", 92)
|
||||
|
||||
# XXX Should we check nested data types also?
|
||||
# offset is always relative to the class...
|
||||
|
||||
def test_packed(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_byte),
|
||||
("b", c_longlong)]
|
||||
_pack_ = 1
|
||||
|
||||
self.assertEqual(sizeof(X), 9)
|
||||
self.assertEqual(X.b.offset, 1)
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_byte),
|
||||
("b", c_longlong)]
|
||||
_pack_ = 2
|
||||
self.assertEqual(sizeof(X), 10)
|
||||
self.assertEqual(X.b.offset, 2)
|
||||
|
||||
import struct
|
||||
longlong_size = struct.calcsize("q")
|
||||
longlong_align = struct.calcsize("bq") - longlong_size
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_byte),
|
||||
("b", c_longlong)]
|
||||
_pack_ = 4
|
||||
self.assertEqual(sizeof(X), min(4, longlong_align) + longlong_size)
|
||||
self.assertEqual(X.b.offset, min(4, longlong_align))
|
||||
|
||||
class X(Structure):
|
||||
_fields_ = [("a", c_byte),
|
||||
("b", c_longlong)]
|
||||
_pack_ = 8
|
||||
|
||||
self.assertEqual(sizeof(X), min(8, longlong_align) + longlong_size)
|
||||
self.assertEqual(X.b.offset, min(8, longlong_align))
|
||||
|
||||
|
||||
d = {"_fields_": [("a", "b"),
|
||||
("b", "q")],
|
||||
"_pack_": -1}
|
||||
self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
|
||||
|
||||
# Issue 15989
|
||||
d = {"_fields_": [("a", c_byte)],
|
||||
"_pack_": _testcapi.INT_MAX + 1}
|
||||
self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
|
||||
d = {"_fields_": [("a", c_byte)],
|
||||
"_pack_": _testcapi.UINT_MAX + 2}
|
||||
self.assertRaises(ValueError, type(Structure), "X", (Structure,), d)
|
||||
|
||||
def test_initializers(self):
|
||||
class Person(Structure):
|
||||
_fields_ = [("name", c_char*6),
|
||||
("age", c_int)]
|
||||
|
||||
self.assertRaises(TypeError, Person, 42)
|
||||
self.assertRaises(ValueError, Person, "asldkjaslkdjaslkdj")
|
||||
self.assertRaises(TypeError, Person, "Name", "HI")
|
||||
|
||||
# short enough
|
||||
self.assertEqual(Person("12345", 5).name, "12345")
|
||||
# exact fit
|
||||
self.assertEqual(Person("123456", 5).name, "123456")
|
||||
# too long
|
||||
self.assertRaises(ValueError, Person, "1234567", 5)
|
||||
|
||||
def test_conflicting_initializers(self):
|
||||
class POINT(Structure):
|
||||
_fields_ = [("x", c_int), ("y", c_int)]
|
||||
# conflicting positional and keyword args
|
||||
self.assertRaises(TypeError, POINT, 2, 3, x=4)
|
||||
self.assertRaises(TypeError, POINT, 2, 3, y=4)
|
||||
|
||||
# too many initializers
|
||||
self.assertRaises(TypeError, POINT, 2, 3, 4)
|
||||
|
||||
def test_keyword_initializers(self):
|
||||
class POINT(Structure):
|
||||
_fields_ = [("x", c_int), ("y", c_int)]
|
||||
pt = POINT(1, 2)
|
||||
self.assertEqual((pt.x, pt.y), (1, 2))
|
||||
|
||||
pt = POINT(y=2, x=1)
|
||||
self.assertEqual((pt.x, pt.y), (1, 2))
|
||||
|
||||
def test_invalid_field_types(self):
|
||||
class POINT(Structure):
|
||||
pass
|
||||
self.assertRaises(TypeError, setattr, POINT, "_fields_", [("x", 1), ("y", 2)])
|
||||
|
||||
def test_invalid_name(self):
|
||||
# field name must be string
|
||||
def declare_with_name(name):
|
||||
class S(Structure):
|
||||
_fields_ = [(name, c_int)]
|
||||
|
||||
self.assertRaises(TypeError, declare_with_name, u"x\xe9")
|
||||
|
||||
def test_intarray_fields(self):
|
||||
class SomeInts(Structure):
|
||||
_fields_ = [("a", c_int * 4)]
|
||||
|
||||
# can use tuple to initialize array (but not list!)
|
||||
self.assertEqual(SomeInts((1, 2)).a[:], [1, 2, 0, 0])
|
||||
self.assertEqual(SomeInts((1, 2)).a[::], [1, 2, 0, 0])
|
||||
self.assertEqual(SomeInts((1, 2)).a[::-1], [0, 0, 2, 1])
|
||||
self.assertEqual(SomeInts((1, 2)).a[::2], [1, 0])
|
||||
self.assertEqual(SomeInts((1, 2)).a[1:5:6], [2])
|
||||
self.assertEqual(SomeInts((1, 2)).a[6:4:-1], [])
|
||||
self.assertEqual(SomeInts((1, 2, 3, 4)).a[:], [1, 2, 3, 4])
|
||||
self.assertEqual(SomeInts((1, 2, 3, 4)).a[::], [1, 2, 3, 4])
|
||||
# too long
|
||||
# XXX Should raise ValueError?, not RuntimeError
|
||||
self.assertRaises(RuntimeError, SomeInts, (1, 2, 3, 4, 5))
|
||||
|
||||
def test_nested_initializers(self):
|
||||
# test initializing nested structures
|
||||
class Phone(Structure):
|
||||
_fields_ = [("areacode", c_char*6),
|
||||
("number", c_char*12)]
|
||||
|
||||
class Person(Structure):
|
||||
_fields_ = [("name", c_char * 12),
|
||||
("phone", Phone),
|
||||
("age", c_int)]
|
||||
|
||||
p = Person("Someone", ("1234", "5678"), 5)
|
||||
|
||||
self.assertEqual(p.name, "Someone")
|
||||
self.assertEqual(p.phone.areacode, "1234")
|
||||
self.assertEqual(p.phone.number, "5678")
|
||||
self.assertEqual(p.age, 5)
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
def test_structures_with_wchar(self):
|
||||
class PersonW(Structure):
|
||||
_fields_ = [("name", c_wchar * 12),
|
||||
("age", c_int)]
|
||||
|
||||
p = PersonW(u"Someone")
|
||||
self.assertEqual(p.name, "Someone")
|
||||
|
||||
self.assertEqual(PersonW(u"1234567890").name, u"1234567890")
|
||||
self.assertEqual(PersonW(u"12345678901").name, u"12345678901")
|
||||
# exact fit
|
||||
self.assertEqual(PersonW(u"123456789012").name, u"123456789012")
|
||||
#too long
|
||||
self.assertRaises(ValueError, PersonW, u"1234567890123")
|
||||
|
||||
def test_init_errors(self):
|
||||
class Phone(Structure):
|
||||
_fields_ = [("areacode", c_char*6),
|
||||
("number", c_char*12)]
|
||||
|
||||
class Person(Structure):
|
||||
_fields_ = [("name", c_char * 12),
|
||||
("phone", Phone),
|
||||
("age", c_int)]
|
||||
|
||||
cls, msg = self.get_except(Person, "Someone", (1, 2))
|
||||
self.assertEqual(cls, RuntimeError)
|
||||
# In Python 2.5, Exception is a new-style class, and the repr changed
|
||||
if issubclass(Exception, object):
|
||||
self.assertEqual(msg,
|
||||
"(Phone) <type 'exceptions.TypeError'>: "
|
||||
"expected string or Unicode object, int found")
|
||||
else:
|
||||
# Compatibility no longer strictly required
|
||||
self.assertEqual(msg,
|
||||
"(Phone) exceptions.TypeError: "
|
||||
"expected string or Unicode object, int found")
|
||||
|
||||
cls, msg = self.get_except(Person, "Someone", ("a", "b", "c"))
|
||||
self.assertEqual(cls, RuntimeError)
|
||||
if issubclass(Exception, object):
|
||||
self.assertEqual(msg,
|
||||
"(Phone) <type 'exceptions.TypeError'>: too many initializers")
|
||||
else:
|
||||
self.assertEqual(msg, "(Phone) exceptions.TypeError: too many initializers")
|
||||
|
||||
def test_huge_field_name(self):
|
||||
# issue12881: segfault with large structure field names
|
||||
def create_class(length):
|
||||
class S(Structure):
|
||||
_fields_ = [('x' * length, c_int)]
|
||||
|
||||
for length in [10 ** i for i in range(0, 8)]:
|
||||
try:
|
||||
create_class(length)
|
||||
except MemoryError:
|
||||
# MemoryErrors are OK, we just don't want to segfault
|
||||
pass
|
||||
|
||||
def get_except(self, func, *args):
|
||||
try:
|
||||
func(*args)
|
||||
except Exception, detail:
|
||||
return detail.__class__, str(detail)
|
||||
|
||||
@unittest.skip('test disabled')
|
||||
def test_subclass_creation(self):
|
||||
meta = type(Structure)
|
||||
# same as 'class X(Structure): pass'
|
||||
# fails, since we need either a _fields_ or a _abstract_ attribute
|
||||
cls, msg = self.get_except(meta, "X", (Structure,), {})
|
||||
self.assertEqual((cls, msg),
|
||||
(AttributeError, "class must define a '_fields_' attribute"))
|
||||
|
||||
def test_abstract_class(self):
|
||||
class X(Structure):
|
||||
_abstract_ = "something"
|
||||
# try 'X()'
|
||||
cls, msg = self.get_except(eval, "X()", locals())
|
||||
self.assertEqual((cls, msg), (TypeError, "abstract class"))
|
||||
|
||||
def test_methods(self):
|
||||
## class X(Structure):
|
||||
## _fields_ = []
|
||||
|
||||
self.assertIn("in_dll", dir(type(Structure)))
|
||||
self.assertIn("from_address", dir(type(Structure)))
|
||||
self.assertIn("in_dll", dir(type(Structure)))
|
||||
|
||||
def test_positional_args(self):
|
||||
# see also http://bugs.python.org/issue5042
|
||||
class W(Structure):
|
||||
_fields_ = [("a", c_int), ("b", c_int)]
|
||||
class X(W):
|
||||
_fields_ = [("c", c_int)]
|
||||
class Y(X):
|
||||
pass
|
||||
class Z(Y):
|
||||
_fields_ = [("d", c_int), ("e", c_int), ("f", c_int)]
|
||||
|
||||
z = Z(1, 2, 3, 4, 5, 6)
|
||||
self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f),
|
||||
(1, 2, 3, 4, 5, 6))
|
||||
z = Z(1)
|
||||
self.assertEqual((z.a, z.b, z.c, z.d, z.e, z.f),
|
||||
(1, 0, 0, 0, 0, 0))
|
||||
self.assertRaises(TypeError, lambda: Z(1, 2, 3, 4, 5, 6, 7))
|
||||
|
||||
def test_pass_by_value(self):
|
||||
# This should mirror the structure in Modules/_ctypes/_ctypes_test.c
|
||||
class X(Structure):
|
||||
_fields_ = [
|
||||
('first', c_ulong),
|
||||
('second', c_ulong),
|
||||
('third', c_ulong),
|
||||
]
|
||||
|
||||
s = X()
|
||||
s.first = 0xdeadbeef
|
||||
s.second = 0xcafebabe
|
||||
s.third = 0x0bad1dea
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
func = dll._testfunc_large_struct_update_value
|
||||
func.argtypes = (X,)
|
||||
func.restype = None
|
||||
func(s)
|
||||
self.assertEqual(s.first, 0xdeadbeef)
|
||||
self.assertEqual(s.second, 0xcafebabe)
|
||||
self.assertEqual(s.third, 0x0bad1dea)
|
||||
|
||||
class PointerMemberTestCase(unittest.TestCase):
|
||||
|
||||
def test(self):
|
||||
# a Structure with a POINTER field
|
||||
class S(Structure):
|
||||
_fields_ = [("array", POINTER(c_int))]
|
||||
|
||||
s = S()
|
||||
# We can assign arrays of the correct type
|
||||
s.array = (c_int * 3)(1, 2, 3)
|
||||
items = [s.array[i] for i in range(3)]
|
||||
self.assertEqual(items, [1, 2, 3])
|
||||
|
||||
# The following are bugs, but are included here because the unittests
|
||||
# also describe the current behaviour.
|
||||
#
|
||||
# This fails with SystemError: bad arg to internal function
|
||||
# or with IndexError (with a patch I have)
|
||||
|
||||
s.array[0] = 42
|
||||
|
||||
items = [s.array[i] for i in range(3)]
|
||||
self.assertEqual(items, [42, 2, 3])
|
||||
|
||||
s.array[0] = 1
|
||||
|
||||
## s.array[1] = 42
|
||||
|
||||
items = [s.array[i] for i in range(3)]
|
||||
self.assertEqual(items, [1, 2, 3])
|
||||
|
||||
def test_none_to_pointer_fields(self):
|
||||
class S(Structure):
|
||||
_fields_ = [("x", c_int),
|
||||
("p", POINTER(c_int))]
|
||||
|
||||
s = S()
|
||||
s.x = 12345678
|
||||
s.p = None
|
||||
self.assertEqual(s.x, 12345678)
|
||||
|
||||
class TestRecursiveStructure(unittest.TestCase):
|
||||
def test_contains_itself(self):
|
||||
class Recursive(Structure):
|
||||
pass
|
||||
|
||||
try:
|
||||
Recursive._fields_ = [("next", Recursive)]
|
||||
except AttributeError, details:
|
||||
self.assertIn("Structure or union cannot contain itself",
|
||||
str(details))
|
||||
else:
|
||||
self.fail("Structure or union cannot contain itself")
|
||||
|
||||
|
||||
def test_vice_versa(self):
|
||||
class First(Structure):
|
||||
pass
|
||||
class Second(Structure):
|
||||
pass
|
||||
|
||||
First._fields_ = [("second", Second)]
|
||||
|
||||
try:
|
||||
Second._fields_ = [("first", First)]
|
||||
except AttributeError, details:
|
||||
self.assertIn("_fields_ is final", str(details))
|
||||
else:
|
||||
self.fail("AttributeError not raised")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
45
Lib/ctypes/test/test_unaligned_structures.py
Normal file
45
Lib/ctypes/test/test_unaligned_structures.py
Normal file
@@ -0,0 +1,45 @@
|
||||
import sys, unittest
|
||||
from ctypes import *
|
||||
|
||||
structures = []
|
||||
byteswapped_structures = []
|
||||
|
||||
|
||||
if sys.byteorder == "little":
|
||||
SwappedStructure = BigEndianStructure
|
||||
else:
|
||||
SwappedStructure = LittleEndianStructure
|
||||
|
||||
for typ in [c_short, c_int, c_long, c_longlong,
|
||||
c_float, c_double,
|
||||
c_ushort, c_uint, c_ulong, c_ulonglong]:
|
||||
class X(Structure):
|
||||
_pack_ = 1
|
||||
_fields_ = [("pad", c_byte),
|
||||
("value", typ)]
|
||||
class Y(SwappedStructure):
|
||||
_pack_ = 1
|
||||
_fields_ = [("pad", c_byte),
|
||||
("value", typ)]
|
||||
structures.append(X)
|
||||
byteswapped_structures.append(Y)
|
||||
|
||||
class TestStructures(unittest.TestCase):
|
||||
def test_native(self):
|
||||
for typ in structures:
|
||||
## print typ.value
|
||||
self.assertEqual(typ.value.offset, 1)
|
||||
o = typ()
|
||||
o.value = 4
|
||||
self.assertEqual(o.value, 4)
|
||||
|
||||
def test_swapped(self):
|
||||
for typ in byteswapped_structures:
|
||||
## print >> sys.stderr, typ.value
|
||||
self.assertEqual(typ.value.offset, 1)
|
||||
o = typ()
|
||||
o.value = 4
|
||||
self.assertEqual(o.value, 4)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
138
Lib/ctypes/test/test_unicode.py
Normal file
138
Lib/ctypes/test/test_unicode.py
Normal file
@@ -0,0 +1,138 @@
|
||||
# coding: latin-1
|
||||
import unittest
|
||||
import ctypes
|
||||
from ctypes.test import need_symbol
|
||||
import _ctypes_test
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
class UnicodeTestCase(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
dll = ctypes.CDLL(_ctypes_test.__file__)
|
||||
cls.wcslen = dll.my_wcslen
|
||||
cls.wcslen.argtypes = [ctypes.c_wchar_p]
|
||||
def setUp(self):
|
||||
self.prev_conv_mode = ctypes.set_conversion_mode("ascii", "strict")
|
||||
|
||||
def tearDown(self):
|
||||
ctypes.set_conversion_mode(*self.prev_conv_mode)
|
||||
|
||||
def test_ascii_strict(self):
|
||||
wcslen = self.wcslen
|
||||
ctypes.set_conversion_mode("ascii", "strict")
|
||||
# no conversions take place with unicode arguments
|
||||
self.assertEqual(wcslen(u"abc"), 3)
|
||||
self.assertEqual(wcslen(u"ab\u2070"), 3)
|
||||
# string args are converted
|
||||
self.assertEqual(wcslen("abc"), 3)
|
||||
self.assertRaises(ctypes.ArgumentError, wcslen, "ab<EFBFBD>")
|
||||
|
||||
def test_ascii_replace(self):
|
||||
wcslen = self.wcslen
|
||||
ctypes.set_conversion_mode("ascii", "replace")
|
||||
self.assertEqual(wcslen(u"abc"), 3)
|
||||
self.assertEqual(wcslen(u"ab\u2070"), 3)
|
||||
self.assertEqual(wcslen("abc"), 3)
|
||||
self.assertEqual(wcslen("ab<EFBFBD>"), 3)
|
||||
|
||||
def test_ascii_ignore(self):
|
||||
wcslen = self.wcslen
|
||||
ctypes.set_conversion_mode("ascii", "ignore")
|
||||
self.assertEqual(wcslen(u"abc"), 3)
|
||||
self.assertEqual(wcslen(u"ab\u2070"), 3)
|
||||
# ignore error mode skips non-ascii characters
|
||||
self.assertEqual(wcslen("abc"), 3)
|
||||
self.assertEqual(wcslen("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 0)
|
||||
|
||||
def test_latin1_strict(self):
|
||||
wcslen = self.wcslen
|
||||
ctypes.set_conversion_mode("latin-1", "strict")
|
||||
self.assertEqual(wcslen(u"abc"), 3)
|
||||
self.assertEqual(wcslen(u"ab\u2070"), 3)
|
||||
self.assertEqual(wcslen("abc"), 3)
|
||||
self.assertEqual(wcslen("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 4)
|
||||
|
||||
def test_buffers(self):
|
||||
ctypes.set_conversion_mode("ascii", "strict")
|
||||
buf = ctypes.create_unicode_buffer("abc")
|
||||
self.assertEqual(len(buf), 3+1)
|
||||
|
||||
ctypes.set_conversion_mode("ascii", "replace")
|
||||
buf = ctypes.create_unicode_buffer("ab<EFBFBD><EFBFBD><EFBFBD>")
|
||||
self.assertEqual(buf[:], u"ab\uFFFD\uFFFD\uFFFD\0")
|
||||
self.assertEqual(buf[::], u"ab\uFFFD\uFFFD\uFFFD\0")
|
||||
self.assertEqual(buf[::-1], u"\0\uFFFD\uFFFD\uFFFDba")
|
||||
self.assertEqual(buf[::2], u"a\uFFFD\uFFFD")
|
||||
self.assertEqual(buf[6:5:-1], u"")
|
||||
|
||||
ctypes.set_conversion_mode("ascii", "ignore")
|
||||
buf = ctypes.create_unicode_buffer("ab<EFBFBD><EFBFBD><EFBFBD>")
|
||||
# is that correct? not sure. But with 'ignore', you get what you pay for..
|
||||
self.assertEqual(buf[:], u"ab\0\0\0\0")
|
||||
self.assertEqual(buf[::], u"ab\0\0\0\0")
|
||||
self.assertEqual(buf[::-1], u"\0\0\0\0ba")
|
||||
self.assertEqual(buf[::2], u"a\0\0")
|
||||
self.assertEqual(buf[6:5:-1], u"")
|
||||
|
||||
@need_symbol('c_wchar')
|
||||
class StringTestCase(UnicodeTestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(StringTestCase, cls).setUpClass()
|
||||
cls.func = ctypes.CDLL(_ctypes_test.__file__)._testfunc_p_p
|
||||
|
||||
def setUp(self):
|
||||
func = self.func
|
||||
self.prev_conv_mode = ctypes.set_conversion_mode("ascii", "strict")
|
||||
func.argtypes = [ctypes.c_char_p]
|
||||
func.restype = ctypes.c_char_p
|
||||
|
||||
def tearDown(self):
|
||||
func = self.func
|
||||
ctypes.set_conversion_mode(*self.prev_conv_mode)
|
||||
func.argtypes = None
|
||||
func.restype = ctypes.c_int
|
||||
|
||||
def test_ascii_strict(self):
|
||||
func = self.func
|
||||
ctypes.set_conversion_mode("ascii", "strict")
|
||||
self.assertEqual(func("abc"), "abc")
|
||||
self.assertEqual(func(u"abc"), "abc")
|
||||
self.assertRaises(ctypes.ArgumentError, func, u"ab<EFBFBD>")
|
||||
|
||||
def test_ascii_ignore(self):
|
||||
func = self.func
|
||||
ctypes.set_conversion_mode("ascii", "ignore")
|
||||
self.assertEqual(func("abc"), "abc")
|
||||
self.assertEqual(func(u"abc"), "abc")
|
||||
self.assertEqual(func(u"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), "")
|
||||
|
||||
def test_ascii_replace(self):
|
||||
func = self.func
|
||||
ctypes.set_conversion_mode("ascii", "replace")
|
||||
self.assertEqual(func("abc"), "abc")
|
||||
self.assertEqual(func(u"abc"), "abc")
|
||||
self.assertEqual(func(u"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), "????")
|
||||
|
||||
def test_buffers(self):
|
||||
ctypes.set_conversion_mode("ascii", "strict")
|
||||
buf = ctypes.create_string_buffer(u"abc")
|
||||
self.assertEqual(len(buf), 3+1)
|
||||
|
||||
ctypes.set_conversion_mode("ascii", "replace")
|
||||
buf = ctypes.create_string_buffer(u"ab<EFBFBD><EFBFBD><EFBFBD>")
|
||||
self.assertEqual(buf[:], "ab???\0")
|
||||
self.assertEqual(buf[::], "ab???\0")
|
||||
self.assertEqual(buf[::-1], "\0???ba")
|
||||
self.assertEqual(buf[::2], "a??")
|
||||
self.assertEqual(buf[6:5:-1], "")
|
||||
|
||||
ctypes.set_conversion_mode("ascii", "ignore")
|
||||
buf = ctypes.create_string_buffer(u"ab<EFBFBD><EFBFBD><EFBFBD>")
|
||||
# is that correct? not sure. But with 'ignore', you get what you pay for..
|
||||
self.assertEqual(buf[:], "ab\0\0\0\0")
|
||||
self.assertEqual(buf[::], "ab\0\0\0\0")
|
||||
self.assertEqual(buf[::-1], "\0\0\0\0ba")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
83
Lib/ctypes/test/test_values.py
Normal file
83
Lib/ctypes/test/test_values.py
Normal file
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
A testcase which accesses *values* in a dll.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
import sys
|
||||
from ctypes import *
|
||||
|
||||
import _ctypes_test
|
||||
|
||||
class ValuesTestCase(unittest.TestCase):
|
||||
|
||||
def test_an_integer(self):
|
||||
ctdll = CDLL(_ctypes_test.__file__)
|
||||
an_integer = c_int.in_dll(ctdll, "an_integer")
|
||||
x = an_integer.value
|
||||
self.assertEqual(x, ctdll.get_an_integer())
|
||||
an_integer.value *= 2
|
||||
self.assertEqual(x*2, ctdll.get_an_integer())
|
||||
|
||||
def test_undefined(self):
|
||||
ctdll = CDLL(_ctypes_test.__file__)
|
||||
self.assertRaises(ValueError, c_int.in_dll, ctdll, "Undefined_Symbol")
|
||||
|
||||
class PythonValuesTestCase(unittest.TestCase):
|
||||
"""This test only works when python itself is a dll/shared library"""
|
||||
|
||||
def test_optimizeflag(self):
|
||||
# This test accesses the Py_OptimizeFlag intger, which is
|
||||
# exported by the Python dll.
|
||||
|
||||
# It's value is set depending on the -O and -OO flags:
|
||||
# if not given, it is 0 and __debug__ is 1.
|
||||
# If -O is given, the flag is 1, for -OO it is 2.
|
||||
# docstrings are also removed in the latter case.
|
||||
opt = c_int.in_dll(pythonapi, "Py_OptimizeFlag").value
|
||||
if __debug__:
|
||||
self.assertEqual(opt, 0)
|
||||
elif ValuesTestCase.__doc__ is not None:
|
||||
self.assertEqual(opt, 1)
|
||||
else:
|
||||
self.assertEqual(opt, 2)
|
||||
|
||||
def test_frozentable(self):
|
||||
# Python exports a PyImport_FrozenModules symbol. This is a
|
||||
# pointer to an array of struct _frozen entries. The end of the
|
||||
# array is marked by an entry containing a NULL name and zero
|
||||
# size.
|
||||
|
||||
# In standard Python, this table contains a __hello__
|
||||
# module, and a __phello__ package containing a spam
|
||||
# module.
|
||||
class struct_frozen(Structure):
|
||||
_fields_ = [("name", c_char_p),
|
||||
("code", POINTER(c_ubyte)),
|
||||
("size", c_int)]
|
||||
FrozenTable = POINTER(struct_frozen)
|
||||
|
||||
ft = FrozenTable.in_dll(pythonapi, "PyImport_FrozenModules")
|
||||
# ft is a pointer to the struct_frozen entries:
|
||||
items = []
|
||||
for entry in ft:
|
||||
# This is dangerous. We *can* iterate over a pointer, but
|
||||
# the loop will not terminate (maybe with an access
|
||||
# violation;-) because the pointer instance has no size.
|
||||
if entry.name is None:
|
||||
break
|
||||
items.append((entry.name, entry.size))
|
||||
|
||||
expected = [("__hello__", 104),
|
||||
("__phello__", -104),
|
||||
("__phello__.spam", 104)]
|
||||
self.assertEqual(items, expected)
|
||||
|
||||
from ctypes import _pointer_type_cache
|
||||
del _pointer_type_cache[struct_frozen]
|
||||
|
||||
def test_undefined(self):
|
||||
self.assertRaises(ValueError, c_int.in_dll, pythonapi,
|
||||
"Undefined_Symbol")
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
50
Lib/ctypes/test/test_varsize_struct.py
Normal file
50
Lib/ctypes/test/test_varsize_struct.py
Normal file
@@ -0,0 +1,50 @@
|
||||
from ctypes import *
|
||||
import unittest
|
||||
|
||||
class VarSizeTest(unittest.TestCase):
|
||||
def test_resize(self):
|
||||
class X(Structure):
|
||||
_fields_ = [("item", c_int),
|
||||
("array", c_int * 1)]
|
||||
|
||||
self.assertEqual(sizeof(X), sizeof(c_int) * 2)
|
||||
x = X()
|
||||
x.item = 42
|
||||
x.array[0] = 100
|
||||
self.assertEqual(sizeof(x), sizeof(c_int) * 2)
|
||||
|
||||
# make room for one additional item
|
||||
new_size = sizeof(X) + sizeof(c_int) * 1
|
||||
resize(x, new_size)
|
||||
self.assertEqual(sizeof(x), new_size)
|
||||
self.assertEqual((x.item, x.array[0]), (42, 100))
|
||||
|
||||
# make room for 10 additional items
|
||||
new_size = sizeof(X) + sizeof(c_int) * 9
|
||||
resize(x, new_size)
|
||||
self.assertEqual(sizeof(x), new_size)
|
||||
self.assertEqual((x.item, x.array[0]), (42, 100))
|
||||
|
||||
# make room for one additional item
|
||||
new_size = sizeof(X) + sizeof(c_int) * 1
|
||||
resize(x, new_size)
|
||||
self.assertEqual(sizeof(x), new_size)
|
||||
self.assertEqual((x.item, x.array[0]), (42, 100))
|
||||
|
||||
def test_array_invalid_length(self):
|
||||
# cannot create arrays with non-positive size
|
||||
self.assertRaises(ValueError, lambda: c_int * -1)
|
||||
self.assertRaises(ValueError, lambda: c_int * -3)
|
||||
|
||||
def test_zerosized_array(self):
|
||||
array = (c_int * 0)()
|
||||
# accessing elements of zero-sized arrays raise IndexError
|
||||
self.assertRaises(IndexError, array.__setitem__, 0, None)
|
||||
self.assertRaises(IndexError, array.__getitem__, 0)
|
||||
self.assertRaises(IndexError, array.__setitem__, 1, None)
|
||||
self.assertRaises(IndexError, array.__getitem__, 1)
|
||||
self.assertRaises(IndexError, array.__setitem__, -1, None)
|
||||
self.assertRaises(IndexError, array.__getitem__, -1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
140
Lib/ctypes/test/test_win32.py
Normal file
140
Lib/ctypes/test/test_win32.py
Normal file
@@ -0,0 +1,140 @@
|
||||
# Windows specific tests
|
||||
|
||||
from ctypes import *
|
||||
from ctypes.test import requires
|
||||
import unittest, sys
|
||||
from test import test_support as support
|
||||
|
||||
import _ctypes_test
|
||||
|
||||
# Only windows 32-bit has different calling conventions.
|
||||
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||||
@unittest.skipUnless(sizeof(c_void_p) == sizeof(c_int),
|
||||
"sizeof c_void_p and c_int differ")
|
||||
class WindowsTestCase(unittest.TestCase):
|
||||
def test_callconv_1(self):
|
||||
# Testing stdcall function
|
||||
|
||||
IsWindow = windll.user32.IsWindow
|
||||
# ValueError: Procedure probably called with not enough arguments
|
||||
# (4 bytes missing)
|
||||
self.assertRaises(ValueError, IsWindow)
|
||||
|
||||
# This one should succeed...
|
||||
self.assertEqual(0, IsWindow(0))
|
||||
|
||||
# ValueError: Procedure probably called with too many arguments
|
||||
# (8 bytes in excess)
|
||||
self.assertRaises(ValueError, IsWindow, 0, 0, 0)
|
||||
|
||||
def test_callconv_2(self):
|
||||
# Calling stdcall function as cdecl
|
||||
|
||||
IsWindow = cdll.user32.IsWindow
|
||||
|
||||
# ValueError: Procedure called with not enough arguments
|
||||
# (4 bytes missing) or wrong calling convention
|
||||
self.assertRaises(ValueError, IsWindow, None)
|
||||
|
||||
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||||
class FunctionCallTestCase(unittest.TestCase):
|
||||
@unittest.skipUnless('MSC' in sys.version, "SEH only supported by MSC")
|
||||
@unittest.skipIf(sys.executable.endswith('_d.exe'),
|
||||
"SEH not enabled in debug builds")
|
||||
def test_SEH(self):
|
||||
requires("SEH")
|
||||
# Call functions with invalid arguments, and make sure
|
||||
# that access violations are trapped and raise an
|
||||
# exception.
|
||||
self.assertRaises(WindowsError, windll.kernel32.GetModuleHandleA, 32)
|
||||
|
||||
def test_noargs(self):
|
||||
# This is a special case on win32 x64
|
||||
windll.user32.GetDesktopWindow()
|
||||
|
||||
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||||
class ReturnStructSizesTestCase(unittest.TestCase):
|
||||
def test_sizes(self):
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
for i in range(1, 11):
|
||||
fields = [ ("f%d" % f, c_char) for f in range(1, i + 1)]
|
||||
class S(Structure):
|
||||
_fields_ = fields
|
||||
f = getattr(dll, "TestSize%d" % i)
|
||||
f.restype = S
|
||||
res = f()
|
||||
for i, f in enumerate(fields):
|
||||
value = getattr(res, f[0])
|
||||
expected = chr(ord('a') + i)
|
||||
self.assertEquals(value, expected)
|
||||
|
||||
|
||||
|
||||
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
|
||||
class TestWintypes(unittest.TestCase):
|
||||
def test_HWND(self):
|
||||
from ctypes import wintypes
|
||||
self.assertEqual(sizeof(wintypes.HWND), sizeof(c_void_p))
|
||||
|
||||
def test_PARAM(self):
|
||||
from ctypes import wintypes
|
||||
self.assertEqual(sizeof(wintypes.WPARAM),
|
||||
sizeof(c_void_p))
|
||||
self.assertEqual(sizeof(wintypes.LPARAM),
|
||||
sizeof(c_void_p))
|
||||
|
||||
def test_COMError(self):
|
||||
from _ctypes import COMError
|
||||
if support.HAVE_DOCSTRINGS:
|
||||
self.assertEqual(COMError.__doc__,
|
||||
"Raised when a COM method call failed.")
|
||||
|
||||
ex = COMError(-1, "text", ("details",))
|
||||
self.assertEqual(ex.hresult, -1)
|
||||
self.assertEqual(ex.text, "text")
|
||||
self.assertEqual(ex.details, ("details",))
|
||||
|
||||
class Structures(unittest.TestCase):
|
||||
def test_struct_by_value(self):
|
||||
class POINT(Structure):
|
||||
_fields_ = [("x", c_long),
|
||||
("y", c_long)]
|
||||
|
||||
class RECT(Structure):
|
||||
_fields_ = [("left", c_long),
|
||||
("top", c_long),
|
||||
("right", c_long),
|
||||
("bottom", c_long)]
|
||||
|
||||
dll = CDLL(_ctypes_test.__file__)
|
||||
|
||||
pt = POINT(15, 25)
|
||||
left = c_long.in_dll(dll, 'left')
|
||||
top = c_long.in_dll(dll, 'top')
|
||||
right = c_long.in_dll(dll, 'right')
|
||||
bottom = c_long.in_dll(dll, 'bottom')
|
||||
rect = RECT(left, top, right, bottom)
|
||||
PointInRect = dll.PointInRect
|
||||
PointInRect.argtypes = [POINTER(RECT), POINT]
|
||||
self.assertEqual(1, PointInRect(byref(rect), pt))
|
||||
|
||||
ReturnRect = dll.ReturnRect
|
||||
ReturnRect.argtypes = [c_int, RECT, POINTER(RECT), POINT, RECT,
|
||||
POINTER(RECT), POINT, RECT]
|
||||
ReturnRect.restype = RECT
|
||||
for i in range(4):
|
||||
ret = ReturnRect(i, rect, pointer(rect), pt, rect,
|
||||
byref(rect), pt, rect)
|
||||
# the c function will check and modify ret if something is
|
||||
# passed in improperly
|
||||
self.assertEqual(ret.left, left.value)
|
||||
self.assertEqual(ret.right, right.value)
|
||||
self.assertEqual(ret.top, top.value)
|
||||
self.assertEqual(ret.bottom, bottom.value)
|
||||
|
||||
# to not leak references, we must clean _pointer_type_cache
|
||||
from ctypes import _pointer_type_cache
|
||||
del _pointer_type_cache[RECT]
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
41
Lib/ctypes/test/test_wintypes.py
Normal file
41
Lib/ctypes/test/test_wintypes.py
Normal file
@@ -0,0 +1,41 @@
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from ctypes import *
|
||||
|
||||
@unittest.skipUnless(sys.platform.startswith('win'), 'Windows-only test')
|
||||
class WinTypesTest(unittest.TestCase):
|
||||
def test_variant_bool(self):
|
||||
from ctypes import wintypes
|
||||
# reads 16-bits from memory, anything non-zero is True
|
||||
for true_value in (1, 32767, 32768, 65535, 65537):
|
||||
true = POINTER(c_int16)(c_int16(true_value))
|
||||
value = cast(true, POINTER(wintypes.VARIANT_BOOL))
|
||||
self.assertEqual(repr(value.contents), 'VARIANT_BOOL(True)')
|
||||
|
||||
vb = wintypes.VARIANT_BOOL()
|
||||
self.assertIs(vb.value, False)
|
||||
vb.value = True
|
||||
self.assertIs(vb.value, True)
|
||||
vb.value = true_value
|
||||
self.assertIs(vb.value, True)
|
||||
|
||||
for false_value in (0, 65536, 262144, 2**33):
|
||||
false = POINTER(c_int16)(c_int16(false_value))
|
||||
value = cast(false, POINTER(wintypes.VARIANT_BOOL))
|
||||
self.assertEqual(repr(value.contents), 'VARIANT_BOOL(False)')
|
||||
|
||||
# allow any bool conversion on assignment to value
|
||||
for set_value in (65536, 262144, 2**33):
|
||||
vb = wintypes.VARIANT_BOOL()
|
||||
vb.value = set_value
|
||||
self.assertIs(vb.value, True)
|
||||
|
||||
vb = wintypes.VARIANT_BOOL()
|
||||
vb.value = [2, 3]
|
||||
self.assertIs(vb.value, True)
|
||||
vb.value = []
|
||||
self.assertIs(vb.value, False)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user