Changeset 459:2f5ad7fd7e74

Show
Ignore:
Timestamp:
08/04/08 12:13:52 (5 months ago)
Author:
"Brian Warner <warner@lothar.com>"
branch:
default
Message:

logging: add tests for 'flogtool dump', handle stdout/stderr better

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • ChangeLog

    r458 r459  
     12008-08-04  Brian Warner  <warner@lothar.com> 
     2 
     3        * foolscap/test/test_logging.py (Dumper): test 'flogtool dump' 
     4 
     5        * foolscap/logging/cli.py (dispatch): pass stdout/stderr through 
     6        attributes on the subcommand's Options instance, rather than as 
     7        separate function arguments.. makes testing easier. 
     8        * foolscap/logging/gatherer.py (create_log_gatherer): same 
     9        (create_incident_gatherer): same 
     10        (CreateGatherOptions): same 
     11        (CreateIncidentGatherOptions): same 
     12        * foolscap/logging/dumper.py (DumpOptions): same 
     13 
    1142008-08-01  Brian Warner  <warner@lothar.com> 
    215 
  • foolscap/logging/cli.py

    r442 r459  
    4444 
    4545 
    46 def dispatch(command, options, stdout, stderr): 
     46def dispatch(command, options): 
    4747    if command == "tail": 
    4848        from foolscap.logging.tail import LogTail 
     
    5252    elif command == "create-gatherer": 
    5353        from foolscap.logging.gatherer import create_log_gatherer 
    54         create_log_gatherer(options, stdout
     54        create_log_gatherer(options
    5555 
    5656    elif command == "create-incident-gatherer": 
    5757        from foolscap.logging.gatherer import create_incident_gatherer 
    58         create_incident_gatherer(options, stdout
     58        create_incident_gatherer(options
    5959 
    6060    elif command == "dump": 
     
    9696    command = config.subCommand 
    9797    so = config.subOptions 
    98     stdout, stderr = sys.stdout, sys.stderr 
    9998    if not run_by_human: 
    100         stdout = StringIO() 
    101         stderr = StringIO() 
    102     dispatch(command, so, stdout, stderr
     99        so.stdout = StringIO() 
     100        so.stderr = StringIO() 
     101    dispatch(command, so
    103102    if not run_by_human: 
    104         return (stdout.getvalue(), stderr.getvalue()) 
     103        return (so.stdout.getvalue(), so.stderr.getvalue()) 
  • foolscap/logging/dumper.py

    r430 r459  
    55 
    66class DumpOptions(usage.Options): 
     7    stdout = sys.stdout 
     8    stderr = sys.stderr 
    79    synopsis = "Usage: flogtool dump DUMPFILE.pickle" 
    810    optFlags = [ 
     
    2022 
    2123    def run(self, options): 
     24        self.options = options 
    2225        try: 
    23             self.start(options
     26            self.start(
    2427        except IOError: 
    2528            sys.exit(1) 
    2629 
    27     def start(self, options): 
    28         for e in self.get_events(options): 
     30    def start(self): 
     31        for e in self.get_events(): 
    2932            if "header" in e: 
    3033                if e["header"]["type"] == "incident": 
     
    3235                    self.trigger = (t["incarnation"], t["num"]) 
    3336            if "d" in e: 
    34                 self.print_event(e, options
     37                self.print_event(e
    3538 
    3639    def format_time(self, when): 
     
    3942        return time_s 
    4043 
    41     def print_event(self, e, options): 
     44    def print_event(self, e): 
    4245        short = e['from'][:8] 
    4346        d = e['d'] 
    4447        when = self.format_time(d['time']) 
    45         if options['just-numbers']: 
    46             print when, d.get('num') 
     48        if self.options['just-numbers']: 
     49            print >>self.options.stdout, when, d.get('num') 
    4750            return 
    4851 
     
    5457 
    5558        t = "%s#%d " % (short, d['num']) 
    56         if options['rx-time']: 
     59        if self.options['rx-time']: 
    5760            rx_when = self.format_time(e['rx_time']) 
    5861            t += "rx(%s) " % rx_when 
     
    6164            t += "%s" % when 
    6265        t += ": %s" % text 
    63         if options['verbose']: 
     66        if self.options['verbose']: 
    6467            t += ": %r" % d 
    6568        if is_trigger: 
    6669            t += " [INCIDENT-TRIGGER]" 
    67         print
     70        print >>self.options.stdout,
    6871        if 'failure' in d: 
    69             print " FAILURE:" 
     72            print >>self.options.stdout," FAILURE:" 
    7073            lines = str(d['failure']).split("\n") 
    7174            for line in lines: 
    72                 print " %s" % (line,) 
     75                print >>self.options.stdout, " %s" % (line,) 
    7376 
    74     def get_events(self, options): 
    75         fn = options.dumpfile 
     77    def get_events(self): 
     78        fn = self.options.dumpfile 
    7679        if fn.endswith(".bz2"): 
    7780            import bz2 
  • foolscap/logging/gatherer.py

    r457 r459  
    7676class CreateGatherOptions(usage.Options): 
    7777    """flogtool create-gatherer GATHERER_DIRECTORY""" 
     78    stdout = sys.stdout 
     79    stderr = sys.stderr 
    7880 
    7981    optFlags = [ 
     
    254256""" 
    255257 
    256 def create_log_gatherer(config, stdout=sys.stdout): 
     258def create_log_gatherer(config): 
    257259    basedir = config["basedir"] 
     260    stdout = config.stdout 
    258261    if not os.path.exists(basedir): 
    259262        os.makedirs(basedir) 
     
    282285class CreateIncidentGatherOptions(usage.Options): 
    283286    """flogtool create-incident-gatherer BASEDIR""" 
     287    stdout = sys.stdout 
     288    stderr = sys.stderr 
    284289 
    285290    optFlags = [ 
     
    511516""" 
    512517 
    513 def create_incident_gatherer(config, stdout=sys.stdout): 
     518def create_incident_gatherer(config): 
    514519    basedir = config["basedir"] 
     520    stdout = config.stdout 
    515521    if not os.path.exists(basedir): 
    516522        os.makedirs(basedir) 
  • foolscap/test/test_logging.py

    r457 r459  
    99from twisted.python import failure, runtime, usage 
    1010import foolscap 
    11 from foolscap.logging import gatherer, log, tail, incident, cli, web, publish 
     11from foolscap.logging import gatherer, log, tail, incident, cli, web, \ 
     12     publish, dumper 
    1213from foolscap.logging.interfaces import RILogObserver 
    1314from foolscap.eventual import fireEventually, flushEventualQueue 
     
    15271528        self.failUnless("to launch the daemon" in out, out) 
    15281529 
     1530class Dumper(unittest.TestCase, LogfileReaderMixin): 
     1531    # create a logfile, then dump it, and examine the output to make sure it 
     1532    # worked right. 
     1533 
     1534    def create_logfile(self): 
     1535        if not os.path.exists(self.basedir): 
     1536            os.makedirs(self.basedir) 
     1537        fn = os.path.join(self.basedir, "dump.flog") 
     1538        l = log.FoolscapLogger() 
     1539        lfo = log.LogFileObserver(fn) 
     1540        l.addObserver(lfo.msg) 
     1541        l.msg("one") 
     1542        l.msg("two") 
     1543        try: 
     1544            raise SampleError("whoops1") 
     1545        except: 
     1546            l.err() 
     1547        l.msg("three") 
     1548        d = fireEventually() 
     1549        def _done(res): 
     1550            lfo._stop() 
     1551            #events = self._read_logfile(fn) 
     1552            #self.failUnlessEqual(len(events), 1+3) 
     1553            return fn 
     1554        d.addCallback(_done) 
     1555        return d 
     1556 
     1557    def test_dump(self): 
     1558        self.basedir = "logging/Dumper/dump" 
     1559        d = self.create_logfile() 
     1560        def _check(fn): 
     1561            events = self._read_logfile(fn) 
     1562            d = dumper.LogDumper() 
     1563 
     1564            argv = ["flogtool", "dump", fn] 
     1565            (out,err) = cli.run_flogtool(argv[1:], run_by_human=False) 
     1566            self.failUnlessEqual(err, "") 
     1567            lines = list(StringIO(out).readlines()) 
     1568            line0 = "local#%d %s: one" % (events[1]["d"]["num"], 
     1569                                          d.format_time(events[1]["d"]["time"])) 
     1570            self.failUnlessEqual(lines[0].strip(), line0) 
     1571            self.failUnless("FAILURE:" in lines[3]) 
     1572            self.failUnless("test_logging.SampleError: whoops1" in lines[-3]) 
     1573            self.failUnless(lines[-1].startswith("local#3 ")) 
     1574 
     1575            argv = ["flogtool", "dump", "--just-numbers", fn] 
     1576            (out,err) = cli.run_flogtool(argv[1:], run_by_human=False) 
     1577            self.failUnlessEqual(err, "") 
     1578            lines = list(StringIO(out).readlines()) 
     1579            line0 = "%s %d" % (d.format_time(events[1]["d"]["time"]), 
     1580                               events[1]["d"]["num"]) 
     1581            self.failUnlessEqual(lines[0].strip(), line0) 
     1582            self.failUnless(lines[1].strip().endswith(" 1")) 
     1583            self.failUnless(lines[-1].strip().endswith(" 3")) 
     1584            # failures are not dumped in --just-numbers 
     1585            self.failUnlessEqual(len(lines), 1+3) 
     1586 
     1587            argv = ["flogtool", "dump", "--rx-time", fn] 
     1588            (out,err) = cli.run_flogtool(argv[1:], run_by_human=False) 
     1589            self.failUnlessEqual(err, "") 
     1590            lines = list(StringIO(out).readlines()) 
     1591            line0 = "local#%d rx(%s) emit(%s): one" % \ 
     1592                    (events[1]["d"]["num"], 
     1593                     d.format_time(events[1]["rx_time"]), 
     1594                     d.format_time(events[1]["d"]["time"])) 
     1595            self.failUnlessEqual(lines[0].strip(), line0) 
     1596            self.failUnless(lines[-1].strip().endswith(" three")) 
     1597 
     1598            argv = ["flogtool", "dump", "--verbose", fn] 
     1599            (out,err) = cli.run_flogtool(argv[1:], run_by_human=False) 
     1600            self.failUnlessEqual(err, "") 
     1601            lines = list(StringIO(out).readlines()) 
     1602            self.failUnless("'message': 'one'" in lines[0]) 
     1603            self.failUnless("'level': 20" in lines[0]) 
     1604            self.failUnless(": three: {" in lines[-1]) 
     1605 
     1606        d.addCallback(_check) 
     1607        return d 
     1608 
     1609    def create_incident(self): 
     1610        if not os.path.exists(self.basedir): 
     1611            os.makedirs(self.basedir) 
     1612        l = log.FoolscapLogger() 
     1613        l.setLogDir(self.basedir) 
     1614        l.setIncidentReporterFactory(NoFollowUpReporter) 
     1615 
     1616        d = defer.Deferred() 
     1617        def _done(name, trigger): 
     1618            d.callback( (name,trigger) ) 
     1619        l.addImmediateIncidentObserver(_done) 
     1620 
     1621        l.msg("one") 
     1622        l.msg("two") 
     1623        l.msg("boom", level=log.WEIRD) 
     1624        l.msg("four") 
     1625 
     1626        d.addCallback(lambda (name,trigger): 
     1627                      os.path.join(self.basedir, name+".flog.bz2")) 
     1628 
     1629        return d 
     1630 
     1631    def test_incident(self): 
     1632        self.basedir = "logging/Dumper/incident" 
     1633        d = self.create_incident() 
     1634        def _check(fn): 
     1635            events = self._read_logfile(fn) 
     1636            # for sanity, make sure we created the incident correctly 
     1637            assert events[0]["header"]["type"] == "incident" 
     1638            assert events[0]["header"]["trigger"]["num"] == 2 
     1639 
     1640            argv = ["flogtool", "dump", fn] 
     1641            (out,err) = cli.run_flogtool(argv[1:], run_by_human=False) 
     1642            self.failUnlessEqual(err, "") 
     1643            lines = list(StringIO(out).readlines()) 
     1644            self.failUnlessEqual(len(lines), 3) 
     1645            self.failIf("[INCIDENT-TRIGGER]" in lines[0]) 
     1646            self.failIf("[INCIDENT-TRIGGER]" in lines[1]) 
     1647            self.failUnless(lines[2].strip().endswith(": boom [INCIDENT-TRIGGER]")) 
     1648             
     1649        d.addCallback(_check) 
     1650        return d 
    15291651 
    15301652class Web(unittest.TestCase):