13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
13 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
14 # details. |
14 # details. |
15 # |
15 # |
16 # You should have received a copy of the GNU Lesser General Public License along |
16 # You should have received a copy of the GNU Lesser General Public License along |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
17 # with CubicWeb. If not, see <http://www.gnu.org/licenses/>. |
18 from os.path import dirname, join, abspath |
18 |
19 from datetime import datetime, timedelta |
19 from datetime import datetime, timedelta |
20 |
|
21 from logilab.common.decorators import cached |
|
22 |
20 |
23 from cubicweb.devtools import TestServerConfiguration, init_test_database |
21 from cubicweb.devtools import TestServerConfiguration, init_test_database |
24 from cubicweb.devtools.testlib import CubicWebTC, refresh_repo |
22 from cubicweb.devtools.testlib import CubicWebTC, refresh_repo |
25 from cubicweb.devtools.repotest import do_monkey_patch, undo_monkey_patch |
23 from cubicweb.devtools.repotest import do_monkey_patch, undo_monkey_patch |
26 |
24 |
27 |
25 |
28 class TwoSourcesConfiguration(TestServerConfiguration): |
|
29 sourcefile = 'sources_multi' |
|
30 |
|
31 |
|
32 class ExternalSource1Configuration(TestServerConfiguration): |
26 class ExternalSource1Configuration(TestServerConfiguration): |
33 sourcefile = 'sources_extern' |
27 sourcefile = 'sources_extern' |
34 |
28 |
35 class ExternalSource2Configuration(TestServerConfiguration): |
29 class ExternalSource2Configuration(TestServerConfiguration): |
36 sourcefile = 'sources_multi2' |
30 sourcefile = 'sources_multi' |
37 |
31 |
38 MTIME = datetime.now() - timedelta(0, 10) |
32 MTIME = datetime.now() - timedelta(0, 10) |
39 repo2, cnx2 = init_test_database(config=ExternalSource1Configuration('data')) |
33 |
40 repo3, cnx3 = init_test_database(config=ExternalSource2Configuration('data')) |
34 EXTERN_SOURCE_CFG = u''' |
|
35 pyro-ns-id = extern |
|
36 cubicweb-user = admin |
|
37 cubicweb-password = gingkow |
|
38 mapping-file = extern_mapping.py |
|
39 base-url=http://extern.org/ |
|
40 ''' |
41 |
41 |
42 # hi-jacking |
42 # hi-jacking |
43 from cubicweb.server.sources.pyrorql import PyroRQLSource |
43 from cubicweb.server.sources.pyrorql import PyroRQLSource |
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 setup_module(*args): |
49 def setup_module(*args): |
|
50 global repo2, cnx2, repo3, cnx3 |
|
51 repo2, cnx2 = init_test_database(config=ExternalSource1Configuration('data')) |
|
52 repo3, cnx3 = init_test_database(config=ExternalSource2Configuration('data')) |
|
53 cnx3.request().create_entity('CWSource', name=u'extern', type=u'pyrorql', |
|
54 config=EXTERN_SOURCE_CFG) |
|
55 cnx3.commit() |
|
56 |
50 TestServerConfiguration.no_sqlite_wrap = True |
57 TestServerConfiguration.no_sqlite_wrap = True |
51 # hi-jack PyroRQLSource.get_connection to access existing connection (no |
58 # hi-jack PyroRQLSource.get_connection to access existing connection (no |
52 # pyro connection) |
59 # pyro connection) |
53 PyroRQLSource.get_connection = lambda x: x.uri == 'extern-multi' and cnx3 or cnx2 |
60 PyroRQLSource.get_connection = lambda x: x.uri == 'extern-multi' and cnx3 or cnx2 |
54 # also necessary since the repository is closing its initial connections |
61 # also necessary since the repository is closing its initial connections |
80 def setUp(self): |
86 def setUp(self): |
81 CubicWebTC.setUp(self) |
87 CubicWebTC.setUp(self) |
82 do_monkey_patch() |
88 do_monkey_patch() |
83 |
89 |
84 def tearDown(self): |
90 def tearDown(self): |
|
91 for source in self.repo.sources[1:]: |
|
92 self.repo.remove_source(source.uri) |
85 CubicWebTC.tearDown(self) |
93 CubicWebTC.tearDown(self) |
86 undo_monkey_patch() |
94 undo_monkey_patch() |
87 |
95 |
88 def setup_database(self): |
96 def setup_database(self): |
89 cu = cnx2.cursor() |
97 cu = cnx2.cursor() |
90 self.ec1 = cu.execute('INSERT Card X: X title "C3: An external card", X wikiid "aaa"')[0][0] |
98 self.ec1 = cu.execute('INSERT Card X: X title "C3: An external card", X wikiid "aaa"')[0][0] |
91 cu.execute('INSERT Card X: X title "C4: Ze external card", X wikiid "zzz"') |
99 cu.execute('INSERT Card X: X title "C4: Ze external card", X wikiid "zzz"') |
92 self.aff1 = cu.execute('INSERT Affaire X: X ref "AFFREF"')[0][0] |
100 self.aff1 = cu.execute('INSERT Affaire X: X ref "AFFREF"')[0][0] |
93 cnx2.commit() |
101 cnx2.commit() |
|
102 for uri, config in [('extern', EXTERN_SOURCE_CFG), |
|
103 ('extern-multi', ''' |
|
104 pyro-ns-id = extern-multi |
|
105 cubicweb-user = admin |
|
106 cubicweb-password = gingkow |
|
107 mapping-file = extern_mapping.py |
|
108 ''')]: |
|
109 self.request().create_entity('CWSource', name=unicode(uri), |
|
110 type=u'pyrorql', |
|
111 config=unicode(config)) |
|
112 self.commit() |
94 # trigger discovery |
113 # trigger discovery |
95 self.sexecute('Card X') |
114 self.sexecute('Card X') |
96 self.sexecute('Affaire X') |
115 self.sexecute('Affaire X') |
97 self.sexecute('State X') |
116 self.sexecute('State X') |
98 # add some entities |
117 # add some entities |
110 # 2 added to the system source, 2 added to the external source |
129 # 2 added to the system source, 2 added to the external source |
111 self.assertEqual(len(rset), 4) |
130 self.assertEqual(len(rset), 4) |
112 # since they are orderd by eid, we know the 3 first one is coming from the system source |
131 # since they are orderd by eid, we know the 3 first one is coming from the system source |
113 # and the others from external source |
132 # and the others from external source |
114 self.assertEqual(rset.get_entity(0, 0).cw_metainformation(), |
133 self.assertEqual(rset.get_entity(0, 0).cw_metainformation(), |
115 {'source': {'adapter': 'native', 'uri': 'system'}, |
134 {'source': {'type': 'native', 'uri': 'system'}, |
116 'type': u'Card', 'extid': None}) |
135 'type': u'Card', 'extid': None}) |
117 externent = rset.get_entity(3, 0) |
136 externent = rset.get_entity(3, 0) |
118 metainf = externent.cw_metainformation() |
137 metainf = externent.cw_metainformation() |
119 self.assertEqual(metainf['source'], {'adapter': 'pyrorql', 'base-url': 'http://extern.org/', 'uri': 'extern'}) |
138 self.assertEqual(metainf['source'], {'type': 'pyrorql', 'base-url': 'http://extern.org/', 'uri': 'extern'}) |
120 self.assertEqual(metainf['type'], 'Card') |
139 self.assertEqual(metainf['type'], 'Card') |
121 self.assert_(metainf['extid']) |
140 self.assert_(metainf['extid']) |
122 etype = self.sexecute('Any ETN WHERE X is ET, ET name ETN, X eid %(x)s', |
141 etype = self.sexecute('Any ETN WHERE X is ET, ET name ETN, X eid %(x)s', |
123 {'x': externent.eid})[0][0] |
142 {'x': externent.eid})[0][0] |
124 self.assertEqual(etype, 'Card') |
143 self.assertEqual(etype, 'Card') |
182 self.assertEqual(rset[0][1], "pitetre") |
201 self.assertEqual(rset[0][1], "pitetre") |
183 |
202 |
184 def test_simplifiable_var_2(self): |
203 def test_simplifiable_var_2(self): |
185 affeid = self.sexecute('Affaire X WHERE X ref "AFFREF"')[0][0] |
204 affeid = self.sexecute('Affaire X WHERE X ref "AFFREF"')[0][0] |
186 rset = self.sexecute('Any E WHERE E eid %(x)s, E in_state S, NOT S name "moved"', |
205 rset = self.sexecute('Any E WHERE E eid %(x)s, E in_state S, NOT S name "moved"', |
187 {'x': affeid, 'u': self.session.user.eid}) |
206 {'x': affeid, 'u': self.session.user.eid}) |
188 self.assertEqual(len(rset), 1) |
207 self.assertEqual(len(rset), 1) |
189 |
208 |
190 def test_sort_func(self): |
209 def test_sort_func(self): |
191 self.sexecute('Affaire X ORDERBY DUMB_SORT(RF) WHERE X ref RF') |
210 self.sexecute('Affaire X ORDERBY DUMB_SORT(RF) WHERE X ref RF') |
192 |
211 |
268 self.assertEqual(len(rset), 1) |
287 self.assertEqual(len(rset), 1) |
269 self.assertEqual(rset[0][1], "pitetre") |
288 self.assertEqual(rset[0][1], "pitetre") |
270 |
289 |
271 def test_not_relation(self): |
290 def test_not_relation(self): |
272 states = set(tuple(x) for x in self.sexecute('Any S,SN WHERE S is State, S name SN')) |
291 states = set(tuple(x) for x in self.sexecute('Any S,SN WHERE S is State, S name SN')) |
273 self.session.user.clear_all_caches() |
|
274 userstate = self.session.user.in_state[0] |
292 userstate = self.session.user.in_state[0] |
275 states.remove((userstate.eid, userstate.name)) |
293 states.remove((userstate.eid, userstate.name)) |
276 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', |
294 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', |
277 {'x': self.session.user.eid})) |
295 {'x': self.session.user.eid})) |
278 self.assertSetEqual(notstates, states) |
296 self.assertSetEqual(notstates, states) |