python-2.5.2/win32/Lib/test/test_logging.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     1 #!/usr/bin/env python
       
     2 #
       
     3 # Copyright 2001-2004 by Vinay Sajip. All Rights Reserved.
       
     4 #
       
     5 # Permission to use, copy, modify, and distribute this software and its
       
     6 # documentation for any purpose and without fee is hereby granted,
       
     7 # provided that the above copyright notice appear in all copies and that
       
     8 # both that copyright notice and this permission notice appear in
       
     9 # supporting documentation, and that the name of Vinay Sajip
       
    10 # not be used in advertising or publicity pertaining to distribution
       
    11 # of the software without specific, written prior permission.
       
    12 # VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
       
    13 # ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
       
    14 # VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
       
    15 # ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
       
    16 # IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
       
    17 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
       
    18 #
       
    19 # This file is part of the Python logging distribution. See
       
    20 # http://www.red-dove.com/python_logging.html
       
    21 #
       
    22 """Test harness for the logging module. Run all tests.
       
    23 
       
    24 Copyright (C) 2001-2002 Vinay Sajip. All Rights Reserved.
       
    25 """
       
    26 
       
    27 import select
       
    28 import os, sys, string, struct, types, cPickle, cStringIO
       
    29 import socket, tempfile, threading, time
       
    30 import logging, logging.handlers, logging.config
       
    31 from test.test_support import run_with_locale
       
    32 
       
    33 BANNER = "-- %-10s %-6s ---------------------------------------------------\n"
       
    34 
       
    35 FINISH_UP = "Finish up, it's closing time. Messages should bear numbers 0 through 24."
       
    36 
       
    37 #----------------------------------------------------------------------------
       
    38 # Log receiver
       
    39 #----------------------------------------------------------------------------
       
    40 
       
    41 TIMEOUT         = 10
       
    42 
       
    43 from SocketServer import ThreadingTCPServer, StreamRequestHandler
       
    44 
       
    45 class LogRecordStreamHandler(StreamRequestHandler):
       
    46     """
       
    47     Handler for a streaming logging request. It basically logs the record
       
    48     using whatever logging policy is configured locally.
       
    49     """
       
    50 
       
    51     def handle(self):
       
    52         """
       
    53         Handle multiple requests - each expected to be a 4-byte length,
       
    54         followed by the LogRecord in pickle format. Logs the record
       
    55         according to whatever policy is configured locally.
       
    56         """
       
    57         while 1:
       
    58             try:
       
    59                 chunk = self.connection.recv(4)
       
    60                 if len(chunk) < 4:
       
    61                     break
       
    62                 slen = struct.unpack(">L", chunk)[0]
       
    63                 chunk = self.connection.recv(slen)
       
    64                 while len(chunk) < slen:
       
    65                     chunk = chunk + self.connection.recv(slen - len(chunk))
       
    66                 obj = self.unPickle(chunk)
       
    67                 record = logging.makeLogRecord(obj)
       
    68                 self.handleLogRecord(record)
       
    69             except:
       
    70                 raise
       
    71 
       
    72     def unPickle(self, data):
       
    73         return cPickle.loads(data)
       
    74 
       
    75     def handleLogRecord(self, record):
       
    76         logname = "logrecv.tcp." + record.name
       
    77         #If the end-of-messages sentinel is seen, tell the server to terminate
       
    78         if record.msg == FINISH_UP:
       
    79             self.server.abort = 1
       
    80         record.msg = record.msg + " (via " + logname + ")"
       
    81         logger = logging.getLogger(logname)
       
    82         logger.handle(record)
       
    83 
       
    84 # The server sets socketDataProcessed when it's done.
       
    85 socketDataProcessed = threading.Event()
       
    86 
       
    87 class LogRecordSocketReceiver(ThreadingTCPServer):
       
    88     """
       
    89     A simple-minded TCP socket-based logging receiver suitable for test
       
    90     purposes.
       
    91     """
       
    92 
       
    93     allow_reuse_address = 1
       
    94 
       
    95     def __init__(self, host='localhost',
       
    96                              port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
       
    97                      handler=LogRecordStreamHandler):
       
    98         ThreadingTCPServer.__init__(self, (host, port), handler)
       
    99         self.abort = 0
       
   100         self.timeout = 1
       
   101 
       
   102     def serve_until_stopped(self):
       
   103         while not self.abort:
       
   104             rd, wr, ex = select.select([self.socket.fileno()], [], [],
       
   105                                        self.timeout)
       
   106             if rd:
       
   107                 self.handle_request()
       
   108         #notify the main thread that we're about to exit
       
   109         socketDataProcessed.set()
       
   110         # close the listen socket
       
   111         self.server_close()
       
   112 
       
   113     def process_request(self, request, client_address):
       
   114         #import threading
       
   115         t = threading.Thread(target = self.finish_request,
       
   116                              args = (request, client_address))
       
   117         t.start()
       
   118 
       
   119 def runTCP(tcpserver):
       
   120     tcpserver.serve_until_stopped()
       
   121 
       
   122 #----------------------------------------------------------------------------
       
   123 # Test 0
       
   124 #----------------------------------------------------------------------------
       
   125 
       
   126 msgcount = 0
       
   127 
       
   128 def nextmessage():
       
   129     global msgcount
       
   130     rv = "Message %d" % msgcount
       
   131     msgcount = msgcount + 1
       
   132     return rv
       
   133 
       
   134 def test0():
       
   135     ERR = logging.getLogger("ERR")
       
   136     ERR.setLevel(logging.ERROR)
       
   137     INF = logging.getLogger("INF")
       
   138     INF.setLevel(logging.INFO)
       
   139     INF_ERR  = logging.getLogger("INF.ERR")
       
   140     INF_ERR.setLevel(logging.ERROR)
       
   141     DEB = logging.getLogger("DEB")
       
   142     DEB.setLevel(logging.DEBUG)
       
   143 
       
   144     INF_UNDEF = logging.getLogger("INF.UNDEF")
       
   145     INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF")
       
   146     UNDEF = logging.getLogger("UNDEF")
       
   147 
       
   148     GRANDCHILD = logging.getLogger("INF.BADPARENT.UNDEF")
       
   149     CHILD = logging.getLogger("INF.BADPARENT")
       
   150 
       
   151     #These should log
       
   152     ERR.log(logging.FATAL, nextmessage())
       
   153     ERR.error(nextmessage())
       
   154 
       
   155     INF.log(logging.FATAL, nextmessage())
       
   156     INF.error(nextmessage())
       
   157     INF.warn(nextmessage())
       
   158     INF.info(nextmessage())
       
   159 
       
   160     INF_UNDEF.log(logging.FATAL, nextmessage())
       
   161     INF_UNDEF.error(nextmessage())
       
   162     INF_UNDEF.warn (nextmessage())
       
   163     INF_UNDEF.info (nextmessage())
       
   164 
       
   165     INF_ERR.log(logging.FATAL, nextmessage())
       
   166     INF_ERR.error(nextmessage())
       
   167 
       
   168     INF_ERR_UNDEF.log(logging.FATAL, nextmessage())
       
   169     INF_ERR_UNDEF.error(nextmessage())
       
   170 
       
   171     DEB.log(logging.FATAL, nextmessage())
       
   172     DEB.error(nextmessage())
       
   173     DEB.warn (nextmessage())
       
   174     DEB.info (nextmessage())
       
   175     DEB.debug(nextmessage())
       
   176 
       
   177     UNDEF.log(logging.FATAL, nextmessage())
       
   178     UNDEF.error(nextmessage())
       
   179     UNDEF.warn (nextmessage())
       
   180     UNDEF.info (nextmessage())
       
   181 
       
   182     GRANDCHILD.log(logging.FATAL, nextmessage())
       
   183     CHILD.log(logging.FATAL, nextmessage())
       
   184 
       
   185     #These should not log
       
   186     ERR.warn(nextmessage())
       
   187     ERR.info(nextmessage())
       
   188     ERR.debug(nextmessage())
       
   189 
       
   190     INF.debug(nextmessage())
       
   191     INF_UNDEF.debug(nextmessage())
       
   192 
       
   193     INF_ERR.warn(nextmessage())
       
   194     INF_ERR.info(nextmessage())
       
   195     INF_ERR.debug(nextmessage())
       
   196     INF_ERR_UNDEF.warn(nextmessage())
       
   197     INF_ERR_UNDEF.info(nextmessage())
       
   198     INF_ERR_UNDEF.debug(nextmessage())
       
   199 
       
   200     INF.info(FINISH_UP)
       
   201 
       
   202 #----------------------------------------------------------------------------
       
   203 # Test 1
       
   204 #----------------------------------------------------------------------------
       
   205 
       
   206 #
       
   207 #   First, we define our levels. There can be as many as you want - the only
       
   208 #     limitations are that they should be integers, the lowest should be > 0 and
       
   209 #   larger values mean less information being logged. If you need specific
       
   210 #   level values which do not fit into these limitations, you can use a
       
   211 #   mapping dictionary to convert between your application levels and the
       
   212 #   logging system.
       
   213 #
       
   214 SILENT      = 10
       
   215 TACITURN    = 9
       
   216 TERSE       = 8
       
   217 EFFUSIVE    = 7
       
   218 SOCIABLE    = 6
       
   219 VERBOSE     = 5
       
   220 TALKATIVE   = 4
       
   221 GARRULOUS   = 3
       
   222 CHATTERBOX  = 2
       
   223 BORING      = 1
       
   224 
       
   225 LEVEL_RANGE = range(BORING, SILENT + 1)
       
   226 
       
   227 #
       
   228 #   Next, we define names for our levels. You don't need to do this - in which
       
   229 #   case the system will use "Level n" to denote the text for the level.
       
   230 #
       
   231 my_logging_levels = {
       
   232     SILENT      : 'Silent',
       
   233     TACITURN    : 'Taciturn',
       
   234     TERSE       : 'Terse',
       
   235     EFFUSIVE    : 'Effusive',
       
   236     SOCIABLE    : 'Sociable',
       
   237     VERBOSE     : 'Verbose',
       
   238     TALKATIVE   : 'Talkative',
       
   239     GARRULOUS   : 'Garrulous',
       
   240     CHATTERBOX  : 'Chatterbox',
       
   241     BORING      : 'Boring',
       
   242 }
       
   243 
       
   244 #
       
   245 #   Now, to demonstrate filtering: suppose for some perverse reason we only
       
   246 #   want to print out all except GARRULOUS messages. Let's create a filter for
       
   247 #   this purpose...
       
   248 #
       
   249 class SpecificLevelFilter(logging.Filter):
       
   250     def __init__(self, lvl):
       
   251         self.level = lvl
       
   252 
       
   253     def filter(self, record):
       
   254         return self.level != record.levelno
       
   255 
       
   256 class GarrulousFilter(SpecificLevelFilter):
       
   257     def __init__(self):
       
   258         SpecificLevelFilter.__init__(self, GARRULOUS)
       
   259 
       
   260 #
       
   261 #   Now, let's demonstrate filtering at the logger. This time, use a filter
       
   262 #   which excludes SOCIABLE and TACITURN messages. Note that GARRULOUS events
       
   263 #   are still excluded.
       
   264 #
       
   265 class VerySpecificFilter(logging.Filter):
       
   266     def filter(self, record):
       
   267         return record.levelno not in [SOCIABLE, TACITURN]
       
   268 
       
   269 def message(s):
       
   270     sys.stdout.write("%s\n" % s)
       
   271 
       
   272 SHOULD1 = "This should only be seen at the '%s' logging level (or lower)"
       
   273 
       
   274 def test1():
       
   275 #
       
   276 #   Now, tell the logging system to associate names with our levels.
       
   277 #
       
   278     for lvl in my_logging_levels.keys():
       
   279         logging.addLevelName(lvl, my_logging_levels[lvl])
       
   280 
       
   281 #
       
   282 #   Now, define a test function which logs an event at each of our levels.
       
   283 #
       
   284 
       
   285     def doLog(log):
       
   286         for lvl in LEVEL_RANGE:
       
   287             log.log(lvl, SHOULD1, logging.getLevelName(lvl))
       
   288 
       
   289     log = logging.getLogger("")
       
   290     hdlr = log.handlers[0]
       
   291 #
       
   292 #   Set the logging level to each different value and call the utility
       
   293 #   function to log events.
       
   294 #   In the output, you should see that each time round the loop, the number of
       
   295 #   logging events which are actually output decreases.
       
   296 #
       
   297     for lvl in LEVEL_RANGE:
       
   298         message("-- setting logging level to '%s' -----" %
       
   299                         logging.getLevelName(lvl))
       
   300         log.setLevel(lvl)
       
   301         doLog(log)
       
   302   #
       
   303   #   Now, we demonstrate level filtering at the handler level. Tell the
       
   304   #   handler defined above to filter at level 'SOCIABLE', and repeat the
       
   305   #   above loop. Compare the output from the two runs.
       
   306   #
       
   307     hdlr.setLevel(SOCIABLE)
       
   308     message("-- Filtering at handler level to SOCIABLE --")
       
   309     for lvl in LEVEL_RANGE:
       
   310         message("-- setting logging level to '%s' -----" %
       
   311                       logging.getLevelName(lvl))
       
   312         log.setLevel(lvl)
       
   313         doLog(log)
       
   314 
       
   315     hdlr.setLevel(0)    #turn off level filtering at the handler
       
   316 
       
   317     garr = GarrulousFilter()
       
   318     hdlr.addFilter(garr)
       
   319     message("-- Filtering using GARRULOUS filter --")
       
   320     for lvl in LEVEL_RANGE:
       
   321         message("-- setting logging level to '%s' -----" %
       
   322                         logging.getLevelName(lvl))
       
   323         log.setLevel(lvl)
       
   324         doLog(log)
       
   325     spec = VerySpecificFilter()
       
   326     log.addFilter(spec)
       
   327     message("-- Filtering using specific filter for SOCIABLE, TACITURN --")
       
   328     for lvl in LEVEL_RANGE:
       
   329         message("-- setting logging level to '%s' -----" %
       
   330                       logging.getLevelName(lvl))
       
   331         log.setLevel(lvl)
       
   332         doLog(log)
       
   333 
       
   334     log.removeFilter(spec)
       
   335     hdlr.removeFilter(garr)
       
   336     #Undo the one level which clashes...for regression tests
       
   337     logging.addLevelName(logging.DEBUG, "DEBUG")
       
   338 
       
   339 #----------------------------------------------------------------------------
       
   340 # Test 2
       
   341 #----------------------------------------------------------------------------
       
   342 
       
   343 MSG = "-- logging %d at INFO, messages should be seen every 10 events --"
       
   344 def test2():
       
   345     logger = logging.getLogger("")
       
   346     sh = logger.handlers[0]
       
   347     sh.close()
       
   348     logger.removeHandler(sh)
       
   349     mh = logging.handlers.MemoryHandler(10,logging.WARNING, sh)
       
   350     logger.setLevel(logging.DEBUG)
       
   351     logger.addHandler(mh)
       
   352     message("-- logging at DEBUG, nothing should be seen yet --")
       
   353     logger.debug("Debug message")
       
   354     message("-- logging at INFO, nothing should be seen yet --")
       
   355     logger.info("Info message")
       
   356     message("-- logging at WARNING, 3 messages should be seen --")
       
   357     logger.warn("Warn message")
       
   358     for i in xrange(102):
       
   359         message(MSG % i)
       
   360         logger.info("Info index = %d", i)
       
   361     mh.close()
       
   362     logger.removeHandler(mh)
       
   363     logger.addHandler(sh)
       
   364 
       
   365 #----------------------------------------------------------------------------
       
   366 # Test 3
       
   367 #----------------------------------------------------------------------------
       
   368 
       
   369 FILTER = "a.b"
       
   370 
       
   371 def doLog3():
       
   372     logging.getLogger("a").info("Info 1")
       
   373     logging.getLogger("a.b").info("Info 2")
       
   374     logging.getLogger("a.c").info("Info 3")
       
   375     logging.getLogger("a.b.c").info("Info 4")
       
   376     logging.getLogger("a.b.c.d").info("Info 5")
       
   377     logging.getLogger("a.bb.c").info("Info 6")
       
   378     logging.getLogger("b").info("Info 7")
       
   379     logging.getLogger("b.a").info("Info 8")
       
   380     logging.getLogger("c.a.b").info("Info 9")
       
   381     logging.getLogger("a.bb").info("Info 10")
       
   382 
       
   383 def test3():
       
   384     root = logging.getLogger()
       
   385     root.setLevel(logging.DEBUG)
       
   386     hand = root.handlers[0]
       
   387     message("Unfiltered...")
       
   388     doLog3()
       
   389     message("Filtered with '%s'..." % FILTER)
       
   390     filt = logging.Filter(FILTER)
       
   391     hand.addFilter(filt)
       
   392     doLog3()
       
   393     hand.removeFilter(filt)
       
   394 
       
   395 #----------------------------------------------------------------------------
       
   396 # Test 4
       
   397 #----------------------------------------------------------------------------
       
   398 
       
   399 # config0 is a standard configuration.
       
   400 config0 = """
       
   401 [loggers]
       
   402 keys=root
       
   403 
       
   404 [handlers]
       
   405 keys=hand1
       
   406 
       
   407 [formatters]
       
   408 keys=form1
       
   409 
       
   410 [logger_root]
       
   411 level=NOTSET
       
   412 handlers=hand1
       
   413 
       
   414 [handler_hand1]
       
   415 class=StreamHandler
       
   416 level=NOTSET
       
   417 formatter=form1
       
   418 args=(sys.stdout,)
       
   419 
       
   420 [formatter_form1]
       
   421 format=%(levelname)s:%(name)s:%(message)s
       
   422 datefmt=
       
   423 """
       
   424 
       
   425 # config1 adds a little to the standard configuration.
       
   426 config1 = """
       
   427 [loggers]
       
   428 keys=root,parser
       
   429 
       
   430 [handlers]
       
   431 keys=hand1
       
   432 
       
   433 [formatters]
       
   434 keys=form1
       
   435 
       
   436 [logger_root]
       
   437 level=NOTSET
       
   438 handlers=hand1
       
   439 
       
   440 [logger_parser]
       
   441 level=DEBUG
       
   442 handlers=hand1
       
   443 propagate=1
       
   444 qualname=compiler.parser
       
   445 
       
   446 [handler_hand1]
       
   447 class=StreamHandler
       
   448 level=NOTSET
       
   449 formatter=form1
       
   450 args=(sys.stdout,)
       
   451 
       
   452 [formatter_form1]
       
   453 format=%(levelname)s:%(name)s:%(message)s
       
   454 datefmt=
       
   455 """
       
   456 
       
   457 # config2 has a subtle configuration error that should be reported
       
   458 config2 = string.replace(config1, "sys.stdout", "sys.stbout")
       
   459 
       
   460 # config3 has a less subtle configuration error
       
   461 config3 = string.replace(
       
   462     config1, "formatter=form1", "formatter=misspelled_name")
       
   463 
       
   464 def test4():
       
   465     for i in range(4):
       
   466         conf = globals()['config%d' % i]
       
   467         sys.stdout.write('config%d: ' % i)
       
   468         loggerDict = logging.getLogger().manager.loggerDict
       
   469         logging._acquireLock()
       
   470         try:
       
   471             saved_handlers = logging._handlers.copy()
       
   472             saved_handler_list = logging._handlerList[:]
       
   473             saved_loggers = loggerDict.copy()
       
   474         finally:
       
   475             logging._releaseLock()
       
   476         try:
       
   477             fn = tempfile.mktemp(".ini")
       
   478             f = open(fn, "w")
       
   479             f.write(conf)
       
   480             f.close()
       
   481             try:
       
   482                 logging.config.fileConfig(fn)
       
   483                 #call again to make sure cleanup is correct
       
   484                 logging.config.fileConfig(fn)
       
   485             except:
       
   486                 t = sys.exc_info()[0]
       
   487                 message(str(t))
       
   488             else:
       
   489                 message('ok.')
       
   490             os.remove(fn)
       
   491         finally:
       
   492             logging._acquireLock()
       
   493             try:
       
   494                 logging._handlers.clear()
       
   495                 logging._handlers.update(saved_handlers)
       
   496                 logging._handlerList[:] = saved_handler_list
       
   497                 loggerDict = logging.getLogger().manager.loggerDict
       
   498                 loggerDict.clear()
       
   499                 loggerDict.update(saved_loggers)
       
   500             finally:
       
   501                 logging._releaseLock()
       
   502 
       
   503 #----------------------------------------------------------------------------
       
   504 # Test 5
       
   505 #----------------------------------------------------------------------------
       
   506 
       
   507 test5_config = """
       
   508 [loggers]
       
   509 keys=root
       
   510 
       
   511 [handlers]
       
   512 keys=hand1
       
   513 
       
   514 [formatters]
       
   515 keys=form1
       
   516 
       
   517 [logger_root]
       
   518 level=NOTSET
       
   519 handlers=hand1
       
   520 
       
   521 [handler_hand1]
       
   522 class=StreamHandler
       
   523 level=NOTSET
       
   524 formatter=form1
       
   525 args=(sys.stdout,)
       
   526 
       
   527 [formatter_form1]
       
   528 class=test.test_logging.FriendlyFormatter
       
   529 format=%(levelname)s:%(name)s:%(message)s
       
   530 datefmt=
       
   531 """
       
   532 
       
   533 class FriendlyFormatter (logging.Formatter):
       
   534     def formatException(self, ei):
       
   535         return "%s... Don't panic!" % str(ei[0])
       
   536 
       
   537 
       
   538 def test5():
       
   539     loggerDict = logging.getLogger().manager.loggerDict
       
   540     logging._acquireLock()
       
   541     try:
       
   542         saved_handlers = logging._handlers.copy()
       
   543         saved_handler_list = logging._handlerList[:]
       
   544         saved_loggers = loggerDict.copy()
       
   545     finally:
       
   546         logging._releaseLock()
       
   547     try:
       
   548         fn = tempfile.mktemp(".ini")
       
   549         f = open(fn, "w")
       
   550         f.write(test5_config)
       
   551         f.close()
       
   552         logging.config.fileConfig(fn)
       
   553         try:
       
   554             raise KeyError
       
   555         except KeyError:
       
   556             logging.exception("just testing")
       
   557         os.remove(fn)
       
   558         hdlr = logging.getLogger().handlers[0]
       
   559         logging.getLogger().handlers.remove(hdlr)
       
   560     finally:
       
   561         logging._acquireLock()
       
   562         try:
       
   563             logging._handlers.clear()
       
   564             logging._handlers.update(saved_handlers)
       
   565             logging._handlerList[:] = saved_handler_list
       
   566             loggerDict = logging.getLogger().manager.loggerDict
       
   567             loggerDict.clear()
       
   568             loggerDict.update(saved_loggers)
       
   569         finally:
       
   570             logging._releaseLock()
       
   571 
       
   572 
       
   573 #----------------------------------------------------------------------------
       
   574 # Test Harness
       
   575 #----------------------------------------------------------------------------
       
   576 def banner(nm, typ):
       
   577     sep = BANNER % (nm, typ)
       
   578     sys.stdout.write(sep)
       
   579     sys.stdout.flush()
       
   580 
       
   581 def test_main_inner():
       
   582     rootLogger = logging.getLogger("")
       
   583     rootLogger.setLevel(logging.DEBUG)
       
   584     hdlr = logging.StreamHandler(sys.stdout)
       
   585     fmt = logging.Formatter(logging.BASIC_FORMAT)
       
   586     hdlr.setFormatter(fmt)
       
   587     rootLogger.addHandler(hdlr)
       
   588 
       
   589     # Find an unused port number
       
   590     port = logging.handlers.DEFAULT_TCP_LOGGING_PORT
       
   591     while port < logging.handlers.DEFAULT_TCP_LOGGING_PORT+100:
       
   592         try:
       
   593             tcpserver = LogRecordSocketReceiver(port=port)
       
   594         except socket.error:
       
   595             port += 1
       
   596         else:
       
   597             break
       
   598     else:
       
   599         raise ImportError, "Could not find unused port"
       
   600 
       
   601 
       
   602     #Set up a handler such that all events are sent via a socket to the log
       
   603     #receiver (logrecv).
       
   604     #The handler will only be added to the rootLogger for some of the tests
       
   605     shdlr = logging.handlers.SocketHandler('localhost', port)
       
   606 
       
   607     #Configure the logger for logrecv so events do not propagate beyond it.
       
   608     #The sockLogger output is buffered in memory until the end of the test,
       
   609     #and printed at the end.
       
   610     sockOut = cStringIO.StringIO()
       
   611     sockLogger = logging.getLogger("logrecv")
       
   612     sockLogger.setLevel(logging.DEBUG)
       
   613     sockhdlr = logging.StreamHandler(sockOut)
       
   614     sockhdlr.setFormatter(logging.Formatter(
       
   615                                    "%(name)s -> %(levelname)s: %(message)s"))
       
   616     sockLogger.addHandler(sockhdlr)
       
   617     sockLogger.propagate = 0
       
   618 
       
   619     #Set up servers
       
   620     threads = []
       
   621     #sys.stdout.write("About to start TCP server...\n")
       
   622     threads.append(threading.Thread(target=runTCP, args=(tcpserver,)))
       
   623 
       
   624     for thread in threads:
       
   625         thread.start()
       
   626     try:
       
   627         banner("log_test0", "begin")
       
   628 
       
   629         rootLogger.addHandler(shdlr)
       
   630         test0()
       
   631         # XXX(nnorwitz): Try to fix timing related test failures.
       
   632         # This sleep gives us some extra time to read messages.
       
   633         # The test generally only fails on Solaris without this sleep.
       
   634         time.sleep(2.0)
       
   635         shdlr.close()
       
   636         rootLogger.removeHandler(shdlr)
       
   637 
       
   638         banner("log_test0", "end")
       
   639 
       
   640         for t in range(1,6):
       
   641             banner("log_test%d" % t, "begin")
       
   642             globals()['test%d' % t]()
       
   643             banner("log_test%d" % t, "end")
       
   644 
       
   645     finally:
       
   646         #wait for TCP receiver to terminate
       
   647         socketDataProcessed.wait()
       
   648         # ensure the server dies
       
   649         tcpserver.abort = 1
       
   650         for thread in threads:
       
   651             thread.join(2.0)
       
   652         banner("logrecv output", "begin")
       
   653         sys.stdout.write(sockOut.getvalue())
       
   654         sockOut.close()
       
   655         sockLogger.removeHandler(sockhdlr)
       
   656         sockhdlr.close()
       
   657         banner("logrecv output", "end")
       
   658         sys.stdout.flush()
       
   659         try:
       
   660             hdlr.close()
       
   661         except:
       
   662             pass
       
   663         rootLogger.removeHandler(hdlr)
       
   664 
       
   665 # Set the locale to the platform-dependent default.  I have no idea
       
   666 # why the test does this, but in any case we save the current locale
       
   667 # first and restore it at the end.
       
   668 @run_with_locale('LC_ALL', '')
       
   669 def test_main():
       
   670     # Save and restore the original root logger level across the tests.
       
   671     # Otherwise, e.g., if any test using cookielib runs after test_logging,
       
   672     # cookielib's debug-level logger tries to log messages, leading to
       
   673     # confusing:
       
   674     #    No handlers could be found for logger "cookielib"
       
   675     # output while the tests are running.
       
   676     root_logger = logging.getLogger("")
       
   677     original_logging_level = root_logger.getEffectiveLevel()
       
   678     try:
       
   679         test_main_inner()
       
   680     finally:
       
   681         root_logger.setLevel(original_logging_level)
       
   682 
       
   683 if __name__ == "__main__":
       
   684     sys.stdout.write("test_logging\n")
       
   685     test_main()