Keyboard firmwares for Atmel AVR and Cortex-M
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_mysql.py 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. """
  2. mbed SDK
  3. Copyright (c) 2011-2014 ARM Limited
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. Author: Przemyslaw Wirkus <[email protected]>
  14. """
  15. import re
  16. import MySQLdb as mdb
  17. # Imports from TEST API
  18. from workspace_tools.test_db import BaseDBAccess
  19. class MySQLDBAccess(BaseDBAccess):
  20. """ Wrapper for MySQL DB access for common test suite interface
  21. """
  22. def __init__(self):
  23. BaseDBAccess.__init__(self)
  24. self.DB_TYPE = 'mysql'
  25. def detect_database(self, verbose=False):
  26. """ detect database and return VERION data structure or string (verbose=True)
  27. """
  28. query = 'SHOW VARIABLES LIKE "%version%"'
  29. rows = self.select_all(query)
  30. if verbose:
  31. result = []
  32. for row in rows:
  33. result.append("\t%s: %s"% (row['Variable_name'], row['Value']))
  34. result = "\n".join(result)
  35. else:
  36. result = rows
  37. return result
  38. def parse_db_connection_string(self, str):
  39. """ Parsing SQL DB connection string. String should contain:
  40. - DB Name, user name, password, URL (DB host), name
  41. Function should return tuple with parsed (host, user, passwd, db) or None if error
  42. E.g. connection string: 'mysql://username:[email protected]/db_name'
  43. """
  44. result = BaseDBAccess().parse_db_connection_string(str)
  45. if result is not None:
  46. (db_type, username, password, host, db_name) = result
  47. if db_type != 'mysql':
  48. result = None
  49. return result
  50. def is_connected(self):
  51. """ Returns True if we are connected to database
  52. """
  53. return self.db_object is not None
  54. def connect(self, host, user, passwd, db):
  55. """ Connects to DB and returns DB object
  56. """
  57. try:
  58. self.db_object = mdb.connect(host=host, user=user, passwd=passwd, db=db)
  59. # Let's remember connection credentials
  60. self.db_type = self.DB_TYPE
  61. self.host = host
  62. self.user = user
  63. self.passwd = passwd
  64. self.db = db
  65. except mdb.Error, e:
  66. print "Error %d: %s"% (e.args[0], e.args[1])
  67. self.db_object = None
  68. self.db_type = None
  69. self.host = None
  70. self.user = None
  71. self.passwd = None
  72. self.db = None
  73. def connect_url(self, db_url):
  74. """ Connects to database using db_url (database url parsing),
  75. store host, username, password, db_name
  76. """
  77. result = self.parse_db_connection_string(db_url)
  78. if result is not None:
  79. (db_type, username, password, host, db_name) = result
  80. if db_type == self.DB_TYPE:
  81. self.connect(host, username, password, db_name)
  82. def reconnect(self):
  83. """ Reconnects to DB and returns DB object using stored host name,
  84. database name and credentials (user name and password)
  85. """
  86. self.connect(self.host, self.user, self.passwd, self.db)
  87. def disconnect(self):
  88. """ Close DB connection
  89. """
  90. if self.db_object:
  91. self.db_object.close()
  92. self.db_object = None
  93. self.db_type = None
  94. def escape_string(self, str):
  95. """ Escapes string so it can be put in SQL query between quotes
  96. """
  97. con = self.db_object
  98. result = con.escape_string(str)
  99. return result if result else ''
  100. def select_all(self, query):
  101. """ Execute SELECT query and get all results
  102. """
  103. con = self.db_object
  104. cur = con.cursor(mdb.cursors.DictCursor)
  105. cur.execute(query)
  106. rows = cur.fetchall()
  107. return rows
  108. def insert(self, query, commit=True):
  109. """ Execute INSERT query, define if you want to commit
  110. """
  111. con = self.db_object
  112. cur = con.cursor()
  113. cur.execute(query)
  114. if commit:
  115. con.commit()
  116. return cur.lastrowid
  117. def get_next_build_id(self, name, desc='', location='', type=None, status=None):
  118. """ Insert new build_id (DB unique build like ID number to send all test results)
  119. """
  120. if status is None:
  121. status = self.BUILD_ID_STATUS_STARTED
  122. if type is None:
  123. type = self.BUILD_ID_TYPE_TEST
  124. query = """INSERT INTO `%s` (%s_name, %s_desc, %s_location, %s_type_fk, %s_status_fk)
  125. VALUES ('%s', '%s', '%s', %d, %d)"""% (self.TABLE_BUILD_ID,
  126. self.TABLE_BUILD_ID,
  127. self.TABLE_BUILD_ID,
  128. self.TABLE_BUILD_ID,
  129. self.TABLE_BUILD_ID,
  130. self.TABLE_BUILD_ID,
  131. self.escape_string(name),
  132. self.escape_string(desc),
  133. self.escape_string(location),
  134. type,
  135. status)
  136. index = self.insert(query) # Provide inserted record PK
  137. return index
  138. def get_table_entry_pk(self, table, column, value, update_db=True):
  139. """ Checks for entries in tables with two columns (<TABLE_NAME>_pk, <column>)
  140. If update_db is True updates table entry if value in specified column doesn't exist
  141. """
  142. # TODO: table buffering
  143. result = None
  144. table_pk = '%s_pk'% table
  145. query = """SELECT `%s`
  146. FROM `%s`
  147. WHERE `%s`='%s'"""% (table_pk,
  148. table,
  149. column,
  150. self.escape_string(value))
  151. rows = self.select_all(query)
  152. if len(rows) == 1:
  153. result = rows[0][table_pk]
  154. elif len(rows) == 0 and update_db:
  155. # Update DB with new value
  156. result = self.update_table_entry(table, column, value)
  157. return result
  158. def update_table_entry(self, table, column, value):
  159. """ Updates table entry if value in specified column doesn't exist
  160. Locks table to perform atomic read + update
  161. """
  162. result = None
  163. con = self.db_object
  164. cur = con.cursor()
  165. cur.execute("LOCK TABLES `%s` WRITE"% table)
  166. table_pk = '%s_pk'% table
  167. query = """SELECT `%s`
  168. FROM `%s`
  169. WHERE `%s`='%s'"""% (table_pk,
  170. table,
  171. column,
  172. self.escape_string(value))
  173. cur.execute(query)
  174. rows = cur.fetchall()
  175. if len(rows) == 0:
  176. query = """INSERT INTO `%s` (%s)
  177. VALUES ('%s')"""% (table,
  178. column,
  179. self.escape_string(value))
  180. cur.execute(query)
  181. result = cur.lastrowid
  182. con.commit()
  183. cur.execute("UNLOCK TABLES")
  184. return result
  185. def update_build_id_info(self, build_id, **kw):
  186. """ Update additional data inside build_id table
  187. Examples:
  188. db.update_build_id_info(build_id, _status_fk=self.BUILD_ID_STATUS_COMPLETED, _shuffle_seed=0.0123456789):
  189. """
  190. if len(kw):
  191. con = self.db_object
  192. cur = con.cursor()
  193. # Prepare UPDATE query
  194. # ["`mtest_build_id_pk`=[value-1]", "`mtest_build_id_name`=[value-2]", "`mtest_build_id_desc`=[value-3]"]
  195. set_list = []
  196. for col_sufix in kw:
  197. assign_str = "`%s%s`='%s'"% (self.TABLE_BUILD_ID, col_sufix, self.escape_string(str(kw[col_sufix])))
  198. set_list.append(assign_str)
  199. set_str = ', '.join(set_list)
  200. query = """UPDATE `%s`
  201. SET %s
  202. WHERE `mtest_build_id_pk`=%d"""% (self.TABLE_BUILD_ID,
  203. set_str,
  204. build_id)
  205. cur.execute(query)
  206. con.commit()
  207. def insert_test_entry(self, build_id, target, toolchain, test_type, test_id, test_result, test_output, test_time, test_timeout, test_loop, test_extra=''):
  208. """ Inserts test result entry to database. All checks regarding existing
  209. toolchain names in DB are performed.
  210. If some data is missing DB will be updated
  211. """
  212. # Get all table FK and if entry is new try to insert new value
  213. target_fk = self.get_table_entry_pk(self.TABLE_TARGET, self.TABLE_TARGET + '_name', target)
  214. toolchain_fk = self.get_table_entry_pk(self.TABLE_TOOLCHAIN, self.TABLE_TOOLCHAIN + '_name', toolchain)
  215. test_type_fk = self.get_table_entry_pk(self.TABLE_TEST_TYPE, self.TABLE_TEST_TYPE + '_name', test_type)
  216. test_id_fk = self.get_table_entry_pk(self.TABLE_TEST_ID, self.TABLE_TEST_ID + '_name', test_id)
  217. test_result_fk = self.get_table_entry_pk(self.TABLE_TEST_RESULT, self.TABLE_TEST_RESULT + '_name', test_result)
  218. con = self.db_object
  219. cur = con.cursor()
  220. query = """ INSERT INTO `%s` (`mtest_build_id_fk`,
  221. `mtest_target_fk`,
  222. `mtest_toolchain_fk`,
  223. `mtest_test_type_fk`,
  224. `mtest_test_id_fk`,
  225. `mtest_test_result_fk`,
  226. `mtest_test_output`,
  227. `mtest_test_time`,
  228. `mtest_test_timeout`,
  229. `mtest_test_loop_no`,
  230. `mtest_test_result_extra`)
  231. VALUES (%d, %d, %d, %d, %d, %d, '%s', %.2f, %.2f, %d, '%s')"""% (self.TABLE_TEST_ENTRY,
  232. build_id,
  233. target_fk,
  234. toolchain_fk,
  235. test_type_fk,
  236. test_id_fk,
  237. test_result_fk,
  238. self.escape_string(test_output),
  239. test_time,
  240. test_timeout,
  241. test_loop,
  242. self.escape_string(test_extra))
  243. cur.execute(query)
  244. con.commit()