Skip to content

Commit 4727ea6

Browse files
committed
fix test issues, use context manager to fix random PyPy failures
1 parent 73ce004 commit 4727ea6

File tree

1 file changed

+116
-126
lines changed

1 file changed

+116
-126
lines changed

test/test_rotating_loggers.py

Lines changed: 116 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,42 @@
66

77
import os
88
from pathlib import Path
9+
from typing import cast
910
from unittest.mock import Mock
1011

1112
import can
13+
from can.io.generic import FileIOMessageWriter
14+
from can.typechecking import StringPathLike
1215

1316
from .data.example_data import generate_message
1417

1518

1619
class TestBaseRotatingLogger:
1720
@staticmethod
18-
def _get_instance(path, *args, **kwargs) -> can.io.BaseRotatingLogger:
21+
def _get_instance(file: StringPathLike) -> can.io.BaseRotatingLogger:
1922
class SubClass(can.io.BaseRotatingLogger):
2023
"""Subclass that implements abstract methods for testing."""
2124

2225
_supported_formats = {".asc", ".blf", ".csv", ".log", ".txt"}
2326

24-
def __init__(self, *args, **kwargs) -> None:
25-
super().__init__(*args, **kwargs)
26-
self._writer = can.Printer(file=path / "__unused.txt")
27+
def __init__(self, file: StringPathLike, **kwargs) -> None:
28+
super().__init__(**kwargs)
29+
suffix = Path(file).suffix.lower()
30+
if suffix not in self._supported_formats:
31+
raise ValueError(f"Unsupported file format: {suffix}")
32+
self._writer = can.Printer(file=file)
33+
34+
@property
35+
def writer(self) -> FileIOMessageWriter:
36+
return cast(FileIOMessageWriter, self._writer)
2737

2838
def should_rollover(self, msg: can.Message) -> bool:
2939
return False
3040

3141
def do_rollover(self):
3242
...
3343

34-
return SubClass(*args, **kwargs)
44+
return SubClass(file=file)
3545

3646
def test_import(self):
3747
assert hasattr(can.io, "BaseRotatingLogger")
@@ -50,90 +60,82 @@ def test_attributes(self):
5060
assert hasattr(can.io.BaseRotatingLogger, "do_rollover")
5161

5262
def test_get_new_writer(self, tmp_path):
53-
logger_instance = self._get_instance(tmp_path)
54-
55-
writer = logger_instance._get_new_writer(tmp_path / "file.ASC")
56-
assert isinstance(writer, can.ASCWriter)
57-
writer.stop()
63+
with self._get_instance(tmp_path / "__unused.txt") as logger_instance:
64+
writer = logger_instance._get_new_writer(tmp_path / "file.ASC")
65+
assert isinstance(writer, can.ASCWriter)
66+
writer.stop()
5867

59-
writer = logger_instance._get_new_writer(tmp_path / "file.BLF")
60-
assert isinstance(writer, can.BLFWriter)
61-
writer.stop()
68+
writer = logger_instance._get_new_writer(tmp_path / "file.BLF")
69+
assert isinstance(writer, can.BLFWriter)
70+
writer.stop()
6271

63-
writer = logger_instance._get_new_writer(tmp_path / "file.CSV")
64-
assert isinstance(writer, can.CSVWriter)
65-
writer.stop()
72+
writer = logger_instance._get_new_writer(tmp_path / "file.CSV")
73+
assert isinstance(writer, can.CSVWriter)
74+
writer.stop()
6675

67-
writer = logger_instance._get_new_writer(tmp_path / "file.LOG")
68-
assert isinstance(writer, can.CanutilsLogWriter)
69-
writer.stop()
76+
writer = logger_instance._get_new_writer(tmp_path / "file.LOG")
77+
assert isinstance(writer, can.CanutilsLogWriter)
78+
writer.stop()
7079

71-
writer = logger_instance._get_new_writer(tmp_path / "file.TXT")
72-
assert isinstance(writer, can.Printer)
73-
writer.stop()
80+
writer = logger_instance._get_new_writer(tmp_path / "file.TXT")
81+
assert isinstance(writer, can.Printer)
82+
writer.stop()
7483

7584
def test_rotation_filename(self, tmp_path):
76-
logger_instance = self._get_instance(tmp_path)
85+
with self._get_instance(tmp_path / "__unused.txt") as logger_instance:
86+
default_name = "default"
87+
assert logger_instance.rotation_filename(default_name) == "default"
7788

78-
default_name = "default"
79-
assert logger_instance.rotation_filename(default_name) == "default"
80-
81-
logger_instance.namer = lambda x: x + "_by_namer"
82-
assert logger_instance.rotation_filename(default_name) == "default_by_namer"
89+
logger_instance.namer = lambda x: x + "_by_namer"
90+
assert logger_instance.rotation_filename(default_name) == "default_by_namer"
8391

