mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
chore: Add a .clang-format that mostly agrees with astyle.
This commit is contained in:
parent
a9ccf1be26
commit
86a528a37a
22
.clang-format
Normal file
22
.clang-format
Normal file
|
@ -0,0 +1,22 @@
|
|||
BasedOnStyle: WebKit
|
||||
ColumnLimit: 100
|
||||
PointerAlignment: Right
|
||||
SpacesBeforeTrailingComments: 2
|
||||
AlignConsecutiveMacros: true
|
||||
AlignEscapedNewlines: Left
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
Cpp11BracedListStyle: true
|
||||
|
||||
IncludeIsMainRegex: '([-_](test))?$'
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
- Regex: '.*'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
|
@ -7,10 +7,12 @@ exclude:
|
|||
restylers:
|
||||
- astyle:
|
||||
arguments: ["--options=other/astyle/astylerc"]
|
||||
include:
|
||||
- "!**/*.cc"
|
||||
- autopep8
|
||||
- black
|
||||
- clang-format:
|
||||
arguments: ["-style={BasedOnStyle: Google, ColumnLimit: 100}"]
|
||||
image: restyled/restyler-clang-format:13.0.1
|
||||
include:
|
||||
- "**/*.cc"
|
||||
- prettier-yaml
|
||||
|
|
|
@ -4,30 +4,31 @@
|
|||
#include "../../toxcore/tox.h"
|
||||
#include "fuzz_adapter.h"
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
network_adapter_init(data, size);
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
network_adapter_init(data, size);
|
||||
|
||||
Tox_Err_New error_new;
|
||||
Tox *tox = tox_new(NULL, &error_new);
|
||||
Tox_Err_New error_new;
|
||||
Tox *tox = tox_new(NULL, &error_new);
|
||||
|
||||
assert(tox != nullptr);
|
||||
assert(error_new == TOX_ERR_NEW_OK);
|
||||
assert(tox != nullptr);
|
||||
assert(error_new == TOX_ERR_NEW_OK);
|
||||
|
||||
uint8_t pub_key[TOX_PUBLIC_KEY_SIZE] = {0};
|
||||
uint8_t pub_key[TOX_PUBLIC_KEY_SIZE] = {0};
|
||||
|
||||
bool success = tox_bootstrap(tox, "127.0.0.1", 12345, pub_key, nullptr);
|
||||
assert(success);
|
||||
bool success = tox_bootstrap(tox, "127.0.0.1", 12345, pub_key, nullptr);
|
||||
assert(success);
|
||||
|
||||
/*
|
||||
* The iteration count here is a magic value in the literal sense, too small
|
||||
* and coverage will be bad, too big and fuzzing will not be efficient.
|
||||
* NOTE: This should be fine tuned after gathering some experience.
|
||||
*/
|
||||
/*
|
||||
* The iteration count here is a magic value in the literal sense, too small
|
||||
* and coverage will be bad, too big and fuzzing will not be efficient.
|
||||
* NOTE: This should be fine tuned after gathering some experience.
|
||||
*/
|
||||
|
||||
for (uint32_t i = 0; i < 100; ++i) {
|
||||
tox_iterate(tox, nullptr);
|
||||
}
|
||||
for (uint32_t i = 0; i < 100; ++i) {
|
||||
tox_iterate(tox, nullptr);
|
||||
}
|
||||
|
||||
tox_kill(tox);
|
||||
return 0; // Non-zero return values are reserved for future use.
|
||||
tox_kill(tox);
|
||||
return 0; // Non-zero return values are reserved for future use.
|
||||
}
|
||||
|
|
|
@ -2,22 +2,23 @@
|
|||
|
||||
#include "../../toxcore/tox.h"
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
Tox_Err_Options_New error_options;
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||
{
|
||||
Tox_Err_Options_New error_options;
|
||||
|
||||
struct Tox_Options *tox_options = tox_options_new(&error_options);
|
||||
struct Tox_Options *tox_options = tox_options_new(&error_options);
|
||||
|
||||
assert(tox_options != nullptr);
|
||||
assert(error_options == TOX_ERR_OPTIONS_NEW_OK);
|
||||
assert(tox_options != nullptr);
|
||||
assert(error_options == TOX_ERR_OPTIONS_NEW_OK);
|
||||
|
||||
// pass test data to Tox
|
||||
tox_options_set_savedata_data(tox_options, data, size);
|
||||
tox_options_set_savedata_type(tox_options, TOX_SAVEDATA_TYPE_TOX_SAVE);
|
||||
// pass test data to Tox
|
||||
tox_options_set_savedata_data(tox_options, data, size);
|
||||
tox_options_set_savedata_type(tox_options, TOX_SAVEDATA_TYPE_TOX_SAVE);
|
||||
|
||||
Tox *tox = tox_new(tox_options, nullptr);
|
||||
Tox *tox = tox_new(tox_options, nullptr);
|
||||
|
||||
tox_options_free(tox_options);
|
||||
tox_options_free(tox_options);
|
||||
|
||||
tox_kill(tox);
|
||||
return 0; // Non-zero return values are reserved for future use.
|
||||
tox_kill(tox);
|
||||
return 0; // Non-zero return values are reserved for future use.
|
||||
}
|
||||
|
|
|
@ -34,378 +34,398 @@ constexpr uint32_t MAX_ACTION_ATTEMPTS = 100;
|
|||
constexpr uint32_t ITERATIONS_PER_ACTION = 1;
|
||||
|
||||
struct Tox_Options_Deleter {
|
||||
void operator()(Tox_Options *options) const { tox_options_free(options); }
|
||||
void operator()(Tox_Options *options) const { tox_options_free(options); }
|
||||
};
|
||||
|
||||
using Tox_Options_Ptr = std::unique_ptr<Tox_Options, Tox_Options_Deleter>;
|
||||
|
||||
struct Tox_Deleter {
|
||||
void operator()(Tox *tox) const { tox_kill(tox); }
|
||||
void operator()(Tox *tox) const { tox_kill(tox); }
|
||||
};
|
||||
|
||||
using Tox_Ptr = std::unique_ptr<Tox, Tox_Deleter>;
|
||||
|
||||
struct Local_State {
|
||||
uint32_t friends_online = 0;
|
||||
uint32_t next_invite = 0;
|
||||
uint32_t friends_online = 0;
|
||||
uint32_t next_invite = 0;
|
||||
|
||||
explicit Local_State(Tox_Ptr tox, uint32_t id) : tox_(std::move(tox)), id_(id) {}
|
||||
explicit Local_State(Tox_Ptr tox, uint32_t id)
|
||||
: tox_(std::move(tox))
|
||||
, id_(id)
|
||||
{
|
||||
}
|
||||
|
||||
Tox *tox() const { return tox_.get(); }
|
||||
uint32_t id() const { return id_; }
|
||||
Tox *tox() const { return tox_.get(); }
|
||||
uint32_t id() const { return id_; }
|
||||
|
||||
private:
|
||||
Tox_Ptr tox_;
|
||||
uint32_t id_;
|
||||
private:
|
||||
Tox_Ptr tox_;
|
||||
uint32_t id_;
|
||||
};
|
||||
|
||||
struct Action;
|
||||
|
||||
struct Random {
|
||||
std::uniform_int_distribution<> tox_selector;
|
||||
std::uniform_int_distribution<> friend_selector;
|
||||
std::uniform_int_distribution<> name_length_selector;
|
||||
std::uniform_int_distribution<> message_length_selector;
|
||||
std::uniform_int_distribution<> byte_selector;
|
||||
std::uniform_int_distribution<> tox_selector;
|
||||
std::uniform_int_distribution<> friend_selector;
|
||||
std::uniform_int_distribution<> name_length_selector;
|
||||
std::uniform_int_distribution<> message_length_selector;
|
||||
std::uniform_int_distribution<> byte_selector;
|
||||
|
||||
std::vector<size_t> action_weights;
|
||||
std::discrete_distribution<size_t> action_selector;
|
||||
std::vector<size_t> action_weights;
|
||||
std::discrete_distribution<size_t> action_selector;
|
||||
|
||||
explicit Random(std::vector<Action> const &actions);
|
||||
explicit Random(std::vector<Action> const &actions);
|
||||
};
|
||||
|
||||
struct Action {
|
||||
uint32_t weight;
|
||||
char const *title;
|
||||
bool (*can)(Local_State const &state);
|
||||
void (*run)(Local_State *state, Random *rnd, std::mt19937 *rng);
|
||||
uint32_t weight;
|
||||
char const *title;
|
||||
bool (*can)(Local_State const &state);
|
||||
void (*run)(Local_State *state, Random *rnd, std::mt19937 *rng);
|
||||
};
|
||||
|
||||
std::vector<size_t> get_action_weights(std::vector<Action> const &actions) {
|
||||
std::vector<size_t> weights;
|
||||
for (Action const &action : actions) {
|
||||
weights.push_back(action.weight);
|
||||
}
|
||||
return weights;
|
||||
std::vector<size_t> get_action_weights(std::vector<Action> const &actions)
|
||||
{
|
||||
std::vector<size_t> weights;
|
||||
for (Action const &action : actions) {
|
||||
weights.push_back(action.weight);
|
||||
}
|
||||
return weights;
|
||||
}
|
||||
|
||||
Random::Random(std::vector<Action> const &actions)
|
||||
: tox_selector(0, NUM_TOXES - 1),
|
||||
friend_selector(0, NUM_TOXES - 2),
|
||||
name_length_selector(0, TOX_MAX_NAME_LENGTH - 1),
|
||||
message_length_selector(0, TOX_MAX_MESSAGE_LENGTH - 1),
|
||||
byte_selector(0, 255),
|
||||
action_weights(get_action_weights(actions)),
|
||||
action_selector(action_weights.begin(), action_weights.end()) {}
|
||||
: tox_selector(0, NUM_TOXES - 1)
|
||||
, friend_selector(0, NUM_TOXES - 2)
|
||||
, name_length_selector(0, TOX_MAX_NAME_LENGTH - 1)
|
||||
, message_length_selector(0, TOX_MAX_MESSAGE_LENGTH - 1)
|
||||
, byte_selector(0, 255)
|
||||
, action_weights(get_action_weights(actions))
|
||||
, action_selector(action_weights.begin(), action_weights.end())
|
||||
{
|
||||
}
|
||||
|
||||
struct Global_State : std::vector<Local_State> {
|
||||
// Non-copyable;
|
||||
Global_State(Global_State const &) = delete;
|
||||
Global_State(Global_State &&) = default;
|
||||
~Global_State();
|
||||
explicit Global_State(std::vector<Action> const &actions)
|
||||
: actions_(actions), rnd_(actions), action_counter_(actions.size()) {}
|
||||
// Non-copyable;
|
||||
Global_State(Global_State const &) = delete;
|
||||
Global_State(Global_State &&) = default;
|
||||
~Global_State();
|
||||
explicit Global_State(std::vector<Action> const &actions)
|
||||
: actions_(actions)
|
||||
, rnd_(actions)
|
||||
, action_counter_(actions.size())
|
||||
{
|
||||
}
|
||||
|
||||
Action const &action(size_t id) const { return actions_.at(id); }
|
||||
Random *rnd() { return &rnd_; }
|
||||
std::vector<unsigned> &action_counter() { return action_counter_; }
|
||||
Action const &action(size_t id) const { return actions_.at(id); }
|
||||
Random *rnd() { return &rnd_; }
|
||||
std::vector<unsigned> &action_counter() { return action_counter_; }
|
||||
|
||||
private:
|
||||
std::vector<Action> const &actions_;
|
||||
Random rnd_;
|
||||
std::vector<unsigned> action_counter_;
|
||||
private:
|
||||
std::vector<Action> const &actions_;
|
||||
Random rnd_;
|
||||
std::vector<unsigned> action_counter_;
|
||||
};
|
||||
|
||||
Global_State::~Global_State() {}
|
||||
Global_State::~Global_State() { }
|
||||
|
||||
void handle_friend_connection_status(Tox *tox, uint32_t friend_number,
|
||||
Tox_Connection connection_status, void *user_data) {
|
||||
Local_State *state = static_cast<Local_State *>(user_data);
|
||||
void handle_friend_connection_status(
|
||||
Tox *tox, uint32_t friend_number, Tox_Connection connection_status, void *user_data)
|
||||
{
|
||||
Local_State *state = static_cast<Local_State *>(user_data);
|
||||
|
||||
if (connection_status == TOX_CONNECTION_NONE) {
|
||||
std::printf("Tox #%u lost friend %u!\n", state->id(), friend_number);
|
||||
state->friends_online--;
|
||||
} else {
|
||||
state->friends_online++;
|
||||
}
|
||||
if (connection_status == TOX_CONNECTION_NONE) {
|
||||
std::printf("Tox #%u lost friend %u!\n", state->id(), friend_number);
|
||||
state->friends_online--;
|
||||
} else {
|
||||
state->friends_online++;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_conference_invite(Tox *tox, uint32_t friend_number, Tox_Conference_Type type,
|
||||
const uint8_t *cookie, size_t length, void *user_data) {
|
||||
Local_State *state = static_cast<Local_State *>(user_data);
|
||||
const uint8_t *cookie, size_t length, void *user_data)
|
||||
{
|
||||
Local_State *state = static_cast<Local_State *>(user_data);
|
||||
|
||||
if (LOG_CALLBACKS) {
|
||||
std::printf("Tox #%u joins the conference it was invited to\n", state->id());
|
||||
}
|
||||
if (LOG_CALLBACKS) {
|
||||
std::printf("Tox #%u joins the conference it was invited to\n", state->id());
|
||||
}
|
||||
|
||||
Tox_Err_Conference_Join err;
|
||||
tox_conference_join(tox, friend_number, cookie, length, &err);
|
||||
assert(err == TOX_ERR_CONFERENCE_JOIN_OK);
|
||||
Tox_Err_Conference_Join err;
|
||||
tox_conference_join(tox, friend_number, cookie, length, &err);
|
||||
assert(err == TOX_ERR_CONFERENCE_JOIN_OK);
|
||||
}
|
||||
|
||||
void handle_conference_message(Tox *tox, uint32_t conference_number, uint32_t peer_number,
|
||||
Tox_Message_Type type, const uint8_t *message, size_t length,
|
||||
void *user_data) {
|
||||
Local_State *state = static_cast<Local_State *>(user_data);
|
||||
Tox_Message_Type type, const uint8_t *message, size_t length, void *user_data)
|
||||
{
|
||||
Local_State *state = static_cast<Local_State *>(user_data);
|
||||
|
||||
if (LOG_CALLBACKS) {
|
||||
std::printf("Tox #%u received a message of length %u\n", state->id(),
|
||||
static_cast<unsigned>(length));
|
||||
}
|
||||
if (LOG_CALLBACKS) {
|
||||
std::printf("Tox #%u received a message of length %u\n", state->id(),
|
||||
static_cast<unsigned>(length));
|
||||
}
|
||||
}
|
||||
|
||||
void handle_conference_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data) {
|
||||
Local_State *state = static_cast<Local_State *>(user_data);
|
||||
void handle_conference_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data)
|
||||
{
|
||||
Local_State *state = static_cast<Local_State *>(user_data);
|
||||
|
||||
if (LOG_CALLBACKS) {
|
||||
std::printf("Tox #%u rebuilds peer list for conference %u\n", state->id(), conference_number);
|
||||
}
|
||||
if (LOG_CALLBACKS) {
|
||||
std::printf(
|
||||
"Tox #%u rebuilds peer list for conference %u\n", state->id(), conference_number);
|
||||
}
|
||||
|
||||
Tox_Err_Conference_Peer_Query err;
|
||||
uint32_t const count = tox_conference_peer_count(tox, conference_number, &err);
|
||||
assert(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK);
|
||||
|
||||
for (uint32_t peer_number = 0; peer_number < count; peer_number++) {
|
||||
size_t size = tox_conference_peer_get_name_size(tox, conference_number, peer_number, &err);
|
||||
Tox_Err_Conference_Peer_Query err;
|
||||
uint32_t const count = tox_conference_peer_count(tox, conference_number, &err);
|
||||
assert(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK);
|
||||
|
||||
std::vector<uint8_t> name(size);
|
||||
tox_conference_peer_get_name(tox, conference_number, peer_number, &name[0], &err);
|
||||
assert(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK);
|
||||
}
|
||||
}
|
||||
for (uint32_t peer_number = 0; peer_number < count; peer_number++) {
|
||||
size_t size = tox_conference_peer_get_name_size(tox, conference_number, peer_number, &err);
|
||||
assert(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK);
|
||||
|
||||
Global_State make_toxes(std::vector<Action> const &actions) {
|
||||
Global_State toxes(actions);
|
||||
|
||||
Tox_Options_Ptr options(tox_options_new(nullptr));
|
||||
tox_options_set_local_discovery_enabled(options.get(), false);
|
||||
|
||||
for (uint32_t i = 0; i < NUM_TOXES; i++) {
|
||||
Tox_Err_New err;
|
||||
toxes.emplace_back(Tox_Ptr(tox_new(options.get(), &err)), i);
|
||||
assert(err == TOX_ERR_NEW_OK);
|
||||
assert(toxes.back().tox() != nullptr);
|
||||
|
||||
tox_callback_friend_connection_status(toxes.back().tox(), handle_friend_connection_status);
|
||||
tox_callback_conference_invite(toxes.back().tox(), handle_conference_invite);
|
||||
tox_callback_conference_message(toxes.back().tox(), handle_conference_message);
|
||||
tox_callback_conference_peer_list_changed(toxes.back().tox(),
|
||||
handle_conference_peer_list_changed);
|
||||
}
|
||||
|
||||
std::printf("Bootstrapping %u toxes\n", NUM_TOXES);
|
||||
|
||||
uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_dht_id(toxes.front().tox(), dht_key);
|
||||
const uint16_t dht_port = tox_self_get_udp_port(toxes.front().tox(), nullptr);
|
||||
|
||||
for (Local_State const &state : toxes) {
|
||||
Tox_Err_Bootstrap err;
|
||||
tox_bootstrap(state.tox(), "localhost", dht_port, dht_key, &err);
|
||||
assert(err == TOX_ERR_BOOTSTRAP_OK);
|
||||
}
|
||||
|
||||
std::printf("Creating full mesh of friendships\n");
|
||||
|
||||
for (Local_State const &state1 : toxes) {
|
||||
for (Local_State const &state2 : toxes) {
|
||||
if (state1.tox() != state2.tox()) {
|
||||
Tox_Err_Friend_Add err;
|
||||
uint8_t key[TOX_PUBLIC_KEY_SIZE];
|
||||
|
||||
tox_self_get_public_key(state1.tox(), key);
|
||||
tox_friend_add_norequest(state2.tox(), key, &err);
|
||||
assert(err == TOX_ERR_FRIEND_ADD_OK);
|
||||
}
|
||||
std::vector<uint8_t> name(size);
|
||||
tox_conference_peer_get_name(tox, conference_number, peer_number, &name[0], &err);
|
||||
assert(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK);
|
||||
}
|
||||
}
|
||||
|
||||
return toxes;
|
||||
}
|
||||
|
||||
bool all_connected(Global_State const &toxes) {
|
||||
return std::all_of(toxes.begin(), toxes.end(), [](Local_State const &state) {
|
||||
return state.friends_online == NUM_TOXES - 1;
|
||||
});
|
||||
}
|
||||
Global_State make_toxes(std::vector<Action> const &actions)
|
||||
{
|
||||
Global_State toxes(actions);
|
||||
|
||||
bool bootstrap_toxes(Global_State *toxes) {
|
||||
std::printf("Waiting for %u iterations for all friends to come online\n",
|
||||
MAX_BOOTSTRAP_ITERATIONS);
|
||||
Tox_Options_Ptr options(tox_options_new(nullptr));
|
||||
tox_options_set_local_discovery_enabled(options.get(), false);
|
||||
|
||||
for (uint32_t i = 0; i < MAX_BOOTSTRAP_ITERATIONS; i++) {
|
||||
c_sleep(tox_iteration_interval(toxes->front().tox()));
|
||||
for (uint32_t i = 0; i < NUM_TOXES; i++) {
|
||||
Tox_Err_New err;
|
||||
toxes.emplace_back(Tox_Ptr(tox_new(options.get(), &err)), i);
|
||||
assert(err == TOX_ERR_NEW_OK);
|
||||
assert(toxes.back().tox() != nullptr);
|
||||
|
||||
for (Local_State &state : *toxes) {
|
||||
tox_iterate(state.tox(), &state);
|
||||
tox_callback_friend_connection_status(toxes.back().tox(), handle_friend_connection_status);
|
||||
tox_callback_conference_invite(toxes.back().tox(), handle_conference_invite);
|
||||
tox_callback_conference_message(toxes.back().tox(), handle_conference_message);
|
||||
tox_callback_conference_peer_list_changed(
|
||||
toxes.back().tox(), handle_conference_peer_list_changed);
|
||||
}
|
||||
|
||||
if (all_connected(*toxes)) {
|
||||
std::printf("Took %u iterations\n", i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
std::printf("Bootstrapping %u toxes\n", NUM_TOXES);
|
||||
|
||||
return false;
|
||||
uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
|
||||
tox_self_get_dht_id(toxes.front().tox(), dht_key);
|
||||
const uint16_t dht_port = tox_self_get_udp_port(toxes.front().tox(), nullptr);
|
||||
|
||||
for (Local_State const &state : toxes) {
|
||||
Tox_Err_Bootstrap err;
|
||||
tox_bootstrap(state.tox(), "localhost", dht_port, dht_key, &err);
|
||||
assert(err == TOX_ERR_BOOTSTRAP_OK);
|
||||
}
|
||||
|
||||
std::printf("Creating full mesh of friendships\n");
|
||||
|
||||
for (Local_State const &state1 : toxes) {
|
||||
for (Local_State const &state2 : toxes) {
|
||||
if (state1.tox() != state2.tox()) {
|
||||
Tox_Err_Friend_Add err;
|
||||
uint8_t key[TOX_PUBLIC_KEY_SIZE];
|
||||
|
||||
tox_self_get_public_key(state1.tox(), key);
|
||||
tox_friend_add_norequest(state2.tox(), key, &err);
|
||||
assert(err == TOX_ERR_FRIEND_ADD_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toxes;
|
||||
}
|
||||
|
||||
bool execute_random_action(Global_State *toxes, std::mt19937 *rng) {
|
||||
// First, choose a random actor.
|
||||
Local_State &actor = toxes->at(toxes->rnd()->tox_selector(*rng));
|
||||
size_t const action_id = toxes->rnd()->action_selector(*rng);
|
||||
Action const &action = toxes->action(action_id);
|
||||
if (!action.can(actor)) {
|
||||
bool all_connected(Global_State const &toxes)
|
||||
{
|
||||
return std::all_of(toxes.begin(), toxes.end(),
|
||||
[](Local_State const &state) { return state.friends_online == NUM_TOXES - 1; });
|
||||
}
|
||||
|
||||
bool bootstrap_toxes(Global_State *toxes)
|
||||
{
|
||||
std::printf(
|
||||
"Waiting for %u iterations for all friends to come online\n", MAX_BOOTSTRAP_ITERATIONS);
|
||||
|
||||
for (uint32_t i = 0; i < MAX_BOOTSTRAP_ITERATIONS; i++) {
|
||||
c_sleep(tox_iteration_interval(toxes->front().tox()));
|
||||
|
||||
for (Local_State &state : *toxes) {
|
||||
tox_iterate(state.tox(), &state);
|
||||
}
|
||||
|
||||
if (all_connected(*toxes)) {
|
||||
std::printf("Took %u iterations\n", i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::printf("Tox #%u %s", actor.id(), action.title);
|
||||
action.run(&actor, toxes->rnd(), rng);
|
||||
std::printf("\n");
|
||||
|
||||
toxes->action_counter().at(action_id)++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool attempt_action(Global_State *toxes, std::mt19937 *rng) {
|
||||
for (uint32_t i = 0; i < MAX_ACTION_ATTEMPTS; i++) {
|
||||
if (execute_random_action(toxes, rng)) {
|
||||
return true;
|
||||
bool execute_random_action(Global_State *toxes, std::mt19937 *rng)
|
||||
{
|
||||
// First, choose a random actor.
|
||||
Local_State &actor = toxes->at(toxes->rnd()->tox_selector(*rng));
|
||||
size_t const action_id = toxes->rnd()->action_selector(*rng);
|
||||
Action const &action = toxes->action(action_id);
|
||||
if (!action.can(actor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
std::printf("Tox #%u %s", actor.id(), action.title);
|
||||
action.run(&actor, toxes->rnd(), rng);
|
||||
std::printf("\n");
|
||||
|
||||
toxes->action_counter().at(action_id)++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool attempt_action(Global_State *toxes, std::mt19937 *rng)
|
||||
{
|
||||
for (uint32_t i = 0; i < MAX_ACTION_ATTEMPTS; i++) {
|
||||
if (execute_random_action(toxes, rng)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
std::vector<Action> const actions = {
|
||||
{
|
||||
10,
|
||||
"creates a new conference",
|
||||
[](Local_State const &state) {
|
||||
return tox_conference_get_chatlist_size(state.tox()) < MAX_CONFERENCES_PER_USER;
|
||||
},
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
Tox_Err_Conference_New err;
|
||||
tox_conference_new(state->tox(), &err);
|
||||
assert(err == TOX_ERR_CONFERENCE_NEW_OK);
|
||||
},
|
||||
},
|
||||
{
|
||||
10,
|
||||
"invites a random friend to a conference",
|
||||
[](Local_State const &state) {
|
||||
return tox_conference_get_chatlist_size(state.tox()) != 0;
|
||||
},
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
size_t chat_count = tox_conference_get_chatlist_size(state->tox());
|
||||
assert(chat_count != 0); // Condition above.
|
||||
Tox_Err_Conference_Invite err;
|
||||
tox_conference_invite(state->tox(), rnd->friend_selector(*rng),
|
||||
state->next_invite % chat_count, &err);
|
||||
state->next_invite++;
|
||||
assert(err == TOX_ERR_CONFERENCE_INVITE_OK);
|
||||
},
|
||||
},
|
||||
{
|
||||
10,
|
||||
"deletes the last conference",
|
||||
[](Local_State const &state) {
|
||||
return tox_conference_get_chatlist_size(state.tox()) != 0;
|
||||
},
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
Tox_Err_Conference_Delete err;
|
||||
tox_conference_delete(state->tox(), tox_conference_get_chatlist_size(state->tox()) - 1,
|
||||
&err);
|
||||
assert(err == TOX_ERR_CONFERENCE_DELETE_OK);
|
||||
},
|
||||
},
|
||||
{
|
||||
10,
|
||||
"sends a message to the last conference",
|
||||
[](Local_State const &state) {
|
||||
return tox_conference_get_chatlist_size(state.tox()) != 0;
|
||||
},
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
std::vector<uint8_t> message(rnd->message_length_selector(*rng));
|
||||
for (uint8_t &byte : message) {
|
||||
byte = rnd->byte_selector(*rng);
|
||||
int main()
|
||||
{
|
||||
std::vector<Action> const actions = {
|
||||
{
|
||||
10,
|
||||
"creates a new conference",
|
||||
[](Local_State const &state) {
|
||||
return tox_conference_get_chatlist_size(state.tox()) < MAX_CONFERENCES_PER_USER;
|
||||
},
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
Tox_Err_Conference_New err;
|
||||
tox_conference_new(state->tox(), &err);
|
||||
assert(err == TOX_ERR_CONFERENCE_NEW_OK);
|
||||
},
|
||||
},
|
||||
{
|
||||
10,
|
||||
"invites a random friend to a conference",
|
||||
[](Local_State const &state) {
|
||||
return tox_conference_get_chatlist_size(state.tox()) != 0;
|
||||
},
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
size_t chat_count = tox_conference_get_chatlist_size(state->tox());
|
||||
assert(chat_count != 0); // Condition above.
|
||||
Tox_Err_Conference_Invite err;
|
||||
tox_conference_invite(state->tox(), rnd->friend_selector(*rng),
|
||||
state->next_invite % chat_count, &err);
|
||||
state->next_invite++;
|
||||
assert(err == TOX_ERR_CONFERENCE_INVITE_OK);
|
||||
},
|
||||
},
|
||||
{
|
||||
10,
|
||||
"deletes the last conference",
|
||||
[](Local_State const &state) {
|
||||
return tox_conference_get_chatlist_size(state.tox()) != 0;
|
||||
},
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
Tox_Err_Conference_Delete err;
|
||||
tox_conference_delete(
|
||||
state->tox(), tox_conference_get_chatlist_size(state->tox()) - 1, &err);
|
||||
assert(err == TOX_ERR_CONFERENCE_DELETE_OK);
|
||||
},
|
||||
},
|
||||
{
|
||||
10,
|
||||
"sends a message to the last conference",
|
||||
[](Local_State const &state) {
|
||||
return tox_conference_get_chatlist_size(state.tox()) != 0;
|
||||
},
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
std::vector<uint8_t> message(rnd->message_length_selector(*rng));
|
||||
for (uint8_t &byte : message) {
|
||||
byte = rnd->byte_selector(*rng);
|
||||
}
|
||||
|
||||
Tox_Err_Conference_Send_Message err;
|
||||
tox_conference_send_message(state->tox(),
|
||||
tox_conference_get_chatlist_size(state->tox()) - 1, TOX_MESSAGE_TYPE_NORMAL,
|
||||
message.data(), message.size(), &err);
|
||||
if (err == TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) {
|
||||
printf(" (OK, length = %u)", static_cast<unsigned>(message.size()));
|
||||
} else {
|
||||
printf(" (FAILED: %u)", err);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
10,
|
||||
"changes their name",
|
||||
[](Local_State const &state) { return true; },
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
std::vector<uint8_t> name(rnd->name_length_selector(*rng));
|
||||
for (uint8_t &byte : name) {
|
||||
byte = rnd->byte_selector(*rng);
|
||||
}
|
||||
|
||||
Tox_Err_Set_Info err;
|
||||
tox_self_set_name(state->tox(), name.data(), name.size(), &err);
|
||||
assert(err == TOX_ERR_SET_INFO_OK);
|
||||
|
||||
printf(" (length = %u)", static_cast<unsigned>(name.size()));
|
||||
},
|
||||
},
|
||||
{
|
||||
10,
|
||||
"sets their name to empty",
|
||||
[](Local_State const &state) { return true; },
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
Tox_Err_Set_Info err;
|
||||
tox_self_set_name(state->tox(), nullptr, 0, &err);
|
||||
assert(err == TOX_ERR_SET_INFO_OK);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Global_State toxes = make_toxes(actions);
|
||||
|
||||
std::mt19937 rng;
|
||||
uint32_t action_number;
|
||||
for (action_number = 0; action_number < MAX_ACTIONS; action_number++) {
|
||||
if (!all_connected(toxes) && !bootstrap_toxes(&toxes)) {
|
||||
std::printf("Bootstrapping took too long; %u actions performed\n", action_number);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!attempt_action(&toxes, &rng)) {
|
||||
std::printf("System is stuck after %u actions: none of the toxes can perform an action "
|
||||
"anymore\n",
|
||||
action_number);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < ITERATIONS_PER_ACTION; i++) {
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
|
||||
for (Local_State &state : toxes) {
|
||||
tox_iterate(state.tox(), &state);
|
||||
}
|
||||
|
||||
Tox_Err_Conference_Send_Message err;
|
||||
tox_conference_send_message(
|
||||
state->tox(), tox_conference_get_chatlist_size(state->tox()) - 1,
|
||||
TOX_MESSAGE_TYPE_NORMAL, message.data(), message.size(), &err);
|
||||
if (err == TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) {
|
||||
printf(" (OK, length = %u)", static_cast<unsigned>(message.size()));
|
||||
} else {
|
||||
printf(" (FAILED: %u)", err);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
10,
|
||||
"changes their name",
|
||||
[](Local_State const &state) { return true; },
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
std::vector<uint8_t> name(rnd->name_length_selector(*rng));
|
||||
for (uint8_t &byte : name) {
|
||||
byte = rnd->byte_selector(*rng);
|
||||
}
|
||||
|
||||
Tox_Err_Set_Info err;
|
||||
tox_self_set_name(state->tox(), name.data(), name.size(), &err);
|
||||
assert(err == TOX_ERR_SET_INFO_OK);
|
||||
|
||||
printf(" (length = %u)", static_cast<unsigned>(name.size()));
|
||||
},
|
||||
},
|
||||
{
|
||||
10,
|
||||
"sets their name to empty",
|
||||
[](Local_State const &state) { return true; },
|
||||
[](Local_State *state, Random *rnd, std::mt19937 *rng) {
|
||||
Tox_Err_Set_Info err;
|
||||
tox_self_set_name(state->tox(), nullptr, 0, &err);
|
||||
assert(err == TOX_ERR_SET_INFO_OK);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Global_State toxes = make_toxes(actions);
|
||||
|
||||
std::mt19937 rng;
|
||||
uint32_t action_number;
|
||||
for (action_number = 0; action_number < MAX_ACTIONS; action_number++) {
|
||||
if (!all_connected(toxes) && !bootstrap_toxes(&toxes)) {
|
||||
std::printf("Bootstrapping took too long; %u actions performed\n", action_number);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!attempt_action(&toxes, &rng)) {
|
||||
std::printf(
|
||||
"System is stuck after %u actions: none of the toxes can perform an action anymore\n",
|
||||
action_number);
|
||||
return EXIT_FAILURE;
|
||||
std::printf("Test execution success: %u actions performed\n", action_number);
|
||||
std::printf("Per-action statistics:\n");
|
||||
for (uint32_t i = 0; i < toxes.action_counter().size(); i++) {
|
||||
std::printf("%u x '%s'\n", toxes.action_counter().at(i), actions[i].title);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < ITERATIONS_PER_ACTION; i++) {
|
||||
c_sleep(ITERATION_INTERVAL);
|
||||
|
||||
for (Local_State &state : toxes) {
|
||||
tox_iterate(state.tox(), &state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::printf("Test execution success: %u actions performed\n", action_number);
|
||||
std::printf("Per-action statistics:\n");
|
||||
for (uint32_t i = 0; i < toxes.action_counter().size(); i++) {
|
||||
std::printf("%u x '%s'\n", toxes.action_counter().at(i), actions[i].title);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,184 +13,202 @@ class TypedRingBuffer;
|
|||
|
||||
template <typename T>
|
||||
class TypedRingBuffer<T *> {
|
||||
public:
|
||||
explicit TypedRingBuffer(int size) : rb_(rb_new(size)) {}
|
||||
~TypedRingBuffer() { rb_kill(rb_); }
|
||||
TypedRingBuffer(TypedRingBuffer const &) = delete;
|
||||
|
||||
bool full() const { return rb_full(rb_); }
|
||||
bool empty() const { return rb_empty(rb_); }
|
||||
T *write(T *p) { return static_cast<T *>(rb_write(rb_, p)); }
|
||||
bool read(T **p) {
|
||||
void *vp;
|
||||
bool res = rb_read(rb_, &vp);
|
||||
*p = static_cast<T *>(vp);
|
||||
return res;
|
||||
}
|
||||
|
||||
uint16_t size() const { return rb_size(rb_); }
|
||||
uint16_t data(T **dest) const {
|
||||
std::vector<void *> vdest(size());
|
||||
uint16_t res = rb_data(rb_, vdest.data());
|
||||
for (uint16_t i = 0; i < size(); i++) {
|
||||
dest[i] = static_cast<T *>(vdest.at(i));
|
||||
public:
|
||||
explicit TypedRingBuffer(int size)
|
||||
: rb_(rb_new(size))
|
||||
{
|
||||
}
|
||||
return res;
|
||||
}
|
||||
~TypedRingBuffer() { rb_kill(rb_); }
|
||||
TypedRingBuffer(TypedRingBuffer const &) = delete;
|
||||
|
||||
bool contains(T *p) const {
|
||||
std::vector<T *> elts(size());
|
||||
data(elts.data());
|
||||
return std::find(elts.begin(), elts.end(), p) != elts.end();
|
||||
}
|
||||
bool full() const { return rb_full(rb_); }
|
||||
bool empty() const { return rb_empty(rb_); }
|
||||
T *write(T *p) { return static_cast<T *>(rb_write(rb_, p)); }
|
||||
bool read(T **p)
|
||||
{
|
||||
void *vp;
|
||||
bool res = rb_read(rb_, &vp);
|
||||
*p = static_cast<T *>(vp);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool ok() const { return rb_ != nullptr; }
|
||||
uint16_t size() const { return rb_size(rb_); }
|
||||
uint16_t data(T **dest) const
|
||||
{
|
||||
std::vector<void *> vdest(size());
|
||||
uint16_t res = rb_data(rb_, vdest.data());
|
||||
for (uint16_t i = 0; i < size(); i++) {
|
||||
dest[i] = static_cast<T *>(vdest.at(i));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
RingBuffer *rb_;
|
||||
bool contains(T *p) const
|
||||
{
|
||||
std::vector<T *> elts(size());
|
||||
data(elts.data());
|
||||
return std::find(elts.begin(), elts.end(), p) != elts.end();
|
||||
}
|
||||
|
||||
bool ok() const { return rb_ != nullptr; }
|
||||
|
||||
private:
|
||||
RingBuffer *rb_;
|
||||
};
|
||||
|
||||
TEST(RingBuffer, EmptyBufferReportsEmpty) {
|
||||
TypedRingBuffer<int *> rb(10);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
EXPECT_TRUE(rb.empty());
|
||||
TEST(RingBuffer, EmptyBufferReportsEmpty)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(10);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
EXPECT_TRUE(rb.empty());
|
||||
}
|
||||
|
||||
TEST(RingBuffer, EmptyBufferReportsNotFull) {
|
||||
TypedRingBuffer<int *> rb(10);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
EXPECT_FALSE(rb.full());
|
||||
TEST(RingBuffer, EmptyBufferReportsNotFull)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(10);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
EXPECT_FALSE(rb.full());
|
||||
}
|
||||
|
||||
TEST(RingBuffer, ZeroSizedRingBufferIsBothEmptyAndFull) {
|
||||
TypedRingBuffer<int *> rb(0);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
EXPECT_TRUE(rb.empty());
|
||||
EXPECT_TRUE(rb.full());
|
||||
TEST(RingBuffer, ZeroSizedRingBufferIsBothEmptyAndFull)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(0);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
EXPECT_TRUE(rb.empty());
|
||||
EXPECT_TRUE(rb.full());
|
||||
}
|
||||
|
||||
TEST(RingBuffer, WritingMakesBufferNotEmpty) {
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
rb.write(&value0);
|
||||
EXPECT_FALSE(rb.empty());
|
||||
TEST(RingBuffer, WritingMakesBufferNotEmpty)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
rb.write(&value0);
|
||||
EXPECT_FALSE(rb.empty());
|
||||
}
|
||||
|
||||
TEST(RingBuffer, WritingOneElementMakesBufferNotFull) {
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
rb.write(&value0);
|
||||
EXPECT_FALSE(rb.full());
|
||||
TEST(RingBuffer, WritingOneElementMakesBufferNotFull)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
rb.write(&value0);
|
||||
EXPECT_FALSE(rb.full());
|
||||
}
|
||||
|
||||
TEST(RingBuffer, WritingAllElementsMakesBufferFull) {
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
int value1 = 231;
|
||||
rb.write(&value0);
|
||||
rb.write(&value1);
|
||||
EXPECT_TRUE(rb.full());
|
||||
TEST(RingBuffer, WritingAllElementsMakesBufferFull)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
int value1 = 231;
|
||||
rb.write(&value0);
|
||||
rb.write(&value1);
|
||||
EXPECT_TRUE(rb.full());
|
||||
}
|
||||
|
||||
TEST(RingBuffer, ReadingElementFromFullBufferMakesItNotFull) {
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
int value1 = 231;
|
||||
rb.write(&value0);
|
||||
rb.write(&value1);
|
||||
EXPECT_TRUE(rb.full());
|
||||
int *retrieved;
|
||||
// Reading deletes the element.
|
||||
EXPECT_TRUE(rb.read(&retrieved));
|
||||
EXPECT_FALSE(rb.full());
|
||||
TEST(RingBuffer, ReadingElementFromFullBufferMakesItNotFull)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
int value1 = 231;
|
||||
rb.write(&value0);
|
||||
rb.write(&value1);
|
||||
EXPECT_TRUE(rb.full());
|
||||
int *retrieved;
|
||||
// Reading deletes the element.
|
||||
EXPECT_TRUE(rb.read(&retrieved));
|
||||
EXPECT_FALSE(rb.full());
|
||||
}
|
||||
|
||||
TEST(RingBuffer, ZeroSizeBufferCanBeWrittenToOnce) {
|
||||
TypedRingBuffer<int *> rb(0);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
// Strange behaviour: we can write one element to a 0-size buffer.
|
||||
EXPECT_EQ(nullptr, rb.write(&value0));
|
||||
EXPECT_EQ(&value0, rb.write(&value0));
|
||||
int *retrieved = nullptr;
|
||||
// But then we can't read it.
|
||||
EXPECT_FALSE(rb.read(&retrieved));
|
||||
EXPECT_EQ(nullptr, retrieved);
|
||||
TEST(RingBuffer, ZeroSizeBufferCanBeWrittenToOnce)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(0);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
// Strange behaviour: we can write one element to a 0-size buffer.
|
||||
EXPECT_EQ(nullptr, rb.write(&value0));
|
||||
EXPECT_EQ(&value0, rb.write(&value0));
|
||||
int *retrieved = nullptr;
|
||||
// But then we can't read it.
|
||||
EXPECT_FALSE(rb.read(&retrieved));
|
||||
EXPECT_EQ(nullptr, retrieved);
|
||||
}
|
||||
|
||||
TEST(RingBuffer, ReadingFromEmptyBufferFails) {
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int *retrieved;
|
||||
EXPECT_FALSE(rb.read(&retrieved));
|
||||
TEST(RingBuffer, ReadingFromEmptyBufferFails)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int *retrieved;
|
||||
EXPECT_FALSE(rb.read(&retrieved));
|
||||
}
|
||||
|
||||
TEST(RingBuffer, WritingToBufferWhenFullOverwritesBeginning) {
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
int value1 = 231;
|
||||
int value2 = 312;
|
||||
int value3 = 432;
|
||||
EXPECT_EQ(nullptr, rb.write(&value0));
|
||||
EXPECT_EQ(nullptr, rb.write(&value1));
|
||||
EXPECT_TRUE(rb.contains(&value0));
|
||||
EXPECT_TRUE(rb.contains(&value1));
|
||||
TEST(RingBuffer, WritingToBufferWhenFullOverwritesBeginning)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(2);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
int value1 = 231;
|
||||
int value2 = 312;
|
||||
int value3 = 432;
|
||||
EXPECT_EQ(nullptr, rb.write(&value0));
|
||||
EXPECT_EQ(nullptr, rb.write(&value1));
|
||||
EXPECT_TRUE(rb.contains(&value0));
|
||||
EXPECT_TRUE(rb.contains(&value1));
|
||||
|
||||
// Adding another element evicts the first element.
|
||||
EXPECT_EQ(&value0, rb.write(&value2));
|
||||
EXPECT_FALSE(rb.contains(&value0));
|
||||
EXPECT_TRUE(rb.contains(&value2));
|
||||
// Adding another element evicts the first element.
|
||||
EXPECT_EQ(&value0, rb.write(&value2));
|
||||
EXPECT_FALSE(rb.contains(&value0));
|
||||
EXPECT_TRUE(rb.contains(&value2));
|
||||
|
||||
// Adding another evicts the second.
|
||||
EXPECT_EQ(&value1, rb.write(&value3));
|
||||
EXPECT_FALSE(rb.contains(&value1));
|
||||
EXPECT_TRUE(rb.contains(&value3));
|
||||
// Adding another evicts the second.
|
||||
EXPECT_EQ(&value1, rb.write(&value3));
|
||||
EXPECT_FALSE(rb.contains(&value1));
|
||||
EXPECT_TRUE(rb.contains(&value3));
|
||||
}
|
||||
|
||||
TEST(RingBuffer, SizeIsNumberOfElementsInBuffer) {
|
||||
TypedRingBuffer<int *> rb(10);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
EXPECT_EQ(rb.size(), 0);
|
||||
rb.write(&value0);
|
||||
EXPECT_EQ(rb.size(), 1);
|
||||
rb.write(&value0);
|
||||
EXPECT_EQ(rb.size(), 2);
|
||||
rb.write(&value0);
|
||||
EXPECT_EQ(rb.size(), 3);
|
||||
rb.write(&value0);
|
||||
EXPECT_EQ(rb.size(), 4);
|
||||
TEST(RingBuffer, SizeIsNumberOfElementsInBuffer)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(10);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
EXPECT_EQ(rb.size(), 0);
|
||||
rb.write(&value0);
|
||||
EXPECT_EQ(rb.size(), 1);
|
||||
rb.write(&value0);
|
||||
EXPECT_EQ(rb.size(), 2);
|
||||
rb.write(&value0);
|
||||
EXPECT_EQ(rb.size(), 3);
|
||||
rb.write(&value0);
|
||||
EXPECT_EQ(rb.size(), 4);
|
||||
|
||||
int *retrieved;
|
||||
rb.read(&retrieved);
|
||||
EXPECT_EQ(rb.size(), 3);
|
||||
rb.read(&retrieved);
|
||||
EXPECT_EQ(rb.size(), 2);
|
||||
rb.read(&retrieved);
|
||||
EXPECT_EQ(rb.size(), 1);
|
||||
rb.read(&retrieved);
|
||||
EXPECT_EQ(rb.size(), 0);
|
||||
int *retrieved;
|
||||
rb.read(&retrieved);
|
||||
EXPECT_EQ(rb.size(), 3);
|
||||
rb.read(&retrieved);
|
||||
EXPECT_EQ(rb.size(), 2);
|
||||
rb.read(&retrieved);
|
||||
EXPECT_EQ(rb.size(), 1);
|
||||
rb.read(&retrieved);
|
||||
EXPECT_EQ(rb.size(), 0);
|
||||
}
|
||||
|
||||
TEST(RingBuffer, SizeIsLimitedByMaxSize) {
|
||||
TypedRingBuffer<int *> rb(4);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
rb.write(&value0);
|
||||
rb.write(&value0);
|
||||
rb.write(&value0);
|
||||
rb.write(&value0);
|
||||
EXPECT_EQ(rb.size(), 4);
|
||||
TEST(RingBuffer, SizeIsLimitedByMaxSize)
|
||||
{
|
||||
TypedRingBuffer<int *> rb(4);
|
||||
ASSERT_TRUE(rb.ok());
|
||||
int value0 = 123;
|
||||
rb.write(&value0);
|
||||
rb.write(&value0);
|
||||
rb.write(&value0);
|
||||
rb.write(&value0);
|
||||
EXPECT_EQ(rb.size(), 4);
|
||||
|
||||
// Add one more.
|
||||
rb.write(&value0);
|
||||
// Still size is 4.
|
||||
EXPECT_EQ(rb.size(), 4);
|
||||
// Add one more.
|
||||
rb.write(&value0);
|
||||
// Still size is 4.
|
||||
EXPECT_EQ(rb.size(), 4);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -6,59 +6,74 @@
|
|||
|
||||
namespace {
|
||||
|
||||
RTPHeader random_header() {
|
||||
return {
|
||||
random_u16(), random_u16(), random_u16(), random_u16(), random_u16(),
|
||||
random_u16(), random_u16(), random_u32(), random_u32(), random_u64(),
|
||||
random_u32(), random_u32(), random_u32(), random_u16(), random_u16(),
|
||||
};
|
||||
RTPHeader random_header()
|
||||
{
|
||||
return {
|
||||
random_u16(),
|
||||
random_u16(),
|
||||
random_u16(),
|
||||
random_u16(),
|
||||
random_u16(),
|
||||
random_u16(),
|
||||
random_u16(),
|
||||
random_u32(),
|
||||
random_u32(),
|
||||
random_u64(),
|
||||
random_u32(),
|
||||
random_u32(),
|
||||
random_u32(),
|
||||
random_u16(),
|
||||
random_u16(),
|
||||
};
|
||||
}
|
||||
|
||||
TEST(Rtp, Deserialisation) {
|
||||
RTPHeader const header = random_header();
|
||||
TEST(Rtp, Deserialisation)
|
||||
{
|
||||
RTPHeader const header = random_header();
|
||||
|
||||
uint8_t rdata[RTP_HEADER_SIZE];
|
||||
EXPECT_EQ(rtp_header_pack(rdata, &header), RTP_HEADER_SIZE);
|
||||
uint8_t rdata[RTP_HEADER_SIZE];
|
||||
EXPECT_EQ(rtp_header_pack(rdata, &header), RTP_HEADER_SIZE);
|
||||
|
||||
RTPHeader unpacked = {0};
|
||||
EXPECT_EQ(rtp_header_unpack(rdata, &unpacked), RTP_HEADER_SIZE);
|
||||
RTPHeader unpacked = {0};
|
||||
EXPECT_EQ(rtp_header_unpack(rdata, &unpacked), RTP_HEADER_SIZE);
|
||||
|
||||
EXPECT_EQ(header.ve, unpacked.ve);
|
||||
EXPECT_EQ(header.pe, unpacked.pe);
|
||||
EXPECT_EQ(header.xe, unpacked.xe);
|
||||
EXPECT_EQ(header.cc, unpacked.cc);
|
||||
EXPECT_EQ(header.ma, unpacked.ma);
|
||||
EXPECT_EQ(header.pt, unpacked.pt);
|
||||
EXPECT_EQ(header.sequnum, unpacked.sequnum);
|
||||
EXPECT_EQ(header.timestamp, unpacked.timestamp);
|
||||
EXPECT_EQ(header.ssrc, unpacked.ssrc);
|
||||
EXPECT_EQ(header.flags, unpacked.flags);
|
||||
EXPECT_EQ(header.offset_full, unpacked.offset_full);
|
||||
EXPECT_EQ(header.data_length_full, unpacked.data_length_full);
|
||||
EXPECT_EQ(header.received_length_full, unpacked.received_length_full);
|
||||
EXPECT_EQ(header.offset_lower, unpacked.offset_lower);
|
||||
EXPECT_EQ(header.data_length_lower, unpacked.data_length_lower);
|
||||
EXPECT_EQ(header.ve, unpacked.ve);
|
||||
EXPECT_EQ(header.pe, unpacked.pe);
|
||||
EXPECT_EQ(header.xe, unpacked.xe);
|
||||
EXPECT_EQ(header.cc, unpacked.cc);
|
||||
EXPECT_EQ(header.ma, unpacked.ma);
|
||||
EXPECT_EQ(header.pt, unpacked.pt);
|
||||
EXPECT_EQ(header.sequnum, unpacked.sequnum);
|
||||
EXPECT_EQ(header.timestamp, unpacked.timestamp);
|
||||
EXPECT_EQ(header.ssrc, unpacked.ssrc);
|
||||
EXPECT_EQ(header.flags, unpacked.flags);
|
||||
EXPECT_EQ(header.offset_full, unpacked.offset_full);
|
||||
EXPECT_EQ(header.data_length_full, unpacked.data_length_full);
|
||||
EXPECT_EQ(header.received_length_full, unpacked.received_length_full);
|
||||
EXPECT_EQ(header.offset_lower, unpacked.offset_lower);
|
||||
EXPECT_EQ(header.data_length_lower, unpacked.data_length_lower);
|
||||
}
|
||||
|
||||
TEST(Rtp, SerialisingAllOnes) {
|
||||
RTPHeader header;
|
||||
memset(&header, 0xff, sizeof header);
|
||||
TEST(Rtp, SerialisingAllOnes)
|
||||
{
|
||||
RTPHeader header;
|
||||
memset(&header, 0xff, sizeof header);
|
||||
|
||||
uint8_t rdata[RTP_HEADER_SIZE];
|
||||
rtp_header_pack(rdata, &header);
|
||||
uint8_t rdata[RTP_HEADER_SIZE];
|
||||
rtp_header_pack(rdata, &header);
|
||||
|
||||
EXPECT_EQ(std::string(reinterpret_cast<char const *>(rdata), sizeof rdata),
|
||||
std::string("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
|
||||
RTP_HEADER_SIZE));
|
||||
EXPECT_EQ(std::string(reinterpret_cast<char const *>(rdata), sizeof rdata),
|
||||
std::string("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
|
||||
RTP_HEADER_SIZE));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -12,102 +12,108 @@ namespace {
|
|||
using PublicKey = std::array<uint8_t, CRYPTO_PUBLIC_KEY_SIZE>;
|
||||
|
||||
template <typename T, size_t N>
|
||||
std::array<T, N> to_array(T const (&arr)[N]) {
|
||||
std::array<T, N> stdarr;
|
||||
memcpy(stdarr.data(), arr, N);
|
||||
return stdarr;
|
||||
std::array<T, N> to_array(T const (&arr)[N])
|
||||
{
|
||||
std::array<T, N> stdarr;
|
||||
memcpy(stdarr.data(), arr, N);
|
||||
return stdarr;
|
||||
}
|
||||
|
||||
TEST(IdClosest, IdenticalKeysAreSameDistance) {
|
||||
PublicKey pk0;
|
||||
random_bytes(pk0.data(), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
|
||||
PublicKey pk1;
|
||||
random_bytes(pk1.data(), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
|
||||
PublicKey pk2 = pk1;
|
||||
|
||||
EXPECT_EQ(id_closest(pk0.data(), pk1.data(), pk2.data()), 0);
|
||||
}
|
||||
|
||||
TEST(IdClosest, DistanceIsCommutative) {
|
||||
for (uint32_t i = 0; i < 100; ++i) {
|
||||
TEST(IdClosest, IdenticalKeysAreSameDistance)
|
||||
{
|
||||
PublicKey pk0;
|
||||
random_bytes(pk0.data(), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
|
||||
PublicKey pk1;
|
||||
random_bytes(pk1.data(), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
|
||||
PublicKey pk2;
|
||||
random_bytes(pk2.data(), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
PublicKey pk2 = pk1;
|
||||
|
||||
ASSERT_NE(pk1, pk2); // RNG can't produce the same random key twice
|
||||
EXPECT_EQ(id_closest(pk0.data(), pk1.data(), pk2.data()), 0);
|
||||
}
|
||||
|
||||
// Two non-equal keys can't have the same distance from any given key.
|
||||
EXPECT_NE(id_closest(pk0.data(), pk1.data(), pk2.data()), 0);
|
||||
TEST(IdClosest, DistanceIsCommutative)
|
||||
{
|
||||
for (uint32_t i = 0; i < 100; ++i) {
|
||||
PublicKey pk0;
|
||||
random_bytes(pk0.data(), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
|
||||
if (id_closest(pk0.data(), pk1.data(), pk2.data()) == 1) {
|
||||
EXPECT_EQ(id_closest(pk0.data(), pk2.data(), pk1.data()), 2);
|
||||
PublicKey pk1;
|
||||
random_bytes(pk1.data(), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
|
||||
PublicKey pk2;
|
||||
random_bytes(pk2.data(), CRYPTO_PUBLIC_KEY_SIZE);
|
||||
|
||||
ASSERT_NE(pk1, pk2); // RNG can't produce the same random key twice
|
||||
|
||||
// Two non-equal keys can't have the same distance from any given key.
|
||||
EXPECT_NE(id_closest(pk0.data(), pk1.data(), pk2.data()), 0);
|
||||
|
||||
if (id_closest(pk0.data(), pk1.data(), pk2.data()) == 1) {
|
||||
EXPECT_EQ(id_closest(pk0.data(), pk2.data(), pk1.data()), 2);
|
||||
}
|
||||
|
||||
if (id_closest(pk0.data(), pk1.data(), pk2.data()) == 2) {
|
||||
EXPECT_EQ(id_closest(pk0.data(), pk2.data(), pk1.data()), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (id_closest(pk0.data(), pk1.data(), pk2.data()) == 2) {
|
||||
EXPECT_EQ(id_closest(pk0.data(), pk2.data(), pk1.data()), 1);
|
||||
TEST(IdClosest, SmallXorDistanceIsCloser)
|
||||
{
|
||||
PublicKey const pk0 = {{0xaa}};
|
||||
PublicKey const pk1 = {{0xa0}};
|
||||
PublicKey const pk2 = {{0x0a}};
|
||||
|
||||
EXPECT_EQ(id_closest(pk0.data(), pk1.data(), pk2.data()), 1);
|
||||
}
|
||||
|
||||
TEST(IdClosest, DistinctKeysCannotHaveTheSameDistance)
|
||||
{
|
||||
PublicKey const pk0 = {{0x06}};
|
||||
PublicKey const pk1 = {{0x00}};
|
||||
PublicKey pk2 = {{0x00}};
|
||||
|
||||
for (uint8_t i = 1; i < 0xff; ++i) {
|
||||
pk2[0] = i;
|
||||
EXPECT_NE(id_closest(pk0.data(), pk1.data(), pk2.data()), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(IdClosest, SmallXorDistanceIsCloser) {
|
||||
PublicKey const pk0 = {{0xaa}};
|
||||
PublicKey const pk1 = {{0xa0}};
|
||||
PublicKey const pk2 = {{0x0a}};
|
||||
TEST(AddToList, OverridesKeysWithCloserKeys)
|
||||
{
|
||||
PublicKey const self_pk = {{0xaa}};
|
||||
PublicKey const keys[] = {
|
||||
{{0xa0}}, // closest
|
||||
{{0x0a}}, //
|
||||
{{0x0b}}, //
|
||||
{{0x0c}}, //
|
||||
{{0x0d}}, //
|
||||
{{0xa1}}, // closer than the 4 keys above
|
||||
};
|
||||
|
||||
EXPECT_EQ(id_closest(pk0.data(), pk1.data(), pk2.data()), 1);
|
||||
}
|
||||
std::array<Node_format, 4> nodes{};
|
||||
|
||||
TEST(IdClosest, DistinctKeysCannotHaveTheSameDistance) {
|
||||
PublicKey const pk0 = {{0x06}};
|
||||
PublicKey const pk1 = {{0x00}};
|
||||
PublicKey pk2 = {{0x00}};
|
||||
IP_Port ip_port = {0};
|
||||
EXPECT_TRUE(add_to_list(nodes.data(), nodes.size(), keys[0].data(), &ip_port, self_pk.data()));
|
||||
EXPECT_TRUE(add_to_list(nodes.data(), nodes.size(), keys[1].data(), &ip_port, self_pk.data()));
|
||||
EXPECT_TRUE(add_to_list(nodes.data(), nodes.size(), keys[2].data(), &ip_port, self_pk.data()));
|
||||
EXPECT_TRUE(add_to_list(nodes.data(), nodes.size(), keys[3].data(), &ip_port, self_pk.data()));
|
||||
|
||||
for (uint8_t i = 1; i < 0xff; ++i) {
|
||||
pk2[0] = i;
|
||||
EXPECT_NE(id_closest(pk0.data(), pk1.data(), pk2.data()), 0);
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(to_array(nodes[0].public_key), keys[0]);
|
||||
EXPECT_EQ(to_array(nodes[1].public_key), keys[1]);
|
||||
EXPECT_EQ(to_array(nodes[2].public_key), keys[2]);
|
||||
EXPECT_EQ(to_array(nodes[3].public_key), keys[3]);
|
||||
|
||||
TEST(AddToList, OverridesKeysWithCloserKeys) {
|
||||
PublicKey const self_pk = {{0xaa}};
|
||||
PublicKey const keys[] = {
|
||||
{{0xa0}}, // closest
|
||||
{{0x0a}}, //
|
||||
{{0x0b}}, //
|
||||
{{0x0c}}, //
|
||||
{{0x0d}}, //
|
||||
{{0xa1}}, // closer than the 4 keys above
|
||||
};
|
||||
// key 4 is less close than keys 0-3
|
||||
EXPECT_FALSE(add_to_list(nodes.data(), nodes.size(), keys[4].data(), &ip_port, self_pk.data()));
|
||||
// 5 is closer than all except key 0
|
||||
EXPECT_TRUE(add_to_list(nodes.data(), nodes.size(), keys[5].data(), &ip_port, self_pk.data()));
|
||||
|
||||
std::array<Node_format, 4> nodes{};
|
||||
|
||||
IP_Port ip_port = {0};
|
||||
EXPECT_TRUE(add_to_list(nodes.data(), nodes.size(), keys[0].data(), &ip_port, self_pk.data()));
|
||||
EXPECT_TRUE(add_to_list(nodes.data(), nodes.size(), keys[1].data(), &ip_port, self_pk.data()));
|
||||
EXPECT_TRUE(add_to_list(nodes.data(), nodes.size(), keys[2].data(), &ip_port, self_pk.data()));
|
||||
EXPECT_TRUE(add_to_list(nodes.data(), nodes.size(), keys[3].data(), &ip_port, self_pk.data()));
|
||||
|
||||
EXPECT_EQ(to_array(nodes[0].public_key), keys[0]);
|
||||
EXPECT_EQ(to_array(nodes[1].public_key), keys[1]);
|
||||
EXPECT_EQ(to_array(nodes[2].public_key), keys[2]);
|
||||
EXPECT_EQ(to_array(nodes[3].public_key), keys[3]);
|
||||
|
||||
// key 4 is less close than keys 0-3
|
||||
EXPECT_FALSE(add_to_list(nodes.data(), nodes.size(), keys[4].data(), &ip_port, self_pk.data()));
|
||||
// 5 is closer than all except key 0
|
||||
EXPECT_TRUE(add_to_list(nodes.data(), nodes.size(), keys[5].data(), &ip_port, self_pk.data()));
|
||||
|
||||
EXPECT_EQ(to_array(nodes[0].public_key), keys[0]);
|
||||
EXPECT_EQ(to_array(nodes[1].public_key), keys[5]);
|
||||
EXPECT_EQ(to_array(nodes[2].public_key), keys[1]);
|
||||
EXPECT_EQ(to_array(nodes[3].public_key), keys[2]);
|
||||
EXPECT_EQ(to_array(nodes[0].public_key), keys[0]);
|
||||
EXPECT_EQ(to_array(nodes[1].public_key), keys[5]);
|
||||
EXPECT_EQ(to_array(nodes[2].public_key), keys[1]);
|
||||
EXPECT_EQ(to_array(nodes[3].public_key), keys[2]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -2567,8 +2567,14 @@ static uint32_t friend_size(void)
|
|||
uint32_t data = 0;
|
||||
const struct Saved_Friend *const temp = nullptr;
|
||||
|
||||
#define VALUE_MEMBER(name) do { data += sizeof(temp->name); } while (0)
|
||||
#define ARRAY_MEMBER(name) do { data += sizeof(temp->name); } while (0)
|
||||
#define VALUE_MEMBER(name) \
|
||||
do { \
|
||||
data += sizeof(temp->name); \
|
||||
} while (0)
|
||||
#define ARRAY_MEMBER(name) \
|
||||
do { \
|
||||
data += sizeof(temp->name); \
|
||||
} while (0)
|
||||
|
||||
// Exactly the same in friend_load, friend_save, and friend_size
|
||||
VALUE_MEMBER(status);
|
||||
|
@ -2595,15 +2601,17 @@ static uint32_t friend_size(void)
|
|||
non_null()
|
||||
static uint8_t *friend_save(const struct Saved_Friend *temp, uint8_t *data)
|
||||
{
|
||||
#define VALUE_MEMBER(name) do { \
|
||||
memcpy(data, &temp->name, sizeof(temp->name)); \
|
||||
data += sizeof(temp->name); \
|
||||
} while (0)
|
||||
#define VALUE_MEMBER(name) \
|
||||
do { \
|
||||
memcpy(data, &temp->name, sizeof(temp->name)); \
|
||||
data += sizeof(temp->name); \
|
||||
} while (0)
|
||||
|
||||
#define ARRAY_MEMBER(name) do { \
|
||||
memcpy(data, temp->name, sizeof(temp->name)); \
|
||||
data += sizeof(temp->name); \
|
||||
} while (0)
|
||||
#define ARRAY_MEMBER(name) \
|
||||
do { \
|
||||
memcpy(data, temp->name, sizeof(temp->name)); \
|
||||
data += sizeof(temp->name); \
|
||||
} while (0)
|
||||
|
||||
// Exactly the same in friend_load, friend_save, and friend_size
|
||||
VALUE_MEMBER(status);
|
||||
|
@ -2631,15 +2639,17 @@ static uint8_t *friend_save(const struct Saved_Friend *temp, uint8_t *data)
|
|||
non_null()
|
||||
static const uint8_t *friend_load(struct Saved_Friend *temp, const uint8_t *data)
|
||||
{
|
||||
#define VALUE_MEMBER(name) do { \
|
||||
memcpy(&temp->name, data, sizeof(temp->name)); \
|
||||
data += sizeof(temp->name); \
|
||||
} while (0)
|
||||
#define VALUE_MEMBER(name) \
|
||||
do { \
|
||||
memcpy(&temp->name, data, sizeof(temp->name)); \
|
||||
data += sizeof(temp->name); \
|
||||
} while (0)
|
||||
|
||||
#define ARRAY_MEMBER(name) do { \
|
||||
memcpy(temp->name, data, sizeof(temp->name)); \
|
||||
data += sizeof(temp->name); \
|
||||
} while (0)
|
||||
#define ARRAY_MEMBER(name) \
|
||||
do { \
|
||||
memcpy(temp->name, data, sizeof(temp->name)); \
|
||||
data += sizeof(temp->name); \
|
||||
} while (0)
|
||||
|
||||
// Exactly the same in friend_load, friend_save, and friend_size
|
||||
VALUE_MEMBER(status);
|
||||
|
|
|
@ -48,18 +48,18 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#define ALLOC_VLA(type, name, size) \
|
||||
const size_t name##_vla_size = (size) * sizeof(type); \
|
||||
type *const name = (type *)alloca(name##_vla_size)
|
||||
#define ALLOC_VLA(type, name, size) \
|
||||
const size_t name##_vla_size = (size) * sizeof(type); \
|
||||
type *const name = (type *)alloca(name##_vla_size)
|
||||
#define SIZEOF_VLA(name) name##_vla_size
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MAX_VLA_SIZE
|
||||
#include <assert.h>
|
||||
#define VLA(type, name, size) \
|
||||
ALLOC_VLA(type, name, size); \
|
||||
assert((size_t)(size) * sizeof(type) <= MAX_VLA_SIZE)
|
||||
#define VLA(type, name, size) \
|
||||
ALLOC_VLA(type, name, size); \
|
||||
assert((size_t)(size) * sizeof(type) <= MAX_VLA_SIZE)
|
||||
#else
|
||||
#define VLA ALLOC_VLA
|
||||
#endif
|
||||
|
|
|
@ -8,39 +8,39 @@
|
|||
|
||||
namespace {
|
||||
|
||||
TEST(CryptoCore, IncrementNonce) {
|
||||
using Nonce = std::array<uint8_t, CRYPTO_NONCE_SIZE>;
|
||||
Nonce nonce{};
|
||||
increment_nonce(nonce.data());
|
||||
EXPECT_EQ(nonce,
|
||||
(Nonce{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}));
|
||||
|
||||
for (int i = 0; i < 0x1F4; ++i) {
|
||||
TEST(CryptoCore, IncrementNonce)
|
||||
{
|
||||
using Nonce = std::array<uint8_t, CRYPTO_NONCE_SIZE>;
|
||||
Nonce nonce{};
|
||||
increment_nonce(nonce.data());
|
||||
}
|
||||
EXPECT_EQ(
|
||||
nonce, (Nonce{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}));
|
||||
|
||||
EXPECT_EQ(
|
||||
nonce,
|
||||
(Nonce{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xF5}}));
|
||||
for (int i = 0; i < 0x1F4; ++i) {
|
||||
increment_nonce(nonce.data());
|
||||
}
|
||||
|
||||
EXPECT_EQ(nonce,
|
||||
(Nonce{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xF5}}));
|
||||
}
|
||||
|
||||
TEST(CryptoCore, IncrementNonceNumber) {
|
||||
using Nonce = std::array<uint8_t, CRYPTO_NONCE_SIZE>;
|
||||
Nonce nonce{};
|
||||
TEST(CryptoCore, IncrementNonceNumber)
|
||||
{
|
||||
using Nonce = std::array<uint8_t, CRYPTO_NONCE_SIZE>;
|
||||
Nonce nonce{};
|
||||
|
||||
increment_nonce_number(nonce.data(), 0x1F5);
|
||||
EXPECT_EQ(
|
||||
nonce,
|
||||
(Nonce{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xF5}}));
|
||||
increment_nonce_number(nonce.data(), 0x1F5);
|
||||
EXPECT_EQ(nonce,
|
||||
(Nonce{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01, 0xF5}}));
|
||||
|
||||
increment_nonce_number(nonce.data(), 0x1F5);
|
||||
EXPECT_EQ(
|
||||
nonce,
|
||||
(Nonce{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03, 0xEA}}));
|
||||
increment_nonce_number(nonce.data(), 0x1F5);
|
||||
EXPECT_EQ(nonce,
|
||||
(Nonce{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x03, 0xEA}}));
|
||||
|
||||
increment_nonce_number(nonce.data(), 0x12345678);
|
||||
EXPECT_EQ(nonce, (Nonce{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0x34, 0x5A, 0x62}}));
|
||||
increment_nonce_number(nonce.data(), 0x12345678);
|
||||
EXPECT_EQ(nonce,
|
||||
(Nonce{
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x12, 0x34, 0x5A, 0x62}}));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
namespace {
|
||||
|
||||
// TODO(Jfreegman) make this useful or remove it after NGC is merged
|
||||
TEST(friend_connection, NullTest) {
|
||||
(void)friend_conn_get_onion_friendnum;
|
||||
(void)friend_conn_get_dht_ip_port;
|
||||
TEST(friend_connection, NullTest)
|
||||
{
|
||||
(void)friend_conn_get_onion_friendnum;
|
||||
(void)friend_conn_get_dht_ip_port;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -4,24 +4,27 @@
|
|||
|
||||
namespace {
|
||||
|
||||
TEST(List, CreateAndDestroyWithNonZeroSize) {
|
||||
BS_List list;
|
||||
bs_list_init(&list, sizeof(int), 10);
|
||||
bs_list_free(&list);
|
||||
TEST(List, CreateAndDestroyWithNonZeroSize)
|
||||
{
|
||||
BS_List list;
|
||||
bs_list_init(&list, sizeof(int), 10);
|
||||
bs_list_free(&list);
|
||||
}
|
||||
|
||||
TEST(List, CreateAndDestroyWithZeroSize) {
|
||||
BS_List list;
|
||||
bs_list_init(&list, sizeof(int), 0);
|
||||
bs_list_free(&list);
|
||||
TEST(List, CreateAndDestroyWithZeroSize)
|
||||
{
|
||||
BS_List list;
|
||||
bs_list_init(&list, sizeof(int), 0);
|
||||
bs_list_free(&list);
|
||||
}
|
||||
|
||||
TEST(List, DeleteFromEmptyList) {
|
||||
BS_List list;
|
||||
bs_list_init(&list, sizeof(int), 0);
|
||||
const uint8_t data[sizeof(int)] = {0};
|
||||
bs_list_remove(&list, data, 0);
|
||||
bs_list_free(&list);
|
||||
TEST(List, DeleteFromEmptyList)
|
||||
{
|
||||
BS_List list;
|
||||
bs_list_init(&list, sizeof(int), 0);
|
||||
const uint8_t data[sizeof(int)] = {0};
|
||||
bs_list_remove(&list, data, 0);
|
||||
bs_list_free(&list);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -59,38 +59,38 @@ void logger_callback_log(Logger *log, logger_cb *function, void *context, void *
|
|||
* be built with -DUSE_STDERR_LOGGER for this to work. It will cause an
|
||||
* assertion failure otherwise.
|
||||
*/
|
||||
non_null()
|
||||
non_null() GNU_PRINTF(6, 7)
|
||||
void logger_write(
|
||||
const Logger *log, Logger_Level level, const char *file, int line, const char *func,
|
||||
const char *format, ...) GNU_PRINTF(6, 7);
|
||||
const char *format, ...);
|
||||
|
||||
|
||||
#define LOGGER_WRITE(log, level, ...) \
|
||||
do { \
|
||||
if (level >= MIN_LOGGER_LEVEL) { \
|
||||
#define LOGGER_WRITE(log, level, ...) \
|
||||
do { \
|
||||
if (level >= MIN_LOGGER_LEVEL) { \
|
||||
logger_write(log, level, __FILE__, __LINE__, __func__, __VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* To log with an logger */
|
||||
#define LOGGER_TRACE(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_TRACE , __VA_ARGS__)
|
||||
#define LOGGER_DEBUG(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_DEBUG , __VA_ARGS__)
|
||||
#define LOGGER_INFO(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_INFO , __VA_ARGS__)
|
||||
#define LOGGER_TRACE(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_TRACE, __VA_ARGS__)
|
||||
#define LOGGER_DEBUG(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_DEBUG, __VA_ARGS__)
|
||||
#define LOGGER_INFO(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_INFO, __VA_ARGS__)
|
||||
#define LOGGER_WARNING(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_WARNING, __VA_ARGS__)
|
||||
#define LOGGER_ERROR(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_ERROR , __VA_ARGS__)
|
||||
#define LOGGER_ERROR(log, ...) LOGGER_WRITE(log, LOGGER_LEVEL_ERROR, __VA_ARGS__)
|
||||
|
||||
#define LOGGER_FATAL(log, ...) \
|
||||
do { \
|
||||
#define LOGGER_FATAL(log, ...) \
|
||||
do { \
|
||||
LOGGER_ERROR(log, __VA_ARGS__); \
|
||||
abort(); \
|
||||
} while(0)
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
#define LOGGER_ASSERT(log, cond, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
#define LOGGER_ASSERT(log, cond, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
LOGGER_ERROR(log, "Assertion failed"); \
|
||||
LOGGER_FATAL(log, __VA_ARGS__); \
|
||||
} \
|
||||
} while(0)
|
||||
LOGGER_FATAL(log, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // C_TOXCORE_TOXCORE_LOGGER_H
|
||||
|
|
|
@ -4,61 +4,65 @@
|
|||
|
||||
namespace {
|
||||
|
||||
TEST(MonoTime, UnixTimeIncreasesOverTime) {
|
||||
Mono_Time *mono_time = mono_time_new();
|
||||
TEST(MonoTime, UnixTimeIncreasesOverTime)
|
||||
{
|
||||
Mono_Time *mono_time = mono_time_new();
|
||||
|
||||
mono_time_update(mono_time);
|
||||
uint64_t const start = mono_time_get(mono_time);
|
||||
|
||||
while (start == mono_time_get(mono_time)) {
|
||||
mono_time_update(mono_time);
|
||||
}
|
||||
uint64_t const start = mono_time_get(mono_time);
|
||||
|
||||
uint64_t const end = mono_time_get(mono_time);
|
||||
EXPECT_GT(end, start);
|
||||
while (start == mono_time_get(mono_time)) {
|
||||
mono_time_update(mono_time);
|
||||
}
|
||||
|
||||
mono_time_free(mono_time);
|
||||
uint64_t const end = mono_time_get(mono_time);
|
||||
EXPECT_GT(end, start);
|
||||
|
||||
mono_time_free(mono_time);
|
||||
}
|
||||
|
||||
TEST(MonoTime, IsTimeout) {
|
||||
Mono_Time *mono_time = mono_time_new();
|
||||
TEST(MonoTime, IsTimeout)
|
||||
{
|
||||
Mono_Time *mono_time = mono_time_new();
|
||||
|
||||
uint64_t const start = mono_time_get(mono_time);
|
||||
EXPECT_FALSE(mono_time_is_timeout(mono_time, start, 1));
|
||||
uint64_t const start = mono_time_get(mono_time);
|
||||
EXPECT_FALSE(mono_time_is_timeout(mono_time, start, 1));
|
||||
|
||||
while (start == mono_time_get(mono_time)) {
|
||||
while (start == mono_time_get(mono_time)) {
|
||||
mono_time_update(mono_time);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(mono_time_is_timeout(mono_time, start, 1));
|
||||
|
||||
mono_time_free(mono_time);
|
||||
}
|
||||
|
||||
uint64_t test_current_time_callback(Mono_Time *mono_time, void *user_data)
|
||||
{
|
||||
return *static_cast<uint64_t *>(user_data);
|
||||
}
|
||||
|
||||
TEST(MonoTime, CustomTime)
|
||||
{
|
||||
Mono_Time *mono_time = mono_time_new();
|
||||
|
||||
uint64_t test_time = current_time_monotonic(mono_time) + 42137;
|
||||
|
||||
mono_time_set_current_time_callback(mono_time, test_current_time_callback, &test_time);
|
||||
mono_time_update(mono_time);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(mono_time_is_timeout(mono_time, start, 1));
|
||||
EXPECT_EQ(current_time_monotonic(mono_time), test_time);
|
||||
|
||||
mono_time_free(mono_time);
|
||||
}
|
||||
uint64_t const start = mono_time_get(mono_time);
|
||||
|
||||
uint64_t test_current_time_callback(Mono_Time *mono_time, void *user_data) {
|
||||
return *static_cast<uint64_t *>(user_data);
|
||||
}
|
||||
test_time += 7000;
|
||||
|
||||
TEST(MonoTime, CustomTime) {
|
||||
Mono_Time *mono_time = mono_time_new();
|
||||
mono_time_update(mono_time);
|
||||
EXPECT_EQ(mono_time_get(mono_time) - start, 7);
|
||||
|
||||
uint64_t test_time = current_time_monotonic(mono_time) + 42137;
|
||||
EXPECT_EQ(current_time_monotonic(mono_time), test_time);
|
||||
|
||||
mono_time_set_current_time_callback(mono_time, test_current_time_callback, &test_time);
|
||||
mono_time_update(mono_time);
|
||||
|
||||
EXPECT_EQ(current_time_monotonic(mono_time), test_time);
|
||||
|
||||
uint64_t const start = mono_time_get(mono_time);
|
||||
|
||||
test_time += 7000;
|
||||
|
||||
mono_time_update(mono_time);
|
||||
EXPECT_EQ(mono_time_get(mono_time) - start, 7);
|
||||
|
||||
EXPECT_EQ(current_time_monotonic(mono_time), test_time);
|
||||
|
||||
mono_time_free(mono_time);
|
||||
mono_time_free(mono_time);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -4,17 +4,18 @@
|
|||
|
||||
namespace {
|
||||
|
||||
TEST(IpNtoa, DoesntWriteOutOfBounds) {
|
||||
char ip_str[IP_NTOA_LEN];
|
||||
IP ip;
|
||||
ip.family = net_family_ipv6;
|
||||
ip.ip.v6.uint64[0] = -1;
|
||||
ip.ip.v6.uint64[1] = -1;
|
||||
TEST(IpNtoa, DoesntWriteOutOfBounds)
|
||||
{
|
||||
char ip_str[IP_NTOA_LEN];
|
||||
IP ip;
|
||||
ip.family = net_family_ipv6;
|
||||
ip.ip.v6.uint64[0] = -1;
|
||||
ip.ip.v6.uint64[1] = -1;
|
||||
|
||||
ip_ntoa(&ip, ip_str, sizeof(ip_str));
|
||||
ip_ntoa(&ip, ip_str, sizeof(ip_str));
|
||||
|
||||
EXPECT_EQ(std::string(ip_str), "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
|
||||
EXPECT_LT(std::string(ip_str).length(), IP_NTOA_LEN);
|
||||
EXPECT_EQ(std::string(ip_str), "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
|
||||
EXPECT_LT(std::string(ip_str).length(), IP_NTOA_LEN);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -9,116 +9,125 @@
|
|||
namespace {
|
||||
|
||||
struct Ping_Array_Deleter {
|
||||
void operator()(Ping_Array *arr) { ping_array_kill(arr); }
|
||||
void operator()(Ping_Array *arr) { ping_array_kill(arr); }
|
||||
};
|
||||
|
||||
using Ping_Array_Ptr = std::unique_ptr<Ping_Array, Ping_Array_Deleter>;
|
||||
|
||||
struct Mono_Time_Deleter {
|
||||
void operator()(Mono_Time *arr) { mono_time_free(arr); }
|
||||
void operator()(Mono_Time *arr) { mono_time_free(arr); }
|
||||
};
|
||||
|
||||
using Mono_Time_Ptr = std::unique_ptr<Mono_Time, Mono_Time_Deleter>;
|
||||
|
||||
TEST(PingArray, MinimumTimeoutIsOne) {
|
||||
EXPECT_EQ(ping_array_new(1, 0), nullptr);
|
||||
EXPECT_NE(Ping_Array_Ptr(ping_array_new(1, 1)), nullptr);
|
||||
TEST(PingArray, MinimumTimeoutIsOne)
|
||||
{
|
||||
EXPECT_EQ(ping_array_new(1, 0), nullptr);
|
||||
EXPECT_NE(Ping_Array_Ptr(ping_array_new(1, 1)), nullptr);
|
||||
}
|
||||
|
||||
TEST(PingArray, MinimumArraySizeIsOne) {
|
||||
EXPECT_EQ(ping_array_new(0, 1), nullptr);
|
||||
EXPECT_NE(Ping_Array_Ptr(ping_array_new(1, 1)), nullptr);
|
||||
TEST(PingArray, MinimumArraySizeIsOne)
|
||||
{
|
||||
EXPECT_EQ(ping_array_new(0, 1), nullptr);
|
||||
EXPECT_NE(Ping_Array_Ptr(ping_array_new(1, 1)), nullptr);
|
||||
}
|
||||
|
||||
TEST(PingArray, ArraySizeMustBePowerOfTwo) {
|
||||
Ping_Array_Ptr arr;
|
||||
arr.reset(ping_array_new(2, 1));
|
||||
EXPECT_NE(arr, nullptr);
|
||||
arr.reset(ping_array_new(4, 1));
|
||||
EXPECT_NE(arr, nullptr);
|
||||
arr.reset(ping_array_new(1024, 1));
|
||||
EXPECT_NE(arr, nullptr);
|
||||
TEST(PingArray, ArraySizeMustBePowerOfTwo)
|
||||
{
|
||||
Ping_Array_Ptr arr;
|
||||
arr.reset(ping_array_new(2, 1));
|
||||
EXPECT_NE(arr, nullptr);
|
||||
arr.reset(ping_array_new(4, 1));
|
||||
EXPECT_NE(arr, nullptr);
|
||||
arr.reset(ping_array_new(1024, 1));
|
||||
EXPECT_NE(arr, nullptr);
|
||||
|
||||
EXPECT_EQ(ping_array_new(1023, 1), nullptr);
|
||||
EXPECT_EQ(ping_array_new(1234, 1), nullptr);
|
||||
EXPECT_EQ(ping_array_new(1023, 1), nullptr);
|
||||
EXPECT_EQ(ping_array_new(1234, 1), nullptr);
|
||||
}
|
||||
|
||||
TEST(PingArray, StoredDataCanBeRetrieved) {
|
||||
Ping_Array_Ptr const arr(ping_array_new(2, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
TEST(PingArray, StoredDataCanBeRetrieved)
|
||||
{
|
||||
Ping_Array_Ptr const arr(ping_array_new(2, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
|
||||
uint64_t const ping_id =
|
||||
ping_array_add(arr.get(), mono_time.get(), std::vector<uint8_t>{1, 2, 3, 4}.data(), 4);
|
||||
EXPECT_NE(ping_id, 0);
|
||||
uint64_t const ping_id
|
||||
= ping_array_add(arr.get(), mono_time.get(), std::vector<uint8_t>{1, 2, 3, 4}.data(), 4);
|
||||
EXPECT_NE(ping_id, 0);
|
||||
|
||||
std::vector<uint8_t> data(4);
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), data.size(), ping_id), 4);
|
||||
EXPECT_EQ(data, std::vector<uint8_t>({1, 2, 3, 4}));
|
||||
std::vector<uint8_t> data(4);
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), data.size(), ping_id), 4);
|
||||
EXPECT_EQ(data, std::vector<uint8_t>({1, 2, 3, 4}));
|
||||
}
|
||||
|
||||
TEST(PingArray, RetrievingDataWithTooSmallOutputBufferHasNoEffect) {
|
||||
Ping_Array_Ptr const arr(ping_array_new(2, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
TEST(PingArray, RetrievingDataWithTooSmallOutputBufferHasNoEffect)
|
||||
{
|
||||
Ping_Array_Ptr const arr(ping_array_new(2, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
|
||||
uint64_t const ping_id =
|
||||
ping_array_add(arr.get(), mono_time.get(), (std::vector<uint8_t>{1, 2, 3, 4}).data(), 4);
|
||||
EXPECT_NE(ping_id, 0);
|
||||
uint64_t const ping_id
|
||||
= ping_array_add(arr.get(), mono_time.get(), (std::vector<uint8_t>{1, 2, 3, 4}).data(), 4);
|
||||
EXPECT_NE(ping_id, 0);
|
||||
|
||||
std::vector<uint8_t> data(4);
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), 3, ping_id), -1);
|
||||
// It doesn't write anything to the data array.
|
||||
EXPECT_EQ(data, std::vector<uint8_t>({0, 0, 0, 0}));
|
||||
// Afterwards, we can still read it.
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), 4, ping_id), 4);
|
||||
EXPECT_EQ(data, std::vector<uint8_t>({1, 2, 3, 4}));
|
||||
std::vector<uint8_t> data(4);
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), 3, ping_id), -1);
|
||||
// It doesn't write anything to the data array.
|
||||
EXPECT_EQ(data, std::vector<uint8_t>({0, 0, 0, 0}));
|
||||
// Afterwards, we can still read it.
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), data.data(), 4, ping_id), 4);
|
||||
EXPECT_EQ(data, std::vector<uint8_t>({1, 2, 3, 4}));
|
||||
}
|
||||
|
||||
TEST(PingArray, ZeroLengthDataCanBeAdded) {
|
||||
Ping_Array_Ptr const arr(ping_array_new(2, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
TEST(PingArray, ZeroLengthDataCanBeAdded)
|
||||
{
|
||||
Ping_Array_Ptr const arr(ping_array_new(2, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
|
||||
uint8_t c = 0;
|
||||
uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), &c, sizeof(c));
|
||||
EXPECT_NE(ping_id, 0);
|
||||
uint8_t c = 0;
|
||||
uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), &c, sizeof(c));
|
||||
EXPECT_NE(ping_id, 0);
|
||||
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), ping_id), 1);
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), ping_id), 1);
|
||||
}
|
||||
|
||||
TEST(PingArray, PingId0IsInvalid) {
|
||||
Ping_Array_Ptr const arr(ping_array_new(2, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
TEST(PingArray, PingId0IsInvalid)
|
||||
{
|
||||
Ping_Array_Ptr const arr(ping_array_new(2, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
|
||||
uint8_t c = 0;
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), 0), -1);
|
||||
uint8_t c = 0;
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), 0), -1);
|
||||
}
|
||||
|
||||
// Protection against replay attacks.
|
||||
TEST(PingArray, DataCanOnlyBeRetrievedOnce) {
|
||||
Ping_Array_Ptr const arr(ping_array_new(2, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
TEST(PingArray, DataCanOnlyBeRetrievedOnce)
|
||||
{
|
||||
Ping_Array_Ptr const arr(ping_array_new(2, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
|
||||
uint8_t c = 0;
|
||||
uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), &c, sizeof(c));
|
||||
EXPECT_NE(ping_id, 0);
|
||||
uint8_t c = 0;
|
||||
uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), &c, sizeof(c));
|
||||
EXPECT_NE(ping_id, 0);
|
||||
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), ping_id), 1);
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), ping_id), -1);
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), ping_id), 1);
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), ping_id), -1);
|
||||
}
|
||||
|
||||
TEST(PingArray, PingIdMustMatchOnCheck) {
|
||||
Ping_Array_Ptr const arr(ping_array_new(1, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
TEST(PingArray, PingIdMustMatchOnCheck)
|
||||
{
|
||||
Ping_Array_Ptr const arr(ping_array_new(1, 1));
|
||||
Mono_Time_Ptr const mono_time(mono_time_new());
|
||||
|
||||
uint8_t c = 0;
|
||||
uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), &c, sizeof(c));
|
||||
EXPECT_NE(ping_id, 0);
|
||||
uint8_t c = 0;
|
||||
uint64_t const ping_id = ping_array_add(arr.get(), mono_time.get(), &c, sizeof(c));
|
||||
EXPECT_NE(ping_id, 0);
|
||||
|
||||
uint64_t const bad_ping_id = ping_id == 1 ? 2 : 1;
|
||||
uint64_t const bad_ping_id = ping_id == 1 ? 2 : 1;
|
||||
|
||||
// bad_ping_id will also be pointing at the same element, but won't match the
|
||||
// actual ping_id.
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), bad_ping_id), -1);
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), ping_id), 1);
|
||||
// bad_ping_id will also be pointing at the same element, but won't match the
|
||||
// actual ping_id.
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), bad_ping_id), -1);
|
||||
EXPECT_EQ(ping_array_check(arr.get(), mono_time.get(), &c, sizeof(c), ping_id), 1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -6,27 +6,29 @@
|
|||
|
||||
namespace {
|
||||
|
||||
TEST(Util, TwoRandomIdsAreNotEqual) {
|
||||
uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t sk1[CRYPTO_SECRET_KEY_SIZE];
|
||||
uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t sk2[CRYPTO_SECRET_KEY_SIZE];
|
||||
TEST(Util, TwoRandomIdsAreNotEqual)
|
||||
{
|
||||
uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t sk1[CRYPTO_SECRET_KEY_SIZE];
|
||||
uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t sk2[CRYPTO_SECRET_KEY_SIZE];
|
||||
|
||||
crypto_new_keypair(pk1, sk1);
|
||||
crypto_new_keypair(pk2, sk2);
|
||||
crypto_new_keypair(pk1, sk1);
|
||||
crypto_new_keypair(pk2, sk2);
|
||||
|
||||
EXPECT_FALSE(id_equal(pk1, pk2));
|
||||
EXPECT_FALSE(id_equal(pk1, pk2));
|
||||
}
|
||||
|
||||
TEST(Util, IdCopyMakesKeysEqual) {
|
||||
uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t sk1[CRYPTO_SECRET_KEY_SIZE];
|
||||
uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE] = {0};
|
||||
TEST(Util, IdCopyMakesKeysEqual)
|
||||
{
|
||||
uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE];
|
||||
uint8_t sk1[CRYPTO_SECRET_KEY_SIZE];
|
||||
uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE] = {0};
|
||||
|
||||
crypto_new_keypair(pk1, sk1);
|
||||
id_copy(pk2, pk1);
|
||||
crypto_new_keypair(pk1, sk1);
|
||||
id_copy(pk2, pk1);
|
||||
|
||||
EXPECT_TRUE(id_equal(pk1, pk2));
|
||||
EXPECT_TRUE(id_equal(pk1, pk2));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Reference in New Issue
Block a user