utils.py 8.4 KB

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