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.

test_win32trace.py 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. import os
  2. import sys
  3. import threading
  4. import time
  5. import unittest
  6. import win32trace
  7. from pywin32_testutil import TestSkipped
  8. if __name__ == "__main__":
  9. this_file = sys.argv[0]
  10. else:
  11. this_file = __file__
  12. def SkipIfCI():
  13. # This test often fails in CI, probably when it is being run multiple times
  14. # (ie, for different Python versions)
  15. # Github actions always have a `CI` variable.
  16. if "CI" in os.environ:
  17. raise TestSkipped("We skip this test on CI")
  18. def CheckNoOtherReaders():
  19. win32trace.write("Hi")
  20. time.sleep(0.05)
  21. if win32trace.read() != "Hi":
  22. # Reset everything so following tests still fail with this error!
  23. win32trace.TermRead()
  24. win32trace.TermWrite()
  25. raise RuntimeError(
  26. "An existing win32trace reader appears to be "
  27. "running - please stop this process and try again"
  28. )
  29. class TestInitOps(unittest.TestCase):
  30. def setUp(self):
  31. SkipIfCI()
  32. # clear old data
  33. win32trace.InitRead()
  34. win32trace.read()
  35. win32trace.TermRead()
  36. def tearDown(self):
  37. try:
  38. win32trace.TermRead()
  39. except win32trace.error:
  40. pass
  41. try:
  42. win32trace.TermWrite()
  43. except win32trace.error:
  44. pass
  45. def testInitTermRead(self):
  46. self.assertRaises(win32trace.error, win32trace.read)
  47. win32trace.InitRead()
  48. result = win32trace.read()
  49. self.assertEqual(result, "")
  50. win32trace.TermRead()
  51. self.assertRaises(win32trace.error, win32trace.read)
  52. win32trace.InitRead()
  53. self.assertRaises(win32trace.error, win32trace.InitRead)
  54. win32trace.InitWrite()
  55. self.assertRaises(win32trace.error, win32trace.InitWrite)
  56. win32trace.TermWrite()
  57. win32trace.TermRead()
  58. def testInitTermWrite(self):
  59. self.assertRaises(win32trace.error, win32trace.write, "Hei")
  60. win32trace.InitWrite()
  61. win32trace.write("Johan Galtung")
  62. win32trace.TermWrite()
  63. self.assertRaises(win32trace.error, win32trace.write, "Hei")
  64. def testTermSematics(self):
  65. win32trace.InitWrite()
  66. win32trace.write("Ta da")
  67. # if we both Write and Read are terminated at the same time,
  68. # we lose the data as the win32 object is closed. Note that
  69. # if another writer is running, we do *not* lose the data - so
  70. # test for either the correct data or an empty string
  71. win32trace.TermWrite()
  72. win32trace.InitRead()
  73. self.assertTrue(win32trace.read() in ("Ta da", ""))
  74. win32trace.TermRead()
  75. # we keep the data because we init read before terminating write
  76. win32trace.InitWrite()
  77. win32trace.write("Ta da")
  78. win32trace.InitRead()
  79. win32trace.TermWrite()
  80. self.assertEqual("Ta da", win32trace.read())
  81. win32trace.TermRead()
  82. class BasicSetupTearDown(unittest.TestCase):
  83. def setUp(self):
  84. SkipIfCI()
  85. win32trace.InitRead()
  86. # If any other writers are running (even if not actively writing),
  87. # terminating the module will *not* close the handle, meaning old data
  88. # will remain. This can cause other tests to fail.
  89. win32trace.read()
  90. win32trace.InitWrite()
  91. def tearDown(self):
  92. win32trace.TermWrite()
  93. win32trace.TermRead()
  94. class TestModuleOps(BasicSetupTearDown):
  95. def testRoundTrip(self):
  96. win32trace.write("Syver Enstad")
  97. syverEnstad = win32trace.read()
  98. self.assertEqual("Syver Enstad", syverEnstad)
  99. def testRoundTripUnicode(self):
  100. win32trace.write("\xa9opyright Syver Enstad")
  101. syverEnstad = win32trace.read()
  102. # str objects are always returned in py2k (latin-1 encoding was used
  103. # on unicode objects)
  104. self.assertEqual("\xa9opyright Syver Enstad", syverEnstad)
  105. def testBlockingRead(self):
  106. win32trace.write("Syver Enstad")
  107. self.assertEqual("Syver Enstad", win32trace.blockingread())
  108. def testBlockingReadUnicode(self):
  109. win32trace.write("\xa9opyright Syver Enstad")
  110. # str objects are always returned in py2k (latin-1 encoding was used
  111. # on unicode objects)
  112. self.assertEqual("\xa9opyright Syver Enstad", win32trace.blockingread())
  113. def testFlush(self):
  114. win32trace.flush()
  115. class TestTraceObjectOps(BasicSetupTearDown):
  116. def testInit(self):
  117. win32trace.TermRead()
  118. win32trace.TermWrite()
  119. traceObject = win32trace.GetTracer()
  120. self.assertRaises(win32trace.error, traceObject.read)
  121. self.assertRaises(win32trace.error, traceObject.write, "")
  122. win32trace.InitRead()
  123. win32trace.InitWrite()
  124. self.assertEqual("", traceObject.read())
  125. traceObject.write("Syver")
  126. def testFlush(self):
  127. traceObject = win32trace.GetTracer()
  128. traceObject.flush()
  129. def testIsatty(self):
  130. tracer = win32trace.GetTracer()
  131. assert tracer.isatty() == False
  132. def testRoundTrip(self):
  133. traceObject = win32trace.GetTracer()
  134. traceObject.write("Syver Enstad")
  135. self.assertEqual("Syver Enstad", traceObject.read())
  136. class WriterThread(threading.Thread):
  137. def run(self):
  138. self.writeCount = 0
  139. for each in range(self.BucketCount):
  140. win32trace.write(str(each))
  141. self.writeCount = self.BucketCount
  142. def verifyWritten(self):
  143. return self.writeCount == self.BucketCount
  144. class TestMultipleThreadsWriting(unittest.TestCase):
  145. # FullBucket is the thread count
  146. FullBucket = 50
  147. BucketCount = 9 # buckets must be a single digit number (ie. less than 10)
  148. def setUp(self):
  149. SkipIfCI()
  150. WriterThread.BucketCount = self.BucketCount
  151. win32trace.InitRead()
  152. win32trace.read() # clear any old data.
  153. win32trace.InitWrite()
  154. CheckNoOtherReaders()
  155. self.threads = [WriterThread() for each in range(self.FullBucket)]
  156. self.buckets = list(range(self.BucketCount))
  157. for each in self.buckets:
  158. self.buckets[each] = 0
  159. def tearDown(self):
  160. win32trace.TermRead()
  161. win32trace.TermWrite()
  162. def areBucketsFull(self):
  163. bucketsAreFull = True
  164. for each in self.buckets:
  165. assert each <= self.FullBucket, each
  166. if each != self.FullBucket:
  167. bucketsAreFull = False
  168. break
  169. return bucketsAreFull
  170. def read(self):
  171. while 1:
  172. readString = win32trace.blockingread()
  173. for ch in readString:
  174. integer = int(ch)
  175. count = self.buckets[integer]
  176. assert count != -1
  177. self.buckets[integer] = count + 1
  178. if self.buckets[integer] == self.FullBucket:
  179. if self.areBucketsFull():
  180. return
  181. def testThreads(self):
  182. for each in self.threads:
  183. each.start()
  184. self.read()
  185. for each in self.threads:
  186. each.join()
  187. for each in self.threads:
  188. assert each.verifyWritten()
  189. assert self.areBucketsFull()
  190. class TestHugeChunks(unittest.TestCase):
  191. # BiggestChunk is the size where we stop stressing the writer
  192. BiggestChunk = 2**16 # 256k should do it.
  193. def setUp(self):
  194. SkipIfCI()
  195. win32trace.InitRead()
  196. win32trace.read() # clear any old data
  197. win32trace.InitWrite()
  198. def testHugeChunks(self):
  199. data = "*" * 1023 + "\n"
  200. while len(data) <= self.BiggestChunk:
  201. win32trace.write(data)
  202. data = data + data
  203. # If we made it here, we passed.
  204. def tearDown(self):
  205. win32trace.TermRead()
  206. win32trace.TermWrite()
  207. import win32event
  208. import win32process
  209. class TraceWriteProcess:
  210. def __init__(self, threadCount):
  211. self.exitCode = -1
  212. self.threadCount = threadCount
  213. def start(self):
  214. procHandle, threadHandle, procId, threadId = win32process.CreateProcess(
  215. None, # appName
  216. 'python.exe "%s" /run_test_process %s %s'
  217. % (this_file, self.BucketCount, self.threadCount),
  218. None, # process security
  219. None, # thread security
  220. 0, # inherit handles
  221. win32process.NORMAL_PRIORITY_CLASS,
  222. None, # new environment
  223. None, # Current directory
  224. win32process.STARTUPINFO(), # startup info
  225. )
  226. self.processHandle = procHandle
  227. def join(self):
  228. win32event.WaitForSingleObject(self.processHandle, win32event.INFINITE)
  229. self.exitCode = win32process.GetExitCodeProcess(self.processHandle)
  230. def verifyWritten(self):
  231. return self.exitCode == 0
  232. class TestOutofProcess(unittest.TestCase):
  233. BucketCount = 9
  234. FullBucket = 50
  235. def setUp(self):
  236. SkipIfCI()
  237. win32trace.InitRead()
  238. TraceWriteProcess.BucketCount = self.BucketCount
  239. self.setUpWriters()
  240. self.buckets = list(range(self.BucketCount))
  241. for each in self.buckets:
  242. self.buckets[each] = 0
  243. def tearDown(self):
  244. win32trace.TermRead()
  245. def setUpWriters(self):
  246. self.processes = []
  247. # 5 processes, quot threads in each process
  248. quot, remainder = divmod(self.FullBucket, 5)
  249. for each in range(5):
  250. self.processes.append(TraceWriteProcess(quot))
  251. if remainder:
  252. self.processes.append(TraceWriteProcess(remainder))
  253. def areBucketsFull(self):
  254. bucketsAreFull = True
  255. for each in self.buckets:
  256. assert each <= self.FullBucket, each
  257. if each != self.FullBucket:
  258. bucketsAreFull = False
  259. break
  260. return bucketsAreFull
  261. def read(self):
  262. while 1:
  263. readString = win32trace.blockingread()
  264. for ch in readString:
  265. integer = int(ch)
  266. count = self.buckets[integer]
  267. assert count != -1
  268. self.buckets[integer] = count + 1
  269. if self.buckets[integer] == self.FullBucket:
  270. if self.areBucketsFull():
  271. return
  272. def testProcesses(self):
  273. for each in self.processes:
  274. each.start()
  275. self.read()
  276. for each in self.processes:
  277. each.join()
  278. for each in self.processes:
  279. assert each.verifyWritten()
  280. assert self.areBucketsFull()
  281. def _RunAsTestProcess():
  282. # Run as an external process by the main tests.
  283. WriterThread.BucketCount = int(sys.argv[2])
  284. threadCount = int(sys.argv[3])
  285. threads = [WriterThread() for each in range(threadCount)]
  286. win32trace.InitWrite()
  287. for t in threads:
  288. t.start()
  289. for t in threads:
  290. t.join()
  291. for t in threads:
  292. if not t.verifyWritten():
  293. sys.exit(-1)
  294. if __name__ == "__main__":
  295. if sys.argv[1:2] == ["/run_test_process"]:
  296. _RunAsTestProcess()
  297. sys.exit(0)
  298. # If some other win32traceutil reader is running, these tests fail
  299. # badly (as the other reader sometimes sees the output!)
  300. win32trace.InitRead()
  301. win32trace.InitWrite()
  302. CheckNoOtherReaders()
  303. # reset state so test env is back to normal
  304. win32trace.TermRead()
  305. win32trace.TermWrite()
  306. unittest.main()