Skip to content

Commit

Permalink
Merge pull request #1666 from private-octopus/provide_data_buffer_test
Browse files Browse the repository at this point in the history
Add unit test of picoquic_provide_stream_data_buffer
  • Loading branch information
huitema authored Apr 2, 2024
2 parents 900c3a8 + 72a1a6c commit 75a85d6
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 14 deletions.
7 changes: 7 additions & 0 deletions UnitTest1/unittest1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,13 @@ namespace UnitTest1
{
int ret = stream_rank_test();

Assert::AreEqual(ret, 0);
}

TEST_METHOD(provide_stream_buffer)
{
int ret = provide_stream_buffer_test();

Assert::AreEqual(ret, 0);
}

Expand Down
13 changes: 1 addition & 12 deletions picoquic/frames.c
Original file line number Diff line number Diff line change
Expand Up @@ -1506,17 +1506,6 @@ uint8_t * picoquic_format_blocked_frames(picoquic_cnx_t* cnx, uint8_t* bytes, ui
/* handling of stream frames
*/

typedef struct st_picoquic_stream_data_buffer_argument_t {
uint8_t* bytes; /* Points to the beginning of the encoding of the stream frame */
size_t byte_index; /* Current index position after encoding type, stream-id and offset */
size_t byte_space; /* Number of bytes available in the packet after the current index */
size_t allowed_space; /* Maximum number of bytes that the application is authorized to write */
size_t length; /* number of bytes that the application commits to write */
int is_fin; /* Whether this is the end of the stream */
int is_still_active; /* whether the stream is still considered active after this call */
uint8_t* app_buffer; /* buffer provided to the application. */
} picoquic_stream_data_buffer_argument_t;

static size_t picoquic_encode_length_of_stream_frame(
uint8_t* bytes, size_t byte_index, size_t byte_space, size_t length, size_t *start_index)
{
Expand Down Expand Up @@ -1573,7 +1562,7 @@ uint8_t* picoquic_provide_stream_data_buffer(void* context, size_t length, int i
return buffer;
}

static uint8_t* picoquic_format_stream_frame_header(uint8_t* bytes, uint8_t* bytes_max, uint64_t stream_id, uint64_t offset)
uint8_t* picoquic_format_stream_frame_header(uint8_t* bytes, uint8_t* bytes_max, uint64_t stream_id, uint64_t offset)
{
uint8_t* bytes0 = bytes;
if ((bytes = picoquic_frames_uint8_encode(bytes, bytes_max, picoquic_frame_type_stream_range_min)) != NULL &&
Expand Down
2 changes: 1 addition & 1 deletion picoquic/packet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ int picoquic_queue_busy_packet(
payload_length = picoquic_aead_encrypt_generic(bytes + header_length,
payload, sizeof(payload), 0, bytes, header_length, aead_ctx);
/* protect the PN */
picoquic_protect_packet_header(bytes, pn_offset, 0x1F, pn_enc_ctx);
picoquic_protect_packet_header(bytes, pn_offset, 0x0F, pn_enc_ctx);
/* Fill up control fields */
sp->length = byte_index + payload_length;
sp->ptype = picoquic_packet_initial;
Expand Down
13 changes: 13 additions & 0 deletions picoquic/picoquic_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1889,8 +1889,21 @@ void picoquic_process_ack_of_frames(picoquic_cnx_t* cnx, picoquic_packet_t* p,
int is_spurious, uint64_t current_time);

/* Coding and decoding of frames */
typedef struct st_picoquic_stream_data_buffer_argument_t {
uint8_t* bytes; /* Points to the beginning of the encoding of the stream frame */
size_t byte_index; /* Current index position after encoding type, stream-id and offset */
size_t byte_space; /* Number of bytes available in the packet after the current index */
size_t allowed_space; /* Maximum number of bytes that the application is authorized to write */
size_t length; /* number of bytes that the application commits to write */
int is_fin; /* Whether this is the end of the stream */
int is_still_active; /* whether the stream is still considered active after this call */
uint8_t* app_buffer; /* buffer provided to the application. */
} picoquic_stream_data_buffer_argument_t;

int picoquic_is_stream_frame_unlimited(const uint8_t* bytes);

uint8_t* picoquic_format_stream_frame_header(uint8_t* bytes, uint8_t* bytes_max, uint64_t stream_id, uint64_t offset);

int picoquic_parse_stream_header(
const uint8_t* bytes, size_t bytes_max,
uint64_t* stream_id, uint64_t* offset, size_t* data_length, int* fin,
Expand Down
1 change: 1 addition & 0 deletions picoquic_t/picoquic_t.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ static const picoquic_test_def_t test_table[] = {
{ "vn_tp", vn_tp_test },
{ "vn_compat", vn_compat_test },
{ "stream_rank", stream_rank_test },
{ "provide_stream_buffer", provide_stream_buffer_test },
{ "transport_param", transport_param_test },
{ "tls_api_sni", tls_api_sni_test },
{ "tls_api_alpn", tls_api_alpn_test },
Expand Down
2 changes: 1 addition & 1 deletion picoquictest/openssl_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ int openssl_cert_test()
openssl_cert_test_one(TEST_CERT3, 2) != 0) {
ret = -1;
}
return 0;
return ret;
}

#endif /* !PTLS_WITHOUT_OPENSSL */
1 change: 1 addition & 0 deletions picoquictest/picoquictest.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ int bad_cnxid_test();
int stream_splay_test();
int stream_output_test();
int stream_rank_test();
int provide_stream_buffer_test();
int not_before_cnxid_test();
int send_stream_blocked_test();
int stream_ack_test();
Expand Down
152 changes: 152 additions & 0 deletions picoquictest/stream0_frame_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,3 +898,155 @@ int stream_rank_test()

return ret;
}

/* Unit test of "picoquic_provide_stream_data_buffer"
*/

static int picoquic_set_stream_buffer_context(picoquic_stream_data_buffer_argument_t * stream_data_context,
uint8_t * bytes, uint8_t * bytes_max, uint64_t stream_id, uint64_t stream_offset)
{
int ret = 0;
uint8_t* bytes0 = bytes;
memset(stream_data_context, 0, sizeof(picoquic_stream_data_buffer_argument_t));
if ((bytes = picoquic_format_stream_frame_header(bytes, bytes_max, stream_id, stream_offset)) == NULL) {
ret = -1;
}
else {
/* Compute the length */
stream_data_context->bytes = bytes0;
stream_data_context->byte_index = bytes - bytes0;
stream_data_context->allowed_space = bytes_max - bytes;
stream_data_context->byte_space = bytes_max - bytes;
stream_data_context->length = 0;
stream_data_context->is_fin = 0;
stream_data_context->is_still_active = 0;
stream_data_context->app_buffer = NULL;
}
return ret;
}

typedef enum {
size_test_full = 0,
size_test_minus_1,
size_test_minus_2,
size_test_minus_3,
size_test_1,
size_test_0,
size_test_too_long,
size_test_last
} size_test_enum;

int provide_stream_buffer_test_one(uint64_t stream_id, uint64_t stream_offset, size_test_enum size_test, int is_fin)
{
uint8_t packet[512];
uint8_t test_data[512];
picoquic_stream_data_buffer_argument_t stream_data_context;
int ret = picoquic_set_stream_buffer_context(&stream_data_context, packet, packet + sizeof(packet), stream_id, stream_offset);
size_t length = 0;

if (ret == 0) {

switch (size_test) {
case size_test_full:
length = stream_data_context.byte_space;
break;
case size_test_minus_1:
length = stream_data_context.byte_space - 1;
break;
case size_test_minus_2:
length = stream_data_context.byte_space - 2;
break;
case size_test_minus_3:
length = stream_data_context.byte_space - 3;
break;
case size_test_1:
length = 1;
break;
case size_test_0:
length = 0;
break;
case size_test_too_long:
length = stream_data_context.byte_space;
stream_data_context.allowed_space = length - 1;
break;
default:
ret = -1;
break;
}
}

if (ret == 0) {
uint8_t * data_ptr = picoquic_provide_stream_data_buffer(&stream_data_context, length, is_fin, 0);

if (size_test == size_test_too_long) {
ret = (data_ptr == NULL) ? 0 : -1;
}
else if (data_ptr == NULL) {
ret = -1;
}
else if (data_ptr + length > packet + sizeof(packet)) {
ret = -1;
}
else {
uint8_t* packet_start = packet;
uint64_t received_stream_id;
uint64_t received_offset;
size_t received_length = 0;
size_t consumed = 0;
int received_fin = 0;

if (length > 0) {
/* set test data value */
for (size_t i = 0; i < length; i++) {
test_data[i] = (uint8_t)(i ^ 0x7f);
}
/* Fill the data space */
memcpy(data_ptr, test_data, length);
}
/* Get the start point of the data frame */
while (*packet_start == picoquic_frame_type_padding && packet_start < packet + sizeof(packet)) {
packet_start++;
}
/* decode the stream header */
if (picoquic_parse_stream_header(packet_start,
sizeof(packet) - (packet_start - packet), &received_stream_id, &received_offset,
&received_length, &received_fin, &consumed) != 0) {
ret = -1;
}
else if (received_stream_id != stream_id ||
received_offset != stream_offset ||
received_length != length ||
received_fin != is_fin) {
ret = -1;
}
else if (length > 0 &&
memcmp(packet_start + consumed, test_data, length) != 0) {
ret = -1;
}
}
}
return ret;
}

int provide_stream_buffer_test()
{
uint64_t stream_ids[4] = { 0, 7, 127, 0x10000 };
uint64_t offsets[4] = { 0, 1, 65, 0x10000 };
int ret = 0;

for (int i_stream = 0; ret == 0 && i_stream < 4; i_stream++) {
for (int i_offset = 0; ret == 0 && i_offset < 4; i_offset++) {
for (int is_fin = 0; ret == 0 && is_fin < 2; is_fin++) {
for (size_test_enum size_test = 0; ret == 0 && size_test < size_test_last; size_test++) {
ret = provide_stream_buffer_test_one(stream_ids[i_stream], offsets[i_offset], size_test, is_fin);
if (ret != 0) {
DBG_PRINTF("Fails for stream %" PRIu64 ", offset %" PRIu64 ", fin %d, test %d",
stream_ids[i_stream], offsets[i_offset], is_fin, size_test);
break;
}
}
}
}
}
return ret;
}

0 comments on commit 75a85d6

Please sign in to comment.