Mercurial > personal > weather-server
comparison weather_server/logfile_test.py @ 24:20c8ec56e447
logfile: Pull logfile thread out of Logger.
This enables automatic garbage collection of Logger instances,
since a running thread no longer has a reference to a Logger's self.
It separates exclusive management of logfile state into the
_writer_thread function, which now opens the file and writes it until
it is told to stop by receiving the poison pill.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sun, 10 Nov 2019 23:07:11 -0500 |
parents | beb42c835c52 |
children | 9bc3687e1e5e |
comparison
equal
deleted
inserted
replaced
23:88249e451566 | 24:20c8ec56e447 |
---|---|
1 import contextlib | 1 import contextlib |
2 import datetime | 2 import datetime |
3 import os.path | |
3 import pathlib | 4 import pathlib |
4 import tempfile | 5 import tempfile |
6 import threading | |
5 import unittest | 7 import unittest |
6 | 8 |
7 import bson | 9 import bson |
8 import pytz | 10 import pytz |
9 | 11 |
10 from . import common | 12 from . import common |
11 from . import logfile | 13 from . import logfile |
12 from . import types | |
13 | 14 |
14 | 15 |
15 def ts(n): | 16 def ts(n): |
16 return datetime.datetime.utcfromtimestamp(n).replace(tzinfo=pytz.UTC) | 17 return datetime.datetime.utcfromtimestamp(n).replace(tzinfo=pytz.UTC) |
17 | 18 |
32 def test_empty(self): | 33 def test_empty(self): |
33 lg = logfile.Logger( | 34 lg = logfile.Logger( |
34 str(self.log_path), sample_field='x') | 35 str(self.log_path), sample_field='x') |
35 with contextlib.closing(lg) as logger: | 36 with contextlib.closing(lg) as logger: |
36 self.assertEqual(logger.data, ()) | 37 self.assertEqual(logger.data, ()) |
38 | |
39 def test_fails_to_open(self): | |
40 with self.assertRaises(OSError): | |
41 logfile.Logger( | |
42 os.path.join( | |
43 self.temp_dir.name, | |
44 'nonexistent-directory', | |
45 'bogus-filename'), | |
46 sample_field='unimportant') | |
47 | |
48 def test_del(self): | |
49 lg = logfile.Logger( | |
50 str(self.log_path), sample_field='x') | |
51 del lg | |
37 | 52 |
38 def test_loading(self): | 53 def test_loading(self): |
39 with self.log_path.open('wb') as outfile: | 54 with self.log_path.open('wb') as outfile: |
40 outfile.write(common.bson_encode(dict( | 55 outfile.write(common.bson_encode(dict( |
41 sample_time=ts(123), | 56 sample_time=ts(123), |
70 str(self.log_path), | 85 str(self.log_path), |
71 sample_field='sample_time', | 86 sample_field='sample_time', |
72 )) as logger: | 87 )) as logger: |
73 logger.write_rows([ | 88 logger.write_rows([ |
74 # Ignored, since it's older than the newest entry. | 89 # Ignored, since it's older than the newest entry. |
75 types.Reading(ts(100), 999, 666, ts(101)).as_dict(), | 90 dict( |
76 types.Reading(ts(125), 333, 777, ts(200)).as_dict(), | 91 sample_time=ts(100), |
92 temp_c=999, | |
93 rh_pct=666, | |
94 ingest_time=ts(101), | |
95 ), | |
96 dict( | |
97 sample_time=ts(125), | |
98 temp_c=333, | |
99 rh_pct=777, | |
100 ingest_time=ts(200), | |
101 ), | |
77 ]) | 102 ]) |
78 self.assertEqual( | 103 self.assertEqual( |
79 logger.data, | 104 logger.data, |
80 ( | 105 ( |
81 types.Reading(ts(123), 420, 69, ts(125)).as_dict(), | 106 dict( |
82 types.Reading(ts(125), 333, 777, ts(200)).as_dict(), | 107 sample_time=ts(123), |
108 temp_c=420, | |
109 rh_pct=69, | |
110 ingest_time=ts(125), | |
111 ), | |
112 dict( | |
113 sample_time=ts(125), | |
114 temp_c=333, | |
115 rh_pct=777, | |
116 ingest_time=ts(200), | |
117 ), | |
83 ) | 118 ) |
84 ) | 119 ) |
85 | 120 |
86 self.assertEqual(self.read_bsons(), [ | 121 self.assertEqual(self.read_bsons(), [ |
87 dict( | 122 dict( |
102 with contextlib.closing(logfile.Logger( | 137 with contextlib.closing(logfile.Logger( |
103 str(self.log_path), | 138 str(self.log_path), |
104 sample_field='sample_time', | 139 sample_field='sample_time', |
105 )) as logger: | 140 )) as logger: |
106 logger.write_rows([ | 141 logger.write_rows([ |
107 types.Reading(ts(100), 999, 666, ts(101)).as_dict(), | 142 dict( |
108 types.Reading(ts(125), 333, 777, ts(200)).as_dict(), | 143 sample_time=ts(100), |
144 temp_c=999, | |
145 rh_pct=666, | |
146 ingest_time=ts(101), | |
147 ), | |
148 dict( | |
149 sample_time=ts(125), | |
150 temp_c=333, | |
151 rh_pct=777, | |
152 ingest_time=ts(200), | |
153 ), | |
109 ]) | 154 ]) |
110 with self.log_path.open('ab') as outfile: | 155 with self.log_path.open('ab') as outfile: |
111 outfile.write(common.bson_encode(dict( | 156 outfile.write(common.bson_encode(dict( |
112 sample_time=ts(1024), | 157 sample_time=ts(1024), |
113 temp_c=256, | 158 temp_c=256, |
114 rh_pct=128, | 159 rh_pct=128, |
115 ingest_time=ts(4096), | 160 ingest_time=ts(4096), |
116 ))) | 161 ))) |
117 outfile.flush() | 162 outfile.flush() |
118 self.assertEqual(logger.data, ( | 163 self.assertEqual(logger.data, ( |
119 types.Reading(ts(100), 999, 666, ts(101)).as_dict(), | 164 dict( |
120 types.Reading(ts(125), 333, 777, ts(200)).as_dict(), | 165 sample_time=ts(100), |
121 types.Reading(ts(1024), 256, 128, ts(4096)).as_dict(), | 166 temp_c=999, |
167 rh_pct=666, | |
168 ingest_time=ts(101), | |
169 ), | |
170 dict( | |
171 sample_time=ts(125), | |
172 temp_c=333, | |
173 rh_pct=777, | |
174 ingest_time=ts(200), | |
175 ), | |
176 dict( | |
177 sample_time=ts(1024), | |
178 temp_c=256, | |
179 rh_pct=128, | |
180 ingest_time=ts(4096), | |
181 ), | |
122 )) | 182 )) |
123 | 183 |
124 def read_bsons(self): | 184 def read_bsons(self): |
125 with self.log_path.open('rb') as infile: | 185 with self.log_path.open('rb') as infile: |
126 return bson.decode_all( | 186 return bson.decode_all( |