8492
def test_rotate_without_rotator(self, tmp_path):
85-
logger_instance = self._get_instance(tmp_path)
86-
87-
source = str(tmp_path / "source.txt")
88-
dest = str(tmp_path / "dest.txt")
93+
with self._get_instance(tmp_path / "__unused.txt") as logger_instance:
94+
source = str(tmp_path / "source.txt")
95+
dest = str(tmp_path / "dest.txt")
8996

90-
assert os.path.exists(source) is False
91-
assert os.path.exists(dest) is False
97+
assert os.path.exists(source) is False
98+
assert os.path.exists(dest) is False
9299

93-
logger_instance._writer = logger_instance._get_new_writer(source)
94-
logger_instance.stop()
100+
logger_instance._writer = logger_instance._get_new_writer(source)
101+
logger_instance.stop()
95102

96-
assert os.path.exists(source) is True
97-
assert os.path.exists(dest) is False
103+
assert os.path.exists(source) is True
104+
assert os.path.exists(dest) is False
98105

99-
logger_instance.rotate(source, dest)
106+
logger_instance.rotate(source, dest)
100107

101-
assert os.path.exists(source) is False
102-
assert os.path.exists(dest) is True
108+
assert os.path.exists(source) is False
109+
assert os.path.exists(dest) is True
103110

104111
def test_rotate_with_rotator(self, tmp_path):
105-
logger_instance = self._get_instance(tmp_path)
106-
107-
rotator_func = Mock()
108-
logger_instance.rotator = rotator_func
112+
with self._get_instance(tmp_path / "__unused.txt") as logger_instance:
113+
rotator_func = Mock()
114+
logger_instance.rotator = rotator_func
109115

110-
source = str(tmp_path / "source.txt")
111-
dest = str(tmp_path / "dest.txt")
116+
source = str(tmp_path / "source.txt")
117+
dest = str(tmp_path / "dest.txt")
112118

113-
assert os.path.exists(source) is False
114-
assert os.path.exists(dest) is False
119+
assert os.path.exists(source) is False
120+
assert os.path.exists(dest) is False
115121

116-
logger_instance._writer = logger_instance._get_new_writer(source)
117-
logger_instance.stop()
122+
logger_instance._writer = logger_instance._get_new_writer(source)
123+
logger_instance.stop()
118124

119-
assert os.path.exists(source) is True
120-
assert os.path.exists(dest) is False
125+
assert os.path.exists(source) is True
126+
assert os.path.exists(dest) is False
121127

122-
logger_instance.rotate(source, dest)
123-
rotator_func.assert_called_with(source, dest)
128+
logger_instance.rotate(source, dest)
129+
rotator_func.assert_called_with(source, dest)
124130

125-
# assert that no rotation was performed since rotator_func
126-
# does not do anything
127-
assert os.path.exists(source) is True
128-
assert os.path.exists(dest) is False
131+
# assert that no rotation was performed since rotator_func
132+
# does not do anything
133+
assert os.path.exists(source) is True
134+
assert os.path.exists(dest) is False
129135

130136
def test_stop(self, tmp_path):
131137
"""Test if stop() method of writer is called."""
132-
with self._get_instance(tmp_path) as logger_instance:
133-
logger_instance._writer = logger_instance._get_new_writer(
134-
tmp_path / "file.ASC"
135-
)
136-
138+
with self._get_instance(tmp_path / "file.ASC") as logger_instance:
137139
# replace stop method of writer with Mock
138140
original_stop = logger_instance.writer.stop
139141
mock_stop = Mock()
@@ -146,44 +148,38 @@ def test_stop(self, tmp_path):
146148
original_stop()
147149

148150
def test_on_message_received(self, tmp_path):
149-
logger_instance = self._get_instance(tmp_path)
151+
with self._get_instance(tmp_path / "file.ASC") as logger_instance:
152+
# Test without rollover
153+
should_rollover = Mock(return_value=False)
154+
do_rollover = Mock()
155+
writers_on_message_received = Mock()
150156

151-
logger_instance._writer = logger_instance._get_new_writer(tmp_path / "file.ASC")
157+
logger_instance.should_rollover = should_rollover
158+
logger_instance.do_rollover = do_rollover
159+
logger_instance.writer.on_message_received = writers_on_message_received
152160

153-
# Test without rollover
154-
should_rollover = Mock(return_value=False)
155-
do_rollover = Mock()
156-
writers_on_message_received = Mock()
157-
158-
logger_instance.should_rollover = should_rollover
159-
logger_instance.do_rollover = do_rollover
160-
logger_instance.writer.on_message_received = writers_on_message_received
161-
162-
msg = generate_message(0x123)
163-
logger_instance.on_message_received(msg)
164-
165-
should_rollover.assert_called_with(msg)
166-
do_rollover.assert_not_called()
167-
writers_on_message_received.assert_called_with(msg)
161+
msg = generate_message(0x123)
162+
logger_instance.on_message_received(msg)
168163

