server/test/unittest_multisources.py
brancholdstable
changeset 7078 bad26a22fe29
parent 6781 5062d86d6ffe
child 7088 76e0dba5f8f3
equal deleted inserted replaced
7074:e4580e5f0703 7078:bad26a22fe29
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    18 
    18 
    19 from datetime import datetime, timedelta
    19 from datetime import datetime, timedelta
    20 
    20 
    21 from cubicweb.devtools import TestServerConfiguration, init_test_database
    21 from cubicweb.devtools import TestServerConfiguration, init_test_database
    22 from cubicweb.devtools.testlib import CubicWebTC, refresh_repo
    22 from cubicweb.devtools.testlib import CubicWebTC, Tags
    23 from cubicweb.devtools.repotest import do_monkey_patch, undo_monkey_patch
    23 from cubicweb.devtools.repotest import do_monkey_patch, undo_monkey_patch
    24 
    24 from cubicweb.devtools import get_test_db_handler
    25 
    25 
    26 class ExternalSource1Configuration(TestServerConfiguration):
    26 class ExternalSource1Configuration(TestServerConfiguration):
    27     sourcefile = 'sources_extern'
    27     sourcefile = 'sources_extern'
    28 
    28 
    29 class ExternalSource2Configuration(TestServerConfiguration):
    29 class ExternalSource2Configuration(TestServerConfiguration):
    44 from cubicweb.dbapi import Connection
    44 from cubicweb.dbapi import Connection
    45 
    45 
    46 PyroRQLSource_get_connection = PyroRQLSource.get_connection
    46 PyroRQLSource_get_connection = PyroRQLSource.get_connection
    47 Connection_close = Connection.close
    47 Connection_close = Connection.close
    48 
    48 
    49 def setUpModule(*args):
    49 def pre_setup_database_extern(session, config):
    50     global repo2, cnx2, repo3, cnx3
    50     session.execute('INSERT Card X: X title "C3: An external card", X wikiid "aaa"')
    51     cfg1 = ExternalSource1Configuration('data', apphome=TwoSourcesTC.datadir)
    51     session.execute('INSERT Card X: X title "C4: Ze external card", X wikiid "zzz"')
    52     repo2, cnx2 = init_test_database(config=cfg1)
    52     session.execute('INSERT Affaire X: X ref "AFFREF"')
    53     cfg2 = ExternalSource2Configuration('data', apphome=TwoSourcesTC.datadir)
    53     session.commit()
    54     repo3, cnx3 = init_test_database(config=cfg2)
    54 
    55     cnx3.request().create_entity('CWSource', name=u'extern', type=u'pyrorql',
    55 def pre_setup_database_multi(session, config):
       
    56     session.create_entity('CWSource', name=u'extern', type=u'pyrorql',
    56                                  config=EXTERN_SOURCE_CFG)
    57                                  config=EXTERN_SOURCE_CFG)
    57     cnx3.commit()
    58     session.commit()
    58 
       
    59     TestServerConfiguration.no_sqlite_wrap = True
       
    60     # hi-jack PyroRQLSource.get_connection to access existing connection (no
       
    61     # pyro connection)
       
    62     PyroRQLSource.get_connection = lambda x: x.uri == 'extern-multi' and cnx3 or cnx2
       
    63     # also necessary since the repository is closing its initial connections
       
    64     # pool though we want to keep cnx2 valid
       
    65     Connection.close = lambda x: None
       
    66 
       
    67 def tearDownModule(*args):
       
    68     PyroRQLSource.get_connection = PyroRQLSource_get_connection
       
    69     Connection.close = Connection_close
       
    70     global repo2, cnx2, repo3, cnx3
       
    71     repo2.shutdown()
       
    72     repo3.shutdown()
       
    73     del repo2, cnx2, repo3, cnx3
       
    74     #del TwoSourcesTC.config.vreg
       
    75     #del TwoSourcesTC.config
       
    76     TestServerConfiguration.no_sqlite_wrap = False
       
    77 
    59 
    78 class TwoSourcesTC(CubicWebTC):
    60 class TwoSourcesTC(CubicWebTC):
    79     """Main repo -> extern-multi -> extern
    61     """Main repo -> extern-multi -> extern
    80                   \-------------/
    62                   \-------------/
    81     """
    63     """
       
    64     test_db_id= 'cw-server-multisources'
       
    65     tags = CubicWebTC.tags | Tags(('multisources'))
       
    66 
    82     @classmethod
    67     @classmethod
    83     def _refresh_repo(cls):
    68     def setUpClass(cls):
    84         super(TwoSourcesTC, cls)._refresh_repo()
    69         cls._cfg2 = ExternalSource1Configuration('data', apphome=TwoSourcesTC.datadir)
    85         cnx2.rollback()
    70         cls._cfg3 = ExternalSource2Configuration('data', apphome=TwoSourcesTC.datadir)
    86         refresh_repo(repo2)
    71         TestServerConfiguration.no_sqlite_wrap = True
    87         cnx3.rollback()
    72         # hi-jack PyroRQLSource.get_connection to access existing connection (no
    88         refresh_repo(repo3)
    73         # pyro connection)
       
    74         PyroRQLSource.get_connection = lambda x: x.uri == 'extern-multi' and cls.cnx3 or cls.cnx2
       
    75         # also necessary since the repository is closing its initial connections
       
    76         # pool though we want to keep cnx2 valid
       
    77         Connection.close = lambda x: None
       
    78 
       
    79     @classmethod
       
    80     def tearDowncls(cls):
       
    81         PyroRQLSource.get_connection = PyroRQLSource_get_connection
       
    82         Connection.close = Connection_close
       
    83         cls.cnx2.close()
       
    84         cls.cnx3.close()
       
    85         TestServerConfiguration.no_sqlite_wrap = False
       
    86 
       
    87 
       
    88     @classmethod
       
    89     def _init_repo(cls):
       
    90         repo2_handler = get_test_db_handler(cls._cfg2)
       
    91         repo2_handler.build_db_cache('4cards-1affaire',pre_setup_func=pre_setup_database_extern)
       
    92         cls.repo2, cls.cnx2 = repo2_handler.get_repo_and_cnx('4cards-1affaire')
       
    93 
       
    94         repo3_handler = get_test_db_handler(cls._cfg3)
       
    95         repo3_handler.build_db_cache('multisource',pre_setup_func=pre_setup_database_multi)
       
    96         cls.repo3, cls.cnx3 = repo3_handler.get_repo_and_cnx('multisource')
       
    97 
       
    98 
       
    99         super(TwoSourcesTC, cls)._init_repo()
    89 
   100 
    90     def setUp(self):
   101     def setUp(self):
    91         CubicWebTC.setUp(self)
   102         CubicWebTC.setUp(self)
       
   103         self.addCleanup(self.cnx2.close)
       
   104         self.addCleanup(self.cnx3.close)
    92         do_monkey_patch()
   105         do_monkey_patch()
    93 
   106 
    94     def tearDown(self):
   107     def tearDown(self):
    95         for source in self.repo.sources[1:]:
   108         for source in self.repo.sources[1:]:
    96             self.repo.remove_source(source.uri)
   109             self.repo.remove_source(source.uri)
    97         CubicWebTC.tearDown(self)
   110         CubicWebTC.tearDown(self)
       
   111         self.cnx2.close()
       
   112         self.cnx3.close()
    98         undo_monkey_patch()
   113         undo_monkey_patch()
    99 
   114 
   100     def setup_database(self):
   115     @staticmethod
   101         cu = cnx2.cursor()
   116     def pre_setup_database(session, config):
   102         self.ec1 = cu.execute('INSERT Card X: X title "C3: An external card", X wikiid "aaa"')[0][0]
   117         for uri, src_config in [('extern', EXTERN_SOURCE_CFG),
   103         cu.execute('INSERT Card X: X title "C4: Ze external card", X wikiid "zzz"')
       
   104         self.aff1 = cu.execute('INSERT Affaire X: X ref "AFFREF"')[0][0]
       
   105         cnx2.commit()
       
   106         for uri, config in [('extern', EXTERN_SOURCE_CFG),
       
   107                             ('extern-multi', '''
   118                             ('extern-multi', '''
   108 pyro-ns-id = extern-multi
   119 pyro-ns-id = extern-multi
   109 cubicweb-user = admin
   120 cubicweb-user = admin
   110 cubicweb-password = gingkow
   121 cubicweb-password = gingkow
   111 mapping-file = extern_mapping.py
   122 mapping-file = extern_mapping.py
   112 ''')]:
   123 ''')]:
   113             self.request().create_entity('CWSource', name=unicode(uri),
   124             session.create_entity('CWSource', name=unicode(uri),
   114                                          type=u'pyrorql',
   125                                          type=u'pyrorql',
   115                                          config=unicode(config))
   126                                          config=unicode(src_config))
   116         self.commit()
   127         session.commit()
   117         # trigger discovery
   128         # trigger discovery
   118         self.sexecute('Card X')
   129         session.execute('Card X')
   119         self.sexecute('Affaire X')
   130         session.execute('Affaire X')
   120         self.sexecute('State X')
   131         session.execute('State X')
       
   132 
       
   133     def setup_database(self):
       
   134         cu2 = self.cnx2.cursor()
       
   135         self.ec1 = cu2.execute('Any X WHERE X is Card, X title "C3: An external card", X wikiid "aaa"')[0][0]
       
   136         self.aff1 = cu2.execute('Any X WHERE X is Affaire, X ref "AFFREF"')[0][0]
       
   137         cu2.close()
   121         # add some entities
   138         # add some entities
   122         self.ic1 = self.sexecute('INSERT Card X: X title "C1: An internal card", X wikiid "aaai"')[0][0]
   139         self.ic1 = self.sexecute('INSERT Card X: X title "C1: An internal card", X wikiid "aaai"')[0][0]
   123         self.ic2 = self.sexecute('INSERT Card X: X title "C2: Ze internal card", X wikiid "zzzi"')[0][0]
   140         self.ic2 = self.sexecute('INSERT Card X: X title "C2: Ze internal card", X wikiid "zzzi"')[0][0]
   124 
   141 
   125     def test_eid_comp(self):
   142     def test_eid_comp(self):
   175         rset = cu.execute('Any X ORDERBY FTIRANK(X) WHERE X has_text "card"')
   192         rset = cu.execute('Any X ORDERBY FTIRANK(X) WHERE X has_text "card"')
   176         self.assertEqual(len(rset), 5, zip(rset.rows, rset.description))
   193         self.assertEqual(len(rset), 5, zip(rset.rows, rset.description))
   177         Connection_close(cnx.cnx) # cnx is a TestCaseConnectionProxy
   194         Connection_close(cnx.cnx) # cnx is a TestCaseConnectionProxy
   178 
   195 
   179     def test_synchronization(self):
   196     def test_synchronization(self):
   180         cu = cnx2.cursor()
   197         cu = self.cnx2.cursor()
   181         assert cu.execute('Any X WHERE X eid %(x)s', {'x': self.aff1})
   198         assert cu.execute('Any X WHERE X eid %(x)s', {'x': self.aff1})
   182         cu.execute('SET X ref "BLAH" WHERE X eid %(x)s', {'x': self.aff1})
   199         cu.execute('SET X ref "BLAH" WHERE X eid %(x)s', {'x': self.aff1})
   183         aff2 = cu.execute('INSERT Affaire X: X ref "AFFREUX"')[0][0]
   200         aff2 = cu.execute('INSERT Affaire X: X ref "AFFREUX"')[0][0]
   184         cnx2.commit()
   201         self.cnx2.commit()
   185         try:
   202         try:
   186             # force sync
   203             # force sync
   187             self.repo.sources_by_uri['extern'].synchronize(MTIME)
   204             self.repo.sources_by_uri['extern'].synchronize(MTIME)
   188             self.failUnless(self.sexecute('Any X WHERE X has_text "blah"'))
   205             self.failUnless(self.sexecute('Any X WHERE X has_text "blah"'))
   189             self.failUnless(self.sexecute('Any X WHERE X has_text "affreux"'))
   206             self.failUnless(self.sexecute('Any X WHERE X has_text "affreux"'))
   190             cu.execute('DELETE Affaire X WHERE X eid %(x)s', {'x': aff2})
   207             cu.execute('DELETE Affaire X WHERE X eid %(x)s', {'x': aff2})
   191             cnx2.commit()
   208             self.cnx2.commit()
   192             self.repo.sources_by_uri['extern'].synchronize(MTIME)
   209             self.repo.sources_by_uri['extern'].synchronize(MTIME)
   193             rset = self.sexecute('Any X WHERE X has_text "affreux"')
   210             rset = self.sexecute('Any X WHERE X has_text "affreux"')
   194             self.failIf(rset)
   211             self.failIf(rset)
   195         finally:
   212         finally:
   196             # restore state
   213             # restore state
   197             cu.execute('SET X ref "AFFREF" WHERE X eid %(x)s', {'x': self.aff1})
   214             cu.execute('SET X ref "AFFREF" WHERE X eid %(x)s', {'x': self.aff1})
   198             cnx2.commit()
   215             self.cnx2.commit()
   199 
   216 
   200     def test_simplifiable_var(self):
   217     def test_simplifiable_var(self):
   201         affeid = self.sexecute('Affaire X WHERE X ref "AFFREF"')[0][0]
   218         affeid = self.sexecute('Affaire X WHERE X ref "AFFREF"')[0][0]
   202         rset = self.sexecute('Any X,AA,AB WHERE E eid %(x)s, E in_state X, X name AA, X modification_date AB',
   219         rset = self.sexecute('Any X,AA,AB WHERE E eid %(x)s, E in_state X, X name AA, X modification_date AB',
   203                             {'x': affeid})
   220                             {'x': affeid})
   223         self.assertEqual(sorted(r[0] for r in rset.rows), sorted([iec1, self.ic1]))
   240         self.assertEqual(sorted(r[0] for r in rset.rows), sorted([iec1, self.ic1]))
   224 
   241 
   225     def test_greater_eid(self):
   242     def test_greater_eid(self):
   226         rset = self.sexecute('Any X WHERE X eid > %s' % (self.ic1 - 1))
   243         rset = self.sexecute('Any X WHERE X eid > %s' % (self.ic1 - 1))
   227         self.assertEqual(len(rset.rows), 2) # self.ic1 and self.ic2
   244         self.assertEqual(len(rset.rows), 2) # self.ic1 and self.ic2
   228         cu = cnx2.cursor()
   245         cu = self.cnx2.cursor()
   229         ec2 = cu.execute('INSERT Card X: X title "glup"')[0][0]
   246         ec2 = cu.execute('INSERT Card X: X title "glup"')[0][0]
   230         cnx2.commit()
   247         self.cnx2.commit()
   231         # 'X eid > something' should not trigger discovery
   248         # 'X eid > something' should not trigger discovery
   232         rset = self.sexecute('Any X WHERE X eid > %s' % (self.ic1 - 1))
   249         rset = self.sexecute('Any X WHERE X eid > %s' % (self.ic1 - 1))
   233         self.assertEqual(len(rset.rows), 2)
   250         self.assertEqual(len(rset.rows), 2)
   234         # trigger discovery using another query
   251         # trigger discovery using another query
   235         crset = self.sexecute('Card X WHERE X title "glup"')
   252         crset = self.sexecute('Card X WHERE X title "glup"')
   245         n2 = self.sexecute('INSERT Note X: X type "AFFREU"')[0][0]
   262         n2 = self.sexecute('INSERT Note X: X type "AFFREU"')[0][0]
   246         rset = self.sexecute('Any X,Y WHERE X is Note, Y is Affaire, X type T, Y ref T')
   263         rset = self.sexecute('Any X,Y WHERE X is Note, Y is Affaire, X type T, Y ref T')
   247         self.assertEqual(len(rset), 1, rset.rows)
   264         self.assertEqual(len(rset), 1, rset.rows)
   248 
   265 
   249     def test_attr_unification_2(self):
   266     def test_attr_unification_2(self):
   250         cu = cnx2.cursor()
   267         cu = self.cnx2.cursor()
   251         ec2 = cu.execute('INSERT Card X: X title "AFFREF"')[0][0]
   268         ec2 = cu.execute('INSERT Card X: X title "AFFREF"')[0][0]
   252         cnx2.commit()
   269         self.cnx2.commit()
   253         try:
   270         try:
   254             c1 = self.sexecute('INSERT Card C: C title "AFFREF"')[0][0]
   271             c1 = self.sexecute('INSERT Card C: C title "AFFREF"')[0][0]
   255             rset = self.sexecute('Any X,Y WHERE X is Card, Y is Affaire, X title T, Y ref T')
   272             rset = self.sexecute('Any X,Y WHERE X is Card, Y is Affaire, X title T, Y ref T')
   256             self.assertEqual(len(rset), 2, rset.rows)
   273             self.assertEqual(len(rset), 2, rset.rows)
   257         finally:
   274         finally:
   258             cu.execute('DELETE Card X WHERE X eid %(x)s', {'x': ec2})
   275             cu.execute('DELETE Card X WHERE X eid %(x)s', {'x': ec2})
   259             cnx2.commit()
   276             self.cnx2.commit()
   260 
   277 
   261     def test_attr_unification_neq_1(self):
   278     def test_attr_unification_neq_1(self):
   262         # XXX complete
   279         # XXX complete
   263         self.sexecute('Any X,Y WHERE X is Note, Y is Affaire, X creation_date D, Y creation_date > D')
   280         self.sexecute('Any X,Y WHERE X is Note, Y is Affaire, X creation_date D, Y creation_date > D')
   264 
   281 
   306         notstates = set(tuple(x) for x in self.sexecute('Any S,SN WHERE S is State, S name SN, NOT X in_state S, X eid %(x)s',
   323         notstates = set(tuple(x) for x in self.sexecute('Any S,SN WHERE S is State, S name SN, NOT X in_state S, X eid %(x)s',
   307                                                        {'x': aff1}))
   324                                                        {'x': aff1}))
   308         self.assertSetEqual(notstates, states)
   325         self.assertSetEqual(notstates, states)
   309 
   326 
   310     def test_absolute_url_base_url(self):
   327     def test_absolute_url_base_url(self):
   311         cu = cnx2.cursor()
   328         cu = self.cnx2.cursor()
   312         ceid = cu.execute('INSERT Card X: X title "without wikiid to get eid based url"')[0][0]
   329         ceid = cu.execute('INSERT Card X: X title "without wikiid to get eid based url"')[0][0]
   313         cnx2.commit()
   330         self.cnx2.commit()
   314         lc = self.sexecute('Card X WHERE X title "without wikiid to get eid based url"').get_entity(0, 0)
   331         lc = self.sexecute('Card X WHERE X title "without wikiid to get eid based url"').get_entity(0, 0)
   315         self.assertEqual(lc.absolute_url(), 'http://extern.org/card/eid/%s' % ceid)
   332         self.assertEqual(lc.absolute_url(), 'http://extern.org/card/eid/%s' % ceid)
   316         cu.execute('DELETE Card X WHERE X eid %(x)s', {'x':ceid})
   333         cu.execute('DELETE Card X WHERE X eid %(x)s', {'x':ceid})
   317         cnx2.commit()
   334         self.cnx2.commit()
   318 
   335 
   319     def test_absolute_url_no_base_url(self):
   336     def test_absolute_url_no_base_url(self):
   320         cu = cnx3.cursor()
   337         cu = self.cnx3.cursor()
   321         ceid = cu.execute('INSERT Card X: X title "without wikiid to get eid based url"')[0][0]
   338         ceid = cu.execute('INSERT Card X: X title "without wikiid to get eid based url"')[0][0]
   322         cnx3.commit()
   339         self.cnx3.commit()
   323         lc = self.sexecute('Card X WHERE X title "without wikiid to get eid based url"').get_entity(0, 0)
   340         lc = self.sexecute('Card X WHERE X title "without wikiid to get eid based url"').get_entity(0, 0)
   324         self.assertEqual(lc.absolute_url(), 'http://testing.fr/cubicweb/card/eid/%s' % lc.eid)
   341         self.assertEqual(lc.absolute_url(), 'http://testing.fr/cubicweb/card/eid/%s' % lc.eid)
   325         cu.execute('DELETE Card X WHERE X eid %(x)s', {'x':ceid})
   342         cu.execute('DELETE Card X WHERE X eid %(x)s', {'x':ceid})
   326         cnx3.commit()
   343         self.cnx3.commit()
   327 
   344 
   328     def test_crossed_relation_noeid_needattr(self):
   345     def test_crossed_relation_noeid_needattr(self):
   329         """http://www.cubicweb.org/ticket/1382452"""
   346         """http://www.cubicweb.org/ticket/1382452"""
   330         aff1 = self.sexecute('INSERT Affaire X: X ref "AFFREF"')[0][0]
   347         aff1 = self.sexecute('INSERT Affaire X: X ref "AFFREF"')[0][0]
   331         # link within extern source
   348         # link within extern source