[rql2sql/test] Move base class from repotest to unittest_rql2sql
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 15 Sep 2017 16:25:51 +0200
changeset 12235 03b94c9863de
parent 12234 14fdd5888cbb
child 12236 75a6b2f40c44
[rql2sql/test] Move base class from repotest to unittest_rql2sql It's only used there, so move it closer to its usage. Along the way, stop using lgc.testlib.
cubicweb/devtools/repotest.py
cubicweb/server/test/unittest_rql2sql.py
--- a/cubicweb/devtools/repotest.py	Fri Sep 15 16:59:13 2017 +0200
+++ b/cubicweb/devtools/repotest.py	Fri Sep 15 16:25:51 2017 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -24,10 +24,14 @@
 from contextlib import contextmanager
 from pprint import pprint
 
-from logilab.common.testlib import SkipTest
 
-from cubicweb.devtools.testlib import RepoAccess
 from cubicweb.entities.authobjs import user_session_cache_key
+from cubicweb.server import set_debug, debugged
+from cubicweb.server.sources.rql2sql import remove_unused_solutions
+
+from .testlib import RepoAccess, BaseTestCase
+from .fake import FakeRequest
+
 
 def tuplify(mylist):
     return [tuple(item) for item in mylist]
@@ -129,67 +133,7 @@
             schema._eid_index[rdef.eid] = rdef
 
 
-from logilab.common.testlib import TestCase, mock_object
-from logilab.database import get_db_helper
-
-from rql import RQLHelper
-
-from cubicweb.devtools.testlib import BaseTestCase
-from cubicweb.devtools.fake import FakeRepo, FakeConfig, FakeRequest, FakeConnection
-from cubicweb.server import set_debug, debugged
-from cubicweb.server.querier import QuerierHelper
-from cubicweb.server.sources.rql2sql import SQLGenerator, remove_unused_solutions
-
-class RQLGeneratorTC(BaseTestCase):
-    schema = backend = None # set this in concrete class
-
-    @classmethod
-    def setUpClass(cls):
-        if cls.backend is not None:
-            try:
-                cls.dbhelper = get_db_helper(cls.backend)
-            except ImportError as ex:
-                raise SkipTest(str(ex))
-
-    def setUp(self):
-        self.repo = FakeRepo(self.schema, config=FakeConfig(apphome=self.datadir))
-        self.repo.system_source = mock_object(dbdriver=self.backend)
-        self.rqlhelper = RQLHelper(self.schema,
-                                   special_relations={'eid': 'uid',
-                                                      'has_text': 'fti'},
-                                   backend=self.backend)
-        self.qhelper = QuerierHelper(self.repo, self.schema)
-        ExecutionPlan._check_permissions = _dummy_check_permissions
-        rqlannotation._select_principal = _select_principal
-        if self.backend is not None:
-            self.o = SQLGenerator(self.schema, self.dbhelper)
-
-    def tearDown(self):
-        ExecutionPlan._check_permissions = _orig_check_permissions
-        rqlannotation._select_principal = _orig_select_principal
-
-    def set_debug(self, debug):
-        set_debug(debug)
-    def debugged(self, debug):
-        return debugged(debug)
-
-    def _prepare(self, rql):
-        #print '******************** prepare', rql
-        union = self.rqlhelper.parse(rql)
-        #print '********* parsed', union.as_string()
-        self.rqlhelper.compute_solutions(union)
-        #print '********* solutions', solutions
-        self.rqlhelper.simplify(union)
-        #print '********* simplified', union.as_string()
-        plan = self.qhelper.plan_factory(union, {}, FakeConnection(self.repo))
-        plan.preprocess(union)
-        for select in union.children:
-            select.solutions.sort(key=lambda x: list(x.items()))
-        #print '********* ppsolutions', solutions
-        return union
-
-
-class BaseQuerierTC(TestCase):
+class BaseQuerierTC(BaseTestCase):
     repo = None # set this in concrete class
 
     def setUp(self):
@@ -316,8 +260,6 @@
     res = DumbOrderedDict(sorted(res.items(), key=lambda x: [list(y.items()) for y in x[1]]))
     return res, restricted
 
-def _dummy_check_permissions(self, rqlst):
-    return {(): rqlst.solutions}, set()
 
 from cubicweb.server import rqlannotation
 _orig_select_principal = rqlannotation._select_principal
--- a/cubicweb/server/test/unittest_rql2sql.py	Fri Sep 15 16:59:13 2017 +0200
+++ b/cubicweb/server/test/unittest_rql2sql.py	Fri Sep 15 16:25:51 2017 +0200
@@ -1,4 +1,4 @@
-# copyright 2003-2016 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# copyright 2003 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
 #
 # This file is part of CubicWeb.
@@ -26,17 +26,24 @@
 from logilab.common.decorators import monkeypatch
 
 from rql import BadRQLQuery
+from rql import RQLHelper
 from rql.utils import register_function, FunctionDescr
 
 from cubicweb import devtools
