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