testGatewayAddresses.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. # The purpose of this test is to ensure that the gateways objects
  2. # do the right thing WRT COM rules about object identity etc.
  3. # Also includes a basic test that we support inheritance correctly in
  4. # gateway interfaces.
  5. # For our test, we create an object of type IID_IPersistStorage
  6. # This interface derives from IPersist.
  7. # Therefore, QI's for IID_IDispatch, IID_IUnknown, IID_IPersist and
  8. # IID_IPersistStorage should all return the same gateway object.
  9. #
  10. # In addition, the interface should only need to declare itself as
  11. # using the IPersistStorage interface, and as the gateway derives
  12. # from IPersist, it should automatically be available without declaration.
  13. #
  14. # We also create an object of type IID_I??, and perform a QI for it.
  15. # We then jump through a number of hoops, ensuring that the objects
  16. # returned by the QIs follow all the rules.
  17. #
  18. # Here is Gregs summary of the rules:
  19. # 1) the set of supported interfaces is static and unchanging
  20. # 2) symmetric: if you QI an interface for that interface, it succeeds
  21. # 3) reflexive: if you QI against A for B, the new pointer must succeed
  22. # for a QI for A
  23. # 4) transitive: if you QI for B, then QI that for C, then QI'ing A for C
  24. # must succeed
  25. #
  26. #
  27. # Note that 1) Requires cooperation of the Python programmer. The rule to keep is:
  28. # "whenever you return an _object_ from _query_interface_(), you must return the
  29. # same object each time for a given IID. Note that you must return the same
  30. # _wrapped_ object
  31. # you
  32. # The rest are tested here.
  33. from win32com.server.util import wrap
  34. import pythoncom
  35. from .util import CheckClean
  36. numErrors = 0
  37. # Check that the 2 objects both have identical COM pointers.
  38. def CheckSameCOMObject(ob1, ob2):
  39. addr1 = repr(ob1).split()[6][:-1]
  40. addr2 = repr(ob2).split()[6][:-1]
  41. return addr1==addr2
  42. # Check that the objects conform to COM identity rules.
  43. def CheckObjectIdentity(ob1, ob2):
  44. u1 = ob1.QueryInterface(pythoncom.IID_IUnknown)
  45. u2 = ob2.QueryInterface(pythoncom.IID_IUnknown)
  46. return CheckSameCOMObject(u1, u2)
  47. def FailObjectIdentity(ob1, ob2, when):
  48. if not CheckObjectIdentity(ob1, ob2):
  49. global numErrors
  50. numErrors = numErrors + 1
  51. print(when, "are not identical (%s, %s)" % (repr(ob1), repr(ob2)))
  52. class Dummy:
  53. _public_methods_ = [] # We never attempt to make a call on this object.
  54. _com_interfaces_ = [pythoncom.IID_IPersistStorage]
  55. class Dummy2:
  56. _public_methods_ = [] # We never attempt to make a call on this object.
  57. _com_interfaces_ = [pythoncom.IID_IPersistStorage, pythoncom.IID_IExternalConnection]
  58. class DeletgatedDummy:
  59. _public_methods_ = []
  60. class Dummy3:
  61. _public_methods_ = [] # We never attempt to make a call on this object.
  62. _com_interfaces_ = [pythoncom.IID_IPersistStorage]
  63. def _query_interface_(self, iid):
  64. if iid==pythoncom.IID_IExternalConnection:
  65. # This will NEVER work - can only wrap the object once!
  66. return wrap(DelegatedDummy())
  67. def TestGatewayInheritance():
  68. # By default, wrap() creates and discards a temporary object.
  69. # This is not necessary, but just the current implementation of wrap.
  70. # As the object is correctly discarded, it doesnt affect this test.
  71. o = wrap(Dummy(), pythoncom.IID_IPersistStorage)
  72. o2 = o.QueryInterface(pythoncom.IID_IUnknown)
  73. FailObjectIdentity(o, o2, "IID_IPersistStorage->IID_IUnknown")
  74. o3 = o2.QueryInterface(pythoncom.IID_IDispatch)
  75. FailObjectIdentity(o2, o3, "IID_IUnknown->IID_IDispatch")
  76. FailObjectIdentity(o, o3, "IID_IPersistStorage->IID_IDispatch")
  77. o4 = o3.QueryInterface(pythoncom.IID_IPersistStorage)
  78. FailObjectIdentity(o, o4, "IID_IPersistStorage->IID_IPersistStorage(2)")
  79. FailObjectIdentity(o2, o4, "IID_IUnknown->IID_IPersistStorage(2)")
  80. FailObjectIdentity(o3, o4, "IID_IDispatch->IID_IPersistStorage(2)")
  81. o5 = o4.QueryInterface(pythoncom.IID_IPersist)
  82. FailObjectIdentity(o, o5, "IID_IPersistStorage->IID_IPersist")
  83. FailObjectIdentity(o2, o5, "IID_IUnknown->IID_IPersist")
  84. FailObjectIdentity(o3, o5, "IID_IDispatch->IID_IPersist")
  85. FailObjectIdentity(o4, o5, "IID_IPersistStorage(2)->IID_IPersist")
  86. def TestMultiInterface():
  87. o = wrap(Dummy2(), pythoncom.IID_IPersistStorage)
  88. o2 = o.QueryInterface(pythoncom.IID_IExternalConnection)
  89. FailObjectIdentity(o, o2, "IID_IPersistStorage->IID_IExternalConnection")
  90. # Make the same QI again, to make sure it is stable.
  91. o22 = o.QueryInterface(pythoncom.IID_IExternalConnection)
  92. FailObjectIdentity(o, o22, "IID_IPersistStorage->IID_IExternalConnection")
  93. FailObjectIdentity(o2, o22, "IID_IPersistStorage->IID_IExternalConnection (stability)")
  94. o3 = o2.QueryInterface(pythoncom.IID_IPersistStorage)
  95. FailObjectIdentity(o2, o3, "IID_IExternalConnection->IID_IPersistStorage")
  96. FailObjectIdentity(o, o3, "IID_IPersistStorage->IID_IExternalConnection->IID_IPersistStorage")
  97. def test():
  98. TestGatewayInheritance()
  99. TestMultiInterface()
  100. if numErrors==0:
  101. print("Worked ok")
  102. else:
  103. print("There were", numErrors, "errors.")
  104. if __name__=='__main__':
  105. test()
  106. CheckClean()