Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better test of spinbit code #1786

Merged
merged 4 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ set(PICOQUIC_TEST_LIBRARY_FILES
picoquictest/skip_frame_test.c
picoquictest/socket_test.c
picoquictest/sockloop_test.c
picoquictest/spinbit_test.c
picoquictest/splay_test.c
picoquictest/stream0_frame_test.c
picoquictest/stresstest.c
Expand Down
31 changes: 29 additions & 2 deletions UnitTest1/unittest1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1398,13 +1398,40 @@ namespace UnitTest1
Assert::AreEqual(ret, 0);
}

TEST_METHOD(test_spin_bit)
TEST_METHOD(spinbit)
{
int ret = spin_bit_test();
int ret = spinbit_test();

Assert::AreEqual(ret, 0);
}

TEST_METHOD(spinbit_bad)
{
int ret = spinbit_bad_test();

Assert::AreEqual(ret, 0);
}

TEST_METHOD(spinbit_null)
{
int ret = spinbit_null_test();

Assert::AreEqual(ret, 0);
}

TEST_METHOD(spinbit_random)
{
int ret = spinbit_random_test();

Assert::AreEqual(ret, 0);
}

TEST_METHOD(spinbit_randclient)
{
int ret = spinbit_randclient_test();

Assert::AreEqual(ret, 0);
}
TEST_METHOD(loss_bit)
{
int ret = loss_bit_test();
Expand Down
10 changes: 8 additions & 2 deletions picoquic/picoquic.h
Original file line number Diff line number Diff line change
Expand Up @@ -638,8 +638,14 @@ void picoquic_enforce_client_only(picoquic_quic_t* quic, int do_enforce);
/* Set default padding policy for the context */
void picoquic_set_default_padding(picoquic_quic_t* quic, uint32_t padding_multiple, uint32_t padding_minsize);

/* Set default spin bit policy for the context */
void picoquic_set_default_spinbit_policy(picoquic_quic_t * quic, picoquic_spinbit_version_enum default_spinbit_policy);
/* Set default spin bit policy for the context
* return 0 if OK, -1 if the policy was invalid.
* Note that "picoquic_spinbit_on" is only allowed as a default policy,
* translating to unconditional setup when connections are created for
* the context. As a per conection setup, it is invalid.
*/
int picoquic_set_default_spinbit_policy(picoquic_quic_t * quic, picoquic_spinbit_version_enum default_spinbit_policy);
int picoquic_set_spinbit_policy(picoquic_cnx_t* cnx, picoquic_spinbit_version_enum spinbit_policy);

/* Set default loss bit policy for the context */
void picoquic_set_default_lossbit_policy(picoquic_quic_t* quic, picoquic_lossbit_version_enum default_lossbit_policy);
Expand Down
26 changes: 24 additions & 2 deletions picoquic/quicctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,9 +798,31 @@ void picoquic_set_default_padding(picoquic_quic_t* quic, uint32_t padding_multip
quic->padding_multiple_default = padding_multiple;
}

void picoquic_set_default_spinbit_policy(picoquic_quic_t * quic, picoquic_spinbit_version_enum default_spinbit_policy)
int picoquic_set_default_spinbit_policy(picoquic_quic_t * quic, picoquic_spinbit_version_enum default_spinbit_policy)
{
quic->default_spin_policy = default_spinbit_policy;
int ret = 0;

if (default_spinbit_policy <= picoquic_spinbit_on) {
quic->default_spin_policy = default_spinbit_policy;
}
else {
ret = -1;
}
return ret;
}

int picoquic_set_spinbit_policy(picoquic_cnx_t* cnx, picoquic_spinbit_version_enum spinbit_policy)
{
int ret = 0;

if (spinbit_policy < picoquic_spinbit_on) {
cnx->spin_policy = spinbit_policy;
}
else
{
ret = -1;
}
return ret;
}

void picoquic_set_default_lossbit_policy(picoquic_quic_t* quic, picoquic_lossbit_version_enum default_lossbit_policy)
Expand Down
6 changes: 5 additions & 1 deletion picoquic_t/picoquic_t.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,11 @@ static const picoquic_test_def_t test_table[] = {
{ "nat_rebinding_zero", nat_rebinding_zero_test },
{ "nat_rebinding_latency", nat_rebinding_latency_test },
{ "nat_rebinding_fast", fast_nat_rebinding_test},
{ "spin_bit", spin_bit_test},
{ "spinbit", spinbit_test },
{ "spinbit_bad", spinbit_bad_test },
{ "spinbit_null", spinbit_null_test },
{ "spinbit_randclient", spinbit_randclient_test },
{ "spinbit_random", spinbit_random_test },
{ "loss_bit", loss_bit_test},
{ "client_error", client_error_test },
{ "client_only", client_only_test },
Expand Down
4 changes: 2 additions & 2 deletions picoquictest/multipath_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1647,8 +1647,8 @@ int multipath_trace_test_one()
* current working directory, and run a basic test scenario */
if (ret == 0) {
picoquic_set_binlog(test_ctx->qserver, ".");
picoquic_set_default_spinbit_policy(test_ctx->qserver, picoquic_spinbit_on);
picoquic_set_default_spinbit_policy(test_ctx->qclient, picoquic_spinbit_on);
(void)picoquic_set_default_spinbit_policy(test_ctx->qserver, picoquic_spinbit_on);
(void)picoquic_set_default_spinbit_policy(test_ctx->qclient, picoquic_spinbit_on);
picoquic_set_default_lossbit_policy(test_ctx->qserver, picoquic_lossbit_send_receive);
picoquic_set_default_lossbit_policy(test_ctx->qclient, picoquic_lossbit_send_receive);
test_ctx->qserver->cnx_id_callback_ctx = (void*)&cnxfn_data_server;
Expand Down
6 changes: 5 additions & 1 deletion picoquictest/picoquictest.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,11 @@ int nat_rebinding_test();
int nat_rebinding_loss_test();
int nat_rebinding_zero_test();
int nat_rebinding_latency_test();
int spin_bit_test();
int spinbit_test();
int spinbit_random_test();
int spinbit_randclient_test();
int spinbit_null_test();
int spinbit_bad_test();
int loss_bit_test();
int client_error_test();
int client_only_test();
Expand Down
1 change: 1 addition & 0 deletions picoquictest/picoquictest.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
<ClCompile Include="socket_test.c" />
<ClCompile Include="cplusplus.cpp" />
<ClCompile Include="sockloop_test.c" />
<ClCompile Include="spinbit_test.c" />
<ClCompile Include="splay_test.c" />
<ClCompile Include="stream0_frame_test.c" />
<ClCompile Include="stresstest.c" />
Expand Down
3 changes: 3 additions & 0 deletions picoquictest/picoquictest.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@
<ClCompile Include="getter_test.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="spinbit_test.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="picoquictest.h">
Expand Down
2 changes: 1 addition & 1 deletion picoquictest/skip_frame_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2131,7 +2131,7 @@ int binlog_test()
}
else {
picoquic_set_binlog(quic, ".");
picoquic_set_default_spinbit_policy(quic, picoquic_spinbit_null);
(void)picoquic_set_default_spinbit_policy(quic, picoquic_spinbit_null);

struct sockaddr_in saddr;
memset(&saddr, 0, sizeof(struct sockaddr_in));
Expand Down
220 changes: 220 additions & 0 deletions picoquictest/spinbit_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/*
* Author: Christian Huitema
* Copyright (c) 2017, Private Octopus, Inc.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Private Octopus, Inc. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "tls_api.h"
#include "picoquic_internal.h"
#include "picoquictest_internal.h"
#include "picoquic.h"
#include <stdlib.h>
#include <string.h>

#include "logreader.h"
#include "picoquic_binlog.h"
#include "picoquic_logger.h"
#include "qlog.h"


/*
* Spin bit test. Verify that the bit does spin, and that the number
* of rotations is plausible given the duration and the min delay
* for various the spin policies.
*/

static test_api_stream_desc_t test_scenario_spin[] = {
{ 4, 0, 257, 1000000 }
};

int spinbit_test_one(picoquic_spinbit_version_enum spin_policy, picoquic_spinbit_version_enum spin_policy_server)
{
uint64_t simulated_time = 0;
uint64_t loss_mask = 0;
uint64_t spin_duration = 0;
picoquic_test_tls_api_ctx_t* test_ctx = NULL;
int spin_count = 0;
int ret = tls_api_init_ctx(&test_ctx, PICOQUIC_INTERNAL_TEST_VERSION_1,
PICOQUIC_TEST_SNI, PICOQUIC_TEST_ALPN, &simulated_time, NULL, NULL, 0, 1, 0);

if (ret != 0)
{
DBG_PRINTF("%s", "Could not create the QUIC test contexts\n");
}

if (ret == 0) {
/* force spinbit policy as specified, then start */
if (picoquic_set_default_spinbit_policy(test_ctx->qserver, spin_policy_server) != 0 ||
picoquic_set_spinbit_policy(test_ctx->cnx_client, spin_policy) != 0)
{
DBG_PRINTF("Invalid policies: %d, %d\n", spin_policy_server, spin_policy);
ret = -1;
}
}
if (ret == 0) {
ret = picoquic_start_client_cnx(test_ctx->cnx_client);
if (ret != 0)
{
DBG_PRINTF("%s", "Could not initialize stream zero for the client\n");
}
}

if (ret == 0) {
ret = tls_api_connection_loop(test_ctx, &loss_mask, 0, &simulated_time);

if (ret != 0)
{
DBG_PRINTF("Connection loop returns error %d\n", ret);
}
}

/* Prepare to send data */
if (ret == 0) {
ret = test_api_init_send_recv_scenario(test_ctx, test_scenario_spin, sizeof(test_scenario_spin));

if (ret != 0)
{
DBG_PRINTF("Init send receive scenario returns %d\n", ret);
}
}

/* Explore the data sending loop so we can observe the spin bit */
if (ret == 0) {
uint64_t spin_begin_time = simulated_time;
uint64_t next_time = simulated_time + 10000000;
int ret = 0;
int nb_trials = 0;
int nb_inactive = 0;
int max_trials = 100000;
int current_spin = test_ctx->cnx_client->path[0]->current_spin;

test_ctx->c_to_s_link->loss_mask = &loss_mask;
test_ctx->s_to_c_link->loss_mask = &loss_mask;

while (ret == 0 && nb_trials < max_trials && simulated_time < next_time && nb_inactive < 256 && TEST_CLIENT_READY && TEST_SERVER_READY) {
int was_active = 0;

nb_trials++;

ret = tls_api_one_sim_round(test_ctx, &simulated_time, next_time, &was_active);

if (ret < 0)
{
break;
}

if (test_ctx->cnx_client->path[0]->current_spin != current_spin) {
spin_count++;
current_spin = test_ctx->cnx_client->path[0]->current_spin;
}

if (was_active) {
nb_inactive = 0;
}
else {
nb_inactive++;
}

if (test_ctx->test_finished) {
if (picoquic_is_cnx_backlog_empty(test_ctx->cnx_client) && picoquic_is_cnx_backlog_empty(test_ctx->cnx_server)) {
break;
}
}
}

spin_duration = simulated_time - spin_begin_time;

if (ret != 0)
{
DBG_PRINTF("Data sending loop fails with ret = %d\n", ret);
}
}

if (ret == 0) {
ret = picoquic_close(test_ctx->cnx_client, 0);
if (ret != 0)
{
DBG_PRINTF("Picoquic close returns %d\n", ret);
}
}

if (ret == 0) {
if (spin_policy == picoquic_spinbit_basic) {
if (spin_policy_server == picoquic_spinbit_on) {
if (spin_count < 6) {
DBG_PRINTF("Unplausible spin bit: %d rotations, rtt_min = %d, duration = %d\n",
spin_count, (int)test_ctx->cnx_client->path[0]->rtt_min, (int)spin_duration);
ret = -1;
}
}
else if (spin_policy_server == picoquic_spinbit_random) {
if (spin_count < 100) {
DBG_PRINTF("Unplausible spin bit: %d rotations, rtt_min = %d, duration = %d\n",
spin_count, (int)test_ctx->cnx_client->path[0]->rtt_min, (int)spin_duration);
ret = -1;
}
}
else if (spin_policy_server == picoquic_spinbit_null) {
if (spin_count > 0) {
DBG_PRINTF("Unplausible spin bit: %d rotations, rtt_min = %d, duration = %d\n",
spin_count, (int)test_ctx->cnx_client->path[0]->rtt_min, (int)spin_duration);
ret = -1;
}
}
}
}

if (test_ctx != NULL) {
tls_api_delete_ctx(test_ctx);
test_ctx = NULL;
}

return ret;
}

int spinbit_test()
{
return spinbit_test_one(picoquic_spinbit_basic, picoquic_spinbit_on);
}

int spinbit_random_test()
{
return spinbit_test_one(picoquic_spinbit_basic, picoquic_spinbit_random);
}

int spinbit_randclient_test()
{
return spinbit_test_one(picoquic_spinbit_random, picoquic_spinbit_basic);
}

int spinbit_null_test()
{
return spinbit_test_one(picoquic_spinbit_basic, picoquic_spinbit_null);
}

int spinbit_bad_test()
{
int ret = 0;
if (spinbit_test_one(picoquic_spinbit_on, 123456) == 0 ||
spinbit_test_one(123455, picoquic_spinbit_null) == 0) {
ret = -1;
}
return ret;
}


Loading
Loading