utils.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. ports.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 not in ["nt", "posix"]:
  39. # Stop now, as we would have no clue on how to kill its subtree
  40. raise Exception("Unknown OS version: " + str(os.name))
  41. command = [sys.executable, "scripts/%s.py" % scriptname] + parameters
  42. if wait:
  43. return subprocess.call(command, shell=False)
  44. else:
  45. return subprocess.Popen(command, shell=False)
  46. def kill(process):
  47. if os.name == "nt":
  48. subprocess.call(["taskkill", "/F", "/T", "/PID", "%i" % process.pid])
  49. elif os.name == "posix":
  50. subprocess.call(["pkill", "-P", "%i" % process.pid])
  51. def flush_data(address, data):
  52. if data:
  53. urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "data": json.dumps(data), "username": username})), timeout=10).read()
  54. return []
  55. def compile_file(address, mod_filename, filename, mode, proc):
  56. # Load in the file required
  57. try:
  58. timeout_val = 120
  59. import random
  60. username = str(random.random())
  61. while 1:
  62. proc2 = execute("compile", [address, mod_filename, username, filename, mode], wait=False)
  63. if proc.returncode is not None:
  64. # Modelverse has already terminated, which isn't a good sign!
  65. raise Exception("Modelverse died!")
  66. while proc2.returncode is None:
  67. time.sleep(0.01)
  68. proc2.poll()
  69. timeout_val -= 0.01
  70. if timeout_val < 0:
  71. kill(proc2)
  72. print("Compilation timeout expired!")
  73. return False
  74. if proc2.returncode != 2:
  75. break
  76. # Make sure everything stopped correctly
  77. assert proc2.returncode == 0
  78. if proc2.returncode != 0:
  79. return False
  80. except:
  81. raise
  82. finally:
  83. try:
  84. kill(proc2)
  85. except UnboundLocalError:
  86. pass
  87. def run_file(files, parameters, expected, mode):
  88. # Resolve file
  89. import os.path
  90. time.sleep(0.01)
  91. port = getFreePort()
  92. address = "http://localhost:%i" % port
  93. try:
  94. # Run Modelverse server
  95. proc = execute("run_local_modelverse", [str(port)], wait=False)
  96. threads = []
  97. for filename in files:
  98. if filename == "--fast":
  99. continue
  100. if os.path.isfile("integration/code/%s" % filename):
  101. mod_filename = "integration/code/%s" % filename
  102. elif os.path.isfile("bootstrap/%s" % filename):
  103. mod_filename = "bootstrap/%s" % filename
  104. else:
  105. raise Exception("File not found: %s" % filename)
  106. print("Found file " + str(mod_filename))
  107. if parallel_push:
  108. import threading
  109. threads.append(threading.Thread(target=compile_file, args=[address, mod_filename, filename, mode, proc]))
  110. threads[-1].start()
  111. else:
  112. compile_file(address, mod_filename, filename, mode, proc)
  113. if parallel_push:
  114. for t in threads:
  115. t.join()
  116. if mode[-1] == "O":
  117. # Fire up the linker
  118. val = execute("link_and_load", [address, username] + files, wait=True)
  119. if val != 0:
  120. raise Exception("Linking error")
  121. # Send in the actual request and wait for replies
  122. data = []
  123. for p in parameters:
  124. if isinstance(p, tuple):
  125. for v in p:
  126. data.append(["V", serialize(v)])
  127. else:
  128. data.append(["V", serialize(p)])
  129. flush_data(address, data)
  130. for e in expected:
  131. c = len(e) if isinstance(e, set) else 1
  132. for _ in range(c):
  133. val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username})), timeout=10).read()
  134. if proc.returncode is not None:
  135. # Modelverse has already terminated, which isn't a good sign!
  136. raise Exception("Modelverse died!")
  137. val = val.split("=", 2)[2]
  138. print("Got %s, expect %s" % (val, e))
  139. if isinstance(e, set):
  140. assert str(val) in e
  141. if str(val) not in e:
  142. return False
  143. else:
  144. assert str(val) == e
  145. if str(val) != e:
  146. return False
  147. # All passed!
  148. return True
  149. except:
  150. raise
  151. finally:
  152. try:
  153. kill(proc)
  154. except UnboundLocalError:
  155. pass
  156. def run_barebone(parameters, expected, interface="0", timeout=False, wait=False, link=None, inputs=[]):
  157. port = getFreePort()
  158. address = "http://localhost:%i" % port
  159. try:
  160. # Run Modelverse server
  161. proc = execute("run_local_modelverse", [str(port)], wait=False)
  162. # Create user and set interface
  163. timeout_val = 15
  164. start = time.time()
  165. while 1:
  166. try:
  167. urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": '"%s"' % username, "username": "user_manager"})), timeout=1).read()
  168. if interface is not None:
  169. urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": interface, "username": username})), timeout=1).read()
  170. break
  171. except:
  172. time.sleep(0.01)
  173. if proc.returncode is not None:
  174. # Modelverse has already terminated, which isn't a good sign!
  175. return False
  176. if time.time() - start > timeout_val:
  177. raise
  178. # Send in the actual request and wait for replies
  179. var_list = {}
  180. data = []
  181. for p in parameters:
  182. if isinstance(p, int):
  183. if p not in var_list:
  184. data = flush_data(address, data)
  185. val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username})), timeout=10).read()
  186. if proc.returncode is not None:
  187. # Modelverse has already terminated, which isn't a good sign!
  188. return False
  189. val = val.split("=", 2)[1].split("&", 1)[0]
  190. var_list[p] = val
  191. continue
  192. else:
  193. val = var_list[p]
  194. t = "R"
  195. else:
  196. val = p
  197. t = "V"
  198. data.append([t, val])
  199. data = flush_data(address, data)
  200. # Now do linking and loading
  201. if link is not None:
  202. # Execute linker
  203. timeout_val = 10
  204. proc2 = execute("link_and_load", [address, username] + link, wait=False)
  205. while proc2.returncode is None:
  206. time.sleep(0.01)
  207. proc2.poll()
  208. timeout_val -= 0.01
  209. if timeout_val < 0:
  210. kill(proc2)
  211. print("Linking timeout expired!")
  212. return False
  213. for inp in inputs:
  214. urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": inp, "username": username})), timeout=1).read()
  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)