utils.py 8.3 KB

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