Skip to content

Commit

Permalink
Revive test_comserver. (#680)
Browse files Browse the repository at this point in the history
* Improve import parts.

* Update `setUpModule` and add `tearDownModule`.

* Remove outdated version bridge.

* Remove unused import.

* Remove `if is_resource_enabled("ui"):`.

* Remove `if is_resource_enabled("memleaks"):`.

* Add `BaseServerTest`.

* Add `unittest.skip` markers.

* Comment out `if is_resource_enabled("CRASHES"):`.

* Add a `unittest.skip` marker to `TestLocalServer.test_get_typeinfo`
  • Loading branch information
junkmd authored Dec 6, 2024
1 parent 45b0dae commit cb92bec
Showing 1 changed file with 107 additions and 115 deletions.
222 changes: 107 additions & 115 deletions comtypes/test/test_comserver.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
import sys
import doctest
import unittest
from ctypes import pointer
from typing import Any

import comtypes.test.TestComServer
from comtypes import BSTR
from comtypes.client import CreateObject
from comtypes.server.register import register # , unregister
from comtypes.server.register import register, unregister
from comtypes.test import is_resource_enabled
from comtypes.test.find_memleak import find_memleak


def setUpModule():
raise unittest.SkipTest(
"This test requires the tests to be run as admin since it tries to "
"register the test COM server. Is this a good idea?"
)
try:
register(comtypes.test.TestComServer.TestComServer)
except WindowsError as e:
if e.winerror != 5: # [Error 5] Access is denied
raise e
raise unittest.SkipTest(
"This test requires the tests to be run as admin since it tries to "
"register the test COM server."
)

# If this test is ever NOT skipped, then this line needs to run. Keeping it here for posterity.
register(comtypes.test.TestComServer.TestComServer)

def tearDownModule():
unregister(comtypes.test.TestComServer.TestComServer)

class TestInproc(unittest.TestCase):
def create_object(self):
return CreateObject(
"TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_INPROC_SERVER
)

class BaseServerTest(object):
def create_object(self) -> Any: ...

def _find_memleak(self, func):
bytes = find_memleak(func)
self.assertFalse(bytes, "Leaks %d bytes" % bytes)
self.assertFalse(bytes, "Leaks %d bytes" % bytes) # type: ignore

def test_mixedinout(self):
o = self.create_object()
self.assertEqual(o.MixedInOut(2, 4), (3, 5))
self.assertEqual(o.MixedInOut(2, 4), (3, 5)) # type: ignore

def test_getname(self):
from ctypes import pointer
from comtypes import BSTR

# This tests a tricky bug, introduced with this patch:
# http://www.python.org/sf/1643874
#
Expand All @@ -53,61 +56,70 @@ def test_getname(self):
for i in range(10):
BSTR("f" * len(name))
# Make sure the pointer is still valid:
self.assertEqual(pb[0], name)
self.assertEqual(pb[0], name) # type: ignore

if is_resource_enabled("memleaks"):
def test_get_id(self):
obj = self.create_object()
self._find_memleak(lambda: obj.id)

def test_get_id(self):
obj = self.create_object()
self._find_memleak(lambda: obj.id)
def test_get_name(self):
obj = self.create_object()
self._find_memleak(lambda: obj.name)

def test_get_name(self):
obj = self.create_object()
self._find_memleak(lambda: obj.name)
def test_set_name(self):
obj = self.create_object()

def test_set_name(self):
obj = self.create_object()
def func():
obj.name = "abcde"

def func():
obj.name = "abcde"
self._find_memleak(func)

self._find_memleak(func)
def test_SetName(self):
obj = self.create_object()

def test_SetName(self):
obj = self.create_object()
def func():
obj.SetName("abcde")

def func():
obj.SetName("abcde")
self._find_memleak(func)

self._find_memleak(func)
def test_eval(self):
obj = self.create_object()

def test_eval(self):
obj = self.create_object()
def func():
return obj.eval("(1, 2, 3)")

def func():
return obj.eval("(1, 2, 3)")
self.assertEqual(func(), (1, 2, 3)) # type: ignore
self._find_memleak(func)

self.assertEqual(func(), (1, 2, 3))
self._find_memleak(func)
def test_get_typeinfo(self):
obj = self.create_object()

def test_get_typeinfo(self):
obj = self.create_object()
def func():
obj.GetTypeInfo(0)
obj.GetTypeInfoCount()
obj.QueryInterface(comtypes.IUnknown)

def func():
obj.GetTypeInfo(0)
obj.GetTypeInfoCount()
obj.QueryInterface(comtypes.IUnknown)
self._find_memleak(func)

self._find_memleak(func)

class TestInproc(BaseServerTest, unittest.TestCase):
def create_object(self):
return CreateObject(
"TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_INPROC_SERVER
)

if is_resource_enabled("ui"):

class TestLocalServer(TestInproc):
def create_object(self):
return CreateObject(
"TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_LOCAL_SERVER
)
class TestLocalServer(BaseServerTest, unittest.TestCase):
def create_object(self):
return CreateObject(
"TestComServerLib.TestComServer", clsctx=comtypes.CLSCTX_LOCAL_SERVER
)

@unittest.skip("This fails. Why?")
def test_get_typeinfo(self):
# Calling `GetTypeInfo` occurs;
# OSError: exception: access violation reading 0x0000000000000000
pass


try:
Expand All @@ -116,6 +128,7 @@ def create_object(self):
pass
else:

@unittest.skip("This depends on 'pywin32'.")
class TestInproc_win32com(TestInproc):
def create_object(self):
return Dispatch("TestComServerLib.TestComServer")
Expand All @@ -134,6 +147,7 @@ def test_mixedinout(self):

if is_resource_enabled("ui"):

@unittest.skip("This depends on 'pywin32'.")
class TestLocalServer_win32com(TestInproc_win32com):
def create_object(self):
return Dispatch(
Expand All @@ -142,72 +156,50 @@ def create_object(self):
)


import doctest
import comtypes.test.test_comserver


class TestCase(unittest.TestCase):
def test(self):
import comtypes.test.test_comserver

doctest.testmod(comtypes.test.test_comserver, optionflags=doctest.ELLIPSIS)

# The following functions are never called, they only contain doctests:

if sys.version_info >= (3, 0):

def ShowEvents(self):
"""
>>> from comtypes.client import CreateObject, ShowEvents
>>>
>>> o = CreateObject("TestComServerLib.TestComServer")
>>> con = ShowEvents(o)
# event found: ITestComServerEvents_EvalStarted
# event found: ITestComServerEvents_EvalCompleted
>>> result = o.eval("10. / 4")
Event ITestComServerEvents_EvalStarted(None, '10. / 4')
Event ITestComServerEvents_EvalCompleted(None, '10. / 4', VARIANT(vt=0x5, 2.5))
>>> result
2.5
>>>
"""

else:

def ShowEvents(self):
"""
>>> from comtypes.client import CreateObject, ShowEvents
>>>
>>> o = CreateObject("TestComServerLib.TestComServer")
>>> con = ShowEvents(o)
# event found: ITestComServerEvents_EvalStarted
# event found: ITestComServerEvents_EvalCompleted
>>> result = o.eval("10. / 4")
Event ITestComServerEvents_EvalStarted(None, u'10. / 4')
Event ITestComServerEvents_EvalCompleted(None, u'10. / 4', VARIANT(vt=0x5, 2.5))
>>> result
2.5
>>>
"""

# The following test, if enabled, works but the testsuit
# crashes elsewhere. Is there s problem with SAFEARRAYs?

if is_resource_enabled("CRASHES"):

def Fails(self):
"""
>>> from comtypes.client import CreateObject, ShowEvents
>>>
>>> o = CreateObject("TestComServerLib.TestComServer")
>>> con = ShowEvents(o)
# event found: ITestComServerEvents_EvalStarted
# event found: ITestComServerEvents_EvalCompleted
>>> result = o.eval("['32'] * 2")
Event ITestComServerEvents_EvalStarted(None, u"['32'] * 2")
Event ITestComServerEvents_EvalCompleted(None, u"['32'] * 2", VARIANT(vt=0x200c, (u'32', u'32')))
>>> result
(u'32', u'32')
>>>
"""
def ShowEventsFloat(self):
"""
>>> from comtypes.client import CreateObject, ShowEvents
>>>
>>> o = CreateObject("TestComServerLib.TestComServer")
>>> con = ShowEvents(o)
# event found: ITestComServerEvents_EvalStarted
# event found: ITestComServerEvents_EvalCompleted
>>> result = o.eval("10. / 4")
Event ITestComServerEvents_EvalStarted(None, '10. / 4')
Event ITestComServerEvents_EvalCompleted(None, '10. / 4', VARIANT(vt=0x5, 2.5))
>>> result
2.5
>>>
"""

# # The following test, if enabled, works but the testsuit
# # crashes elsewhere. Is there s problem with SAFEARRAYs?

# if is_resource_enabled("CRASHES"):

# def Fails(self):
# """
# >>> from comtypes.client import CreateObject, ShowEvents
# >>>
# >>> o = CreateObject("TestComServerLib.TestComServer")
# >>> con = ShowEvents(o)
# # event found: ITestComServerEvents_EvalStarted
# # event found: ITestComServerEvents_EvalCompleted
# >>> result = o.eval("['32'] * 2")
# Event ITestComServerEvents_EvalStarted(None, u"['32'] * 2")
# Event ITestComServerEvents_EvalCompleted(None, u"['32'] * 2", VARIANT(vt=0x200c, (u'32', u'32')))
# >>> result
# (u'32', u'32')
# >>>
# """

def GetEvents(self):
"""
Expand Down

0 comments on commit cb92bec

Please sign in to comment.