Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

testShell.py 9.5KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. import datetime
  2. import os
  3. import struct
  4. import sys
  5. import win32timezone
  6. try:
  7. sys_maxsize = sys.maxsize # 2.6 and later - maxsize != maxint on 64bits
  8. except AttributeError:
  9. sys_maxsize = sys.maxint
  10. import pythoncom
  11. import pywintypes
  12. import win32com.test.util
  13. import win32con
  14. from pywin32_testutil import str2bytes
  15. from win32com.shell import shell
  16. from win32com.shell.shellcon import *
  17. from win32com.storagecon import *
  18. class ShellTester(win32com.test.util.TestCase):
  19. def testShellLink(self):
  20. desktop = str(shell.SHGetSpecialFolderPath(0, CSIDL_DESKTOP))
  21. num = 0
  22. shellLink = pythoncom.CoCreateInstance(
  23. shell.CLSID_ShellLink,
  24. None,
  25. pythoncom.CLSCTX_INPROC_SERVER,
  26. shell.IID_IShellLink,
  27. )
  28. persistFile = shellLink.QueryInterface(pythoncom.IID_IPersistFile)
  29. names = [os.path.join(desktop, n) for n in os.listdir(desktop)]
  30. programs = str(shell.SHGetSpecialFolderPath(0, CSIDL_PROGRAMS))
  31. names.extend([os.path.join(programs, n) for n in os.listdir(programs)])
  32. for name in names:
  33. try:
  34. persistFile.Load(name, STGM_READ)
  35. except pythoncom.com_error:
  36. continue
  37. # Resolve is slow - avoid it for our tests.
  38. # shellLink.Resolve(0, shell.SLR_ANY_MATCH | shell.SLR_NO_UI)
  39. fname, findData = shellLink.GetPath(0)
  40. unc = shellLink.GetPath(shell.SLGP_UNCPRIORITY)[0]
  41. num += 1
  42. if num == 0:
  43. # This isn't a fatal error, but is unlikely.
  44. print(
  45. "Could not find any links on your desktop or programs dir, which is unusual"
  46. )
  47. def testShellFolder(self):
  48. sf = shell.SHGetDesktopFolder()
  49. names_1 = []
  50. for i in sf: # Magically calls EnumObjects
  51. name = sf.GetDisplayNameOf(i, SHGDN_NORMAL)
  52. names_1.append(name)
  53. # And get the enumerator manually
  54. enum = sf.EnumObjects(
  55. 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN
  56. )
  57. names_2 = []
  58. for i in enum:
  59. name = sf.GetDisplayNameOf(i, SHGDN_NORMAL)
  60. names_2.append(name)
  61. names_1.sort()
  62. names_2.sort()
  63. self.assertEqual(names_1, names_2)
  64. class PIDLTester(win32com.test.util.TestCase):
  65. def _rtPIDL(self, pidl):
  66. pidl_str = shell.PIDLAsString(pidl)
  67. pidl_rt = shell.StringAsPIDL(pidl_str)
  68. self.assertEqual(pidl_rt, pidl)
  69. pidl_str_rt = shell.PIDLAsString(pidl_rt)
  70. self.assertEqual(pidl_str_rt, pidl_str)
  71. def _rtCIDA(self, parent, kids):
  72. cida = parent, kids
  73. cida_str = shell.CIDAAsString(cida)
  74. cida_rt = shell.StringAsCIDA(cida_str)
  75. self.assertEqual(cida, cida_rt)
  76. cida_str_rt = shell.CIDAAsString(cida_rt)
  77. self.assertEqual(cida_str_rt, cida_str)
  78. def testPIDL(self):
  79. # A PIDL of "\1" is: cb pidl cb
  80. expect = str2bytes("\03\00" "\1" "\0\0")
  81. self.assertEqual(shell.PIDLAsString([str2bytes("\1")]), expect)
  82. self._rtPIDL([str2bytes("\0")])
  83. self._rtPIDL([str2bytes("\1"), str2bytes("\2"), str2bytes("\3")])
  84. self._rtPIDL([str2bytes("\0") * 2048] * 2048)
  85. # PIDL must be a list
  86. self.assertRaises(TypeError, shell.PIDLAsString, "foo")
  87. def testCIDA(self):
  88. self._rtCIDA([str2bytes("\0")], [[str2bytes("\0")]])
  89. self._rtCIDA([str2bytes("\1")], [[str2bytes("\2")]])
  90. self._rtCIDA(
  91. [str2bytes("\0")], [[str2bytes("\0")], [str2bytes("\1")], [str2bytes("\2")]]
  92. )
  93. def testBadShortPIDL(self):
  94. # A too-short child element: cb pidl cb
  95. pidl = str2bytes("\01\00" "\1")
  96. self.assertRaises(ValueError, shell.StringAsPIDL, pidl)
  97. # ack - tried to test too long PIDLs, but a len of 0xFFFF may not
  98. # always fail.
  99. class FILEGROUPDESCRIPTORTester(win32com.test.util.TestCase):
  100. def _getTestTimes(self):
  101. if issubclass(pywintypes.TimeType, datetime.datetime):
  102. ctime = win32timezone.now()
  103. # FILETIME only has ms precision...
  104. ctime = ctime.replace(microsecond=ctime.microsecond // 1000 * 1000)
  105. atime = ctime + datetime.timedelta(seconds=1)
  106. wtime = atime + datetime.timedelta(seconds=1)
  107. else:
  108. ctime = pywintypes.Time(11)
  109. atime = pywintypes.Time(12)
  110. wtime = pywintypes.Time(13)
  111. return ctime, atime, wtime
  112. def _testRT(self, fd):
  113. fgd_string = shell.FILEGROUPDESCRIPTORAsString([fd])
  114. fd2 = shell.StringAsFILEGROUPDESCRIPTOR(fgd_string)[0]
  115. fd = fd.copy()
  116. fd2 = fd2.copy()
  117. # The returned objects *always* have dwFlags and cFileName.
  118. if "dwFlags" not in fd:
  119. del fd2["dwFlags"]
  120. if "cFileName" not in fd:
  121. self.assertEqual(fd2["cFileName"], "")
  122. del fd2["cFileName"]
  123. self.assertEqual(fd, fd2)
  124. def _testSimple(self, make_unicode):
  125. fgd = shell.FILEGROUPDESCRIPTORAsString([], make_unicode)
  126. header = struct.pack("i", 0)
  127. self.assertEqual(header, fgd[: len(header)])
  128. self._testRT(dict())
  129. d = dict()
  130. fgd = shell.FILEGROUPDESCRIPTORAsString([d], make_unicode)
  131. header = struct.pack("i", 1)
  132. self.assertEqual(header, fgd[: len(header)])
  133. self._testRT(d)
  134. def testSimpleBytes(self):
  135. self._testSimple(False)
  136. def testSimpleUnicode(self):
  137. self._testSimple(True)
  138. def testComplex(self):
  139. clsid = pythoncom.MakeIID("{CD637886-DB8B-4b04-98B5-25731E1495BE}")
  140. ctime, atime, wtime = self._getTestTimes()
  141. d = dict(
  142. cFileName="foo.txt",
  143. clsid=clsid,
  144. sizel=(1, 2),
  145. pointl=(3, 4),
  146. dwFileAttributes=win32con.FILE_ATTRIBUTE_NORMAL,
  147. ftCreationTime=ctime,
  148. ftLastAccessTime=atime,
  149. ftLastWriteTime=wtime,
  150. nFileSize=sys_maxsize + 1,
  151. )
  152. self._testRT(d)
  153. def testUnicode(self):
  154. # exercise a bug fixed in build 210 - multiple unicode objects failed.
  155. ctime, atime, wtime = self._getTestTimes()
  156. d = [
  157. dict(
  158. cFileName="foo.txt",
  159. sizel=(1, 2),
  160. pointl=(3, 4),
  161. dwFileAttributes=win32con.FILE_ATTRIBUTE_NORMAL,
  162. ftCreationTime=ctime,
  163. ftLastAccessTime=atime,
  164. ftLastWriteTime=wtime,
  165. nFileSize=sys_maxsize + 1,
  166. ),
  167. dict(
  168. cFileName="foo2.txt",
  169. sizel=(1, 2),
  170. pointl=(3, 4),
  171. dwFileAttributes=win32con.FILE_ATTRIBUTE_NORMAL,
  172. ftCreationTime=ctime,
  173. ftLastAccessTime=atime,
  174. ftLastWriteTime=wtime,
  175. nFileSize=sys_maxsize + 1,
  176. ),
  177. dict(
  178. cFileName="foo\xa9.txt",
  179. sizel=(1, 2),
  180. pointl=(3, 4),
  181. dwFileAttributes=win32con.FILE_ATTRIBUTE_NORMAL,
  182. ftCreationTime=ctime,
  183. ftLastAccessTime=atime,
  184. ftLastWriteTime=wtime,
  185. nFileSize=sys_maxsize + 1,
  186. ),
  187. ]
  188. s = shell.FILEGROUPDESCRIPTORAsString(d, 1)
  189. d2 = shell.StringAsFILEGROUPDESCRIPTOR(s)
  190. # clobber 'dwFlags' - they are not expected to be identical
  191. for t in d2:
  192. del t["dwFlags"]
  193. self.assertEqual(d, d2)
  194. class FileOperationTester(win32com.test.util.TestCase):
  195. def setUp(self):
  196. import tempfile
  197. self.src_name = os.path.join(tempfile.gettempdir(), "pywin32_testshell")
  198. self.dest_name = os.path.join(tempfile.gettempdir(), "pywin32_testshell_dest")
  199. self.test_data = str2bytes("Hello from\0Python")
  200. f = open(self.src_name, "wb")
  201. f.write(self.test_data)
  202. f.close()
  203. try:
  204. os.unlink(self.dest_name)
  205. except os.error:
  206. pass
  207. def tearDown(self):
  208. for fname in (self.src_name, self.dest_name):
  209. if os.path.isfile(fname):
  210. os.unlink(fname)
  211. def testCopy(self):
  212. s = (0, FO_COPY, self.src_name, self.dest_name) # hwnd, # operation
  213. rc, aborted = shell.SHFileOperation(s)
  214. self.assertTrue(not aborted)
  215. self.assertEqual(0, rc)
  216. self.assertTrue(os.path.isfile(self.src_name))
  217. self.assertTrue(os.path.isfile(self.dest_name))
  218. def testRename(self):
  219. s = (0, FO_RENAME, self.src_name, self.dest_name) # hwnd, # operation
  220. rc, aborted = shell.SHFileOperation(s)
  221. self.assertTrue(not aborted)
  222. self.assertEqual(0, rc)
  223. self.assertTrue(os.path.isfile(self.dest_name))
  224. self.assertTrue(not os.path.isfile(self.src_name))
  225. def testMove(self):
  226. s = (0, FO_MOVE, self.src_name, self.dest_name) # hwnd, # operation
  227. rc, aborted = shell.SHFileOperation(s)
  228. self.assertTrue(not aborted)
  229. self.assertEqual(0, rc)
  230. self.assertTrue(os.path.isfile(self.dest_name))
  231. self.assertTrue(not os.path.isfile(self.src_name))
  232. def testDelete(self):
  233. s = (
  234. 0, # hwnd,
  235. FO_DELETE, # operation
  236. self.src_name,
  237. None,
  238. FOF_NOCONFIRMATION,
  239. )
  240. rc, aborted = shell.SHFileOperation(s)
  241. self.assertTrue(not aborted)
  242. self.assertEqual(0, rc)
  243. self.assertTrue(not os.path.isfile(self.src_name))
  244. if __name__ == "__main__":
  245. win32com.test.util.testmain()