framework_test.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. import importlib
  2. import os
  3. import subprocess
  4. import time
  5. import re
  6. import pprint
  7. import sys
  8. import traceback
  9. class FrameworkTest:
  10. ##########################################################################################
  11. # Class variables
  12. ##########################################################################################
  13. headers_template = "-H 'Host: localhost' -H '{accept}' -H 'Connection: keep-alive'"
  14. headers_full_template = "-H 'Host: localhost' -H '{accept}' -H 'Accept-Language: en-US,en;q=0.5' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) Gecko/20130501 Firefox/30.0 AppleWebKit/600.00 Chrome/30.0.0000.0 Trident/10.0 Safari/600.00' -H 'Cookie: uid=12345678901234567890; __utma=1.1234567890.1234567890.1234567890.1234567890.12; wd=2560x1600' -H 'Connection: keep-alive'"
  15. accept_json = "Accept: application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7"
  16. accept_html = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
  17. accept_plaintext = "Accept: text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7"
  18. concurrency_template = """
  19. echo ""
  20. echo "---------------------------------------------------------"
  21. echo " Running Primer {name}"
  22. echo " {wrk} {headers} -d 5 -c 8 -t 8 \"http://{server_host}:{port}{url}\""
  23. echo "---------------------------------------------------------"
  24. echo ""
  25. {wrk} {headers} -d 5 -c 8 -t 8 "http://{server_host}:{port}{url}"
  26. sleep 5
  27. echo ""
  28. echo "---------------------------------------------------------"
  29. echo " Running Warmup {name}"
  30. echo " {wrk} {headers} -d {duration} -c {max_concurrency} -t {max_threads} \"http://{server_host}:{port}{url}\""
  31. echo "---------------------------------------------------------"
  32. echo ""
  33. {wrk} {headers} -d {duration} -c {max_concurrency} -t {max_threads} "http://{server_host}:{port}{url}"
  34. sleep 5
  35. for c in {interval}
  36. do
  37. echo ""
  38. echo "---------------------------------------------------------"
  39. echo " Concurrency: $c for {name}"
  40. echo " {wrk} {headers} {pipeline} -d {duration} -c $c -t $(($c>{max_threads}?{max_threads}:$c)) \"http://{server_host}:{port}{url}\""
  41. echo "---------------------------------------------------------"
  42. echo ""
  43. {wrk} {headers} {pipeline} -d {duration} -c "$c" -t "$(($c>{max_threads}?{max_threads}:$c))" http://{server_host}:{port}{url}
  44. sleep 2
  45. done
  46. """
  47. query_template = """
  48. echo ""
  49. echo "---------------------------------------------------------"
  50. echo " Running Primer {name}"
  51. echo " wrk {headers} -d 5 -c 8 -t 8 \"http://{server_host}:{port}{url}2\""
  52. echo "---------------------------------------------------------"
  53. echo ""
  54. wrk {headers} -d 5 -c 8 -t 8 "http://{server_host}:{port}{url}2"
  55. sleep 5
  56. echo ""
  57. echo "---------------------------------------------------------"
  58. echo " Running Warmup {name}"
  59. echo " wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} \"http://{server_host}:{port}{url}2\""
  60. echo "---------------------------------------------------------"
  61. echo ""
  62. wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} "http://{server_host}:{port}{url}2"
  63. sleep 5
  64. for c in {interval}
  65. do
  66. echo ""
  67. echo "---------------------------------------------------------"
  68. echo " Queries: $c for {name}"
  69. echo " wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} \"http://{server_host}:{port}{url}$c\""
  70. echo "---------------------------------------------------------"
  71. echo ""
  72. wrk {headers} -d {duration} -c {max_concurrency} -t {max_threads} "http://{server_host}:{port}{url}$c"
  73. sleep 2
  74. done
  75. """
  76. language = None
  77. platform = None
  78. webserver = None
  79. classification = None
  80. database = None
  81. approach = None
  82. orm = None
  83. framework = None
  84. os = None
  85. database_os = None
  86. display_name = None
  87. notes = None
  88. versus = None
  89. ############################################################
  90. # Test Variables
  91. ############################################################
  92. JSON = "JSON"
  93. DB = "DB"
  94. QUERY = "QUERY"
  95. FORTUNE = "FORTUNE"
  96. UPDATE = "UPDATE"
  97. PLAINTEXT = "PLAINTEXT"
  98. ##########################################################################################
  99. # Public Methods
  100. ##########################################################################################
  101. def validateJson(self, jsonString):
  102. obj = json.loads(jsonString)
  103. if not obj:
  104. return false
  105. else if not obj.message:
  106. return false
  107. else if not obj.message.lower() == "hello, world!":
  108. return false
  109. return true
  110. ############################################################
  111. # start(benchmarker)
  112. # Start the test using it's setup file
  113. ############################################################
  114. def start(self, out, err):
  115. return self.setup_module.start(self.benchmarker, out, err)
  116. ############################################################
  117. # End start
  118. ############################################################
  119. ############################################################
  120. # stop(benchmarker)
  121. # Stops the test using it's setup file
  122. ############################################################
  123. def stop(self, out, err):
  124. return self.setup_module.stop(out, err)
  125. ############################################################
  126. # End stop
  127. ############################################################
  128. ############################################################
  129. # verify_urls
  130. # Verifys each of the URLs for this test. THis will sinply
  131. # curl the URL and check for it's return status.
  132. # For each url, a flag will be set on this object for whether
  133. # or not it passed
  134. ############################################################
  135. def verify_urls(self, out, err):
  136. # JSON
  137. try:
  138. out.write( "VERIFYING JSON (" + self.json_url + ") ...\n" )
  139. out.flush()
  140. url = self.benchmarker.generate_url(self.json_url, self.port)
  141. output = self.__curl_url(url, self.JSON, out, err)
  142. if self.validateJson(output):
  143. self.json_url_passed = True
  144. else:
  145. self.json_url_passed = False
  146. except (AttributeError, subprocess.CalledProcessError) as e:
  147. self.json_url_passed = False
  148. # DB
  149. try:
  150. out.write( "VERIFYING DB (" + self.db_url + ") ...\n" )
  151. out.flush()
  152. url = self.benchmarker.generate_url(self.db_url, self.port)
  153. output = self.__curl_url(url, self.DB, out, err)
  154. self.db_url_passed = True
  155. except (AttributeError, subprocess.CalledProcessError) as e:
  156. self.db_url_passed = False
  157. # Query
  158. try:
  159. out.write( "VERIFYING Query (" + self.query_url + "2) ...\n" )
  160. out.flush()
  161. url = self.benchmarker.generate_url(self.query_url + "2", self.port)
  162. output = self.__curl_url(url, self.QUERY, out, err)
  163. self.query_url_passed = True
  164. except (AttributeError, subprocess.CalledProcessError) as e:
  165. self.query_url_passed = False
  166. # Fortune
  167. try:
  168. out.write( "VERIFYING Fortune (" + self.fortune_url + ") ...\n" )
  169. out.flush()
  170. url = self.benchmarker.generate_url(self.fortune_url, self.port)
  171. output = self.__curl_url(url, self.FORTUNE, out, err)
  172. self.fortune_url_passed = True
  173. except (AttributeError, subprocess.CalledProcessError) as e:
  174. self.fortune_url_passed = False
  175. # Update
  176. try:
  177. out.write( "VERIFYING Update (" + self.update_url + "2) ...\n" )
  178. out.flush()
  179. url = self.benchmarker.generate_url(self.update_url + "2", self.port)
  180. output = self.__curl_url(url, self.UPDATE, out, err)
  181. self.update_url_passed = True
  182. except (AttributeError, subprocess.CalledProcessError) as e:
  183. self.update_url_passed = False
  184. # plaintext
  185. try:
  186. out.write( "VERIFYING Plaintext (" + self.plaintext_url + ") ...\n" )
  187. out.flush()
  188. url = self.benchmarker.generate_url(self.plaintext_url, self.port)
  189. output = self.__curl_url(url, self.PLAINTEXT, out, err)
  190. self.plaintext_url_passed = True
  191. except (AttributeError, subprocess.CalledProcessError) as e:
  192. self.plaintext_url_passed = False
  193. ############################################################
  194. # End verify_urls
  195. ############################################################
  196. ############################################################
  197. # contains_type(type)
  198. # true if this test contains an implementation of the given
  199. # test type (json, db, etc.)
  200. ############################################################
  201. def contains_type(self, type):
  202. try:
  203. if type == 'json' and self.json_url != None:
  204. return True
  205. if type == 'db' and self.db_url != None:
  206. return True
  207. if type == 'query' and self.query_url != None:
  208. return True
  209. if type == 'fortune' and self.fortune_url != None:
  210. return True
  211. if type == 'update' and self.update_url != None:
  212. return True
  213. if type == 'plaintext' and self.plaintext_url != None:
  214. return True
  215. except AttributeError:
  216. pass
  217. return False
  218. ############################################################
  219. # End stop
  220. ############################################################
  221. ############################################################
  222. # benchmark
  223. # Runs the benchmark for each type of test that it implements
  224. # JSON/DB/Query.
  225. ############################################################
  226. def benchmark(self, out, err):
  227. # JSON
  228. try:
  229. if self.json_url_passed and (self.benchmarker.type == "all" or self.benchmarker.type == "json"):
  230. out.write("BENCHMARKING JSON ... ")
  231. out.flush()
  232. remote_script = self.__generate_concurrency_script(self.json_url, self.port, self.accept_json)
  233. self.__run_benchmark(remote_script, self.benchmarker.output_file(self.name, 'json'), err)
  234. results = self.__parse_test('json')
  235. self.benchmarker.report_results(framework=self, test="json", results=results['results'])
  236. out.write( "Complete\n" )
  237. out.flush()
  238. except AttributeError:
  239. pass
  240. # DB
  241. try:
  242. if self.db_url_passed and (self.benchmarker.type == "all" or self.benchmarker.type == "db"):
  243. out.write("BENCHMARKING DB ... ")
  244. out.flush()
  245. remote_script = self.__generate_concurrency_script(self.db_url, self.port, self.accept_json)
  246. self.__run_benchmark(remote_script, self.benchmarker.output_file(self.name, 'db'), err)
  247. results = self.__parse_test('db')
  248. self.benchmarker.report_results(framework=self, test="db", results=results['results'])
  249. out.write( "Complete\n" )
  250. except AttributeError:
  251. traceback.print_exc()
  252. pass
  253. # Query
  254. try:
  255. if self.query_url_passed and (self.benchmarker.type == "all" or self.benchmarker.type == "query"):
  256. out.write("BENCHMARKING Query ... ")
  257. out.flush()
  258. remote_script = self.__generate_query_script(self.query_url, self.port, self.accept_json)
  259. self.__run_benchmark(remote_script, self.benchmarker.output_file(self.name, 'query'), err)
  260. results = self.__parse_test('query')
  261. self.benchmarker.report_results(framework=self, test="query", results=results['results'])
  262. out.write( "Complete\n" )
  263. out.flush()
  264. except AttributeError:
  265. traceback.print_exc()
  266. pass
  267. # fortune
  268. try:
  269. if self.fortune_url_passed and (self.benchmarker.type == "all" or self.benchmarker.type == "fortune"):
  270. out.write("BENCHMARKING Fortune ... ")
  271. out.flush()
  272. remote_script = self.__generate_concurrency_script(self.fortune_url, self.port, self.accept_html)
  273. self.__run_benchmark(remote_script, self.benchmarker.output_file(self.name, 'fortune'), err)
  274. results = self.__parse_test('fortune')
  275. self.benchmarker.report_results(framework=self, test="fortune", results=results['results'])
  276. out.write( "Complete\n" )
  277. out.flush()
  278. except AttributeError:
  279. traceback.print_exc()
  280. pass
  281. # update
  282. try:
  283. if self.update_url_passed and (self.benchmarker.type == "all" or self.benchmarker.type == "update"):
  284. out.write("BENCHMARKING Update ... ")
  285. out.flush()
  286. remote_script = self.__generate_query_script(self.update_url, self.port, self.accept_json)
  287. self.__run_benchmark(remote_script, self.benchmarker.output_file(self.name, 'update'), err)
  288. results = self.__parse_test('update')
  289. self.benchmarker.report_results(framework=self, test="update", results=results['results'])
  290. out.write( "Complete\n" )
  291. out.flush()
  292. except AttributeError:
  293. # TODO - this needs to report some logging
  294. traceback.print_exc()
  295. pass
  296. # plaintext
  297. try:
  298. if self.plaintext_url_passed and (self.benchmarker.type == "all" or self.benchmarker.type == "plaintext"):
  299. out.write("BENCHMARKING Plaintext ... ")
  300. out.flush()
  301. remote_script = self.__generate_concurrency_script(self.plaintext_url, self.port, self.accept_plaintext, wrk_command="wrk-pipeline", intervals=[256,1024,4096,16384], pipeline="--pipeline 16")
  302. self.__run_benchmark(remote_script, self.benchmarker.output_file(self.name, 'plaintext'), err)
  303. results = self.__parse_test('plaintext')
  304. self.benchmarker.report_results(framework=self, test="plaintext", results=results['results'])
  305. out.write( "Complete\n" )
  306. out.flush()
  307. except AttributeError:
  308. traceback.print_exc()
  309. pass
  310. ############################################################
  311. # End benchmark
  312. ############################################################
  313. ############################################################
  314. # parse_all
  315. # Method meant to be run for a given timestamp
  316. ############################################################
  317. def parse_all(self):
  318. # JSON
  319. if os.path.exists(self.benchmarker.output_file(self.name, 'json')):
  320. results = self.__parse_test('json')
  321. self.benchmarker.report_results(framework=self, test="json", results=results['results'])
  322. # DB
  323. if os.path.exists(self.benchmarker.output_file(self.name, 'db')):
  324. results = self.__parse_test('db')
  325. self.benchmarker.report_results(framework=self, test="db", results=results['results'])
  326. # Query
  327. if os.path.exists(self.benchmarker.output_file(self.name, 'query')):
  328. results = self.__parse_test('query')
  329. self.benchmarker.report_results(framework=self, test="query", results=results['results'])
  330. # Fortune
  331. if os.path.exists(self.benchmarker.output_file(self.name, 'fortune')):
  332. results = self.__parse_test('fortune')
  333. self.benchmarker.report_results(framework=self, test="fortune", results=results['results'])
  334. # Update
  335. if os.path.exists(self.benchmarker.output_file(self.name, 'update')):
  336. results = self.__parse_test('update')
  337. self.benchmarker.report_results(framework=self, test="update", results=results['results'])
  338. # Plaintext
  339. if os.path.exists(self.benchmarker.output_file(self.name, 'plaintext')):
  340. results = self.__parse_test('plaintext')
  341. self.benchmarker.report_results(framework=self, test="plaintext", results=results['results'])
  342. ############################################################
  343. # End parse_all
  344. ############################################################
  345. ############################################################
  346. # __parse_test(test_type)
  347. ############################################################
  348. def __parse_test(self, test_type):
  349. try:
  350. results = dict()
  351. results['results'] = []
  352. with open(self.benchmarker.output_file(self.name, test_type)) as raw_data:
  353. is_warmup = True
  354. rawData = None
  355. for line in raw_data:
  356. if "Queries:" in line or "Concurrency:" in line:
  357. is_warmup = False
  358. rawData = None
  359. continue
  360. if "Warmup" in line or "Primer" in line:
  361. is_warmup = True
  362. continue
  363. if not is_warmup:
  364. if rawData == None:
  365. rawData = dict()
  366. results['results'].append(rawData)
  367. #if "Requests/sec:" in line:
  368. # m = re.search("Requests/sec:\s+([0-9]+)", line)
  369. # rawData['reportedResults'] = m.group(1)
  370. # search for weighttp data such as succeeded and failed.
  371. if "Latency" in line:
  372. m = re.findall("([0-9]+\.*[0-9]*[us|ms|s|m|%]+)", line)
  373. if len(m) == 4:
  374. rawData['latencyAvg'] = m[0]
  375. rawData['latencyStdev'] = m[1]
  376. rawData['latencyMax'] = m[2]
  377. # rawData['latencyStdevPercent'] = m[3]
  378. #if "Req/Sec" in line:
  379. # m = re.findall("([0-9]+\.*[0-9]*[k|%]*)", line)
  380. # if len(m) == 4:
  381. # rawData['requestsAvg'] = m[0]
  382. # rawData['requestsStdev'] = m[1]
  383. # rawData['requestsMax'] = m[2]
  384. # rawData['requestsStdevPercent'] = m[3]
  385. #if "requests in" in line:
  386. # m = re.search("requests in ([0-9]+\.*[0-9]*[ms|s|m|h]+)", line)
  387. # if m != None:
  388. # # parse out the raw time, which may be in minutes or seconds
  389. # raw_time = m.group(1)
  390. # if "ms" in raw_time:
  391. # rawData['total_time'] = float(raw_time[:len(raw_time)-2]) / 1000.0
  392. # elif "s" in raw_time:
  393. # rawData['total_time'] = float(raw_time[:len(raw_time)-1])
  394. # elif "m" in raw_time:
  395. # rawData['total_time'] = float(raw_time[:len(raw_time)-1]) * 60.0
  396. # elif "h" in raw_time:
  397. # rawData['total_time'] = float(raw_time[:len(raw_time)-1]) * 3600.0
  398. if "requests in" in line:
  399. m = re.search("([0-9]+) requests in", line)
  400. if m != None:
  401. rawData['totalRequests'] = int(m.group(1))
  402. if "Socket errors" in line:
  403. if "connect" in line:
  404. m = re.search("connect ([0-9]+)", line)
  405. rawData['connect'] = int(m.group(1))
  406. if "read" in line:
  407. m = re.search("read ([0-9]+)", line)
  408. rawData['read'] = int(m.group(1))
  409. if "write" in line:
  410. m = re.search("write ([0-9]+)", line)
  411. rawData['write'] = int(m.group(1))
  412. if "timeout" in line:
  413. m = re.search("timeout ([0-9]+)", line)
  414. rawData['timeout'] = int(m.group(1))
  415. if "Non-2xx" in line:
  416. m = re.search("Non-2xx or 3xx responses: ([0-9]+)", line)
  417. if m != None:
  418. rawData['5xx'] = int(m.group(1))
  419. return results
  420. except IOError:
  421. return None
  422. ############################################################
  423. # End benchmark
  424. ############################################################
  425. ##########################################################################################
  426. # Private Methods
  427. ##########################################################################################
  428. ############################################################
  429. # __run_benchmark(script, output_file)
  430. # Runs a single benchmark using the script which is a bash
  431. # template that uses weighttp to run the test. All the results
  432. # outputed to the output_file.
  433. ############################################################
  434. def __run_benchmark(self, script, output_file, err):
  435. with open(output_file, 'w') as raw_file:
  436. p = subprocess.Popen(self.benchmarker.client_ssh_string.split(" "), stdin=subprocess.PIPE, stdout=raw_file, stderr=err)
  437. p.communicate(script)
  438. err.flush()
  439. ############################################################
  440. # End __run_benchmark
  441. ############################################################
  442. ############################################################
  443. # __generate_concurrency_script(url, port)
  444. # Generates the string containing the bash script that will
  445. # be run on the client to benchmark a single test. This
  446. # specifically works for the variable concurrency tests (JSON
  447. # and DB)
  448. ############################################################
  449. def __generate_concurrency_script(self, url, port, accept_header, wrk_command="wrk", intervals=[], pipeline=""):
  450. if len(intervals) == 0:
  451. intervals = self.benchmarker.concurrency_levels
  452. headers = self.__get_request_headers(accept_header)
  453. return self.concurrency_template.format(max_concurrency=self.benchmarker.max_concurrency,
  454. max_threads=self.benchmarker.max_threads, name=self.name, duration=self.benchmarker.duration,
  455. interval=" ".join("{}".format(item) for item in intervals),
  456. server_host=self.benchmarker.server_host, port=port, url=url, headers=headers, wrk=wrk_command,
  457. pipeline=pipeline)
  458. ############################################################
  459. # End __generate_concurrency_script
  460. ############################################################
  461. ############################################################
  462. # __generate_query_script(url, port)
  463. # Generates the string containing the bash script that will
  464. # be run on the client to benchmark a single test. This
  465. # specifically works for the variable query tests (Query)
  466. ############################################################
  467. def __generate_query_script(self, url, port, accept_header):
  468. headers = self.__get_request_headers(accept_header)
  469. return self.query_template.format(max_concurrency=self.benchmarker.max_concurrency,
  470. max_threads=self.benchmarker.max_threads, name=self.name, duration=self.benchmarker.duration,
  471. interval=" ".join("{}".format(item) for item in self.benchmarker.query_intervals),
  472. server_host=self.benchmarker.server_host, port=port, url=url, headers=headers)
  473. ############################################################
  474. # End __generate_query_script
  475. ############################################################
  476. ############################################################
  477. # __get_request_headers(accept_header)
  478. # Generates the complete HTTP header string
  479. ############################################################
  480. def __get_request_headers(self, accept_header):
  481. return self.headers_template.format(accept=accept_header)
  482. ############################################################
  483. # End __format_request_headers
  484. ############################################################
  485. ############################################################
  486. # __curl_url
  487. # Dump HTTP response and headers. Throw exception if there
  488. # is an HTTP error.
  489. ############################################################
  490. def __curl_url(self, url, testType, out, err):
  491. # Use -i to output response with headers.
  492. # Don't use -f so that the HTTP response code is ignored.
  493. # Use --stderr - to redirect stderr to stdout so we get
  494. # error output for sure in stdout.
  495. # Use -sS to hide progress bar, but show errors.
  496. subprocess.check_call(["curl", "-i", "-sS", url], stderr=err, stdout=out)
  497. out.flush()
  498. err.flush()
  499. # HTTP output may not end in a newline, so add that here.
  500. out.write( "\n" )
  501. out.flush()
  502. # We need to get the respond body from the curl and return it.
  503. p = subprocess.Popen(["curl", "-s", url], stdout=subprocess.PIPE)
  504. output = p.communicate()
  505. # In the curl invocation above we could not use -f because
  506. # then the HTTP response would not be output, so use -f in
  507. # an additional invocation so that if there is an HTTP error,
  508. # subprocess.CalledProcessError will be thrown. Note that this
  509. # uses check_output() instead of check_call() so that we can
  510. # ignore the HTTP response because we already output that in
  511. # the first curl invocation.
  512. subprocess.check_output(["curl", "-fsS", url], stderr=err)
  513. out.flush()
  514. err.flush()
  515. # HTTP output may not end in a newline, so add that here.
  516. out.write( "\n" )
  517. out.flush()
  518. if output:
  519. # We have the response body - return it
  520. return output[0]
  521. ##############################################################
  522. # End __curl_url
  523. ##############################################################
  524. ##########################################################################################
  525. # Constructor
  526. ##########################################################################################
  527. def __init__(self, name, directory, benchmarker, args):
  528. self.name = name
  529. self.directory = directory
  530. self.benchmarker = benchmarker
  531. self.__dict__.update(args)
  532. # ensure directory has __init__.py file so that we can use it as a Python package
  533. if not os.path.exists(os.path.join(directory, "__init__.py")):
  534. open(os.path.join(directory, "__init__.py"), 'w').close()
  535. self.setup_module = setup_module = importlib.import_module(directory + '.' + self.setup_file)
  536. ############################################################
  537. # End __init__
  538. ############################################################
  539. ############################################################
  540. # End FrameworkTest
  541. ############################################################
  542. ##########################################################################################
  543. # Static methods
  544. ##########################################################################################
  545. ##############################################################
  546. # parse_config(config, directory, benchmarker)
  547. # parses a config file and returns a list of FrameworkTest
  548. # objects based on that config file.
  549. ##############################################################
  550. def parse_config(config, directory, benchmarker):
  551. tests = []
  552. # The config object can specify multiple tests, we neep to loop
  553. # over them and parse them out
  554. for test in config['tests']:
  555. for key, value in test.iteritems():
  556. test_name = config['framework']
  557. # if the test uses the 'defualt' keywork, then we don't
  558. # append anything to it's name. All configs should only have 1 default
  559. if key != 'default':
  560. # we need to use the key in the test_name
  561. test_name = test_name + "-" + key
  562. tests.append(FrameworkTest(test_name, directory, benchmarker, value))
  563. return tests
  564. ##############################################################
  565. # End parse_config
  566. ##############################################################