108 'help': 'password of the CubicWeb user account matching login', |
109 'help': 'password of the CubicWeb user account matching login', |
109 'group': 'main', 'level': 1, |
110 'group': 'main', 'level': 1, |
110 }), |
111 }), |
111 )) |
112 )) |
112 |
113 |
113 def __init__(self, appid, log_threshold=logging.CRITICAL+10): |
114 def __init__(self, appid, apphome=None, log_threshold=logging.CRITICAL+10): |
|
115 # must be set before calling parent __init__ |
|
116 if apphome is None: |
|
117 if exists(appid): |
|
118 apphome = abspath(appid) |
|
119 else: # cube test |
|
120 apphome = abspath('..') |
|
121 self._apphome = apphome |
114 ServerConfiguration.__init__(self, appid) |
122 ServerConfiguration.__init__(self, appid) |
115 self.init_log(log_threshold, force=True) |
123 self.init_log(log_threshold, force=True) |
116 # need this, usually triggered by cubicweb-ctl |
124 # need this, usually triggered by cubicweb-ctl |
117 self.load_cwctl_plugins() |
125 self.load_cwctl_plugins() |
118 |
126 |
119 anonymous_user = TwistedConfiguration.anonymous_user.im_func |
127 anonymous_user = TwistedConfiguration.anonymous_user.im_func |
120 |
128 |
121 @property |
129 @property |
122 def apphome(self): |
130 def apphome(self): |
123 if exists(self.appid): |
131 return self._apphome |
124 return abspath(self.appid) |
|
125 # cube test |
|
126 return abspath('..') |
|
127 appdatahome = apphome |
132 appdatahome = apphome |
128 |
133 |
129 def load_configuration(self): |
134 def load_configuration(self): |
130 super(TestServerConfiguration, self).load_configuration() |
135 super(TestServerConfiguration, self).load_configuration() |
131 self.global_set_option('anonymous-user', 'anon') |
136 self.global_set_option('anonymous-user', 'anon') |
179 cube_appobject_path = TestServerConfiguration.cube_appobject_path | TwistedConfiguration.cube_appobject_path |
190 cube_appobject_path = TestServerConfiguration.cube_appobject_path | TwistedConfiguration.cube_appobject_path |
180 |
191 |
181 def available_languages(self, *args): |
192 def available_languages(self, *args): |
182 return ('en', 'fr', 'de') |
193 return ('en', 'fr', 'de') |
183 |
194 |
184 def ext_resources_file(self): |
|
185 """return instance's external resources file""" |
|
186 return join(self.apphome, 'data', 'external_resources') |
|
187 |
|
188 def pyro_enabled(self): |
195 def pyro_enabled(self): |
189 # but export PYRO_MULTITHREAD=0 or you get problems with sqlite and threads |
196 # but export PYRO_MULTITHREAD=0 or you get problems with sqlite and |
|
197 # threads |
190 return True |
198 return True |
191 |
199 |
192 |
200 # XXX merge with BaseApptestConfiguration ? |
193 class ApptestConfiguration(BaseApptestConfiguration): |
201 class ApptestConfiguration(BaseApptestConfiguration): |
194 |
202 |
195 def __init__(self, appid, log_threshold=logging.CRITICAL, sourcefile=None): |
203 def __init__(self, appid, apphome=None, |
196 BaseApptestConfiguration.__init__(self, appid, log_threshold=log_threshold) |
204 log_threshold=logging.CRITICAL, sourcefile=None): |
|
205 BaseApptestConfiguration.__init__(self, appid, apphome, |
|
206 log_threshold=log_threshold) |
197 self.init_repository = sourcefile is None |
207 self.init_repository = sourcefile is None |
198 self.sourcefile = sourcefile |
208 self.sourcefile = sourcefile |
|
209 |
|
210 |
|
211 class RealDatabaseConfiguration(ApptestConfiguration): |
|
212 """configuration class for tests to run on a real database. |
|
213 |
|
214 The intialization is done by specifying a source file path. |
|
215 |
|
216 Important note: init_test_database / reset_test_database steps are |
|
217 skipped. It's thus up to the test developer to implement setUp/tearDown |
|
218 accordingly. |
|
219 |
|
220 Example usage:: |
|
221 |
|
222 class MyTests(CubicWebTC): |
|
223 _config = RealDatabseConfiguration('myapp', |
|
224 sourcefile='/path/to/sources') |
|
225 def test_something(self): |
|
226 rset = self.execute('Any X WHERE X is CWUser') |
|
227 self.view('foaf', rset) |
|
228 |
|
229 """ |
|
230 db_require_setup = False # skip init_db / reset_db steps |
|
231 read_instance_schema = True # read schema from database |
199 |
232 |
200 |
233 |
201 # test database handling ####################################################### |
234 # test database handling ####################################################### |
202 |
235 |
203 def init_test_database(config=None, configdir='data'): |
236 def init_test_database(config=None, configdir='data'): |
204 """init a test database for a specific driver""" |
237 """init a test database for a specific driver""" |
205 from cubicweb.dbapi import in_memory_cnx |
238 from cubicweb.dbapi import in_memory_cnx |
206 config = config or TestServerConfiguration(configdir) |
239 config = config or TestServerConfiguration(configdir) |
207 sources = config.sources() |
240 sources = config.sources() |
208 driver = sources['system']['db-driver'] |
241 driver = sources['system']['db-driver'] |
209 if driver == 'sqlite': |
242 if config.db_require_setup: |
210 init_test_database_sqlite(config) |
243 if driver == 'sqlite': |
211 elif driver == 'postgres': |
244 init_test_database_sqlite(config) |
212 init_test_database_postgres(config) |
245 elif driver == 'postgres': |
213 elif driver == 'sqlserver2005': |
246 init_test_database_postgres(config) |
214 init_test_database_sqlserver2005(config) |
247 else: |
215 else: |
248 raise ValueError('no initialization function for driver %r' % driver) |
216 raise ValueError('no initialization function for driver %r' % driver) |
|
217 config._cubes = None # avoid assertion error |
249 config._cubes = None # avoid assertion error |
218 repo, cnx = in_memory_cnx(config, unicode(sources['admin']['login']), |
250 repo, cnx = in_memory_cnx(config, unicode(sources['admin']['login']), |
219 password=sources['admin']['password'] or 'xxx') |
251 password=sources['admin']['password'] or 'xxx') |
220 if driver == 'sqlite': |
252 if driver == 'sqlite': |
221 install_sqlite_patch(repo.querier) |
253 install_sqlite_patch(repo.querier) |
222 return repo, cnx |
254 return repo, cnx |
223 |
255 |
224 |
|
225 def reset_test_database(config): |
256 def reset_test_database(config): |
226 """init a test database for a specific driver""" |
257 """init a test database for a specific driver""" |
|
258 if not config.db_require_setup: |
|
259 return |
227 driver = config.sources()['system']['db-driver'] |
260 driver = config.sources()['system']['db-driver'] |
228 if driver == 'sqlite': |
261 if driver == 'sqlite': |
229 reset_test_database_sqlite(config) |
262 reset_test_database_sqlite(config) |
230 elif driver in ('sqlserver2005', 'postgres'): |
263 elif driver == 'postgres': |
231 # XXX do something with dump/restore ? |
264 init_test_database_postgres(config) |
232 print 'resetting the database is not done for', driver |
|
233 print 'you should handle it manually' |
|
234 else: |
265 else: |
235 raise ValueError('no reset function for driver %r' % driver) |
266 raise ValueError('no reset function for driver %r' % driver) |
236 |
267 |
237 |
268 |
238 ### postgres test database handling ############################################ |
269 ### postgres test database handling ############################################ |
239 |
270 |
240 def init_test_database_postgres(config): |
271 def init_test_database_postgres(config): |
241 """initialize a fresh postgresql databse used for testing purpose""" |
272 """initialize a fresh postgresql databse used for testing purpose""" |
242 if config.init_repository: |
273 from logilab.database import get_db_helper |
243 from cubicweb.server import init_repository |
274 from cubicweb.server import init_repository |
244 init_repository(config, interactive=False, drop=True) |
275 from cubicweb.server.serverctl import (createdb, system_source_cnx, |
245 |
276 _db_sys_cnx) |
246 ### sqlserver2005 test database handling ############################################ |
277 source = config.sources()['system'] |
|
278 dbname = source['db-name'] |
|
279 templdbname = dbname + '_template' |
|
280 helper = get_db_helper('postgres') |
|
281 # connect on the dbms system base to create our base |
|
282 dbcnx = _db_sys_cnx(source, 'CREATE DATABASE and / or USER', verbose=0) |
|
283 cursor = dbcnx.cursor() |
|
284 try: |
|
285 if dbname in helper.list_databases(cursor): |
|
286 cursor.execute('DROP DATABASE %s' % dbname) |
|
287 if not templdbname in helper.list_databases(cursor): |
|
288 source['db-name'] = templdbname |
|
289 createdb(helper, source, dbcnx, cursor) |
|
290 dbcnx.commit() |
|
291 cnx = system_source_cnx(source, special_privs='LANGUAGE C', verbose=0) |
|
292 templcursor = cnx.cursor() |
|
293 # XXX factorize with db-create code |
|
294 helper.init_fti_extensions(templcursor) |
|
295 # install plpythonu/plpgsql language if not installed by the cube |
|
296 langs = sys.platform == 'win32' and ('plpgsql',) or ('plpythonu', 'plpgsql') |
|
297 for extlang in langs: |
|
298 helper.create_language(templcursor, extlang) |
|
299 cnx.commit() |
|
300 templcursor.close() |
|
301 cnx.close() |
|
302 init_repository(config, interactive=False) |
|
303 source['db-name'] = dbname |
|
304 except: |
|
305 dbcnx.rollback() |
|
306 # XXX drop template |
|
307 raise |
|
308 createdb(helper, source, dbcnx, cursor, template=templdbname) |
|
309 dbcnx.commit() |
|
310 dbcnx.close() |
|
311 |
|
312 ### sqlserver2005 test database handling ####################################### |
247 |
313 |
248 def init_test_database_sqlserver2005(config): |
314 def init_test_database_sqlserver2005(config): |
249 """initialize a fresh sqlserver databse used for testing purpose""" |
315 """initialize a fresh sqlserver databse used for testing purpose""" |
250 if config.init_repository: |
316 if config.init_repository: |
251 from cubicweb.server import init_repository |
317 from cubicweb.server import init_repository |