169-
# Test with rollover
170-
should_rollover = Mock(return_value=True)
171-
do_rollover = Mock()
172-
writers_on_message_received = Mock()
164+
should_rollover.assert_called_with(msg)
165+
do_rollover.assert_not_called()
166+
writers_on_message_received.assert_called_with(msg)
173167

174-
logger_instance.should_rollover = should_rollover
175-
logger_instance.do_rollover = do_rollover
176-
logger_instance.writer.on_message_received = writers_on_message_received
168+
# Test with rollover
169+
should_rollover = Mock(return_value=True)
170+
do_rollover = Mock()
171+
writers_on_message_received = Mock()
177172

178-
msg = generate_message(0x123)
179-
logger_instance.on_message_received(msg)
173+
logger_instance.should_rollover = should_rollover
174+
logger_instance.do_rollover = do_rollover
175+
logger_instance.writer.on_message_received = writers_on_message_received
180176

181-
should_rollover.assert_called_with(msg)
182-
do_rollover.assert_called()
183-
writers_on_message_received.assert_called_with(msg)
177+
msg = generate_message(0x123)
178+
logger_instance.on_message_received(msg)
184179

185-
# stop writer to enable cleanup of temp_dir
186-
logger_instance.stop()
180+
should_rollover.assert_called_with(msg)
181+
do_rollover.assert_called()
182+
writers_on_message_received.assert_called_with(msg)
187183

188184

189185
class TestSizedRotatingLogger:
@@ -202,54 +198,48 @@ def test_create_instance(self, tmp_path):
202198
base_filename = "mylogfile.ASC"
203199
max_bytes = 512
204200

205-
logger_instance = can.SizedRotatingLogger(
201+
with can.SizedRotatingLogger(
206202
base_filename=tmp_path / base_filename, max_bytes=max_bytes
207-
)
208-
assert Path(logger_instance.base_filename).name == base_filename
209-
assert logger_instance.max_bytes == max_bytes
210-
assert logger_instance.rollover_count == 0
211-
assert isinstance(logger_instance.writer, can.ASCWriter)
212-
213-
logger_instance.stop()
203+
) as logger_instance:
204+
assert Path(logger_instance.base_filename).name == base_filename
205+
assert logger_instance.max_bytes == max_bytes
206+
assert logger_instance.rollover_count == 0
207+
assert isinstance(logger_instance.writer, can.ASCWriter)
214208

215209
def test_should_rollover(self, tmp_path):
216210
base_filename = "mylogfile.ASC"
217211
max_bytes = 512
218212

219-
logger_instance = can.SizedRotatingLogger(
213+
with can.SizedRotatingLogger(
220214
base_filename=tmp_path / base_filename, max_bytes=max_bytes
221-
)
222-
msg = generate_message(0x123)
223-
do_rollover = Mock()
224-
logger_instance.do_rollover = do_rollover
225-
226-
logger_instance.writer.file.tell = Mock(return_value=511)
227-
assert logger_instance.should_rollover(msg) is False
228-
logger_instance.on_message_received(msg)
229-
do_rollover.assert_not_called()
215+
) as logger_instance:
216+
msg = generate_message(0x123)
217+
do_rollover = Mock()
218+
logger_instance.do_rollover = do_rollover
230219

231-
logger_instance.writer.file.tell = Mock(return_value=512)
232-
assert logger_instance.should_rollover(msg) is True
233-
logger_instance.on_message_received(msg)
234-
do_rollover.assert_called()
220+
logger_instance.writer.file.tell = Mock(return_value=511)
221+
assert logger_instance.should_rollover(msg) is False
222+
logger_instance.on_message_received(msg)
223+
do_rollover.assert_not_called()
235224

236-
logger_instance.stop()
225+
logger_instance.writer.file.tell = Mock(return_value=512)
226+
assert logger_instance.should_rollover(msg) is True
227+
logger_instance.on_message_received(msg)
228+
do_rollover.assert_called()
237229

238230
def test_logfile_size(self, tmp_path):
239231
base_filename = "mylogfile.ASC"
240232
max_bytes = 1024
241233
msg = generate_message(0x123)
242234

243-
logger_instance = can.SizedRotatingLogger(
235+
with can.SizedRotatingLogger(
244236
base_filename=tmp_path / base_filename, max_bytes=max_bytes
245-
)
246-
for _ in range(128):
247-
logger_instance.on_message_received(msg)
248-
249-
for file_path in os.listdir(tmp_path):
250-
assert os.path.getsize(tmp_path / file_path) <= 1100
237+
) as logger_instance:
238+
for _ in range(128):
239+
logger_instance.on_message_received(msg)
251240

252-
logger_instance.stop()
241+
for file_path in os.listdir(tmp_path):
242+
assert os.path.getsize(tmp_path / file_path) <= 1100
253243

254244
def test_logfile_size_context_manager(self, tmp_path):
255245
base_filename = "mylogfile.ASC"

0 commit comments

Comments
 (0)