utils.py 7.9 KB

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