goa/testlib.py
changeset 0 b97547f5f1fa
child 444 c6f20e605b84
equal deleted inserted replaced
-1:000000000000 0:b97547f5f1fa
       
     1 from logilab.common.testlib import TestCase, mock_object
       
     2 
       
     3 import os, os.path as osp
       
     4 import time
       
     5 from shutil import copy
       
     6 
       
     7 # additional monkey patches necessary in regular cubicweb environment
       
     8 from cubicweb.server import rqlannotation
       
     9 from cubicweb.goa.overrides import rqlannotation as goarqlannotation
       
    10 rqlannotation.sqlgen_annotate = goarqlannotation.sqlgen_annotate
       
    11 rqlannotation.set_qdata = goarqlannotation.set_qdata
       
    12 
       
    13 try:
       
    14     from google.appengine.api import apiproxy_stub_map
       
    15     from google.appengine.api import datastore_file_stub
       
    16     from google.appengine.ext import db as gdb
       
    17     from cubicweb.goa import db, do_monkey_patch
       
    18     from cubicweb.goa.dbmyams import load_schema
       
    19     import_appengine_failed = None
       
    20 except ImportError, exc:
       
    21     raise
       
    22     class db:
       
    23         class Model:
       
    24             pass
       
    25         class DummyProperty:
       
    26             def __init__(self, *args, **kwargs):
       
    27                 pass
       
    28         TextProperty = DummyProperty
       
    29         StringProperty = DummyProperty
       
    30         BlobProperty = DummyProperty
       
    31         DateProperty = DummyProperty
       
    32         ReferenceProperty = DummyProperty
       
    33         SelfReferenceProperty = DummyProperty
       
    34     import_appengine_failed = 'cannot import appengine: %s' % exc
       
    35     
       
    36 
       
    37 from cubicweb import CW_SOFTWARE_ROOT
       
    38 from cubicweb.server.utils import crypt_password
       
    39 from cubicweb.devtools.fake import FakeRequest
       
    40 from cubicweb.goa.goavreg import GAERegistry
       
    41 from cubicweb.goa.goaconfig import GAEConfiguration
       
    42 from cubicweb.goa.dbinit import (create_user, create_groups, fix_entities,
       
    43                               init_persistent_schema, insert_versions)
       
    44 
       
    45 import logging
       
    46 logger = logging.getLogger()
       
    47 logger.setLevel(logging.CRITICAL)
       
    48 
       
    49 do_monkey_patch()
       
    50 
       
    51 class GAEBasedTC(TestCase):
       
    52     APP_ID = u'test_app'
       
    53     AUTH_DOMAIN = 'gmail.com'
       
    54     LOGGED_IN_USER = u't...@example.com'  # set to '' for no logged in user
       
    55     MODEL_CLASSES = None
       
    56     LOAD_APP_MODULES = None
       
    57     config = None
       
    58     _DS_TEMPL_FILE = 'tmpdb-template'
       
    59 
       
    60     def load_schema_hook(self, loader):
       
    61         loader.import_yams_template_schema('data')
       
    62     
       
    63     @property
       
    64     def DS_FILE(self):
       
    65         return self.DS_TEMPL_FILE.replace('-template', '')
       
    66     
       
    67     @property
       
    68     def DS_TEMPL_FILE(self):
       
    69         return self._DS_TEMPL_FILE + '_'.join(sorted(cls.__name__ for cls in self.MODEL_CLASSES))
       
    70 
       
    71     def _set_ds_file(self, dsfile):
       
    72         # Start with a fresh api proxy.
       
    73         apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap()
       
    74         # Use a fresh stub datastore.
       
    75         stub = datastore_file_stub.DatastoreFileStub(self.APP_ID, dsfile,
       
    76                                                      dsfile+'.history')
       
    77         apiproxy_stub_map.apiproxy.RegisterStub('datastore_v3', stub)
       
    78         
       
    79     def setUp(self):
       
    80         if import_appengine_failed:
       
    81             self.skip(import_appengine_failed)
       
    82         # Ensure we're in UTC.
       
    83         os.environ['TZ'] = 'UTC'
       
    84         time.tzset()
       
    85         if osp.exists(self.DS_TEMPL_FILE):
       
    86             copy(self.DS_TEMPL_FILE, self.DS_FILE)
       
    87             need_ds_init = False
       
    88             self._set_ds_file(self.DS_FILE)
       
    89         else:
       
    90             need_ds_init = True
       
    91             self._set_ds_file(self.DS_TEMPL_FILE)
       
    92 #         from google.appengine.api import mail_stub
       
    93 #         from google3.apphosting.api import urlfetch_stub
       
    94 #         from google3.apphosting.api import user_service_stub        
       
    95 #         # Use a fresh stub UserService.
       
    96 #         apiproxy_stub_map.apiproxy.RegisterStub(
       
    97 #             'user', user_service_stub.UserServiceStub())
       
    98         os.environ['AUTH_DOMAIN'] = self.AUTH_DOMAIN
       
    99         os.environ['USER_EMAIL'] = self.LOGGED_IN_USER
       
   100 #         # Use a fresh urlfetch stub.
       
   101 #         apiproxy_stub_map.apiproxy.RegisterStub(
       
   102 #             'urlfetch', urlfetch_stub.URLFetchServiceStub())
       
   103 #         # Use a fresh mail stub.
       
   104 #         apiproxy_stub_map.apiproxy.RegisterStub(
       
   105 #             'mail', mail_stub.MailServiceStub())
       
   106         if self.MODEL_CLASSES is None:
       
   107             raise Exception('GAEBasedTC should set MODEL_CLASSES class attribute')
       
   108         gdb._kind_map = {}
       
   109         self.config = self.config or GAEConfiguration('toto')
       
   110         self.config.init_log(logging.CRITICAL)
       
   111         self.schema = self.config.load_schema(self.MODEL_CLASSES,
       
   112                                               self.load_schema_hook)
       
   113         self.vreg = GAERegistry(self.config)
       
   114         self.vreg.schema = self.schema
       
   115         self.vreg.load_module(db)
       
   116         from cubicweb.goa.appobjects import sessions
       
   117         self.vreg.load_module(sessions)
       
   118         from cubicweb.entities import authobjs, schemaobjs
       
   119         self.vreg.load_module(authobjs)
       
   120         self.vreg.load_module(schemaobjs)
       
   121         if self.config['use-google-auth']:
       
   122             from cubicweb.goa.appobjects import gauthservice
       
   123             self.vreg.load_module(gauthservice)
       
   124         if self.LOAD_APP_MODULES is not None:
       
   125             for module in self.LOAD_APP_MODULES:
       
   126                 self.vreg.load_module(module)
       
   127         for cls in self.MODEL_CLASSES:
       
   128             self.vreg.load_object(cls)
       
   129         self.session_manager = self.vreg.select_component('sessionmanager')
       
   130         if need_ds_init:
       
   131             # create default groups and create entities according to the schema
       
   132             create_groups()
       
   133             if not self.config['use-google-auth']:
       
   134                 create_user(self.LOGGED_IN_USER, 'toto', ('users', 'managers'))
       
   135                 self.session = self.login(self.LOGGED_IN_USER, 'toto')
       
   136             else:
       
   137                 req = FakeRequest(vreg=self.vreg)
       
   138                 self.session = self.session_manager.open_session(req)
       
   139             self.user = self.session.user()
       
   140             ssession = self.config.repo_session(self.session.sessionid)
       
   141             ssession.set_pool()
       
   142             init_persistent_schema(ssession, self.schema)
       
   143             insert_versions(ssession, self.config)
       
   144             ssession.commit()
       
   145             fix_entities(self.schema)
       
   146             copy(self.DS_TEMPL_FILE, self.DS_FILE)
       
   147             self._set_ds_file(self.DS_FILE)
       
   148         else:
       
   149             if not self.config['use-google-auth']:
       
   150                 self.session = self.login(self.LOGGED_IN_USER, 'toto')
       
   151             else:
       
   152                 req = FakeRequest(vreg=self.vreg)
       
   153                 self.session = self.session_manager.open_session(req)
       
   154             self.user = self.session.user()
       
   155             
       
   156     def tearDown(self):
       
   157         self.session.close()
       
   158         
       
   159     def request(self):
       
   160         req = FakeRequest(vreg=self.vreg)
       
   161         req.set_connection(self.session, self.user)
       
   162         return req
       
   163     
       
   164     def add_entity(self, etype, **kwargs):
       
   165         cu = self.session.cursor()
       
   166         rql = 'INSERT %s X' % etype
       
   167         if kwargs:
       
   168             rql += ': %s' % ', '.join('X %s %%(%s)s' % (key, key) for key in kwargs)
       
   169         rset = cu.execute(rql, kwargs)
       
   170         return rset.get_entity(0, 0)
       
   171 
       
   172     def execute(self, *args):
       
   173         return self.session.cursor().execute(*args)
       
   174 
       
   175     def commit(self):
       
   176         self.session.commit()
       
   177 
       
   178     def rollback(self):
       
   179         self.session.rollback()
       
   180         
       
   181     def create_user(self, login, groups=('users',), req=None):
       
   182         assert not self.config['use-google-auth']
       
   183         user = self.add_entity('EUser', upassword=str(login), login=unicode(login))
       
   184         cu = self.session.cursor()
       
   185         cu.execute('SET X in_group G WHERE X eid %%(x)s, G name IN(%s)'
       
   186                     % ','.join(repr(g) for g in groups),
       
   187                     {'x': user.eid}, 'x')
       
   188         return user
       
   189 
       
   190     def login(self, login, password=None):
       
   191         assert not self.config['use-google-auth']
       
   192         req = FakeRequest(vreg=self.vreg)
       
   193         req.form['__login'] = login
       
   194         req.form['__password'] = password or login
       
   195         return self.session_manager.open_session(req)
       
   196