mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-04-09 08:21:08 -04:00
test: add AVTP audio data path tests
Add 10 Phase 6 tests for the AVTP audio data path: - IEC61883 and AAF packet structure layout validation - 802.1Q frame header construction - PDU size calculations for various audio configurations - Ringbuffer audio data round-trip integrity - Ringbuffer wrap-around with multiple PDU-sized writes - IEC61883 receive simulation (packet → ringbuffer) - IEC61883 transmit PDU construction and field verification - Ringbuffer overrun detection - Sequence number and DBC counter wrapping These tests validate the AVTP packet formats and audio data path logic without requiring hardware, AF_PACKET sockets, or CLOCK_TAI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fdfede8b96
commit
cec53759dd
2 changed files with 523 additions and 0 deletions
|
|
@ -20,6 +20,9 @@
|
|||
#include "module-avb/aecp-aem.h"
|
||||
#include "module-avb/aecp-aem-descriptors.h"
|
||||
#include "module-avb/aecp-aem-state.h"
|
||||
#include "module-avb/iec61883.h"
|
||||
#include "module-avb/aaf.h"
|
||||
#include "module-avb/stream.h"
|
||||
#include "module-avb/descriptors.h"
|
||||
#include "module-avb/avb-transport-loopback.h"
|
||||
|
||||
|
|
|
|||
520
test/test-avb.c
520
test/test-avb.c
|
|
@ -2060,6 +2060,514 @@ PWTEST(avb_aecp_read_descriptor_milan)
|
|||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
/*
|
||||
* =====================================================================
|
||||
* Phase 6: AVTP Audio Data Path Tests
|
||||
* =====================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test: Verify IEC61883 packet struct layout and size.
|
||||
* The struct must be exactly 24 bytes (packed) for the header,
|
||||
* followed by the flexible payload array.
|
||||
*/
|
||||
PWTEST(avb_iec61883_packet_layout)
|
||||
{
|
||||
struct avb_packet_iec61883 pkt;
|
||||
struct avb_frame_header fh;
|
||||
|
||||
/* IEC61883 header (packed) with CIP fields = 32 bytes */
|
||||
pwtest_int_eq((int)sizeof(struct avb_packet_iec61883), 32);
|
||||
|
||||
/* Frame header with 802.1Q tag should be 18 bytes */
|
||||
pwtest_int_eq((int)sizeof(struct avb_frame_header), 18);
|
||||
|
||||
/* Total PDU header = frame_header + iec61883 = 50 bytes */
|
||||
pwtest_int_eq((int)(sizeof(fh) + sizeof(pkt)), 50);
|
||||
|
||||
/* Verify critical field positions by setting and reading */
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.subtype = AVB_SUBTYPE_61883_IIDC;
|
||||
pwtest_int_eq(pkt.subtype, 0x00);
|
||||
|
||||
pkt.sv = 1;
|
||||
pkt.tv = 1;
|
||||
pkt.seq_num = 42;
|
||||
pkt.stream_id = htobe64(0x020000fffe000001ULL);
|
||||
pkt.timestamp = htonl(1000000);
|
||||
pkt.data_len = htons(200);
|
||||
pkt.tag = 0x1;
|
||||
pkt.channel = 0x1f;
|
||||
pkt.tcode = 0xa;
|
||||
pkt.sid = 0x3f;
|
||||
pkt.dbs = 8;
|
||||
pkt.qi2 = 0x2;
|
||||
pkt.format_id = 0x10;
|
||||
pkt.fdf = 0x2;
|
||||
pkt.syt = htons(0x0008);
|
||||
pkt.dbc = 0;
|
||||
|
||||
/* Read back and verify */
|
||||
pwtest_int_eq(pkt.seq_num, 42);
|
||||
pwtest_int_eq(pkt.dbs, 8);
|
||||
pwtest_int_eq(be64toh(pkt.stream_id), (int64_t)0x020000fffe000001ULL);
|
||||
pwtest_int_eq(ntohs(pkt.data_len), 200);
|
||||
pwtest_int_eq((int)pkt.sv, 1);
|
||||
pwtest_int_eq((int)pkt.tv, 1);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test: Verify AAF packet struct layout.
|
||||
*/
|
||||
PWTEST(avb_aaf_packet_layout)
|
||||
{
|
||||
struct avb_packet_aaf pkt;
|
||||
|
||||
/* AAF header should be 24 bytes (same as IEC61883) */
|
||||
pwtest_int_eq((int)sizeof(struct avb_packet_aaf), 24);
|
||||
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
pkt.subtype = AVB_SUBTYPE_AAF;
|
||||
pkt.sv = 1;
|
||||
pkt.tv = 1;
|
||||
pkt.seq_num = 99;
|
||||
pkt.stream_id = htobe64(0x020000fffe000002ULL);
|
||||
pkt.timestamp = htonl(2000000);
|
||||
pkt.format = AVB_AAF_FORMAT_INT_24BIT;
|
||||
pkt.nsr = AVB_AAF_PCM_NSR_48KHZ;
|
||||
pkt.chan_per_frame = 8;
|
||||
pkt.bit_depth = 24;
|
||||
pkt.data_len = htons(192); /* 6 frames * 8 channels * 4 bytes */
|
||||
pkt.sp = AVB_AAF_PCM_SP_NORMAL;
|
||||
|
||||
pwtest_int_eq(pkt.subtype, AVB_SUBTYPE_AAF);
|
||||
pwtest_int_eq(pkt.seq_num, 99);
|
||||
pwtest_int_eq(pkt.format, AVB_AAF_FORMAT_INT_24BIT);
|
||||
pwtest_int_eq((int)pkt.nsr, AVB_AAF_PCM_NSR_48KHZ);
|
||||
pwtest_int_eq(pkt.chan_per_frame, 8);
|
||||
pwtest_int_eq(pkt.bit_depth, 24);
|
||||
pwtest_int_eq(ntohs(pkt.data_len), 192);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test: 802.1Q frame header construction for AVB.
|
||||
*/
|
||||
PWTEST(avb_frame_header_construction)
|
||||
{
|
||||
struct avb_frame_header h;
|
||||
static const uint8_t dest[6] = { 0x91, 0xe0, 0xf0, 0x00, 0x01, 0x00 };
|
||||
static const uint8_t src[6] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 };
|
||||
int prio = 3;
|
||||
int vlan_id = 2;
|
||||
|
||||
memset(&h, 0, sizeof(h));
|
||||
memcpy(h.dest, dest, 6);
|
||||
memcpy(h.src, src, 6);
|
||||
h.type = htons(0x8100); /* 802.1Q VLAN tag */
|
||||
h.prio_cfi_id = htons((prio << 13) | vlan_id);
|
||||
h.etype = htons(0x22f0); /* AVB/TSN EtherType */
|
||||
|
||||
/* Verify the 802.1Q header */
|
||||
pwtest_int_eq(ntohs(h.type), 0x8100);
|
||||
pwtest_int_eq(ntohs(h.etype), 0x22f0);
|
||||
|
||||
/* Extract priority from prio_cfi_id */
|
||||
pwtest_int_eq((ntohs(h.prio_cfi_id) >> 13) & 0x7, prio);
|
||||
/* Extract VLAN ID (lower 12 bits) */
|
||||
pwtest_int_eq(ntohs(h.prio_cfi_id) & 0xFFF, vlan_id);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test: PDU size calculations for various audio configurations.
|
||||
* Verifies the math used in setup_pdu().
|
||||
*/
|
||||
PWTEST(avb_pdu_size_calculations)
|
||||
{
|
||||
size_t hdr_size, payload_size, pdu_size;
|
||||
int64_t pdu_period;
|
||||
|
||||
/* Default config: 8 channels, S24_32_BE (4 bytes), 6 frames/PDU, 48kHz */
|
||||
int channels = 8;
|
||||
int sample_size = 4; /* S24_32_BE */
|
||||
int frames_per_pdu = 6;
|
||||
int rate = 48000;
|
||||
int stride = channels * sample_size;
|
||||
|
||||
hdr_size = sizeof(struct avb_frame_header) + sizeof(struct avb_packet_iec61883);
|
||||
payload_size = stride * frames_per_pdu;
|
||||
pdu_size = hdr_size + payload_size;
|
||||
pdu_period = SPA_NSEC_PER_SEC * frames_per_pdu / rate;
|
||||
|
||||
/* Header: 18 (frame) + 32 (iec61883) = 50 bytes */
|
||||
pwtest_int_eq((int)hdr_size, 50);
|
||||
|
||||
/* Payload: 8 ch * 4 bytes * 6 frames = 192 bytes */
|
||||
pwtest_int_eq((int)payload_size, 192);
|
||||
|
||||
/* Total PDU: 50 + 192 = 242 bytes */
|
||||
pwtest_int_eq((int)pdu_size, 242);
|
||||
|
||||
/* PDU period: 6/48000 seconds = 125000 ns = 125 us */
|
||||
pwtest_int_eq((int)pdu_period, 125000);
|
||||
|
||||
/* Stride: 8 * 4 = 32 bytes per frame */
|
||||
pwtest_int_eq(stride, 32);
|
||||
|
||||
/* IEC61883 data_len field = payload + 8 CIP header bytes */
|
||||
pwtest_int_eq((int)(payload_size + 8), 200);
|
||||
|
||||
/* 2-channel configuration */
|
||||
channels = 2;
|
||||
stride = channels * sample_size;
|
||||
payload_size = stride * frames_per_pdu;
|
||||
pwtest_int_eq((int)payload_size, 48);
|
||||
pwtest_int_eq(stride, 8);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test: Ringbuffer audio data round-trip.
|
||||
* Write audio frames to the ringbuffer, read them back, verify integrity.
|
||||
*/
|
||||
PWTEST(avb_ringbuffer_audio_roundtrip)
|
||||
{
|
||||
struct spa_ringbuffer ring;
|
||||
uint8_t buffer[BUFFER_SIZE];
|
||||
int stride = 32; /* 8 channels * 4 bytes */
|
||||
int frames = 48; /* 48 frames = 1ms at 48kHz */
|
||||
int n_bytes = frames * stride;
|
||||
uint8_t write_data[2048];
|
||||
uint8_t read_data[2048];
|
||||
uint32_t index;
|
||||
int32_t avail;
|
||||
|
||||
spa_ringbuffer_init(&ring);
|
||||
|
||||
/* Fill write_data with a recognizable pattern */
|
||||
for (int i = 0; i < n_bytes; i++)
|
||||
write_data[i] = (uint8_t)(i & 0xFF);
|
||||
|
||||
/* Write to ringbuffer */
|
||||
avail = spa_ringbuffer_get_write_index(&ring, &index);
|
||||
pwtest_int_eq(avail, 0);
|
||||
|
||||
spa_ringbuffer_write_data(&ring, buffer, sizeof(buffer),
|
||||
index % sizeof(buffer), write_data, n_bytes);
|
||||
index += n_bytes;
|
||||
spa_ringbuffer_write_update(&ring, index);
|
||||
|
||||
/* Read back from ringbuffer */
|
||||
avail = spa_ringbuffer_get_read_index(&ring, &index);
|
||||
pwtest_int_eq(avail, n_bytes);
|
||||
|
||||
spa_ringbuffer_read_data(&ring, buffer, sizeof(buffer),
|
||||
index % sizeof(buffer), read_data, n_bytes);
|
||||
index += n_bytes;
|
||||
spa_ringbuffer_read_update(&ring, index);
|
||||
|
||||
/* Verify data integrity */
|
||||
pwtest_int_eq(memcmp(write_data, read_data, n_bytes), 0);
|
||||
|
||||
/* After read, buffer should be empty */
|
||||
avail = spa_ringbuffer_get_read_index(&ring, &index);
|
||||
pwtest_int_eq(avail, 0);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test: Ringbuffer wrap-around behavior with multiple writes.
|
||||
* Simulates multiple PDU-sized writes filling past the buffer end.
|
||||
*/
|
||||
PWTEST(avb_ringbuffer_wraparound)
|
||||
{
|
||||
struct spa_ringbuffer ring;
|
||||
uint8_t *buffer;
|
||||
int stride = 32;
|
||||
int frames_per_pdu = 6;
|
||||
int payload_size = stride * frames_per_pdu; /* 192 bytes */
|
||||
int num_writes = (BUFFER_SIZE / payload_size) + 5; /* Write past buffer end */
|
||||
uint8_t write_data[192];
|
||||
uint8_t read_data[192];
|
||||
uint32_t w_index, r_index;
|
||||
int32_t avail;
|
||||
|
||||
buffer = calloc(1, BUFFER_SIZE);
|
||||
pwtest_ptr_notnull(buffer);
|
||||
|
||||
spa_ringbuffer_init(&ring);
|
||||
|
||||
/* Write many PDU payloads, reading as we go to prevent overrun */
|
||||
for (int i = 0; i < num_writes; i++) {
|
||||
/* Fill with per-PDU pattern */
|
||||
memset(write_data, (uint8_t)(i + 1), payload_size);
|
||||
|
||||
avail = spa_ringbuffer_get_write_index(&ring, &w_index);
|
||||
spa_ringbuffer_write_data(&ring, buffer, BUFFER_SIZE,
|
||||
w_index % BUFFER_SIZE, write_data, payload_size);
|
||||
w_index += payload_size;
|
||||
spa_ringbuffer_write_update(&ring, w_index);
|
||||
|
||||
/* Read it back immediately */
|
||||
avail = spa_ringbuffer_get_read_index(&ring, &r_index);
|
||||
pwtest_int_eq(avail, payload_size);
|
||||
|
||||
spa_ringbuffer_read_data(&ring, buffer, BUFFER_SIZE,
|
||||
r_index % BUFFER_SIZE, read_data, payload_size);
|
||||
r_index += payload_size;
|
||||
spa_ringbuffer_read_update(&ring, r_index);
|
||||
|
||||
/* Verify the pattern survived the wrap-around */
|
||||
for (int j = 0; j < payload_size; j++) {
|
||||
if (read_data[j] != (uint8_t)(i + 1)) {
|
||||
free(buffer);
|
||||
return PWTEST_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test: IEC61883 packet receive simulation.
|
||||
* Builds IEC61883 packets and writes their payload into a ringbuffer,
|
||||
* mirroring the logic of handle_iec61883_packet().
|
||||
*/
|
||||
PWTEST(avb_iec61883_receive_simulation)
|
||||
{
|
||||
struct spa_ringbuffer ring;
|
||||
uint8_t *rb_buffer;
|
||||
uint8_t pkt_buf[2048];
|
||||
struct avb_frame_header *h;
|
||||
struct avb_packet_iec61883 *p;
|
||||
int channels = 8;
|
||||
int sample_size = 4;
|
||||
int stride = channels * sample_size;
|
||||
int frames_per_pdu = 6;
|
||||
int payload_size = stride * frames_per_pdu; /* 192 bytes */
|
||||
int n_packets = 10;
|
||||
uint32_t index;
|
||||
int32_t filled;
|
||||
uint8_t read_data[192];
|
||||
|
||||
rb_buffer = calloc(1, BUFFER_SIZE);
|
||||
pwtest_ptr_notnull(rb_buffer);
|
||||
spa_ringbuffer_init(&ring);
|
||||
|
||||
for (int i = 0; i < n_packets; i++) {
|
||||
/* Build a receive packet like on_socket_data() would see */
|
||||
memset(pkt_buf, 0, sizeof(pkt_buf));
|
||||
h = (struct avb_frame_header *)pkt_buf;
|
||||
p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
p->subtype = AVB_SUBTYPE_61883_IIDC;
|
||||
p->sv = 1;
|
||||
p->tv = 1;
|
||||
p->seq_num = i;
|
||||
p->stream_id = htobe64(0x020000fffe000001ULL);
|
||||
p->timestamp = htonl(i * 125000);
|
||||
p->data_len = htons(payload_size + 8); /* payload + 8 CIP bytes */
|
||||
p->tag = 0x1;
|
||||
p->dbs = channels;
|
||||
p->dbc = i * frames_per_pdu;
|
||||
|
||||
/* Fill payload with audio-like pattern */
|
||||
for (int j = 0; j < payload_size; j++)
|
||||
p->payload[j] = (uint8_t)((i * payload_size + j) & 0xFF);
|
||||
|
||||
/* Simulate handle_iec61883_packet() logic */
|
||||
{
|
||||
int n_bytes = ntohs(p->data_len) - 8;
|
||||
pwtest_int_eq(n_bytes, payload_size);
|
||||
|
||||
filled = spa_ringbuffer_get_write_index(&ring, &index);
|
||||
|
||||
if (filled + (int32_t)n_bytes <= (int32_t)BUFFER_SIZE) {
|
||||
spa_ringbuffer_write_data(&ring, rb_buffer, BUFFER_SIZE,
|
||||
index % BUFFER_SIZE, p->payload, n_bytes);
|
||||
index += n_bytes;
|
||||
spa_ringbuffer_write_update(&ring, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify all packets were received */
|
||||
filled = spa_ringbuffer_get_read_index(&ring, &index);
|
||||
pwtest_int_eq(filled, n_packets * payload_size);
|
||||
|
||||
/* Read back first packet's data and verify */
|
||||
spa_ringbuffer_read_data(&ring, rb_buffer, BUFFER_SIZE,
|
||||
index % BUFFER_SIZE, read_data, payload_size);
|
||||
|
||||
for (int j = 0; j < payload_size; j++) {
|
||||
if (read_data[j] != (uint8_t)(j & 0xFF)) {
|
||||
free(rb_buffer);
|
||||
return PWTEST_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
free(rb_buffer);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test: IEC61883 transmit PDU construction simulation.
|
||||
* Builds PDU like setup_pdu() + flush_write() would, verifies structure.
|
||||
*/
|
||||
PWTEST(avb_iec61883_transmit_pdu)
|
||||
{
|
||||
uint8_t pdu[2048];
|
||||
struct avb_frame_header *h;
|
||||
struct avb_packet_iec61883 *p;
|
||||
static const uint8_t dest[6] = { 0x91, 0xe0, 0xf0, 0x00, 0x01, 0x00 };
|
||||
static const uint8_t src[6] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 };
|
||||
int channels = 8;
|
||||
int stride = channels * 4;
|
||||
int frames_per_pdu = 6;
|
||||
int payload_size = stride * frames_per_pdu;
|
||||
int prio = 3;
|
||||
int vlan_id = 2;
|
||||
uint64_t stream_id = 0x020000fffe000001ULL;
|
||||
|
||||
/* Simulate setup_pdu() */
|
||||
memset(pdu, 0, sizeof(pdu));
|
||||
h = (struct avb_frame_header *)pdu;
|
||||
p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
memcpy(h->dest, dest, 6);
|
||||
memcpy(h->src, src, 6);
|
||||
h->type = htons(0x8100);
|
||||
h->prio_cfi_id = htons((prio << 13) | vlan_id);
|
||||
h->etype = htons(0x22f0);
|
||||
|
||||
p->subtype = AVB_SUBTYPE_61883_IIDC;
|
||||
p->sv = 1;
|
||||
p->stream_id = htobe64(stream_id);
|
||||
p->data_len = htons(payload_size + 8);
|
||||
p->tag = 0x1;
|
||||
p->channel = 0x1f;
|
||||
p->tcode = 0xa;
|
||||
p->sid = 0x3f;
|
||||
p->dbs = channels;
|
||||
p->qi2 = 0x2;
|
||||
p->format_id = 0x10;
|
||||
p->fdf = 0x2;
|
||||
p->syt = htons(0x0008);
|
||||
|
||||
/* Simulate flush_write() per-PDU setup */
|
||||
p->seq_num = 0;
|
||||
p->tv = 1;
|
||||
p->timestamp = htonl(125000);
|
||||
p->dbc = 0;
|
||||
|
||||
/* Verify the PDU */
|
||||
pwtest_int_eq(p->subtype, AVB_SUBTYPE_61883_IIDC);
|
||||
pwtest_int_eq(be64toh(p->stream_id), (int64_t)stream_id);
|
||||
pwtest_int_eq(ntohs(p->data_len), payload_size + 8);
|
||||
pwtest_int_eq(p->dbs, channels);
|
||||
pwtest_int_eq(p->seq_num, 0);
|
||||
pwtest_int_eq((int)ntohl(p->timestamp), 125000);
|
||||
pwtest_int_eq(p->dbc, 0);
|
||||
pwtest_int_eq(ntohs(h->etype), 0x22f0);
|
||||
|
||||
/* Simulate second PDU — verify sequence and DBC advance */
|
||||
p->seq_num = 1;
|
||||
p->timestamp = htonl(250000);
|
||||
p->dbc = frames_per_pdu;
|
||||
|
||||
pwtest_int_eq(p->seq_num, 1);
|
||||
pwtest_int_eq(p->dbc, frames_per_pdu);
|
||||
pwtest_int_eq((int)ntohl(p->timestamp), 250000);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test: Ringbuffer overrun detection.
|
||||
* Simulates the overrun check in handle_iec61883_packet().
|
||||
*/
|
||||
PWTEST(avb_ringbuffer_overrun)
|
||||
{
|
||||
struct spa_ringbuffer ring;
|
||||
uint8_t *buffer;
|
||||
uint8_t data[256];
|
||||
uint32_t index;
|
||||
int32_t filled;
|
||||
int payload_size = 192;
|
||||
int overrun_count = 0;
|
||||
|
||||
buffer = calloc(1, BUFFER_SIZE);
|
||||
pwtest_ptr_notnull(buffer);
|
||||
spa_ringbuffer_init(&ring);
|
||||
|
||||
memset(data, 0xAA, sizeof(data));
|
||||
|
||||
/* Fill the buffer to capacity */
|
||||
int max_writes = BUFFER_SIZE / payload_size;
|
||||
for (int i = 0; i < max_writes; i++) {
|
||||
filled = spa_ringbuffer_get_write_index(&ring, &index);
|
||||
if (filled + payload_size > (int32_t)BUFFER_SIZE) {
|
||||
overrun_count++;
|
||||
break;
|
||||
}
|
||||
spa_ringbuffer_write_data(&ring, buffer, BUFFER_SIZE,
|
||||
index % BUFFER_SIZE, data, payload_size);
|
||||
index += payload_size;
|
||||
spa_ringbuffer_write_update(&ring, index);
|
||||
}
|
||||
|
||||
/* Try one more write — should detect overrun */
|
||||
filled = spa_ringbuffer_get_write_index(&ring, &index);
|
||||
if (filled + payload_size > (int32_t)BUFFER_SIZE)
|
||||
overrun_count++;
|
||||
|
||||
/* Should have hit at least one overrun */
|
||||
pwtest_int_gt(overrun_count, 0);
|
||||
|
||||
/* Verify data still readable from the full buffer */
|
||||
filled = spa_ringbuffer_get_read_index(&ring, &index);
|
||||
pwtest_int_gt(filled, 0);
|
||||
|
||||
free(buffer);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test: Sequence number wrapping at 256 (uint8_t).
|
||||
* Verifies that sequence numbers wrap correctly as in flush_write().
|
||||
*/
|
||||
PWTEST(avb_sequence_number_wrapping)
|
||||
{
|
||||
uint8_t seq = 0;
|
||||
uint8_t dbc = 0;
|
||||
int frames_per_pdu = 6;
|
||||
|
||||
/* Simulate 300 PDU transmissions — seq wraps at 256 */
|
||||
for (int i = 0; i < 300; i++) {
|
||||
pwtest_int_eq(seq, (uint8_t)(i & 0xFF));
|
||||
seq++;
|
||||
dbc += frames_per_pdu;
|
||||
}
|
||||
|
||||
/* After 300 PDUs: seq = 300 & 0xFF = 44, dbc = 300*6 = 1800 & 0xFF = 8 */
|
||||
pwtest_int_eq(seq, (uint8_t)(300 & 0xFF));
|
||||
pwtest_int_eq(dbc, (uint8_t)(300 * frames_per_pdu));
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
||||
PWTEST_SUITE(avb)
|
||||
{
|
||||
/* Phase 2: ADP and basic tests */
|
||||
|
|
@ -2110,5 +2618,17 @@ PWTEST_SUITE(avb)
|
|||
pwtest_add(avb_aecp_acquire_entity_milan, PWTEST_NOARG);
|
||||
pwtest_add(avb_aecp_read_descriptor_milan, PWTEST_NOARG);
|
||||
|
||||
/* Phase 6: AVTP audio data path tests */
|
||||
pwtest_add(avb_iec61883_packet_layout, PWTEST_NOARG);
|
||||
pwtest_add(avb_aaf_packet_layout, PWTEST_NOARG);
|
||||
pwtest_add(avb_frame_header_construction, PWTEST_NOARG);
|
||||
pwtest_add(avb_pdu_size_calculations, PWTEST_NOARG);
|
||||
pwtest_add(avb_ringbuffer_audio_roundtrip, PWTEST_NOARG);
|
||||
pwtest_add(avb_ringbuffer_wraparound, PWTEST_NOARG);
|
||||
pwtest_add(avb_iec61883_receive_simulation, PWTEST_NOARG);
|
||||
pwtest_add(avb_iec61883_transmit_pdu, PWTEST_NOARG);
|
||||
pwtest_add(avb_ringbuffer_overrun, PWTEST_NOARG);
|
||||
pwtest_add(avb_sequence_number_wrapping, PWTEST_NOARG);
|
||||
|
||||
return PWTEST_PASS;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue