2323# SOFTWARE.
2424#
2525###############################################################################
26+ import types
27+
2628import pytest
2729
2830from nodescraper .connection .inband .inband import CommandArtifact
@@ -115,7 +117,7 @@ def test_bad_exit_code(conn_mock, system_info):
115117
116118 res , _ = collector .collect_data ()
117119 assert res .status == ExecutionStatus .ERROR
118- assert len (res .events ) == 1
120+ assert len (res .events ) == 2
119121 assert res .events [0 ].description == "Error reading dmesg"
120122
121123
@@ -141,3 +143,141 @@ def test_data_model():
141143 assert dmesg_data2 .dmesg_content == (
142144 "2023-06-01T01:00:00,685236-05:00 test message1\n 2023-06-01T02:30:00,685106-05:00 test message2"
143145 )
146+
147+
148+ class DummyRes :
149+ def __init__ (self , command = "" , stdout = "" , exit_code = 0 , stderr = "" ):
150+ self .command = command
151+ self .stdout = stdout
152+ self .exit_code = exit_code
153+ self .stderr = stderr
154+
155+
156+ def get_collector (monkeypatch , run_map , system_info , conn_mock ):
157+ c = DmesgCollector (
158+ system_info = system_info ,
159+ system_interaction_level = SystemInteractionLevel .INTERACTIVE ,
160+ connection = conn_mock ,
161+ )
162+ c .result = types .SimpleNamespace (artifacts = [], message = None ) # minimal fields we use
163+ c ._events = []
164+
165+ def _log_event (** kw ):
166+ c ._events .append (kw )
167+
168+ def _run_sut_cmd (cmd , * args , ** kwargs ):
169+ return run_map (cmd , * args , ** kwargs )
170+
171+ monkeypatch .setattr (c , "_log_event" , _log_event , raising = True )
172+ monkeypatch .setattr (c , "_run_sut_cmd" , _run_sut_cmd , raising = True )
173+ return c
174+
175+
176+ def test_collect_rotations_good_path (monkeypatch , system_info , conn_mock ):
177+ ls_out = (
178+ "\n " .join (
179+ [
180+ "/var/log/dmesg" ,
181+ "/var/log/dmesg.1" ,
182+ "/var/log/dmesg.2.gz" ,
183+ "/var/log/dmesg.10.gz" ,
184+ ]
185+ )
186+ + "\n "
187+ )
188+
189+ def run_map (cmd , ** kwargs ):
190+ if cmd .startswith ("ls -1 /var/log/dmesg" ):
191+ return DummyRes (command = cmd , stdout = ls_out , exit_code = 0 )
192+ if cmd .startswith ("cat '" ):
193+ if "/var/log/dmesg.1'" in cmd :
194+ return DummyRes (command = cmd , stdout = "dmesg.1 content\n " , exit_code = 0 )
195+ if "/var/log/dmesg'" in cmd :
196+ return DummyRes (command = cmd , stdout = "dmesg content\n " , exit_code = 0 )
197+ if "gzip -dc" in cmd and "/var/log/dmesg.2.gz" in cmd :
198+ return DummyRes (command = cmd , stdout = "gz2 content\n " , exit_code = 0 )
199+ if "gzip -dc" in cmd and "/var/log/dmesg.10.gz" in cmd :
200+ return DummyRes (command = cmd , stdout = "gz10 content\n " , exit_code = 0 )
201+ return DummyRes (command = cmd , stdout = "" , exit_code = 1 , stderr = "unexpected" )
202+
203+ c = get_collector (monkeypatch , run_map , system_info , conn_mock )
204+
205+ collected = c ._collect_dmesg_rotations ()
206+
207+ names = {a .filename for a in c .result .artifacts }
208+ assert names == {"dmesg.log" , "dmesg.1.log" , "dmesg.2.gz.log" , "dmesg.10.gz.log" }
209+
210+ assert isinstance (collected , list )
211+ assert len (collected ) == 4
212+
213+ descs = [e ["description" ] for e in c ._events ]
214+ assert "Collected dmesg rotated files" in descs
215+
216+
217+ def test_collect_rotations_no_files (monkeypatch , system_info , conn_mock ):
218+ def run_map (cmd , ** kwargs ):
219+ if cmd .startswith ("ls -1 /var/log/dmesg" ):
220+ return DummyRes (command = cmd , stdout = "" , exit_code = 0 )
221+ return DummyRes (command = cmd , stdout = "" , exit_code = 1 )
222+
223+ c = get_collector (monkeypatch , run_map , system_info , conn_mock )
224+
225+ collected = c ._collect_dmesg_rotations ()
226+
227+ assert collected == 0
228+ assert c .result .artifacts == []
229+
230+ events = c ._events
231+ assert any (
232+ e ["description" ].startswith ("No /var/log/dmesg files found" )
233+ and e ["priority" ].name == "WARNING"
234+ for e in events
235+ )
236+
237+
238+ def test_collect_rotations_gz_failure (monkeypatch , system_info , conn_mock ):
239+ ls_out = "/var/log/dmesg.2.gz\n "
240+
241+ def run_map (cmd , ** kwargs ):
242+ if cmd .startswith ("ls -1 /var/log/dmesg" ):
243+ return DummyRes (command = cmd , stdout = ls_out , exit_code = 0 )
244+ if "gzip -dc" in cmd and "/var/log/dmesg.2.gz" in cmd :
245+ return DummyRes (command = cmd , stdout = "" , exit_code = 1 , stderr = "gzip: not found" )
246+ return DummyRes (command = cmd , stdout = "" , exit_code = 1 )
247+
248+ c = get_collector (monkeypatch , run_map , system_info , conn_mock )
249+
250+ collected = c ._collect_dmesg_rotations ()
251+
252+ assert isinstance (collected , list )
253+ assert len (collected ) == 0
254+ assert c .result .artifacts == []
255+
256+ fail_events = [
257+ e for e in c ._events if e ["description" ] == "Some dmesg files could not be collected."
258+ ]
259+ assert fail_events , "Expected a failure event"
260+ failed = fail_events [- 1 ]["data" ]["failed" ]
261+ assert any (item ["path" ].endswith ("/var/log/dmesg.2.gz" ) for item in failed )
262+
263+
264+ def test_collect_data_integration (monkeypatch , system_info , conn_mock ):
265+ def run_map (cmd , ** kwargs ):
266+ if cmd == DmesgCollector .DMESG_CMD :
267+ return DummyRes (command = cmd , stdout = "DMESG OUTPUT\n " , exit_code = 0 )
268+ if cmd .startswith ("ls -1 /var/log/dmesg" ):
269+ return DummyRes (command = cmd , stdout = "/var/log/dmesg\n " , exit_code = 0 )
270+ if cmd .startswith ("cat '" ) and "/var/log/dmesg'" in cmd :
271+ return DummyRes (command = cmd , stdout = "dmesg file content\n " , exit_code = 0 )
272+ return DummyRes (command = cmd , stdout = "" , exit_code = 1 )
273+
274+ c = get_collector (monkeypatch , run_map , system_info , conn_mock )
275+
276+ result , data = c .collect_data ()
277+
278+ assert isinstance (data , DmesgData )
279+ assert data .dmesg_content == "DMESG OUTPUT\n "
280+
281+ assert len (c .result .artifacts ) == 1
282+ assert c .result .artifacts [0 ].filename == "dmesg.log"
283+ assert c .result .message == "Dmesg data collected"
0 commit comments