[Osaas-commits] r18 - in trunk: . server/osaas server/test

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Tue Aug 28 19:32:58 CEST 2007


Author: bh
Date: 2007-08-28 19:32:58 +0200 (Tue, 28 Aug 2007)
New Revision: 18

Modified:
   trunk/ChangeLog
   trunk/server/osaas/dbbackend.py
   trunk/server/osaas/formparser.py
   trunk/server/osaas/run.py
   trunk/server/test/test_dbbackend.py
Log:
* server/osaas/run.py (OSAASServerProgram.instantiate_server):
Create a logger for the database backend

* server/osaas/formparser.py (parse_formdata): Add the raw
formdata as a field to the record so that it can be used by the
database backend when logging errors

* server/osaas/dbbackend.py (DBBackend.__init__): Added parameter
logger
(DBBackend.log_debug, DBBackend.log_error): Added.
(DBBackend.ensure_connection, DBBackend.handle_record): Produce
log message

* server/test/test_dbbackend.py (MockConnection.rollback): Added.
(MockLogger): New class to test logging in the db backend
(TestDBBackend.setUp): Create a logger
(TestDBBackend.method_called, TestDBBackend.check_method_called):
Provide a way for tests to simulate errors in database tests
(TestDBBackend.test_create_tables)
(TestDBBackend.test_handle_record): Pass the mock logger to the
database backend and test the logs
(TestDBBackend.test_handle_record_error)
(TestDBBackend.test_create_tables_error): New.  Test error
handling


Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-08-28 14:33:18 UTC (rev 17)
+++ trunk/ChangeLog	2007-08-28 17:32:58 UTC (rev 18)
@@ -1,5 +1,32 @@
 2007-08-28  Bernhard Herzog  <bh at intevation.de>
 
+	* server/osaas/run.py (OSAASServerProgram.instantiate_server):
+	Create a logger for the database backend
+
+	* server/osaas/formparser.py (parse_formdata): Add the raw
+	formdata as a field to the record so that it can be used by the
+	database backend when logging errors
+
+	* server/osaas/dbbackend.py (DBBackend.__init__): Added parameter
+	logger
+	(DBBackend.log_debug, DBBackend.log_error): Added.
+	(DBBackend.ensure_connection, DBBackend.handle_record): Produce
+	log message
+
+	* server/test/test_dbbackend.py (MockConnection.rollback): Added.
+	(MockLogger): New class to test logging in the db backend
+	(TestDBBackend.setUp): Create a logger
+	(TestDBBackend.method_called, TestDBBackend.check_method_called):
+	Provide a way for tests to simulate errors in database tests
+	(TestDBBackend.test_create_tables)
+	(TestDBBackend.test_handle_record): Pass the mock logger to the
+	database backend and test the logs
+	(TestDBBackend.test_handle_record_error)
+	(TestDBBackend.test_create_tables_error): New.  Test error
+	handling
+
+2007-08-28  Bernhard Herzog  <bh at intevation.de>
+
 	* server/osaas/dbinit.py, server/osaas/server.py,
 	server/test/test_httpserver.py: Remove unused imports
 

Modified: trunk/server/osaas/dbbackend.py
===================================================================
--- trunk/server/osaas/dbbackend.py	2007-08-28 14:33:18 UTC (rev 17)
+++ trunk/server/osaas/dbbackend.py	2007-08-28 17:32:58 UTC (rev 18)
@@ -34,13 +34,23 @@
 
 class DBBackend(object):
 
-    def __init__(self, connection_parameters, rules):
+    def __init__(self, connection_parameters, rules, logger=None):
         self.connection = None
         self.connection_parameters = connection_parameters
         self.rules = rules
+        self.logger = logger
 
+    def log_debug(self, message, *args):
+        if self.logger is not None:
+            self.logger.debug(message, *args)
+
+    def log_error(self, message, *args):
+        if self.logger is not None:
+            self.logger.error(message, *args)
+
     def ensure_connection(self):
         if self.connection is None:
+            self.log_debug("Connecting to database")
             self.connection = self.connect(*self.connection_parameters)
 
     def connect(self, *args):
@@ -60,6 +70,7 @@
         try:
             cursor.execute(statement, values)
         except:
+            self.log_error("could not write record %s", record.raw_record)
             self.connection.rollback()
             raise
         else:

Modified: trunk/server/osaas/formparser.py
===================================================================
--- trunk/server/osaas/formparser.py	2007-08-28 14:33:18 UTC (rev 17)
+++ trunk/server/osaas/formparser.py	2007-08-28 17:32:58 UTC (rev 18)
@@ -87,4 +87,5 @@
     record.set_fields(form_fields, formdata)
     record.set_fields(request_fields, record.requeststring,
                       fieldname_normalizer=lambda s: s.upper())
+    record.raw_record = formdata
     return record

Modified: trunk/server/osaas/run.py
===================================================================
--- trunk/server/osaas/run.py	2007-08-28 14:33:18 UTC (rev 17)
+++ trunk/server/osaas/run.py	2007-08-28 17:32:58 UTC (rev 18)
@@ -5,6 +5,8 @@
 # This program is free software under the GPL (>=v2)
 # Read the file COPYING coming with the software for details.
 
