/desktop/core/ext-py/MySQL-python-1.2.3c1/tests/capabilities.py

https://github.com/jcrobak/hue · Python · 289 lines · 234 code · 34 blank · 21 comment · 50 complexity · 07a55140086d44583602322c35def8dd MD5 · raw file

  1. #!/usr/bin/env python -O
  2. """ Script to test database capabilities and the DB-API interface
  3. for functionality and memory leaks.
  4. Adapted from a script by M-A Lemburg.
  5. """
  6. from time import time
  7. import array
  8. import unittest
  9. class DatabaseTest(unittest.TestCase):
  10. db_module = None
  11. connect_args = ()
  12. connect_kwargs = dict()
  13. create_table_extra = ''
  14. rows = 10
  15. debug = False
  16. def setUp(self):
  17. import gc
  18. db = self.db_module.connect(*self.connect_args, **self.connect_kwargs)
  19. self.connection = db
  20. self.cursor = db.cursor()
  21. self.BLOBText = ''.join([chr(i) for i in range(256)] * 100);
  22. self.BLOBUText = u''.join([unichr(i) for i in range(16384)])
  23. self.BLOBBinary = self.db_module.Binary(''.join([chr(i) for i in range(256)] * 16))
  24. leak_test = True
  25. def tearDown(self):
  26. if self.leak_test:
  27. import gc
  28. del self.cursor
  29. orphans = gc.collect()
  30. self.failIf(orphans, "%d orphaned objects found after deleting cursor" % orphans)
  31. del self.connection
  32. orphans = gc.collect()
  33. self.failIf(orphans, "%d orphaned objects found after deleting connection" % orphans)
  34. def table_exists(self, name):
  35. try:
  36. self.cursor.execute('select * from %s where 1=0' % name)
  37. except:
  38. return False
  39. else:
  40. return True
  41. def quote_identifier(self, ident):
  42. return '"%s"' % ident
  43. def new_table_name(self):
  44. i = id(self.cursor)
  45. while True:
  46. name = self.quote_identifier('tb%08x' % i)
  47. if not self.table_exists(name):
  48. return name
  49. i = i + 1
  50. def create_table(self, columndefs):
  51. """ Create a table using a list of column definitions given in
  52. columndefs.
  53. generator must be a function taking arguments (row_number,
  54. col_number) returning a suitable data object for insertion
  55. into the table.
  56. """
  57. self.table = self.new_table_name()
  58. self.cursor.execute('CREATE TABLE %s (%s) %s' %
  59. (self.table,
  60. ',\n'.join(columndefs),
  61. self.create_table_extra))
  62. def check_data_integrity(self, columndefs, generator):
  63. # insert
  64. self.create_table(columndefs)
  65. insert_statement = ('INSERT INTO %s VALUES (%s)' %
  66. (self.table,
  67. ','.join(['%s'] * len(columndefs))))
  68. data = [ [ generator(i,j) for j in range(len(columndefs)) ]
  69. for i in range(self.rows) ]
  70. if self.debug:
  71. print data
  72. self.cursor.executemany(insert_statement, data)
  73. self.connection.commit()
  74. # verify
  75. self.cursor.execute('select * from %s' % self.table)
  76. l = self.cursor.fetchall()
  77. if self.debug:
  78. print l
  79. self.assertEquals(len(l), self.rows)
  80. try:
  81. for i in range(self.rows):
  82. for j in range(len(columndefs)):
  83. self.assertEquals(l[i][j], generator(i,j))
  84. finally:
  85. if not self.debug:
  86. self.cursor.execute('drop table %s' % (self.table))
  87. def test_transactions(self):
  88. columndefs = ( 'col1 INT', 'col2 VARCHAR(255)')
  89. def generator(row, col):
  90. if col == 0: return row
  91. else: return ('%i' % (row%10))*255
  92. self.create_table(columndefs)
  93. insert_statement = ('INSERT INTO %s VALUES (%s)' %
  94. (self.table,
  95. ','.join(['%s'] * len(columndefs))))
  96. data = [ [ generator(i,j) for j in range(len(columndefs)) ]
  97. for i in range(self.rows) ]
  98. self.cursor.executemany(insert_statement, data)
  99. # verify
  100. self.connection.commit()
  101. self.cursor.execute('select * from %s' % self.table)
  102. l = self.cursor.fetchall()
  103. self.assertEquals(len(l), self.rows)
  104. for i in range(self.rows):
  105. for j in range(len(columndefs)):
  106. self.assertEquals(l[i][j], generator(i,j))
  107. delete_statement = 'delete from %s where col1=%%s' % self.table
  108. self.cursor.execute(delete_statement, (0,))
  109. self.cursor.execute('select col1 from %s where col1=%s' % \
  110. (self.table, 0))
  111. l = self.cursor.fetchall()
  112. self.failIf(l, "DELETE didn't work")
  113. self.connection.rollback()
  114. self.cursor.execute('select col1 from %s where col1=%s' % \
  115. (self.table, 0))
  116. l = self.cursor.fetchall()
  117. self.failUnless(len(l) == 1, "ROLLBACK didn't work")
  118. self.cursor.execute('drop table %s' % (self.table))
  119. def test_truncation(self):
  120. columndefs = ( 'col1 INT', 'col2 VARCHAR(255)')
  121. def generator(row, col):
  122. if col == 0: return row
  123. else: return ('%i' % (row%10))*((255-self.rows/2)+row)
  124. self.create_table(columndefs)
  125. insert_statement = ('INSERT INTO %s VALUES (%s)' %
  126. (self.table,
  127. ','.join(['%s'] * len(columndefs))))
  128. try:
  129. self.cursor.execute(insert_statement, (0, '0'*256))
  130. except Warning:
  131. if self.debug: print self.cursor.messages
  132. except self.connection.DataError:
  133. pass
  134. else:
  135. self.fail("Over-long column did not generate warnings/exception with single insert")
  136. self.connection.rollback()
  137. try:
  138. for i in range(self.rows):
  139. data = []
  140. for j in range(len(columndefs)):
  141. data.append(generator(i,j))
  142. self.cursor.execute(insert_statement,tuple(data))
  143. except Warning:
  144. if self.debug: print self.cursor.messages
  145. except self.connection.DataError:
  146. pass
  147. else:
  148. self.fail("Over-long columns did not generate warnings/exception with execute()")
  149. self.connection.rollback()
  150. try:
  151. data = [ [ generator(i,j) for j in range(len(columndefs)) ]
  152. for i in range(self.rows) ]
  153. self.cursor.executemany(insert_statement, data)
  154. except Warning:
  155. if self.debug: print self.cursor.messages
  156. except self.connection.DataError:
  157. pass
  158. else:
  159. self.fail("Over-long columns did not generate warnings/exception with executemany()")
  160. self.connection.rollback()
  161. self.cursor.execute('drop table %s' % (self.table))
  162. def test_CHAR(self):
  163. # Character data
  164. def generator(row,col):
  165. return ('%i' % ((row+col) % 10)) * 255
  166. self.check_data_integrity(
  167. ('col1 char(255)','col2 char(255)'),
  168. generator)
  169. def test_INT(self):
  170. # Number data
  171. def generator(row,col):
  172. return row*row
  173. self.check_data_integrity(
  174. ('col1 INT',),
  175. generator)
  176. def test_DECIMAL(self):
  177. # DECIMAL
  178. def generator(row,col):
  179. from decimal import Decimal
  180. return Decimal("%d.%02d" % (row, col))
  181. self.check_data_integrity(
  182. ('col1 DECIMAL(5,2)',),
  183. generator)
  184. def test_DATE(self):
  185. ticks = time()
  186. def generator(row,col):
  187. return self.db_module.DateFromTicks(ticks+row*86400-col*1313)
  188. self.check_data_integrity(
  189. ('col1 DATE',),
  190. generator)
  191. def test_TIME(self):
  192. ticks = time()
  193. def generator(row,col):
  194. return self.db_module.TimeFromTicks(ticks+row*86400-col*1313)
  195. self.check_data_integrity(
  196. ('col1 TIME',),
  197. generator)
  198. def test_DATETIME(self):
  199. ticks = time()
  200. def generator(row,col):
  201. return self.db_module.TimestampFromTicks(ticks+row*86400-col*1313)
  202. self.check_data_integrity(
  203. ('col1 DATETIME',),
  204. generator)
  205. def test_TIMESTAMP(self):
  206. ticks = time()
  207. def generator(row,col):
  208. return self.db_module.TimestampFromTicks(ticks+row*86400-col*1313)
  209. self.check_data_integrity(
  210. ('col1 TIMESTAMP',),
  211. generator)
  212. def test_fractional_TIMESTAMP(self):
  213. ticks = time()
  214. def generator(row,col):
  215. return self.db_module.TimestampFromTicks(ticks+row*86400-col*1313+row*0.7*col/3.0)
  216. self.check_data_integrity(
  217. ('col1 TIMESTAMP',),
  218. generator)
  219. def test_LONG(self):
  220. def generator(row,col):
  221. if col == 0:
  222. return row
  223. else:
  224. return self.BLOBUText # 'BLOB Text ' * 1024
  225. self.check_data_integrity(
  226. ('col1 INT','col2 LONG'),
  227. generator)
  228. def test_TEXT(self):
  229. def generator(row,col):
  230. return self.BLOBUText # 'BLOB Text ' * 1024
  231. self.check_data_integrity(
  232. ('col2 TEXT',),
  233. generator)
  234. def test_LONG_BYTE(self):
  235. def generator(row,col):
  236. if col == 0:
  237. return row
  238. else:
  239. return self.BLOBBinary # 'BLOB\000Binary ' * 1024
  240. self.check_data_integrity(
  241. ('col1 INT','col2 LONG BYTE'),
  242. generator)
  243. def test_BLOB(self):
  244. def generator(row,col):
  245. if col == 0:
  246. return row
  247. else:
  248. return self.BLOBBinary # 'BLOB\000Binary ' * 1024
  249. self.check_data_integrity(
  250. ('col1 INT','col2 BLOB'),
  251. generator)