| 1 | """ |
|---|
| 2 | Tests for allmydata.util.log. |
|---|
| 3 | |
|---|
| 4 | Ported to Python 3. |
|---|
| 5 | """ |
|---|
| 6 | |
|---|
| 7 | from twisted.trial import unittest |
|---|
| 8 | from twisted.python.failure import Failure |
|---|
| 9 | |
|---|
| 10 | from foolscap.logging import log |
|---|
| 11 | |
|---|
| 12 | from allmydata.util import log as tahoe_log |
|---|
| 13 | |
|---|
| 14 | |
|---|
| 15 | class SampleError(Exception): |
|---|
| 16 | pass |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | class Log(unittest.TestCase): |
|---|
| 20 | def setUp(self): |
|---|
| 21 | self.messages = [] |
|---|
| 22 | |
|---|
| 23 | def msg(msg, facility, parent, *args, **kwargs): |
|---|
| 24 | self.messages.append((msg, facility, parent, args, kwargs)) |
|---|
| 25 | return "msg{}".format(len(self.messages)) |
|---|
| 26 | |
|---|
| 27 | self.patch(log, "msg", msg) |
|---|
| 28 | |
|---|
| 29 | def test_err(self): |
|---|
| 30 | """Logging with log.err() causes tests to fail.""" |
|---|
| 31 | try: |
|---|
| 32 | raise SampleError("simple sample") |
|---|
| 33 | except: |
|---|
| 34 | f = Failure() |
|---|
| 35 | tahoe_log.err(format="intentional sample error", |
|---|
| 36 | failure=f, level=tahoe_log.OPERATIONAL, umid="wO9UoQ") |
|---|
| 37 | result = self.flushLoggedErrors(SampleError) |
|---|
| 38 | self.assertEqual(len(result), 1) |
|---|
| 39 | |
|---|
| 40 | def test_default_facility(self): |
|---|
| 41 | """ |
|---|
| 42 | If facility is passed to PrefixingLogMixin.__init__, it is used as |
|---|
| 43 | default facility. |
|---|
| 44 | """ |
|---|
| 45 | class LoggingObject1(tahoe_log.PrefixingLogMixin): |
|---|
| 46 | pass |
|---|
| 47 | |
|---|
| 48 | obj = LoggingObject1(facility="defaultfac") |
|---|
| 49 | obj.log("hello") |
|---|
| 50 | obj.log("world", facility="override") |
|---|
| 51 | self.assertEqual(self.messages[-2][1], "defaultfac") |
|---|
| 52 | self.assertEqual(self.messages[-1][1], "override") |
|---|
| 53 | |
|---|
| 54 | def test_with_prefix(self): |
|---|
| 55 | """ |
|---|
| 56 | If prefix is passed to PrefixingLogMixin.__init__, it is used in |
|---|
| 57 | message rendering. |
|---|
| 58 | """ |
|---|
| 59 | class LoggingObject4(tahoe_log.PrefixingLogMixin): |
|---|
| 60 | pass |
|---|
| 61 | |
|---|
| 62 | obj = LoggingObject4("fac", prefix="pre1") |
|---|
| 63 | obj.log("hello") |
|---|
| 64 | obj.log("world") |
|---|
| 65 | self.assertEqual(self.messages[-2][0], '<LoggingObject4 #1>(pre1): hello') |
|---|
| 66 | self.assertEqual(self.messages[-1][0], '<LoggingObject4 #1>(pre1): world') |
|---|
| 67 | |
|---|
| 68 | def test_with_bytes_prefix(self): |
|---|
| 69 | """ |
|---|
| 70 | If bytes prefix is passed to PrefixingLogMixin.__init__, it is used in |
|---|
| 71 | message rendering. |
|---|
| 72 | """ |
|---|
| 73 | class LoggingObject5(tahoe_log.PrefixingLogMixin): |
|---|
| 74 | pass |
|---|
| 75 | |
|---|
| 76 | obj = LoggingObject5("fac", prefix=b"pre1") |
|---|
| 77 | obj.log("hello") |
|---|
| 78 | obj.log("world") |
|---|
| 79 | self.assertEqual(self.messages[-2][0], '<LoggingObject5 #1>(pre1): hello') |
|---|
| 80 | self.assertEqual(self.messages[-1][0], '<LoggingObject5 #1>(pre1): world') |
|---|
| 81 | |
|---|
| 82 | def test_no_prefix(self): |
|---|
| 83 | """ |
|---|
| 84 | If no prefix is passed to PrefixingLogMixin.__init__, it is not used in |
|---|
| 85 | message rendering. |
|---|
| 86 | """ |
|---|
| 87 | class LoggingObject2(tahoe_log.PrefixingLogMixin): |
|---|
| 88 | pass |
|---|
| 89 | |
|---|
| 90 | obj = LoggingObject2() |
|---|
| 91 | obj.log("hello") |
|---|
| 92 | obj.log("world") |
|---|
| 93 | self.assertEqual(self.messages[-2][0], '<LoggingObject2 #1>: hello') |
|---|
| 94 | self.assertEqual(self.messages[-1][0], '<LoggingObject2 #1>: world') |
|---|
| 95 | |
|---|
| 96 | def test_numming(self): |
|---|
| 97 | """ |
|---|
| 98 | Objects inheriting from PrefixingLogMixin get a unique number from a |
|---|
| 99 | class-specific counter. |
|---|
| 100 | """ |
|---|
| 101 | class LoggingObject3(tahoe_log.PrefixingLogMixin): |
|---|
| 102 | pass |
|---|
| 103 | |
|---|
| 104 | obj = LoggingObject3() |
|---|
| 105 | obj2 = LoggingObject3() |
|---|
| 106 | obj.log("hello") |
|---|
| 107 | obj2.log("world") |
|---|
| 108 | self.assertEqual(self.messages[-2][0], '<LoggingObject3 #1>: hello') |
|---|
| 109 | self.assertEqual(self.messages[-1][0], '<LoggingObject3 #2>: world') |
|---|
| 110 | |
|---|
| 111 | def test_parent_id(self): |
|---|
| 112 | """ |
|---|
| 113 | The parent message id can be passed in, otherwise the first message's |
|---|
| 114 | id is used as the parent. |
|---|
| 115 | |
|---|
| 116 | This logic is pretty bogus, but that's what the code does. |
|---|
| 117 | """ |
|---|
| 118 | class LoggingObject1(tahoe_log.PrefixingLogMixin): |
|---|
| 119 | pass |
|---|
| 120 | |
|---|
| 121 | obj = LoggingObject1() |
|---|
| 122 | result = obj.log("zero") |
|---|
| 123 | self.assertEqual(result, "msg1") |
|---|
| 124 | obj.log("one", parent="par1") |
|---|
| 125 | obj.log("two", parent="par2") |
|---|
| 126 | obj.log("three") |
|---|
| 127 | obj.log("four") |
|---|
| 128 | self.assertEqual([m[2] for m in self.messages], |
|---|
| 129 | [None, "par1", "par2", "msg1", "msg1"]) |
|---|
| 130 | |
|---|
| 131 | def test_grandparent_id(self): |
|---|
| 132 | """ |
|---|
| 133 | If grandparent message id is given, it's used as parent id of the first |
|---|
| 134 | message. |
|---|
| 135 | """ |
|---|
| 136 | class LoggingObject1(tahoe_log.PrefixingLogMixin): |
|---|
| 137 | pass |
|---|
| 138 | |
|---|
| 139 | obj = LoggingObject1(grandparentmsgid="grand") |
|---|
| 140 | result = obj.log("zero") |
|---|
| 141 | self.assertEqual(result, "msg1") |
|---|
| 142 | obj.log("one", parent="par1") |
|---|
| 143 | obj.log("two", parent="par2") |
|---|
| 144 | obj.log("three") |
|---|
| 145 | obj.log("four") |
|---|
| 146 | self.assertEqual([m[2] for m in self.messages], |
|---|
| 147 | ["grand", "par1", "par2", "msg1", "msg1"]) |
|---|
| 148 | |
|---|
| 149 | def test_native_string_keys(self): |
|---|
| 150 | """Keyword argument keys are all native strings.""" |
|---|
| 151 | class LoggingObject17(tahoe_log.PrefixingLogMixin): |
|---|
| 152 | pass |
|---|
| 153 | |
|---|
| 154 | obj = LoggingObject17() |
|---|
| 155 | # Native string by default: |
|---|
| 156 | obj.log(hello="world") |
|---|
| 157 | # Will be Unicode on Python 2: |
|---|
| 158 | obj.log(**{"my": "message"}) |
|---|
| 159 | for message in self.messages: |
|---|
| 160 | for k in message[-1].keys(): |
|---|
| 161 | self.assertIsInstance(k, str) |
|---|