Block-based Testing Guidelines
Guidelines for testing block-based components in this SDR component library.
Introduction
Components that process samples in groups should use the block-based generators in ocpi_testing, which produce sample messages with consideration for the processing length. Examples of block-based components include:
Framer components, where samples are processed in an internal buffer and are only output once the buffer is full.
Decimating components, where the sampling rate is reduced.
Any other component with an internal buffer or run-length processing where the grouping of samples is significant.
Unit Test XML Description File
Test cases are ordered as follows in the unit test description XML file:
typical
property
sample
input_stressing
message_size
time
sample_interval
flush
discontinuity
metadata
time_calculation
opcode_interaction
custom(only if custom input data is required)
soak
Typical
This is to test a component under normal operating circumstances, with property values set to that which is considered “typical”. The generated input data contains only sample messages.
<tests usehdlfileio="true">
<property test="true" name="subcase" type="string"/>
<case>
<input port="input" script="generate.py --case typical" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
</case>
Property
A separate test case exists for each of the properties of a component, in this example there are two properties. The properties are individually set to different values around zero, minimum and maximum to thoroughly exercise them.
In this worked example we will take A to be a short, where the minimum is -32768 and the maximum is 32767. B is a boolean and therefore setting it to the inverse of its value in the typical test case is sufficient.
Note that for all other test cases properties should generally use the same values as the typical test case, apart from the property test case where they are being exercised, or the final soak test where they are set to random values.
The generated input data contains only sample messages.
<case>
<input port="input" script="generate.py --case property" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" values="0,1,-1,2,-2,100,-100,1024,-1024,32766,32767,-32767,-32768"/>
<property name="my_component_s.hdl.B" value="false"/>
</case>
<case>
<input port="input" script="generate.py --case property" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="true"/>
</case>
Sample
This test case generates only sample messages whose samples are around an order of magnitude defined by subcase. Since the component input port is of type short (“_s” suffix implies both input and output ports are short), the subcases result in the following input data being generated:
all_zerois only 0sall_maximumis only 32767sall_minimumis only -32768slarge_positiveis values near 32767large_negativeis values near -32768near_zerois values near 0randomis random values that are a subset of the supported range of shortsinusoidalis the superposition of several sinusoidal waves
<case>
<input port="input" script="generate.py --case sample" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
<property name="subcase" values="all_zero,all_maximum,all_minimum,large_positive,large_negative,near_zero,random,sinusoidal">
</case>
Depending on the input port type, options for different subcase values exist.
Input Type |
Subcase Values |
|---|---|
Boolean |
all_zero,all_maximum |
Character, Short, Long, Long-long |
all_zero,all_maximum,all_minimum,large_positive,
large_negative,near_zero,random,sinusoidal
|
Unsigned Character, Unsigned Short,
Unsigned Long, Unsigned Long-long
|
all_zero,all_maximum,large_positive,near_zero,
random,sinusoidal
|
Complex Character, Complex Short,
Complex Long, Complex Long-long
|
all_zero,all_maximum,all_minimum,real_zero,imaginary_zero,
large_positive,large_negative,near_zero,random,sinusoidal
|
Float, Double |
all_zero,all_maximum,all_minimum,large_positive,
large_negative,near_zero,positive_infinity,
negative_infinity,not_a_number,random,sinusoidal
|
Complex Float, Complex Double |
all_zero,all_maximum,all_minimum,real_zero,imaginary_zero,
large_positive,large_negative,near_zero,positive_infinity,
negative_infinity,not_a_number,random,sinusoidal
|
Input Stressing
Setting stressormode to full varies the range of input behaviour to provide coverage of what HDL workers might see on their input ports.
The generated input data contains only sample messages.
<case>
<input port="input" script="generate.py --case input_stressing" messagesinfile="true" messagesize="16384" stressormode="full"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
</case>
Message Size
This tests a component’s ability to process shortest, longest and mixed message sizes. For the short timed sample protocol, the “shortest” message size contains 1 sample, which is 2 bytes long, and the “longest” message size contains 8192 samples, which is 16384 bytes / 2 bytes. The “different_sizes” subcase value results in a mixture of different message sizes being generated.
The generated input data contains only sample messages.
<case>
<input port="input" script="generate.py --case message_size" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
<property name="subcase" values="shortest,longest,different_sizes">
</case>
Time
The generated input data for this test is a sample message, followed by a time message, and a final sample message. The subcase value determines the value of the time message.
Other subcases are:
single: Generates atimemessage first, and again between blocks.
intra_single: Generates atimemessage in the middle of a block.
consecutive: Generates two consecutivetimemessages between blocks.
intra_consecutive: Generates two consecutivetimemessages in the middle of a block.
intra_multiple: Generatestimemessages with various buffer fill states.
<case>
<input port="input" script="generate.py --case time" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
<property name="subcase" values="zero,positive,maximum,single,intra_single,consecutive,intra_consecutive,intra_multiple">
</case>
Sample Interval
The generated input data for this test is a sample message, followed by a sample_interval message, and a final sample message. The subcase value determines the value of the sample_interval message.
Other subcases are:
single: Generates asample_intervalmessage first, and again between blocks.
intra_single: Generates asample_intervalmessage in the middle of a block.
consecutive: Generates two consecutivesample_intervalmessages between blocks.
intra_consecutive: Generates two consecutivesample_intervalmessages in the middle of a block.
intra_multiple: Generatessample_intervalmessages with various buffer fill states.
<case>
<input port="input" script="generate.py --case sample_interval" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
<property name="subcase" values="zero,positive,maximum,single,intra_single,consecutive,intra_consecutive,intra_multiple">
</case>
Flush
The following subcases are supported:
single: Generates aflushmessage first, and again between blocks.
intra_single: Generates aflushmessage in the middle of a block.
consecutive: Generates two consecutiveflushmessages between blocks.
intra_consecutive: Generates two consecutiveflushmessages in the middle of a block.
intra_multiple: Generatesflushmessages with various buffer fill states.
<case>
<input port="input" script="generate.py --case flush" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
<property name="subcase" values="single,intra_single,consecutive,intra_consecutive,intra_multiple">
</case>
Discontinuity
The following subcases are supported:
single: Generates adiscontinuitymessage first, and again between blocks.
intra_single: Generates adiscontinuitymessage in the middle of a block.
consecutive: Generates two consecutivediscontinuitymessages between blocks.
intra_consecutive: Generates two consecutivediscontinuitymessages in the middle of a block.
intra_multiple: Generatesdiscontinuitymessages with various buffer fill states.
<case>
<input port="input" script="generate.py --case discontinuity" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
<property name="subcase" values="single,intra_single,consecutive,intra_consecutive,intra_multiple">
</case>
Metadata
The generated input data for this test is a sample message, followed by a metadata message, and a final sample message. The subcase value determines the value of the metadata message.
Other subcases are:
none: Generates onlysamplemessages.
single: Generates ametadatamessage first, and again between blocks.
intra_single: Generates ametadatamessage in the middle of a block.
consecutive: Generates two consecutivemetadatamessages between blocks.
intra_consecutive: Generates two consecutivemetadatamessages in the middle of a block.
intra_multiple: Generatesmetadatamessages with various buffer fill states.
<case>
<input port="input" script="generate.py --case metadata" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
<property name="subcase" values="zero,positive,maximum,none,single,intra_single,consecutive,intra_consecutive,intra_multiple">
</case>
Time Calculation
The generated input data contains sample_interval, time, and sample messages to test the ability of a component to calculate and output correct time and sample interval values. All subcases include a non-zero sample_interval as the first message and have a flush message at the end.
The following subcases are supported:
interval_change: Generates a change in sample interval during a partially filled buffer.
time_change: Generates a change in time during a partially filled buffer.
minimum_increment: Generates the smallest validsample_intervalto test minimum time increments.
single: Generates atimemessage, and again between blocks.
intra_single: Generates atimemessage in the middle of a block.
consecutive: Generates two consecutivetimemessages between blocks.
intra_consecutive: Generates two consecutivetimemessages in the middle of a block.
intra_multiple: Generatestimemessages with various buffer fill states.
<case>
<input port="input" script="generate.py --case time_calculation" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
<property name="subcase" values="interval_change,time_change,minimum_increment,single,intra_single,consecutive,intra_consecutive,intra_multiple">
</case>
Opcode Interaction
The generated input data contains messages to test the interaction between and re-ordering of different messages and buffer fill states. All subcases include a non-zero sample_interval as the first message.
The following subcases are supported:
time_flush: Generatestime,flushandsamplemessages for interaction testing.
time_discontinuity: Generatestime,discontinuityandsamplemessages for interaction testing.
time_metadata: Generatestime,metadataandsamplemessages for interaction testing. Four consecutive metadata opcodes are generated, which can be used to test metadata FIFO overflow handling (by setting the FIFO size to less than four).
all_opcodes: Generates all permutations of messages. This is suited to components with complex message interactions where the previous tests might not pick up all edge cases.
single: Generates atimemessage, and again between blocks.
intra_single: Generates atimemessage in the middle of a block.
consecutive: Generates two consecutivetimemessages between blocks.
intra_consecutive: Generates two consecutivetimemessages in the middle of a block.
intra_multiple: Generatestimemessages with various buffer fill states.
<case>
<input port="input" script="generate.py --case opcode_interaction" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="fifo_size" values="4,3"/>
<property name="my_component_s.hdl.B" value="false"/>
<property name="subcase" values="time_flush,time_discontinuity,time_metadata,all_opcodes,single,intra_single,consecutive,intra_consecutive,intra_multiple">
</case>
Custom
If a custom test case is required, the Generator() class custom method in generate.py can be overridden. The subcase property allows for multiple tests with different generated input data.
<case>
<input port="input" script="generate.py --case custom" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" value="1"/>
<property name="my_component_s.hdl.B" value="false"/>
<property name="subcase" values="custom_test_1,custom_test_2">
</case>
Soak
The final soak test exercises random combinations of property values and generated input data. Multiple random property values are selected for this test. When the subcase value is sample_only only sample message are generated on the input, and when it is all_opcodes a mix of message types is generated.
<case>
<input port="input" script="generate.py --case soak" messagesinfile="true" messagesize="16384"/>
<output port="output" script="verify.py" messagesinfile="true"/>
<property name="A" values="22756,-12173,-23562,2742,10479,31312,6912,-1850"/>
<property name="my_component_s.hdl.B" values="false,true"/>
<property name="subcase" values="sample_only,all_opcodes">
</case>
</tests>