Changeset: 7ccdc2865d62 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=7ccdc2865d62
Modified Files:
        testing/sqltest.py
Branch: mtest
Log Message:

run test cases wit mclient as well


diffs (truncated from 387 to 300 lines):

diff --git a/testing/sqltest.py b/testing/sqltest.py
--- a/testing/sqltest.py
+++ b/testing/sqltest.py
@@ -7,8 +7,9 @@ import os
 import sys
 import unittest
 import pymonetdb
-import MonetDBtesting.utils as utils
 import difflib
+from abc import ABCMeta, abstractmethod
+import MonetDBtesting.process as process
 
 TSTDB=os.getenv("TSTDB")
 MAPIPORT=os.getenv("MAPIPORT")
@@ -64,7 +65,7 @@ def filter_matching_blocks(a: [str] = []
         s.set_seq1(a[i].replace('\t', '').replace(' ', ''))
         s.set_seq2(b[i].replace('\t', '').replace(' ', ''))
         # should be high matching ratio
-        if s.real_quick_ratio() < 0.95:
+        if s.quick_ratio() < 0.95:
             red_a.append(a[i])
             red_b.append(b[i])
             # keep track of last mismatch to add some ctx in between
@@ -121,36 +122,30 @@ class PyMonetDBConnectionContext(object)
             self.dbh.close()
             self.dbh = None
 
-class SQLTestResult(object):
-    """Holder of sql execution information. Managed by SQLTestCase."""
+class RunnableTestResult(metaclass=ABCMeta):
+    """Abstract class for sql result"""
+
+    @abstractmethod
+    def run(self, query:str, *args, stdin=None):
+        """Run query with specific client"""
+        pass
+
+class TestCaseResult(object):
+    """TestCase connected result"""
     test_case = None
 
     def __init__(self, test_case):
         self.test_case = test_case
+        self.assertion_errors = [] # holds assertion errors
         self.query = None
-        self.assertion_errors = [] # holds assertion errors
         self.query_error = None
+        self.err_code = None
+        self.err_message = None
         self.data = []
         self.rows = []
         self.rowcount = -1
         self.description = None
 
-    def run(self, query:str):
-        # ensure runs only once
-        if self.query is None:
-            self.query = query
-            try:
-                with self.test_case.conn_ctx as ctx:
-                    ctx.crs.execute(query)
-                    self.rowcount = ctx.crs.rowcount
-                    self.rows = ctx.crs._rows
-                    if ctx.crs.description:
-                        self.data = ctx.crs.fetchall()
-                        self.description = ctx.crs.description
-            except (pymonetdb.Error, ValueError) as e:
-                self.query_error = e
-        return self
-
     def fail(self, msg, data=None):
         """ logs errors to test case err file"""
         err_file = self.test_case.err_file
@@ -181,18 +176,17 @@ class SQLTestResult(object):
             msg = "expected to fail but didn't"
             self.fail(msg)
         else:
-            err_code_received, err_msg_received = 
utils.parse_mapi_err_msg(self.query_error.args[0])
             if err_code and err_message:
-                if err_code != err_code_received or err_message.lower() != 
err_msg_received.lower():
-                    msg = "expected to fail with error code {} and error 
message {} but failed with error code {} and error message {}".format(err_code, 
err_message, err_code_received, err_msg_received)
+                if err_code != self.err_code or err_message.lower() != 
self.err_message.lower():
+                    msg = "expected to fail with error code {} and error 
message {} but failed with error code {} and error message {}".format(err_code, 
err_message, self.err_code, self.err_message)
                     self.fail(msg)
             elif err_code and not err_message:
-                if err_code_received != err_code:
-                    msg = "expected to fail with error code {} but failed with 
error code {}".format(err_code, err_code_received)
+                if self.err_code != err_code:
+                    msg = "expected to fail with error code {} but failed with 
error code {}".format(err_code, self.err_code)
                     self.fail(msg)
             elif err_message and not err_code:
-                if err_message.lower() != err_msg_received.lower():
-                    msg = "expected to fail with error message {} but failed 
with error message {}".format(err_message, err_msg_received)
+                if err_message.lower() != self.err_message.lower():
+                    msg = "expected to fail with error message {} but failed 
with error message {}".format(err_message, self.err_message)
                     self.fail(msg)
         return self
 
@@ -212,6 +206,127 @@ class SQLTestResult(object):
     def assertResultHashTo(self, hash_value):
         raise NotImplementedError()
 