+import logging
+
 from osaas.http.run import ServerProgram
 from osaas.server import OSAASServer
 from osaas.config import OSAASOption, read_config_file
@@ -38,7 +40,7 @@
 
     def instantiate_server(self, server_class, server_address, opts, **kw):
         dbbackend = DBBackend((opts.db_user, opts.db_password, opts.db_dsn),
-                              opts.db_rules)
+                              opts.db_rules, logging.getLogger("dbbackend"))
         return server_class(server_address, userdbfile=opts.userdb_file,
                             dbbackend=dbbackend, **kw)
 

Modified: trunk/server/test/test_dbbackend.py
===================================================================
--- trunk/server/test/test_dbbackend.py	2007-08-28 14:33:18 UTC (rev 17)
+++ trunk/server/test/test_dbbackend.py	2007-08-28 17:32:58 UTC (rev 18)
@@ -22,7 +22,10 @@
     def commit(self):
         self.testcase.method_called("Connection.commit")
 
+    def rollback(self):
+        self.testcase.method_called("Connection.rollback")
 
+
 class MockCursor(object):
 
     def __init__(self, testcase):
@@ -43,13 +46,25 @@
         self.testcase.assertEquals(args, self.connection_parameters)
         return MockConnection(self.testcase)
 
+class MockLogger(object):
 
+    def __init__(self):
+        self.log = []
+
+    def __getattr__(self, name):
+        def logmethod(*args):
+            self.log.append((name, args))
+        return logmethod
+
+
 class TestDBBackend(unittest.TestCase):
 
     def setUp(self):
         self.method_log = []
+        self.logger = MockLogger()
 
     def method_called(self, name, *args, **kw):
+        self.check_method_called(name, *args, **kw)
         entry = [name]
         if args:
             entry.append(args)
@@ -57,12 +72,17 @@
             entry.append(args)
         self.method_log.append(tuple(entry))
 
+    def check_method_called(self, name, *args, **kw):
+        """Called by method_called so that tests can simulate errors"""
+        pass
+
     def test_create_tables(self):
         backend = TestBackend(self,
                               ("someuser", "aPassword", "mydns"),
                               [Insertion("mytable",
                                          [DBField("REQUEST", "req",
-                                                  "character varying(11)")])])
+                                                  "character varying(11)")])],
+                              self.logger)
         backend.create_tables()
 
         self.assertEquals(self.method_log,
@@ -73,14 +93,36 @@
                                                "    req character varying(11)\n"
                                                ")",)),
                            ("Connection.commit",)])
+        self.assertEquals(self.logger.log,
+                          [('debug', ('Connecting to database',))])
 
+    def test_create_tables_error(self):
+        def check_method_called(name, *args, **kw):
+            if name == "Cursor.execute" and args[0].startswith("CREATE TABLE"):
+                raise RuntimeError("Simulated database error")
+        self.check_method_called = check_method_called
 
+        backend = TestBackend(self,
+                              ("someuser", "aPassword", "mynds"),
+                              [Insertion("mytable",
+                                         [DBField("REQUEST", "req",
+                                                  "character varying(11)")])])
+        try:
+            backend.create_tables()
+        except RuntimeError:
+            pass
+
+        self.assertEquals(self.method_log,
+                          [('Cursor.execute', ('CREATE SEQUENCE mytable_seq',)),
+                           ("Connection.rollback",)])
+
     def test_handle_record(self):
         backend = TestBackend(self,
                               ("someuser", "aPassword", "mydns"),
                               [Insertion("mytable",
                                          [DBField("REQUEST", "req",
-                                                  "character varying(11)")])])
+                                                  "character varying(11)")])],
+                              self.logger)
         record = Record()
         record.REQUEST = "SERVICE=WMS&REQUEST=GetMap"
         backend.handle_record(record)
@@ -91,4 +133,31 @@
                              " VALUES (mytable_seq.nextval, :req)",
                              {"req": "SERVICE=WMS&REQUEST=GetMap"})),
                            ("Connection.commit",)])
+        self.assertEquals(self.logger.log,
+                          [('debug', ('Connecting to database',))])
 
+    def test_handle_record_error(self):
+        def check_method_called(name, *args, **kw):
+            if name == "Cursor.execute" and args[0].startswith("INSERT"):
+                raise RuntimeError("Simulated database error")
+        self.check_method_called = check_method_called
+        backend = TestBackend(self,
+                              ("someuser", "aPassword", "mydns"),
+                              [Insertion("mytable",
+                                         [DBField("REQUEST", "req",
+                                                  "character varying(11)")])],
+                              self.logger)
+        record = Record()
+        record.REQUEST = "SERVICE=WMS&REQUEST=GetMap"
+        record.raw_record = "REQUEST=SERVICE=WMS%26REQUEST=GetMap"
+        try:
+            backend.handle_record(record)
+        except RuntimeError:
+            pass
+
+        self.assertEquals(self.method_log,
+                          [("Connection.rollback",)])
+        self.assertEquals(self.logger.log,
+                          [('debug', ('Connecting to database',)),
+                           ('error', ('could not write record %s',
+                                      'REQUEST=SERVICE=WMS%26REQUEST=GetMap'))])



More information about the Osaas-commits mailing list