13from b2test_utils
import run_in_subprocess, clean_working_directory
14from contextlib
import redirect_stdout
21class PythonLogInterface(unittest.TestCase):
22 def assertDeath(self, function, *args, **kwargs):
23 """Run function in child process and check if it died. Only way to check for B2FATAL"""
24 exitcode = run_in_subprocess(target=function, *args, **kwargs)
25 self.assertNotEqual(exitcode, 0)
27 def check_logs(self, target):
28 """Check the output of the log messages"""
29 with open(
"logmessages.txt")
as f:
30 self.assertEqual(target, f.read())
34 basf2.logging.enable_summary(
False)
38 basf2.log_to_console(
True)
39 basf2.log_to_file(
"logmessages.txt")
41 basf2.logging.log_level = basf2.LogLevel.INFO
42 basf2.logging.debug_level = 100
44 for level
in basf2.LogLevel.values.values():
45 basf2.logging.set_info(level, basf2.LogInfo.LEVEL | basf2.LogInfo.MESSAGE)
49 with self.assertRaises(TypeError):
51 with self.assertRaises(TypeError):
53 with self.assertRaises(TypeError):
54 basf2.B2DEBUG(
"foo",
"bar")
55 with self.assertRaises(TypeError):
56 basf2.B2DEBUG(3.14,
"bar")
57 with self.assertRaises(TypeError):
58 basf2.B2DEBUG([34, 324],
"bar")
61 basf2.B2DEBUG(101,
"should not show")
62 basf2.B2DEBUG(100,
"this neither")
63 basf2.logging.log_level = basf2.LogLevel.DEBUG
64 basf2.B2DEBUG(101,
"should still not show")
65 basf2.B2DEBUG(100,
"this should")
66 basf2.B2DEBUG(99,
"and with variables", foo=
"bar", bar=
"foo", int=42, float=3.14)
67 self.check_logs(
"[DEBUG:100] this should\n"
68 "[DEBUG:99] and with variables\n"
76 with self.assertRaises(TypeError):
82 basf2.B2ERROR(
"should not show")
83 self.assertDeath(checkfatal)
85 self.check_logs(
"[FATAL] exit\n")
87 def test_fatal_pythonlogging(self):
89 basf2.logging.enable_python_logging =
True
95 except Exception
as e:
96 basf2.B2ERROR(
"raised exception: ", e)
97 basf2.B2ERROR(
"should not show")
98 self.assertDeath(checkfatal)
100 self.check_logs(
"[FATAL] exit\n")
102 def test_others(self):
104 for i, f
in enumerate([basf2.B2INFO, basf2.B2WARNING, basf2.B2ERROR]):
105 with self.assertRaises(TypeError):
108 f(
"Show me",
" a message with index ", i, index=i, dictvar={
"i": i})
111 basf2.logging.log_level = basf2.LogLevel.ERROR
112 basf2.B2INFO(
"No output here")
113 basf2.B2WARNING(
"Nor here")
114 basf2.B2ERROR(
"But here")
116 self.check_logs(
"[INFO] Show me a message with index 0\n"
117 "\tdictvar = {'i': 0}\n"
119 "[WARNING] Show me a message with index 1\n"
120 "\tdictvar = {'i': 1}\n"
122 "[ERROR] Show me a message with index 2\n"
123 "\tdictvar = {'i': 2}\n"
125 "[ERROR] But here\n")
127 def test_inspect(self):
130 basf2.logging.set_info(basf2.LogLevel.INFO, li.MESSAGE | li.LEVEL | li.PACKAGE | li.FUNCTION | li.FILE | li.LINE)
135 filename = inspect.currentframe().f_code.co_filename
136 lineno = inspect.currentframe().f_lineno + 2
138 basf2.B2INFO(
"show current frame info", why=
"because we can")
140 "[INFO] show current frame info\n"
141 "\twhy = because we can { package: steering function: test_inspect @%s:%d }\n" % (filename, lineno))
144class PythonLogJSON(unittest.TestCase):
147 basf2.logging.enable_summary(
False)
149 basf2.logging.enable_python_logging =
True
153 basf2.logging.add_json()
155 basf2.logging.log_level = basf2.LogLevel.INFO
156 basf2.logging.debug_level = 100
158 for level
in basf2.LogLevel.values.values():
159 basf2.logging.set_info(level, basf2.LogInfo.LEVEL | basf2.LogInfo.MESSAGE)
161 def getLogMessage(self, message, **argk):
163 with redirect_stdout(out):
164 basf2.B2INFO(message, **argk)
167 self.assertEqual(raw[-1],
"\n")
169 self.assertTrue(raw[:-1].find(
"\n") < 0)
171 logobject = json.loads(raw)
174 def assertLogMessage(self, message, **argk):
176 logobject = self.getLogMessage(message, **argk)
178 stringified = {str(key): str(val)
for key, val
in argk.items()}
179 self.assertDictEqual(logobject, {
"level":
"INFO",
"message": message,
"variables": stringified})
181 self.assertDictEqual(logobject, {
"level":
"INFO",
"message": message})
184 self.assertLogMessage(
"message")
186 def test_multiline(self):
187 self.assertLogMessage(
"message\ncontaining\nnewlines")
190 self.assertLogMessage(
"message", var1=
"foo", var2=
"bar", int=3)
192 def test_vars_newline(self):
193 self.assertLogMessage(
"message", var1=
"foo\nbar", var2=
"bar\nboo")
196 zalgo =
"h͌̉e̳̞̞͆ͨ̏͋̕ ͍͚̱̰̀͡c͟o͛҉̟̰̫͔̟̪̠m̴̀ͯ̿͌ͨ̃͆e̡̦̦͖̳͉̗ͨͬ̑͌̃ͅt̰̝͈͚͍̳͇͌h̭̜̙̦̣̓̌̃̓̀̉͜!̱̞̻̈̿̒̀͢!̋̽̍̈͐ͫ͏̠̹̺̜̬͍ͅ"
197 self.assertLogMessage(zalgo, **{zalgo: zalgo})
199 def test_loginfo(self):
200 """Make sure all loginfo settings are honored in json output"""
203 cumul_keys = {
"level"}
206 for val, key
in basf2.LogInfo.values.items():
208 key = key.name.lower()
210 for info, keys
in (val, {
"level", key}), (cumul_info, cumul_keys):
211 basf2.logging.set_info(basf2.LogLevel.INFO, info)
212 logobject = self.getLogMessage(
"simple")
213 self.assertEqual(set(logobject.keys()), keys)
214 varkeys = keys.copy()
217 if "message" in keys:
218 varkeys.add(
"variables")
219 logobject = self.getLogMessage(
"with var", var=
"val")
220 self.assertEqual(set(logobject.keys()), varkeys)
222 def test_complete(self):
223 """Test that we always get all fields when setting output to complete"""
225 basf2.logging.add_json(
True)
226 logobject = self.getLogMessage(
"message")
227 self.assertSetEqual(set(logobject.keys()), {
"level",
"message",
"variables",
"module",
"package",
228 "function",
"file",
"line",
"timestamp",
"proc",
229 "initialize",
"count"})
232if __name__ ==
"__main__":
233 with clean_working_directory():
234 unittest.main(verbosity=0)