blob: a72ee1a267e0c52d94afdaf87a4dc9e6082a8802 [file] [log] [blame]
/** @file
*
* A brief file description
*
* @section license License
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "catch.hpp"
#include "QUICFrameRetransmitter.h"
constexpr static uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05,
0x06, 0x07, 0x08, 0x09, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10};
TEST_CASE("QUICFrameRetransmitter ignore frame which can not be retransmitted", "[quic]")
{
QUICFrameRetransmitter retransmitter;
QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
info->type = QUICFrameType::PING;
info->level = QUICEncryptionLevel::NONE;
retransmitter.save_frame_info(std::move(info));
uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
CHECK(retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX) == nullptr);
}
// TEST_CASE("QUICFrameRetransmitter ignore frame which can not be split", "[quic]")
// {
// QUICFrameRetransmitter retransmitter;
// QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
// info->type = QUICFrameType::STOP_SENDING;
// info->level = QUICEncryptionLevel::NONE;
//
// retransmitter.save_frame_info(info);
// CHECK(retransmitter.create_retransmitted_frame(QUICEncryptionLevel::INITIAL, 0) == nullptr);
// }
TEST_CASE("QUICFrameRetransmitter ignore frame which has wrong level", "[quic]")
{
QUICFrameRetransmitter retransmitter;
QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
info->type = QUICFrameType::STREAM;
info->level = QUICEncryptionLevel::HANDSHAKE;
retransmitter.save_frame_info(std::move(info));
uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
CHECK(retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX) == nullptr);
}
TEST_CASE("QUICFrameRetransmitter successfully create retransmitted frame", "[quic]")
{
QUICFrameRetransmitter retransmitter;
QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
info->type = QUICFrameType::STREAM;
info->level = QUICEncryptionLevel::INITIAL;
Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
block->alloc(BUFFER_SIZE_INDEX_32K);
memcpy(block->start(), data, sizeof(data));
block->fill(sizeof(data));
StreamFrameInfo *frame_info = reinterpret_cast<StreamFrameInfo *>(info->data);
frame_info->stream_id = 0x12345;
frame_info->offset = 0x67890;
frame_info->block = block;
retransmitter.save_frame_info(std::move(info));
uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
auto frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX);
CHECK(frame != nullptr);
CHECK(frame->type() == QUICFrameType::STREAM);
}
TEST_CASE("QUICFrameRetransmitter successfully create stream frame", "[quic]")
{
QUICFrameRetransmitter retransmitter;
QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
info->type = QUICFrameType::STREAM;
info->level = QUICEncryptionLevel::INITIAL;
Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
block->alloc(BUFFER_SIZE_INDEX_32K);
memcpy(block->start(), data, sizeof(data));
block->fill(sizeof(data));
StreamFrameInfo *frame_info = reinterpret_cast<StreamFrameInfo *>(info->data);
frame_info->stream_id = 0x12345;
frame_info->offset = 0x67890;
frame_info->block = block;
CHECK(block->refcount() == 2);
retransmitter.save_frame_info(std::move(info));
CHECK(block->refcount() == 2); // block's refcount doesn't change
uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
auto frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX);
CHECK(frame != nullptr);
CHECK(frame->type() == QUICFrameType::STREAM);
auto stream_frame = static_cast<QUICStreamFrame *>(frame);
CHECK(stream_frame->stream_id() == 0x12345);
CHECK(stream_frame->offset() == 0x67890);
CHECK(stream_frame->data_length() == sizeof(data));
CHECK(memcmp(stream_frame->data()->start(), data, sizeof(data)) == 0);
std::destroy_at(frame);
frame = nullptr;
// Because the info has been released, the refcount should be 1 (var block).
CHECK(block->refcount() == 1);
}
TEST_CASE("QUICFrameRetransmitter successfully split stream frame", "[quic]")
{
QUICFrameRetransmitter retransmitter;
QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
info->type = QUICFrameType::STREAM;
info->level = QUICEncryptionLevel::INITIAL;
Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
block->alloc(BUFFER_SIZE_INDEX_32K);
memcpy(block->start(), data, sizeof(data));
block->fill(sizeof(data));
StreamFrameInfo *frame_info = reinterpret_cast<StreamFrameInfo *>(info->data);
frame_info->stream_id = 0x12345;
frame_info->offset = 0x67890;
frame_info->block = block;
CHECK(block->refcount() == 2);
retransmitter.save_frame_info(std::move(info));
uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
auto frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, 25);
CHECK(frame != nullptr);
CHECK(frame->type() == QUICFrameType::STREAM);
auto stream_frame = static_cast<QUICStreamFrame *>(frame);
CHECK(stream_frame->stream_id() == 0x12345);
CHECK(stream_frame->offset() == 0x67890);
CHECK(stream_frame->size() <= 25);
auto size = stream_frame->data_length();
CHECK(memcmp(stream_frame->data()->start(), data, stream_frame->data_length()) == 0);
// one for var block, one for the left data which saved in retransmitter
CHECK(block->data->refcount() == 2);
// one for var block, one for the left data which saved in retransmitter, one for var frame
CHECK(block->refcount() == 2);
std::destroy_at(frame);
frame = nullptr;
// one for var block, one for var info
CHECK(block->refcount() == 2);
CHECK(block->data->refcount() == 1);
frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX);
CHECK(frame != nullptr);
CHECK(frame->type() == QUICFrameType::STREAM);
stream_frame = static_cast<QUICStreamFrame *>(frame);
CHECK(stream_frame->stream_id() == 0x12345);
CHECK(stream_frame->offset() == 0x67890 + size);
CHECK(stream_frame->data_length() == sizeof(data) - size);
CHECK(memcmp(stream_frame->data()->start(), data + size, stream_frame->data_length()) == 0);
CHECK(block->refcount() == 1); // one for var block
std::destroy_at(frame);
frame = nullptr;
CHECK(block->refcount() == 1);
CHECK(block->data->refcount() == 1);
}
TEST_CASE("QUICFrameRetransmitter successfully split crypto frame", "[quic]")
{
QUICFrameRetransmitter retransmitter;
QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
info->type = QUICFrameType::CRYPTO;
info->level = QUICEncryptionLevel::INITIAL;
Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
block->alloc(BUFFER_SIZE_INDEX_32K);
memcpy(block->start(), data, sizeof(data));
block->fill(sizeof(data));
CryptoFrameInfo *frame_info = reinterpret_cast<CryptoFrameInfo *>(info->data);
frame_info->offset = 0x67890;
frame_info->block = block;
CHECK(block->refcount() == 2);
retransmitter.save_frame_info(std::move(info));
uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
auto frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, 25);
CHECK(frame != nullptr);
CHECK(frame->type() == QUICFrameType::CRYPTO);
auto crypto_frame = static_cast<QUICCryptoFrame *>(frame);
CHECK(crypto_frame->offset() == 0x67890);
CHECK(crypto_frame->size() <= 25);
auto size = crypto_frame->data_length();
CHECK(memcmp(crypto_frame->data()->start(), data, crypto_frame->data_length()) == 0);
// one for var block, one for the left data which saved in retransmitter
CHECK(block->data->refcount() == 2);
// one for var block, one for the left data which saved in retransmitter, one for var frame
CHECK(block->refcount() == 2);
std::destroy_at(frame);
frame = nullptr;
// one for var block, one for var info
CHECK(block->refcount() == 2);
CHECK(block->data->refcount() == 1);
frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX);
CHECK(frame != nullptr);
CHECK(frame->type() == QUICFrameType::CRYPTO);
crypto_frame = static_cast<QUICCryptoFrame *>(frame);
CHECK(crypto_frame->offset() == 0x67890 + size);
CHECK(crypto_frame->data_length() == sizeof(data) - size);
CHECK(memcmp(crypto_frame->data()->start(), data + size, crypto_frame->data_length()) == 0);
CHECK(block->refcount() == 1); // one for var block
std::destroy_at(frame);
frame = nullptr;
CHECK(block->refcount() == 1);
CHECK(block->data->refcount() == 1);
}
TEST_CASE("QUICFrameRetransmitter successfully split stream frame with fin flag", "[quic]")
{
QUICFrameRetransmitter retransmitter;
QUICFrameInformationUPtr info = QUICFrameInformationUPtr(quicFrameInformationAllocator.alloc());
info->type = QUICFrameType::STREAM;
info->level = QUICEncryptionLevel::INITIAL;
Ptr<IOBufferBlock> block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
block->alloc(BUFFER_SIZE_INDEX_32K);
memcpy(block->start(), data, sizeof(data));
block->fill(sizeof(data));
StreamFrameInfo *frame_info = reinterpret_cast<StreamFrameInfo *>(info->data);
frame_info->stream_id = 0x12345;
frame_info->offset = 0x67890;
frame_info->block = block;
frame_info->has_fin = true;
CHECK(block->refcount() == 2);
retransmitter.save_frame_info(std::move(info));
uint8_t frame_buf[QUICFrame::MAX_INSTANCE_SIZE];
auto frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, 25);
CHECK(frame != nullptr);
CHECK(frame->type() == QUICFrameType::STREAM);
auto stream_frame = static_cast<QUICStreamFrame *>(frame);
CHECK(stream_frame->stream_id() == 0x12345);
CHECK(stream_frame->offset() == 0x67890);
CHECK(stream_frame->size() <= 25);
CHECK(stream_frame->has_fin_flag() == false);
auto size = stream_frame->data_length();
CHECK(memcmp(stream_frame->data()->start(), data, stream_frame->data_length()) == 0);
// one for var block, one for the left data which saved in retransmitter
CHECK(block->data->refcount() == 2);
// one for var block, one for the left data which saved in retransmitter, one for var frame
CHECK(block->refcount() == 2);
std::destroy_at(frame);
frame = nullptr;
// one for var block, one for var info
CHECK(block->refcount() == 2);
CHECK(block->data->refcount() == 1);
frame = retransmitter.create_retransmitted_frame(frame_buf, QUICEncryptionLevel::INITIAL, UINT16_MAX);
CHECK(frame != nullptr);
CHECK(frame->type() == QUICFrameType::STREAM);
stream_frame = static_cast<QUICStreamFrame *>(frame);
CHECK(stream_frame->stream_id() == 0x12345);
CHECK(stream_frame->offset() == 0x67890 + size);
CHECK(stream_frame->data_length() == sizeof(data) - size);
CHECK(memcmp(stream_frame->data()->start(), data + size, stream_frame->data_length()) == 0);
CHECK(block->refcount() == 1); // one for var block
CHECK(stream_frame->has_fin_flag() == true);
std::destroy_at(frame);
frame = nullptr;
CHECK(block->refcount() == 1);
CHECK(block->data->refcount() == 1);
}