utils.py 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import unittest
  2. import sys
  3. import os
  4. import sys
  5. import time
  6. import json
  7. import urllib
  8. import urllib2
  9. import subprocess
  10. import signal
  11. import random
  12. username = "test_user"
  13. parallel_push = True
  14. ports = []
  15. def getFreePort():
  16. while 1:
  17. port = random.randint(10000, 20000)
  18. ports.append(port)
  19. exists = False
  20. for p in ports:
  21. if p == port:
  22. if not exists:
  23. # We have hopefully found our own
  24. exists = True
  25. else:
  26. # We seem to be the second entry, so chose another one
  27. p.remove(port)
  28. break
  29. else:
  30. # Didn't find a duplicate
  31. return port
  32. def serialize(value):
  33. if isinstance(value, str):
  34. return '"%s"' % value
  35. else:
  36. return str(value)
  37. def execute(scriptname, parameters=[], wait=False):
  38. if os.name == "nt":
  39. command = ["%s.bat" % scriptname] + parameters
  40. elif os.name == "posix":
  41. command = ["./%s.sh" % scriptname] + parameters
  42. else:
  43. raise Exception("Unknown OS: " + str(os.name))
  44. if wait:
  45. return subprocess.call(command, shell=False)
  46. else:
  47. return subprocess.Popen(command, shell=False)
  48. def kill(process):
  49. if os.name == "nt":
  50. subprocess.call(["taskkill", "/F", "/T", "/PID", "%i" % process.pid])
  51. elif os.name == "posix":
  52. subprocess.call(["pkill", "-P", "%i" % process.pid])
  53. def flush_data(address, data):
  54. if data:
  55. urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "data": json.dumps(data), "username": username})), timeout=10).read()
  56. return []
  57. def compile_file(address, mod_filename, filename, mode, proc):
  58. # Load in the file required
  59. try:
  60. timeout_val = 120
  61. import random
  62. username = str(random.random())
  63. while 1:
  64. proc2 = execute("compile", [address, mod_filename, username, filename, mode], wait=False)
  65. if proc.returncode is not None:
  66. # Modelverse has already terminated, which isn't a good sign!
  67. raise Exception("Modelverse died!")
  68. while proc2.returncode is None:
  69. time.sleep(0.01)
  70. proc2.poll()
  71. timeout_val -= 0.01
  72. if timeout_val < 0:
  73. kill(proc2)
  74. print("Compilation timeout expired!")
  75. return False
  76. if proc2.returncode not in [7, 56]:
  77. break
  78. # Make sure everything stopped correctly
  79. assert proc2.returncode == 0
  80. if proc2.returncode != 0:
  81. return False
  82. except:
  83. raise
  84. finally:
  85. try:
  86. kill(proc2)
  87. except UnboundLocalError:
  88. pass
  89. def run_file(files, parameters, expected, mode):
  90. # Resolve file
  91. import os.path
  92. time.sleep(0.01)
  93. port = getFreePort()
  94. address = "http://localhost:%i" % port
  95. try:
  96. # Run Modelverse server
  97. proc = execute("run_local_modelverse", [str(port)], wait=False)
  98. threads = []
  99. for filename in files:
  100. if filename == "--fast":
  101. continue
  102. if os.path.isfile("integration/code/%s" % filename):
  103. mod_filename = "integration/code/%s" % filename
  104. elif os.path.isfile("bootstrap/%s" % filename):
  105. mod_filename = "bootstrap/%s" % filename
  106. else:
  107. raise Exception("File not found: %s" % filename)
  108. print("Found file " + str(mod_filename))
  109. if parallel_push:
  110. import threading
  111. threads.append(threading.Thread(target=compile_file, args=[address, mod_filename, filename, mode, proc]))
  112. threads[-1].start()
  113. else:
  114. compile_file(address, mod_filename, filename, mode, proc)
  115. if parallel_push:
  116. for t in threads:
  117. t.join()
  118. if mode[-1] == "O":
  119. # Fire up the linker
  120. val = execute("link_and_load", [address, username] + files, wait=True)
  121. if val != 0:
  122. raise Exception("Linking error")
  123. # Send in the actual request and wait for replies
  124. data = []
  125. for p in parameters:
  126. if isinstance(p, tuple):
  127. for v in p:
  128. data.append(["V", serialize(v)])
  129. else:
  130. data.append(["V", serialize(p)])
  131. flush_data(address, data)
  132. for e in expected:
  133. c = len(e) if isinstance(e, set) else 1
  134. for _ in range(c):
  135. val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username})), timeout=10).read()
  136. if proc.returncode is not None:
  137. # Modelverse has already terminated, which isn't a good sign!
  138. raise Exception("Modelverse died!")
  139. val = val.split("=", 2)[2]
  140. print("Got %s, expect %s" % (val, e))
  141. if isinstance(e, set):
  142. assert str(val) in e
  143. if str(val) not in e:
  144. return False
  145. else:
  146. assert str(val) == e
  147. if str(val) != e:
  148. return False
  149. # All passed!
  150. return True
  151. except:
  152. raise
  153. finally:
  154. try:
  155. kill(proc)
  156. except UnboundLocalError:
  157. pass
  158. def run_barebone(parameters, expected, interface="0", timeout=False, wait=False, link=None):
  159. port = getFreePort()
  160. address = "http://localhost:%i" % port
  161. try:
  162. # Run Modelverse server
  163. proc = execute("run_local_modelverse", [str(port)], wait=False)
  164. # Create user and set interface
  165. timeout_val = 15
  166. start = time.time()
  167. while 1:
  168. try:
  169. urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": '"%s"' % username, "username": "user_manager"})), timeout=1).read()
  170. if interface is not None:
  171. urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": interface, "username": username})), timeout=1).read()
  172. break
  173. except:
  174. time.sleep(0.01)
  175. if proc.returncode is not None:
  176. # Modelverse has already terminated, which isn't a good sign!
  177. return False
  178. if time.time() - start > timeout_val:
  179. raise
  180. # Send in the actual request and wait for replies
  181. var_list = {}
  182. data = []
  183. for p in parameters:
  184. if isinstance(p, int):
  185. if p not in var_list:
  186. data = flush_data(address, data)
  187. val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username})), timeout=10).read()
  188. if proc.returncode is not None:
  189. # Modelverse has already terminated, which isn't a good sign!
  190. return False
  191. val = val.split("=", 2)[1].split("&", 1)[0]
  192. var_list[p] = val
  193. continue
  194. else:
  195. val = var_list[p]
  196. t = "R"
  197. else:
  198. val = p
  199. t = "V"
  200. data.append([t, val])
  201. data = flush_data(address, data)
  202. # Now do linking and loading
  203. if link is not None:
  204. # Execute linker
  205. timeout_val = 10
  206. proc2 = execute("link_and_load", [address, username] + link, wait=False)
  207. while proc2.returncode is None:
  208. time.sleep(0.01)
  209. proc2.poll()
  210. timeout_val -= 0.01
  211. if timeout_val < 0:
  212. kill(proc2)
  213. print("Linking timeout expired!")
  214. return False
  215. counter = 0
  216. for e in expected:
  217. print("Expect " + str(e))
  218. c = len(e) if isinstance(e, set) else 1
  219. for _ in range(c):
  220. try:
  221. val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username})), timeout=15).read()
  222. except:
  223. if timeout:
  224. return True
  225. else:
  226. raise
  227. val = val.split("=", 2)[2]
  228. print("Got %s, expect %s" % (val, e))
  229. if isinstance(e, set):
  230. assert str(val) in e
  231. if str(val) not in e:
  232. return False
  233. else:
  234. assert str(val) == e
  235. if str(val) != e:
  236. return False
  237. # All passed!
  238. return not timeout
  239. finally:
  240. kill(proc)