Skip to content

Commit 3b49235

Browse files
committed
Create unit tests for fw-logs
1 parent 2e1d522 commit 3b49235

File tree

2 files changed

+228
-0
lines changed

2 files changed

+228
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# License: Apache 2.0. See LICENSE file in root directory.
2+
# Copyright(c) 2025 Intel Corporation. All Rights Reserved.
3+
4+
# DDS devices have not implemented firmware_logger interface yet
5+
##test:donotrun:!dds
6+
#test:device each(D500*) !D555
7+
8+
from rspy import log, test
9+
from rspy import librs as rs
10+
import xml.etree.ElementTree as ET
11+
import os.path
12+
13+
# Working directory changes between manual runs and CI runs
14+
path = os.path.dirname( os.path.realpath(__file__) )
15+
16+
if log.is_debug_on():
17+
rs.log_to_console( rs.log_severity.debug )
18+
19+
with test.closure( 'Create the logger', on_fail=test.ABORT ):
20+
context = rs.context()
21+
dev = context.query_devices()[0]
22+
logger = dev.as_firmware_logger()
23+
test.check( logger )
24+
raw_message = logger.create_message()
25+
parsed_message = logger.create_parsed_message()
26+
27+
with test.closure( 'Create xml files', on_fail=test.ABORT ):
28+
# Events based on real events file, representing logs we are most likely to receive
29+
events_real = ET.fromstring(
30+
"""<Format>
31+
<Event id="50" numberOfArguments="0" format="Event50" />
32+
<Event id="52" numberOfArguments="3" format="Event52 Arg1:{0}, Arg2:{1}, Arg3:{2}" />
33+
<Event id="59" numberOfArguments="1" format="Event59 Arg1:{0}" />
34+
<File id="5" Name="File5" />
35+
<Module id="2" Name="Module2" />
36+
</Format>""" )
37+
events_real_path = os.path.join( path, 'events_real.xml' )
38+
ET.ElementTree( events_real ).write( events_real_path )
39+
40+
events_dummy = ET.fromstring(
41+
"""<Format>
42+
<Event id="1" numberOfArguments="0" format="Event1" />
43+
<Event id="2" numberOfArguments="0" format="Event2" />
44+
<File id="1" Name="File1" />
45+
<File id="2" Name="File2" />
46+
<Module id="1" Name="Module1" />
47+
<Module id="2" Name="Module2" />
48+
</Format>""" )
49+
events_dummy_path = os.path.join( path, 'events_dummy.xml' )
50+
ET.ElementTree( events_dummy ).write( events_dummy_path )
51+
52+
# Expected events are from source1 module2, set verbosity to "enable all"
53+
definitions = ET.fromstring(
54+
"""<Format>
55+
<Source id="0" Name="source1">
56+
<File Path="" />
57+
<Module id="1" verbosity="0" Name="source1module1" Path=""/>
58+
<Module id="2" verbosity="63" Name="source1module2" />
59+
</Source>
60+
<Source id="1" Name="source2">
61+
<File Path="" />
62+
<Module id="1" verbosity="0" Name="source2module1" />
63+
<Module id="2" verbosity="0" Name="source2module2" />
64+
</Source>
65+
<Source id="2" Name="source3">
66+
<File Path="" />
67+
<Module id="1" verbosity="0" Name="source3module1" />
68+
<Module id="2" verbosity="0" Name="source3module2" />
69+
</Source>
70+
</Format>""" )
71+
definitions[0][0].set( "Path", events_real_path )
72+
definitions[1][0].set( "Path", events_dummy_path )
73+
definitions[2][0].set( "Path", events_dummy_path )
74+
definitions_path = os.path.join( path, 'definitions.xml' )
75+
ET.ElementTree( definitions ).write( definitions_path )
76+
77+
with test.closure( 'Load unsupported definitions file' ):
78+
with open( events_real_path , 'r') as f:
79+
definitions = f.read()
80+
test.check_throws( lambda: logger.init_parser( definitions ), RuntimeError, "Did not find 'Source' node with id 0" )
81+
82+
with test.closure( 'Load supported definitions file' ):
83+
with open( definitions_path , 'r') as f:
84+
definitions = f.read()
85+
logger.init_parser( definitions )
86+
logger.start_collecting()
87+
logger.get_firmware_log( raw_message ) # Get a log entry from the camera with unknown content
88+
logger.parse_log( raw_message, parsed_message )
89+
log.d( 'Parsed message: ', parsed_message.get_message() )
90+
logger.stop_collecting()
91+
92+
with test.closure( 'All done' ):
93+
if os.path.exists( events_real_path ):
94+
os.remove( events_real_path )
95+
if os.path.exists( events_dummy_path ):
96+
os.remove( events_dummy_path )
97+
if os.path.exists( definitions_path ):
98+
os.remove( definitions_path )
99+
del dev
100+
del context
101+
102+
test.print_results()
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# License: Apache 2.0. See LICENSE file in root directory.
2+
# Copyright(c) 2025 Intel Corporation. All Rights Reserved.
3+
4+
# DDS devices have not implemented firmware_logger interface yet
5+
##test:donotrun:!dds
6+
#test:device each(D400*)
7+
8+
from rspy import log, test
9+
from rspy import librs as rs
10+
import xml.etree.ElementTree as ET
11+
import os.path
12+
13+
# Working directory changes between manual runs and CI runs
14+
path = os.path.dirname( os.path.realpath(__file__) )
15+
16+
if log.is_debug_on():
17+
rs.log_to_console( rs.log_severity.debug )
18+
19+
with test.closure( 'Create the logger', on_fail=test.ABORT ):
20+
context = rs.context()
21+
dev = context.query_devices()[0]
22+
logger = dev.as_firmware_logger()
23+
test.check( logger )
24+
raw_message = logger.create_message()
25+
parsed_message = logger.create_parsed_message()
26+
27+
with test.closure( 'Load unsupported definitions file' ):
28+
events = ET.fromstring(
29+
"""<Format>
30+
<Event id="0" numberOfArguments="0" format="Event0" />
31+
</Format>""" )
32+
events_path = os.path.join( path, 'events.xml' )
33+
ET.ElementTree( events ).write( events_path )
34+
definitions = ET.fromstring(
35+
"""<Format>
36+
<Source id="0" Name="source1">
37+
<File Path="" />
38+
<Module id="1" verbosity="0" Name="source0module1" />
39+
</Source>
40+
<Source id="1" Name="source2">
41+
<File Path="" />
42+
<Module id="1" verbosity="0" Name="source1module1" />
43+
</Source>
44+
</Format>""" )
45+
definitions[0][0].set( "Path", events_path )
46+
definitions[1][0].set( "Path", events_path )
47+
definitions_path = os.path.join( path, 'definitions.xml' )
48+
ET.ElementTree( definitions ).write( definitions_path )
49+
with open( definitions_path, 'r') as f:
50+
definitions = f.read()
51+
logger.init_parser( definitions )
52+
logger.get_firmware_log( raw_message ) # Get a log entry from the camera with unknown content
53+
test.check_throws( lambda: logger.parse_log( raw_message, parsed_message ), RuntimeError, 'FW logs parser expect one formating options, have 2' )
54+
55+
with test.closure( 'Load supported definitions file' ):
56+
# Events based on real events file, representing logs we are most likely to receive
57+
# Use all entry options - Event, File, Thread, Enum
58+
events = ET.fromstring(
59+
"""<Format>
60+
<Event id="37" numberOfArguments="3" format="Event37 Arg1:{0} Arg2:{1}, Arg3:0x{2:x}" />
61+
<Event id="49" numberOfArguments="3" format="Event49 Arg1:{0} EnumArg2: {1,ETSystemSubStates} EnumArg3: {2,ETSystemSubStates}" />
62+
<Event id="90" numberOfArguments="3" format="Event90 Arg1:0x{0:x}, Arg2:{1}, Arg3:0x{2:x}" />
63+
<Event id="272" numberOfArguments="1" format="Event272 Arg1 0x{0:x}" />
64+
<Event id="277" numberOfArguments="2" format="Event277 Arg1 0x{0:x}, Arg2 0x{1:x}" />
65+
<Event id="304" numberOfArguments="1" format="Event304 Arg1 0x{0:x}" />
66+
<Event id="380" numberOfArguments="1" format="Event380 Arg1:{0:x}" />
67+
<File id="13" Name="File13" />
68+
<File id="29" Name="File29" />
69+
<File id="49" Name="File49" />
70+
<Thread id="0" Name="Thread0" />
71+
<Thread id="7" Name="Thread7" />
72+
<Enums>
73+
<Enum Name="ETSystemSubStates">
74+
<EnumValue Key="0" Value="Enum1Litteral0" />
75+
<EnumValue Key="1" Value="Enum1Litteral1" />
76+
<EnumValue Key="2" Value="Enum1Litteral2" />
77+
<EnumValue Key="4" Value="Enum1Litteral4" />
78+
<EnumValue Key="8" Value="Enum1Litteral8" />
79+
<EnumValue Key="16" Value="Enum1Litteral16" />
80+
<EnumValue Key="32" Value="Enum1Litteral32" />
81+
<EnumValue Key="64" Value="Enum1Litteral64" />
82+
<EnumValue Key="128" Value="Enum1Litteral128" />
83+
</Enum>
84+
</Enums>
85+
</Format>""" )
86+
events_path = os.path.join( path, 'events.xml' )
87+
ET.ElementTree( events ).write( events_path )
88+
definitions = ET.fromstring(
89+
"""<Format>
90+
<Source id="0" Name="DS5">
91+
<File Path="" />
92+
</Source>
93+
</Format>""" )
94+
definitions[0][0].set( "Path", events_path )
95+
definitions_path = os.path.join( path, 'definitions.xml' )
96+
ET.ElementTree( definitions ).write( definitions_path )
97+
with open( definitions_path, 'r') as f:
98+
definitions = f.read()
99+
logger.init_parser( definitions )
100+
try:
101+
logger.get_firmware_log( raw_message ) # Get a log entry from the camera with unknown content
102+
logger.parse_log( raw_message, parsed_message )
103+
log.d( 'Parsed message: ', parsed_message.get_message() )
104+
except:
105+
test.unexpected_exception()
106+
107+
with test.closure( 'Load events file directly' ):
108+
with open( events_path, 'r') as f:
109+
events = f.read()
110+
logger.init_parser( events )
111+
try:
112+
logger.get_firmware_log( raw_message ) # Get a log entry from the camera with unknown content
113+
logger.parse_log( raw_message, parsed_message )
114+
log.d( 'Parsed message: ', parsed_message.get_message() )
115+
except:
116+
test.unexpected_exception()
117+
118+
with test.closure( 'All done' ):
119+
if os.path.exists( events_path ):
120+
os.remove( events_path )
121+
if os.path.exists( definitions_path ):
122+
os.remove( definitions_path )
123+
del dev
124+
del context
125+
126+
test.print_results()

0 commit comments

Comments
 (0)