Advertisement
Guest User

Untitled

a guest
Apr 18th, 2015
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.99 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. import argparse
  4. import datetime
  5. import logging
  6. import math
  7. import os
  8. import os.path
  9. import subprocess
  10. import threading
  11.  
  12. print_details = False
  13.  
  14. def timed_call(cmds, timeout, cwd='.', stdin=None, stdout=None):
  15. # returns: (return code, total time in second, error message)
  16. scope = [None, None, None]
  17. def target():
  18. scope[0] = subprocess.Popen(cmds, cwd=cwd,
  19. stdin=stdin, stdout=stdout,
  20. stderr=subprocess.PIPE)
  21. (scope[1], scope[2]) = scope[0].communicate()
  22. thread = threading.Thread(target = target)
  23. t0 = os.times()
  24. thread.start()
  25. thread.join(timeout)
  26. t1 = os.times()
  27. total_time = (t1[2] - t0[2]) + (t1[3] - t0[3]) # already in second
  28. if thread.is_alive():
  29. scope[0].terminate()
  30. thread.join()
  31. t1 = os.times()
  32. total_time = (t1[2] - t0[2]) + (t1[3] - t0[3])
  33. if scope[0] is not None:
  34. error = scope[2].replace('\n', ' ').replace('\r', ' ')
  35. return (scope[0].returncode, total_time, error)
  36. return (None, total_time, "failed to create subprocess")
  37.  
  38. def run(cwd, target, kind, repeat, timeout, in_file_path, out_file_path):
  39. # returns: (target return code, mean time in second, error message)
  40. total_time = 0
  41. for i in range(repeat):
  42. time = 0
  43. input_file = None
  44. output_file = None
  45. try:
  46. input_file = open(in_file_path, 'r')
  47. output_file = open(out_file_path, 'w')
  48. result = 0
  49. error = None
  50. if kind == 'exe':
  51. (result, time, error) =\
  52. timed_call([target], timeout=timeout, cwd=cwd,
  53. stdin=input_file, stdout=output_file)
  54. elif kind == 'java':
  55. target_name = os.path.basename(target)
  56. (result, time, error) =\
  57. timed_call(['java', '-cp', cwd, target_name],
  58. timeout=timeout, cwd=cwd,
  59. stdin=input_file, stdout=output_file)
  60. if result is None:
  61. return (result, -1, "result is None")
  62. elif result != 0:
  63. return (result, -1, error)
  64. elif i > 0: # skip the first execution
  65. total_time += time
  66. finally:
  67. if input_file is not None:
  68. input_file.close()
  69. if output_file is not None:
  70. output_file.close()
  71. mean_time = total_time / (repeat - 1)
  72. return (0, mean_time, None)
  73.  
  74. def calc_path_len(points, path):
  75. path_len = 0
  76. for k in range(len(path) - 1):
  77. i = path[k]
  78. j = path[k+1]
  79. (x1, y1) = points[i]
  80. (x2, y2) = points[j]
  81. step = math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
  82. path_len += step
  83. if print_details:
  84. print("dist from ({0},{1}) to ({2},{3}) is {4};\tacc dist={5}".format(
  85. x1, y1, x2, y2, step, path_len))
  86. return path_len
  87.  
  88. def validate(the_points, out_file_path):
  89. # returns: (successful or not, path len or error message)
  90. if not os.path.exists(out_file_path) or not os.path.isfile(out_file_path):
  91. return (False, 'file not found: ' + out_file_path)
  92. the_num_points = len(the_points)
  93. path = []
  94. path_len = 0
  95. claimed_path_len = 0
  96. f = None
  97. try:
  98. f = open(out_file_path)
  99. lines = f.readlines()
  100. # remove empty lines
  101. lines = [line for line in lines if len(line.strip()) > 0]
  102. n = len(lines)
  103. if n > 0:
  104. for i in range(n-1):
  105. line = lines[i].strip()
  106. try:
  107. p = int(line)
  108. path.append(p)
  109. except ValueError:
  110. print("point index expected but got \"{0}\"".format(line))
  111. continue
  112. try:
  113. claimed_path_len = float(lines[-1])
  114. except ValueError:
  115. return (False, "unable to parse path len: " + lines[-1])
  116. else:
  117. return (False, "empty output")
  118. finally:
  119. if f is not None:
  120. f.close()
  121.  
  122. # 1. path goes through each point once and only once and get back:
  123. if path[0] != path[-1]:
  124. return (False, "path not closed")
  125. points = path[:-1]
  126. the_point_set = set(range(1000))
  127. point_set = set(path[:-1])
  128. missing = the_point_set - point_set
  129. extra = point_set - the_point_set
  130. dup = [x for x in point_set if points.count(x) > 1]
  131. if len(missing) > 0:
  132. return (False, "missing points: {0}".format(missing))
  133. if len(extra) > 0:
  134. return (False, "extra points: {0}".format(extra))
  135. if len(dup) > 0:
  136. return (False, "duplicate points: {1}".format(dup))
  137.  
  138. # 2. path length error is within 1%
  139. path_len = calc_path_len(the_points, path)
  140. error = math.fabs(claimed_path_len - path_len)
  141. error_rate = error / path_len
  142. if error_rate > 0.01:
  143. return (False,
  144. "claimed len: {0:.0f}, actual len: {1:.0f}"
  145. .format(claimed_path_len, path_len))
  146.  
  147. # all passed!
  148. return (True, path_len)
  149.  
  150. def read_points(file_path):
  151. points = []
  152. f = open(file_path)
  153. try:
  154. lines = f.readlines()
  155. for line in lines:
  156. line = line.strip()
  157. if line.startswith('#') or len(line) == 0:
  158. continue
  159. if line.startswith('\x04') or line.startswith('^D'):
  160. break
  161. (sx, sy) = line.split()
  162. (x, y) = (float(sx), float(sy))
  163. points.append((x, y))
  164. finally:
  165. f.close()
  166. return points
  167.  
  168. def run_and_validate(working_dir, target, kind,
  169. in_file_path, out_file_path, repeat, timeout):
  170. points = read_points(in_file_path)
  171. return_code = 0
  172. time = 0
  173. try:
  174. (code, time, error) = run(working_dir, target, kind, repeat, timeout,
  175. in_file_path, out_file_path)
  176. if code == 0:
  177. (succ, v_res) = validate(points, out_file_path)
  178. if succ:
  179. print("success: mean time={0}, path len={1}".format(time, v_res))
  180. else:
  181. print("validation error: {0}".format(v_res))
  182. else:
  183. print("failed to run: return code={0}, error={1}"
  184. .format(code, error))
  185. except Exception as e:
  186. print("exception: {0}".format(str(e)))
  187.  
  188. if __name__ == '__main__':
  189. parser = argparse.ArgumentParser()
  190. parser.add_argument('--dir', '-d', dest='dir', default='.',
  191. help="The working directory")
  192. parser.add_argument('--type', '-t', dest='target_type',
  193. choices=['exe', 'java'], default='exe',
  194. help="The type of the target")
  195. parser.add_argument('--timeout', '-s', type=float,
  196. dest='timeout', default=100,
  197. help="Max seconds to wait before terminating the run")
  198. parser.add_argument('--repeat', '-n', type=int,
  199. dest='repeat', metavar='N', default=5,
  200. help="Repeat N times to calculate an average time")
  201. parser.add_argument('--output_file_name', '-o',
  202. dest='output_file_name', default="output.txt",
  203. help="Name of the output file")
  204. parser.add_argument('--details', '-D', dest='details', action='store_true',
  205. help="Print detailed information")
  206. parser.add_argument('target',
  207. help="Name of the executable or Java class")
  208. parser.add_argument('input_file_path',
  209. help="Path to the input file")
  210. args = parser.parse_args()
  211. print_details = args.details
  212. working_dir = os.path.abspath(args.dir)
  213. run_and_validate(working_dir,
  214. os.path.join(working_dir, args.target),
  215. args.target_type,
  216. os.path.abspath(args.input_file_path),
  217. os.path.join(working_dir, args.output_file_name),
  218. args.repeat,
  219. args.timeout)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement