230 # threads |
230 # threads |
231 return True |
231 return True |
232 |
232 |
233 # XXX merge with BaseApptestConfiguration ? |
233 # XXX merge with BaseApptestConfiguration ? |
234 class ApptestConfiguration(BaseApptestConfiguration): |
234 class ApptestConfiguration(BaseApptestConfiguration): |
|
235 # `skip_db_create_and_restore` controls wether or not the test database |
|
236 # should be created / backuped / restored. If set to True, those |
|
237 # steps are completely skipped, the database is used as is and is |
|
238 # considered initialized |
|
239 skip_db_create_and_restore = False |
235 |
240 |
236 def __init__(self, appid, apphome=None, |
241 def __init__(self, appid, apphome=None, |
237 log_threshold=logging.CRITICAL, sourcefile=None): |
242 log_threshold=logging.CRITICAL, sourcefile=None): |
238 BaseApptestConfiguration.__init__(self, appid, apphome, |
243 BaseApptestConfiguration.__init__(self, appid, apphome, |
239 log_threshold=log_threshold) |
244 log_threshold=log_threshold) |
258 def test_something(self): |
263 def test_something(self): |
259 rset = self.execute('Any X WHERE X is CWUser') |
264 rset = self.execute('Any X WHERE X is CWUser') |
260 self.view('foaf', rset) |
265 self.view('foaf', rset) |
261 |
266 |
262 """ |
267 """ |
|
268 skip_db_create_and_restore = True |
263 read_instance_schema = True # read schema from database |
269 read_instance_schema = True # read schema from database |
264 |
270 |
265 |
271 |
266 # test database handling ####################################################### |
272 # test database handling ####################################################### |
267 |
273 |
475 pre_setup_func(session, self.config) |
481 pre_setup_func(session, self.config) |
476 session.commit() |
482 session.commit() |
477 cnx.close() |
483 cnx.close() |
478 self.backup_database(test_db_id) |
484 self.backup_database(test_db_id) |
479 |
485 |
|
486 |
|
487 class NoCreateDropDatabaseHandler(TestDataBaseHandler): |
|
488 """This handler is used if config.skip_db_create_and_restore is True |
|
489 |
|
490 This is typically the case with RealDBConfig. In that case, |
|
491 we explicitely want to skip init / backup / restore phases. |
|
492 |
|
493 This handler redefines the three corresponding methods and delegates |
|
494 to original handler for any other method / attribute |
|
495 """ |
|
496 |
|
497 def __init__(self, base_handler): |
|
498 self.base_handler = base_handler |
|
499 |
|
500 # override init / backup / restore methods |
|
501 def init_test_database(self): |
|
502 pass |
|
503 |
|
504 def backup_database(self, db_id): |
|
505 pass |
|
506 |
|
507 def restore_database(self, db_id): |
|
508 pass |
|
509 |
|
510 # delegate to original handler in all other cases |
|
511 def __getattr__(self, attrname): |
|
512 return getattr(self.base_handler, attrname) |
|
513 |
|
514 |
480 ### postgres test database handling ############################################ |
515 ### postgres test database handling ############################################ |
481 |
516 |
482 class PostgresTestDataBaseHandler(TestDataBaseHandler): |
517 class PostgresTestDataBaseHandler(TestDataBaseHandler): |
483 |
|
484 # XXX |
|
485 # XXX PostgresTestDataBaseHandler Have not been tested at all. |
|
486 # XXX |
|
487 DRIVER = 'postgres' |
518 DRIVER = 'postgres' |
488 |
519 |
489 @property |
520 @property |
490 @cached |
521 @cached |
491 def helper(self): |
522 def helper(self): |
502 @property |
533 @property |
503 @cached |
534 @cached |
504 def cursor(self): |
535 def cursor(self): |
505 return self.dbcnx.cursor() |
536 return self.dbcnx.cursor() |
506 |
537 |
|
538 def process_cache_entry(self, directory, dbname, db_id, entry): |
|
539 backup_name = self._backup_name(db_id) |
|
540 if backup_name in self.helper.list_databases(self.cursor): |
|
541 return backup_name |
|
542 return None |
|
543 |
507 def init_test_database(self): |
544 def init_test_database(self): |
508 """initialize a fresh postgresql databse used for testing purpose""" |
545 """initialize a fresh postgresql database used for testing purpose""" |
509 from cubicweb.server import init_repository |
546 from cubicweb.server import init_repository |
510 from cubicweb.server.serverctl import system_source_cnx, createdb |
547 from cubicweb.server.serverctl import system_source_cnx, createdb |
511 # connect on the dbms system base to create our base |
548 # connect on the dbms system base to create our base |
512 try: |
549 try: |
513 self._drop(self.dbname) |
550 self._drop(self.dbname) |
514 |
|
515 createdb(self.helper, self.system_source, self.dbcnx, self.cursor) |
551 createdb(self.helper, self.system_source, self.dbcnx, self.cursor) |
516 self.dbcnx.commit() |
552 self.dbcnx.commit() |
517 cnx = system_source_cnx(self.system_source, special_privs='LANGUAGE C', |
553 cnx = system_source_cnx(self.system_source, special_privs='LANGUAGE C', |
518 interactive=False) |
554 interactive=False) |
519 templcursor = cnx.cursor() |
555 templcursor = cnx.cursor() |
553 backup_name = '_'.join(('cache', self._config_id, self.dbname, db_id)) |
589 backup_name = '_'.join(('cache', self._config_id, self.dbname, db_id)) |
554 return backup_name.lower() |
590 return backup_name.lower() |
555 |
591 |
556 def _drop(self, db_name): |
592 def _drop(self, db_name): |
557 if db_name in self.helper.list_databases(self.cursor): |
593 if db_name in self.helper.list_databases(self.cursor): |
558 #print 'dropping overwritted database:', db_name |
|
559 self.cursor.execute('DROP DATABASE %s' % db_name) |
594 self.cursor.execute('DROP DATABASE %s' % db_name) |
560 self.dbcnx.commit() |
595 self.dbcnx.commit() |
561 |
596 |
562 def _backup_database(self, db_id): |
597 def _backup_database(self, db_id): |
563 """Actual backup the current database. |
598 """Actual backup the current database. |
565 return a value to be stored in db_cache to allow restoration""" |
600 return a value to be stored in db_cache to allow restoration""" |
566 from cubicweb.server.serverctl import createdb |
601 from cubicweb.server.serverctl import createdb |
567 orig_name = self.system_source['db-name'] |
602 orig_name = self.system_source['db-name'] |
568 try: |
603 try: |
569 backup_name = self._backup_name(db_id) |
604 backup_name = self._backup_name(db_id) |
570 #print 'storing postgres backup as', backup_name |
|
571 self._drop(backup_name) |
605 self._drop(backup_name) |
572 self.system_source['db-name'] = backup_name |
606 self.system_source['db-name'] = backup_name |
573 createdb(self.helper, self.system_source, self.dbcnx, self.cursor, template=orig_name) |
607 createdb(self.helper, self.system_source, self.dbcnx, self.cursor, template=orig_name) |
574 self.dbcnx.commit() |
608 self.dbcnx.commit() |
575 return backup_name |
609 return backup_name |
579 def _restore_database(self, backup_coordinates, config): |
613 def _restore_database(self, backup_coordinates, config): |
580 from cubicweb.server.serverctl import createdb |
614 from cubicweb.server.serverctl import createdb |
581 """Actual restore of the current database. |
615 """Actual restore of the current database. |
582 |
616 |
583 Use the value tostored in db_cache as input """ |
617 Use the value tostored in db_cache as input """ |
584 #print 'restoring postgrest backup from', backup_coordinates |
|
585 self._drop(self.dbname) |
618 self._drop(self.dbname) |
586 createdb(self.helper, self.system_source, self.dbcnx, self.cursor, |
619 createdb(self.helper, self.system_source, self.dbcnx, self.cursor, |
587 template=backup_coordinates) |
620 template=backup_coordinates) |
588 self.dbcnx.commit() |
621 self.dbcnx.commit() |
589 |
622 |
645 |
678 |
646 def _restore_database(self, backup_coordinates, _config): |
679 def _restore_database(self, backup_coordinates, _config): |
647 # remove database file if it exists ? |
680 # remove database file if it exists ? |
648 dbfile = self.absolute_dbfile() |
681 dbfile = self.absolute_dbfile() |
649 self._cleanup_database(dbfile) |
682 self._cleanup_database(dbfile) |
650 #print 'resto from', backup_coordinates |
|
651 shutil.copy(backup_coordinates, dbfile) |
683 shutil.copy(backup_coordinates, dbfile) |
652 repo = self.get_repo() |
684 repo = self.get_repo() |
653 |
685 |
654 def init_test_database(self): |
686 def init_test_database(self): |
655 """initialize a fresh sqlite databse used for testing purpose""" |
687 """initialize a fresh sqlite databse used for testing purpose""" |
752 driver = sources['system']['db-driver'] |
784 driver = sources['system']['db-driver'] |
753 key = (driver, config) |
785 key = (driver, config) |
754 handlerkls = HANDLERS.get(driver, None) |
786 handlerkls = HANDLERS.get(driver, None) |
755 if handlerkls is not None: |
787 if handlerkls is not None: |
756 handler = handlerkls(config) |
788 handler = handlerkls(config) |
|
789 if config.skip_db_create_and_restore: |
|
790 handler = NoCreateDropDatabaseHandler(handler) |
757 HCACHE.set(config, handler) |
791 HCACHE.set(config, handler) |
758 return handler |
792 return handler |
759 else: |
793 else: |
760 raise ValueError('no initialization function for driver %r' % driver) |
794 raise ValueError('no initialization function for driver %r' % driver) |
761 |
795 |