+class MclientTestResult(RunnableTestResult, TestCaseResult):
+    """Holder of a sql execution result as returned from mclinet"""
+
+    def __init__(self, test_case):
+        super().__init__(test_case)
+        self.did_run = False
+
+    def _parse_error(self, err:str):
+        err_code = None
+        err_message = None
+        for l in err.splitlines():
+            l = l.strip()
+            if l.startswith('ERROR'):
+                err_message = l.split('=').pop().strip()
+            if l.startswith('CODE'):
+                err_code = l.split('=').pop().strip()
+        return err_code, err_message
+
+    def _get_row_count(self, data):
+        count = 0
+        data = list(filter(filter_junk, data.splitlines()))
+        for l in data:
+            l = l.strip()
+            if l.startswith('[') and l.endswith(']'):
+                count+=1
+        return count
+
+
+    def run(self, query:str, *args, stdin=None):
+        # ensure runs only once
+        if self.did_run is False:
+            conn_ctx = self.test_case.conn_ctx
+            kwargs = dict(
+                host = conn_ctx.hostname,
+                port = conn_ctx.port,
+                dbname = conn_ctx.database,
+                user = conn_ctx.username,
+                passwd = conn_ctx.password)
+            try:
+                if query:
+                    self.query = query
+                    with process.client('sql', **kwargs, \
+                            args=list(args), \
+                            stdin=process.PIPE, \
+                            stdout=process.PIPE, stderr=process.PIPE) as p:
+                        out, err = p.communicate(query)
+                        if out:
+                            self.data = out
+                            self.rowcount = self._get_row_count(out)
+                        if err:
+                            self.query_error = err
+                            self.err_code, self.err_message = 
self._parse_error(err)
+                elif stdin:
+                    # TODO
+                    pass
+                self.did_run = True
+            except Exception as e:
+                raise SystemExit(e)
+        return self
+
+    def assertMatchStableOut(self, fout):
+        stable = []
+        data = list(filter(filter_junk, self.data.split('\n')))
+        with open(fout, 'r') as f:
+            stable = list(filter(filter_junk, f.read().split('\n')))
+        a, b = filter_matching_blocks(stable, data)
+        diff = list(difflib.unified_diff(a, b, fromfile='stable', 
tofile='test'))
+        if len(diff) > 0:
+            err_file = self.test_case.err_file
+            msg = "sql query result expected to match stable output {} but it 
didnt\'t\n".format(fout)
+            msg+='\n'.join(diff)
+            self.assertion_errors.append(AssertionError(msg))
+            self.fail(msg)
+        return self
+
+
+class PyMonetDBTestResult(RunnableTestResult, TestCaseResult):
+    """Holder of sql execution information. Managed by SQLTestCase."""
+    test_case = None
+
+    def __init__(self, test_case):
+        super().__init__(test_case)
+        self.did_run = False
+
+    def _parse_error(self, error:str=''):
+        """Parse error string and returns (err_code, err_msg) tuple
+        """
+        err_code = None
+        err_msg = None
+        tmp = error.split('!')
+        if len(tmp) > 1:
+            try:
+                err_code = tmp[0].strip()
+            except (ValueError, TypeError):
+                pass
+            # reconstruct
+            err_msg = ('!'.join(tmp[1:])).strip()
+        elif len(tmp) == 1:
+            if tmp[0]:
+                err_msg = tmp[0].strip()
+        return err_code, err_msg
+
+    def run(self, query:str, *args, stdin=None):
+        # ensure runs only once
+        if self.did_run is False:
+            if query:
+                self.query = query
+                try:
+                    with self.test_case.conn_ctx as ctx:
+                        ctx.crs.execute(query)
+                        self.rowcount = ctx.crs.rowcount
+                        self.rows = ctx.crs._rows
+                        if ctx.crs.description:
+                            self.data = ctx.crs.fetchall()
+                            self.description = ctx.crs.description
+                except (pymonetdb.Error, ValueError) as e:
+                    self.query_error = e
+                    self.err_code, self.err_message = 
self._parse_error(e.args[0])
+            self.did_run = True
+        return self
+
     def assertValue(self, row, col, val):
         """assert on a value matched against row, col in the result"""
         received = None
@@ -320,9 +435,12 @@ class SQLTestCase():
     def conn_ctx(self):
         return self._conn_ctx or self.default_conn_ctx()
 
-    def execute(self, query:str):
-        res = SQLTestResult(self)
-        res.run(query)
+    def execute(self, query:str, client='pymonetdb', *args):
+        if client == 'mclient':
+            res = MclientTestResult(self)
+        else:
+            res = PyMonetDBTestResult(self)
+        res.run(query, *args)
         self.test_results.append(res)
         return res
 
@@ -338,7 +456,6 @@ class SQLTestCase():
             passwd = self.conn_ctx.password)
         dump = None
         try:
-            import MonetDBtesting.process as process
             with process.client('sqldump', **kwargs, args=list(args), 
stdout=process.PIPE, stderr=process.PIPE) as p:
                 dump, err = p.communicate()
         except Exception as e:
@@ -347,3 +464,136 @@ class SQLTestCase():
         self.test_results.append(res)
         return res
 
+
+#-----------------------
+
+#class PyMonetDBTestResult(SQLTestResult):
+#    """Holder of sql execution information. Managed by SQLTestCase."""
+#    test_case = None
+#
+#    def __init__(self, test_case):
+#        self.test_case = test_case
+#        self.query = None
+#        self.assertion_errors = [] # holds assertion errors
+#        self.query_error = None
+#        self.data = []
+#        self.rows = []
+#        self.rowcount = -1
+#        self.description = None
+#
+#    def run(self, query:str):
+#        # ensure runs only once
+#        if self.query is None:
+#            self.query = query
+#            try:
+#                with self.test_case.conn_ctx as ctx:
+#                    ctx.crs.execute(query)
+#                    self.rowcount = ctx.crs.rowcount
+#                    self.rows = ctx.crs._rows
+#                    if ctx.crs.description:
+#                        self.data = ctx.crs.fetchall()
+#                        self.description = ctx.crs.description
+#            except (pymonetdb.Error, ValueError) as e:
+#                self.query_error = e
+#        return self
+#
+#    def fail(self, msg, data=None):
+#        """ logs errors to test case err file"""
+#        err_file = self.test_case.err_file
+#        if len(self.assertion_errors) == 0:
+#            print(self.query, file=err_file)
+#            print('----', file=err_file)
+#        self.assertion_errors.append(AssertionError(msg))
+#        print(msg, file=err_file)
+#        if data is not None:
+#            if len(data) < 100:
+#                print('query result:', file=err_file)
+#            else:
+#                print('truncated query result:', file=err_file)
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to