-from cubicweb.devtools.repotest import RQLGeneratorTC
-from cubicweb.server.sources.rql2sql import SQLGenerator, remove_unused_solutions
+from cubicweb.devtools.fake import FakeRepo, FakeConfig, FakeConnection
+from cubicweb.devtools.testlib import BaseTestCase
+from cubicweb.server import rqlannotation
+from cubicweb.server.querier import QuerierHelper, ExecutionPlan
+from cubicweb.server.sources import rql2sql
+
+_orig_select_principal = rqlannotation._select_principal
+_orig_check_permissions = ExecutionPlan._check_permissions
 
 
 def setUpModule():
     """Monkey-patch the SQL generator to ensure solutions order is predictable."""
     global orig_solutions_sql
-    orig_solutions_sql = SQLGenerator._solutions_sql
+    orig_solutions_sql = rql2sql.SQLGenerator._solutions_sql
 
     @monkeypatch
     def _solutions_sql(self, select, solutions, distinct, needalias):
@@ -45,7 +52,7 @@
 
 def tearDownModule():
     """Remove monkey-patch done in setUpModule"""
-    SQLGenerator._solutions_sql = orig_solutions_sql
+    rql2sql.SQLGenerator._solutions_sql = orig_solutions_sql
 
 
 # add a dumb registered procedure
@@ -1226,8 +1233,67 @@
      '''SELECT rel_is0.eid_from
 FROM is_relation AS rel_is0
 WHERE rel_is0.eid_to=2'''),
+]
 
-    ]
+
+class RQLGeneratorTC(BaseTestCase):
+    schema = backend = None  # set this in concrete class
+
+    @classmethod
+    def setUpClass(cls):
+        if cls.backend is not None:
+            try:
+                cls.dbhelper = db.get_db_helper(cls.backend)
+            except ImportError as ex:
+                self.skipTest(str(ex))
+
+    def setUp(self):
+        self.repo = FakeRepo(self.schema, config=FakeConfig(apphome=self.datadir))
+        self.repo.system_source = mock_object(dbdriver=self.backend)
+        self.rqlhelper = RQLHelper(self.schema,
+                                   special_relations={'eid': 'uid',
+                                                      'has_text': 'fti'},
+                                   backend=self.backend)
+        self.qhelper = QuerierHelper(self.repo, self.schema)
+
+        def _dummy_check_permissions(self, rqlst):
+            return {(): rqlst.solutions}, set()
+
+        ExecutionPlan._check_permissions = _dummy_check_permissions
+
+        def _select_principal(scope, relations):
+            def sort_key(something):
+                try:
+                    return something.r_type
+                except AttributeError:
+                    return (something[0].r_type, something[1])
+            return _orig_select_principal(scope, relations,
+                                          _sort=lambda rels: sorted(rels, key=sort_key))
+
+        rqlannotation._select_principal = _select_principal
+        if self.backend is not None:
+            self.o = rql2sql.SQLGenerator(self.schema, self.dbhelper)
+
+    def tearDown(self):
+        ExecutionPlan._check_permissions = _orig_check_permissions
+        rqlannotation._select_principal = _orig_select_principal
+
+    def _prepare(self, rql):
+        #print '******************** prepare', rql
+        union = self.rqlhelper.parse(rql)
+        #print '********* parsed', union.as_string()
+        self.rqlhelper.compute_solutions(union)
+        #print '********* solutions', solutions
+        self.rqlhelper.simplify(union)
+        #print '********* simplified', union.as_string()
+        plan = self.qhelper.plan_factory(union, {}, FakeConnection(self.repo))
+        plan.preprocess(union)
+        for select in union.children:
+            select.solutions.sort(key=lambda x: list(x.items()))
+        #print '********* ppsolutions', solutions
+        return union
+
+
 class CWRQLTC(RQLGeneratorTC):
     backend = 'sqlite'
 
@@ -2273,21 +2339,23 @@
         rqlst = mock_object(defined_vars={})
         rqlst.defined_vars['A'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=True)
         rqlst.defined_vars['B'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=False)
-        self.assertEqual(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
-                                                          {'A': 'FootGroup', 'B': 'FootTeam'}], None),
-                          ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
-                            {'A': 'FootGroup', 'B': 'FootTeam'}],
-                           {}, set('B'))
-                          )
+        self.assertEqual(
+            rql2sql.remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
+                                                    {'A': 'FootGroup', 'B': 'FootTeam'}], None),
+            ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
+              {'A': 'FootGroup', 'B': 'FootTeam'}],
+             {}, set('B'))
+        )
 
     def test_invariant_varying(self):
         rqlst = mock_object(defined_vars={})
         rqlst.defined_vars['A'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=True)
         rqlst.defined_vars['B'] = mock_object(scope=rqlst, stinfo={}, _q_invariant=False)
-        self.assertEqual(remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
-                                                          {'A': 'FootGroup', 'B': 'RugbyTeam'}], None),
-                          ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'}], {}, set())
-                          )
+        self.assertEqual(
+            rql2sql.remove_unused_solutions(rqlst, [{'A': 'RugbyGroup', 'B': 'RugbyTeam'},
+                                                    {'A': 'FootGroup', 'B': 'RugbyTeam'}], None),
+            ([{'A': 'RugbyGroup', 'B': 'RugbyTeam'}], {}, set())
+        )
 
 
 if __name__ == '__main__':