test: Add test coverage docker build for local tests.

This uses mallocfail to further increase coverage using the existing
tests. Also:
* Moved the non-auto "tox_one_test" to gtest. This should be
  split into smaller tests later.
* Changed `hole_punching` to `bool`.
This commit is contained in:
iphydf 2022-02-24 15:51:18 +00:00
parent 2ce6f5b169
commit aa72c47125
No known key found for this signature in database
GPG Key ID: 3855DBA2D74403C9
14 changed files with 322 additions and 154 deletions

View File

@ -406,6 +406,7 @@ unit_test(toxcore DHT)
unit_test(toxcore crypto_core)
unit_test(toxcore mono_time)
unit_test(toxcore ping_array)
unit_test(toxcore tox)
unit_test(toxcore util)
################################################################################
@ -478,7 +479,6 @@ auto_test(tox_dispatch)
auto_test(tox_events)
auto_test(tox_many)
auto_test(tox_many_tcp)
auto_test(tox_one)
auto_test(tox_strncasecmp)
auto_test(typing)
auto_test(version)

View File

@ -38,7 +38,6 @@ TESTS = \
tox_dispatch_test \
tox_many_tcp_test \
tox_many_test \
tox_one_test \
tox_strncasecmp_test \
typing_test \
version_test
@ -212,10 +211,6 @@ tox_many_test_SOURCES = ../auto_tests/tox_many_test.c
tox_many_test_CFLAGS = $(AUTOTEST_CFLAGS)
tox_many_test_LDADD = $(AUTOTEST_LDADD)
tox_one_test_SOURCES = ../auto_tests/tox_one_test.c
tox_one_test_CFLAGS = $(AUTOTEST_CFLAGS)
tox_one_test_LDADD = $(AUTOTEST_LDADD)
tox_strncasecmp_test_SOURCES = ../auto_tests/tox_strncasecmp_test.c
tox_strncasecmp_test_CFLAGS = $(AUTOTEST_CFLAGS)
tox_strncasecmp_test_LDADD = $(AUTOTEST_LDADD)

View File

@ -55,9 +55,18 @@ int main(void)
{
setvbuf(stdout, nullptr, _IONBF, 0);
struct Tox_Options *tox_options = tox_options_new(nullptr);
ck_assert(tox_options != nullptr);
Run_Auto_Options options = default_run_auto_options;
options.graph = GRAPH_LINEAR;
run_auto_test(nullptr, 2, send_message_test, sizeof(State), &options);
tox_options_set_ipv6_enabled(tox_options, true);
run_auto_test(tox_options, 2, send_message_test, sizeof(State), &options);
tox_options_set_ipv6_enabled(tox_options, false);
run_auto_test(tox_options, 2, send_message_test, sizeof(State), &options);
tox_options_free(tox_options);
return 0;
}

View File

@ -1,141 +0,0 @@
/* Auto Tests: One instance.
*/
#include <stdlib.h>
#include <string.h>
#include "../testing/misc_tools.h"
#include "../toxcore/ccompat.h"
#include "../toxcore/crypto_core.h"
#include "../toxcore/tox.h"
#include "../toxcore/util.h"
#include "auto_test_support.h"
#include "check_compat.h"
static void set_random_name_and_status_message(Tox *tox, uint8_t *name, uint8_t *status_message)
{
int i;
for (i = 0; i < TOX_MAX_NAME_LENGTH; ++i) {
name[i] = random_u08();
}
for (i = 0; i < TOX_MAX_STATUS_MESSAGE_LENGTH; ++i) {
status_message[i] = random_u08();
}
}
static void test_one(void)
{
uint8_t name[TOX_MAX_NAME_LENGTH];
uint8_t status_message[TOX_MAX_STATUS_MESSAGE_LENGTH];
uint8_t name2[TOX_MAX_NAME_LENGTH];
uint8_t status_message2[TOX_MAX_STATUS_MESSAGE_LENGTH];
uint32_t index[] = { 1, 2 };
Tox *tox1 = tox_new_log(nullptr, nullptr, &index[0]);
ck_assert(tox1 != nullptr);
set_random_name_and_status_message(tox1, name, status_message);
Tox *tox2 = tox_new_log(nullptr, nullptr, &index[1]);
ck_assert(tox2 != nullptr);
set_random_name_and_status_message(tox2, name2, status_message2);
uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(tox1, address);
Tox_Err_Friend_Add error;
uint32_t ret = tox_friend_add(tox1, address, (const uint8_t *)"m", 1, &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_OWN_KEY, "Adding own address worked.");
tox_self_get_address(tox2, address);
uint8_t message[TOX_MAX_FRIEND_REQUEST_LENGTH + 1] = {0};
ret = tox_friend_add(tox1, address, nullptr, 0, &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_NULL, "Sending request with no message worked.");
ret = tox_friend_add(tox1, address, message, 0, &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_NO_MESSAGE, "Sending request with no message worked.");
ret = tox_friend_add(tox1, address, message, sizeof(message), &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_TOO_LONG,
"TOX_MAX_FRIEND_REQUEST_LENGTH is too big.");
address[0]++;
ret = tox_friend_add(tox1, address, (const uint8_t *)"m", 1, &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_BAD_CHECKSUM,
"Adding address with bad checksum worked.");
tox_self_get_address(tox2, address);
ret = tox_friend_add(tox1, address, message, TOX_MAX_FRIEND_REQUEST_LENGTH, &error);
ck_assert_msg(ret == 0 && error == TOX_ERR_FRIEND_ADD_OK, "Failed to add friend.");
ret = tox_friend_add(tox1, address, message, TOX_MAX_FRIEND_REQUEST_LENGTH, &error);
ck_assert_msg(ret == UINT32_MAX && error == TOX_ERR_FRIEND_ADD_ALREADY_SENT, "Adding friend twice worked.");
tox_self_set_name(tox1, name, sizeof(name), nullptr);
ck_assert_msg(tox_self_get_name_size(tox1) == sizeof(name), "Can't set name of TOX_MAX_NAME_LENGTH");
tox_self_set_status_message(tox1, status_message, sizeof(status_message), nullptr);
ck_assert_msg(tox_self_get_status_message_size(tox1) == sizeof(status_message),
"Can't set status message of TOX_MAX_STATUS_MESSAGE_LENGTH");
tox_self_get_address(tox1, address);
size_t save_size = tox_get_savedata_size(tox1);
uint8_t *data = (uint8_t *)malloc(save_size);
tox_get_savedata(tox1, data);
tox_kill(tox2);
Tox_Err_New err_n;
struct Tox_Options *options = tox_options_new(nullptr);
ck_assert(options != nullptr);
tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
tox_options_set_savedata_data(options, data, save_size);
tox2 = tox_new_log(options, &err_n, &index[1]);
ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed");
ck_assert_msg(tox_self_get_name_size(tox2) == sizeof name, "Wrong name size.");
ck_assert_msg(tox_self_get_status_message_size(tox2) == sizeof status_message, "Wrong status message size");
uint8_t name_loaded[TOX_MAX_NAME_LENGTH] = { 0 };
tox_self_get_name(tox2, name_loaded);
ck_assert_msg(!memcmp(name, name_loaded, sizeof name), "Wrong name.");
uint8_t status_message_loaded[TOX_MAX_STATUS_MESSAGE_LENGTH] = { 0 };
tox_self_get_status_message(tox2, status_message_loaded);
ck_assert_msg(!memcmp(status_message, status_message_loaded, sizeof status_message_loaded), "Wrong status message.");
uint8_t address2[TOX_ADDRESS_SIZE] = { 0 };
tox_self_get_address(tox2, address2);
ck_assert_msg(memcmp(address2, address, TOX_ADDRESS_SIZE) == 0, "Wrong address.");
uint8_t new_name[TOX_MAX_NAME_LENGTH] = { 0 };
tox_self_get_name(tox2, new_name);
ck_assert_msg(memcmp(name, new_name, TOX_MAX_NAME_LENGTH) == 0, "Wrong name");
uint8_t sk[TOX_SECRET_KEY_SIZE];
tox_self_get_secret_key(tox2, sk);
tox_kill(tox2);
tox_options_default(options);
tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_SECRET_KEY);
tox_options_set_savedata_data(options, sk, sizeof(sk));
tox2 = tox_new_log(options, &err_n, &index[1]);
ck_assert_msg(err_n == TOX_ERR_NEW_OK, "Load failed");
uint8_t address3[TOX_ADDRESS_SIZE];
tox_self_get_address(tox2, address3);
ck_assert_msg(memcmp(address3, address, TOX_PUBLIC_KEY_SIZE) == 0, "Wrong public key.");
uint8_t pk[TOX_PUBLIC_KEY_SIZE];
tox_self_get_public_key(tox2, pk);
ck_assert_msg(memcmp(pk, address, TOX_PUBLIC_KEY_SIZE) == 0, "Wrong public key.");
tox_options_free(options);
tox_kill(tox1);
tox_kill(tox2);
free(data);
}
int main(void)
{
setvbuf(stdout, nullptr, _IONBF, 0);
test_one();
return 0;
}

View File

@ -1 +1 @@
b899ee4325e854deafa435b697c0e37430222f4f87537f4b12021eb40d12857d /usr/local/bin/tox-bootstrapd
3b7df7850212de052071b23f6b8085852467e227c232f80c97a76e4cf28d0327 /usr/local/bin/tox-bootstrapd

View File

@ -0,0 +1,61 @@
FROM toxchat/c-toxcore:sources AS src
FROM ubuntu:20.04 AS build
RUN apt-get update && \
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
build-essential \
cmake \
git \
libconfig-dev \
libgtest-dev \
libmsgpack-dev \
libopus-dev \
libsodium-dev \
libvpx-dev \
llvm-dev \
ninja-build \
pkg-config \
python3-pip \
python3-pygments \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& pip3 install --no-cache-dir gcovr
WORKDIR /work/mallocfail
RUN ["git", "clone", "--depth=1", "https://github.com/ralight/mallocfail", "/work/mallocfail"]
RUN ["make", "install"]
WORKDIR /work
COPY --from=src /src/ /work/
RUN ["cmake", "-B_build", "-H.", "-GNinja", \
"-DCMAKE_C_FLAGS=-fsanitize=undefined -fno-sanitize-recover=all -fprofile-arcs -ftest-coverage -O2 -fno-omit-frame-pointer -fno-inline -g", \
"-DENABLE_SHARED=OFF", \
"-DMIN_LOGGER_LEVEL=TRACE", \
"-DMUST_BUILD_TOXAV=ON", \
"-DNON_HERMETIC_TESTS=ON", \
"-DSTRICT_ABI=ON", \
"-DAUTOTEST=ON"]
RUN ["cmake", "--build", "_build", "--parallel", "8", "--target", "install"]
WORKDIR /work/_build
RUN ["ctest", "-j50", "--output-on-failure", "--rerun-failed", "--repeat", "until-pass:6"]
COPY run_mallocfail /usr/local/bin/
ENV PYTHONUNBUFFERED=1 \
UBSAN_OPTIONS=color=always,print_stacktrace=1
RUN run_mallocfail ./unit_*_test
RUN run_mallocfail ./auto_send_message_test
RUN ["gcovr", \
"--sort-percentage", \
"--gcov-executable=gcov", \
"--html-details=html/", \
"--html-self-contained", \
"--root=..", \
"--exclude=CMakeFiles/", \
"--exclude=_deps/", \
"--exclude=(.+/)?auto_tests/", \
"--exclude=(.+/)?other/", \
"--exclude=(.+/)?testing/"]
FROM nginx:alpine
COPY --from=build /work/_build/html/coverage_details.html /usr/share/nginx/html/index.html
COPY --from=build /work/_build/html/ /usr/share/nginx/html/

7
other/docker/coverage/run Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
set -eux
docker build -t toxchat/c-toxcore:sources -f other/docker/sources/Dockerfile .
docker build -t toxchat/c-toxcore:coverage other/docker/coverage
docker run --rm -it -p "28192:80" toxchat/c-toxcore:coverage

View File

@ -0,0 +1,76 @@
#!/usr/bin/env python3
"""Run a test repeatedly with mallocfail.
Usage: run_mallocfail <exe>
This runs the program with mallocfail until there are no more additional stack
hashes for mallocfail to try out.
You need to build mallocfail (https://github.com/ralight/mallocfail) and install
it to /usr/local/lib/mallocfail. Change _MALLOCFAIL_SO below if you want it
elsewhere.
"""
import os
import shutil
import subprocess
import sys
from typing import List
_MALLOCFAIL_SO = "/usr/local/lib/mallocfail.so"
_HASHES = "mallocfail_hashes"
_HASHES_PREV = "mallocfail_hashes.prev"
_TIMEOUT = 3
def run_mallocfail(exe: str, iteration: int) -> bool:
"""Run a program with mallocfail."""
print(f"\x1b[1;33mmallocfail '{exe}' run #{iteration}\x1b[0m")
if os.path.exists(_HASHES):
shutil.copy(_HASHES, _HASHES_PREV)
try:
proc = subprocess.run([exe],
timeout=_TIMEOUT,
env={"LD_PRELOAD": _MALLOCFAIL_SO})
except subprocess.TimeoutExpired:
print(f"\x1b[1;34mProgram {exe} timed out\x1b[0m")
return True
finally:
assert os.path.exists(_HASHES)
if os.path.exists(_HASHES_PREV):
with open(_HASHES_PREV, "r") as prev:
with open(_HASHES, "r") as cur:
if prev.read() == cur.read():
# Done: no new stack hashes.
return False
if proc.returncode >= 0:
# Process exited cleanly (success or failure).
pass
elif proc.returncode == -6:
# Assertion failed.
pass
elif proc.returncode == -14:
print(f"\x1b[0;34mProgram '{exe}' timed out\x1b[0m")
else:
print(
f"\x1b[1;34mProgram '{exe}' failed to handle OOM situation cleanly\x1b[0m"
)
sys.exit(1)
return True
def main(args: List[str]) -> None:
"""Run a program repeatedly under mallocfail."""
if len(args) == 1:
print(f"Usage: {args[0]} <exe>")
sys.exit(1)
for exe in args[1:]:
i = 1
while run_mallocfail(exe, i):
i += 1
if __name__ == "__main__":
main(sys.argv)

View File

@ -0,0 +1,14 @@
FROM scratch
# Roughly in order of change frequency.
COPY cmake/ /src/cmake/
COPY other/bootstrap_daemon/ /src/other/bootstrap_daemon/
COPY other/pkgconfig/ /src/other/pkgconfig/
COPY other/rpm/ /src/other/rpm/
COPY other/*.[ch] /src/other/
COPY CMakeLists.txt so.version /src/
COPY toxencryptsave/ /src/toxencryptsave/
COPY testing/ /src/testing/
COPY toxav/ /src/toxav/
COPY toxcore/ /src/toxcore/
COPY auto_tests/ /src/auto_tests/

View File

@ -491,6 +491,18 @@ cc_library(
],
)
cc_test(
name = "tox_test",
size = "small",
srcs = ["tox_test.cc"],
deps = [
":crypto_core",
":tox",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
],
)
cc_library(
name = "tox_unpack",
srcs = ["tox_unpack.c"],

View File

@ -2200,7 +2200,7 @@ static int handle_NATping(void *object, const IP_Port *source, const uint8_t *so
if (packet[0] == NAT_PING_RESPONSE) {
if (dht_friend->nat.nat_ping_id == ping_id) {
dht_friend->nat.nat_ping_id = random_u64();
dht_friend->nat.hole_punching = 1;
dht_friend->nat.hole_punching = true;
return 0;
}
}
@ -2340,7 +2340,7 @@ static void do_NAT(DHT *dht)
dht->friends_list[i].nat.nat_ping_timestamp = temp_time;
}
if (dht->friends_list[i].nat.hole_punching == 1 &&
if (dht->friends_list[i].nat.hole_punching &&
dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time &&
dht->friends_list[i].nat.recv_nat_ping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
@ -2361,7 +2361,7 @@ static void do_NAT(DHT *dht)
punch_holes(dht, &ip, port_list, numports, i);
dht->friends_list[i].nat.punching_timestamp = temp_time;
dht->friends_list[i].nat.hole_punching = 0;
dht->friends_list[i].nat.hole_punching = false;
}
}
}

View File

@ -111,8 +111,8 @@ typedef struct Client_data {
/*----------------------------------------------------------------------------------*/
typedef struct NAT {
/* 1 if currently hole punching, otherwise 0 */
uint8_t hole_punching;
/* true if currently hole punching */
bool hole_punching;
uint32_t punching_index;
uint32_t tries;
uint32_t punching_index2;

View File

@ -7,6 +7,7 @@ namespace {
TEST(MonoTime, UnixTimeIncreasesOverTime)
{
Mono_Time *mono_time = mono_time_new();
ASSERT_NE(mono_time, nullptr);
mono_time_update(mono_time);
uint64_t const start = mono_time_get(mono_time);
@ -24,6 +25,7 @@ TEST(MonoTime, UnixTimeIncreasesOverTime)
TEST(MonoTime, IsTimeout)
{
Mono_Time *mono_time = mono_time_new();
ASSERT_NE(mono_time, nullptr);
uint64_t const start = mono_time_get(mono_time);
EXPECT_FALSE(mono_time_is_timeout(mono_time, start, 1));
@ -45,6 +47,7 @@ uint64_t test_current_time_callback(Mono_Time *mono_time, void *user_data)
TEST(MonoTime, CustomTime)
{
Mono_Time *mono_time = mono_time_new();
ASSERT_NE(mono_time, nullptr);
uint64_t test_time = current_time_monotonic(mono_time) + 42137;

132
toxcore/tox_test.cc Normal file
View File

@ -0,0 +1,132 @@
#include "tox.h"
#include <gtest/gtest.h>
#include "crypto_core.h"
namespace {
static void set_random_name_and_status_message(Tox *tox, uint8_t *name, uint8_t *status_message)
{
for (uint16_t i = 0; i < TOX_MAX_NAME_LENGTH; ++i) {
name[i] = random_u08();
}
for (uint16_t i = 0; i < TOX_MAX_STATUS_MESSAGE_LENGTH; ++i) {
status_message[i] = random_u08();
}
}
TEST(Tox, OneTest)
{
std::array<uint8_t, TOX_MAX_NAME_LENGTH> name;
std::array<uint8_t, TOX_MAX_STATUS_MESSAGE_LENGTH> status_message;
std::array<uint8_t, TOX_MAX_NAME_LENGTH> name2;
std::array<uint8_t, TOX_MAX_STATUS_MESSAGE_LENGTH> status_message2;
Tox *tox1 = tox_new(nullptr, nullptr);
ASSERT_NE(tox1, nullptr);
set_random_name_and_status_message(tox1, name.data(), status_message.data());
Tox *tox2 = tox_new(nullptr, nullptr);
ASSERT_NE(tox2, nullptr);
set_random_name_and_status_message(tox2, name2.data(), status_message2.data());
std::array<uint8_t, TOX_ADDRESS_SIZE> address;
tox_self_get_address(tox1, address.data());
Tox_Err_Friend_Add error;
uint32_t ret
= tox_friend_add(tox1, address.data(), reinterpret_cast<const uint8_t *>("m"), 1, &error);
EXPECT_EQ(error, TOX_ERR_FRIEND_ADD_OWN_KEY) << "Adding own address worked.";
EXPECT_EQ(ret, UINT32_MAX);
tox_self_get_address(tox2, address.data());
uint8_t message[TOX_MAX_FRIEND_REQUEST_LENGTH + 1] = {0};
ret = tox_friend_add(tox1, address.data(), nullptr, 0, &error);
EXPECT_EQ(error, TOX_ERR_FRIEND_ADD_NULL) << "Sending request with no message worked.";
EXPECT_EQ(ret, UINT32_MAX);
ret = tox_friend_add(tox1, address.data(), message, 0, &error);
EXPECT_EQ(error, TOX_ERR_FRIEND_ADD_NO_MESSAGE) << "Sending request with no message worked.";
EXPECT_EQ(ret, UINT32_MAX);
ret = tox_friend_add(tox1, address.data(), message, sizeof(message), &error);
EXPECT_EQ(error, TOX_ERR_FRIEND_ADD_TOO_LONG) << "TOX_MAX_FRIEND_REQUEST_LENGTH is too big.";
EXPECT_EQ(ret, UINT32_MAX);
address[0]++;
ret = tox_friend_add(tox1, address.data(), reinterpret_cast<const uint8_t *>("m"), 1, &error);
EXPECT_EQ(error, TOX_ERR_FRIEND_ADD_BAD_CHECKSUM) << "Adding address with bad checksum worked.";
EXPECT_EQ(ret, UINT32_MAX);
tox_self_get_address(tox2, address.data());
ret = tox_friend_add(tox1, address.data(), message, TOX_MAX_FRIEND_REQUEST_LENGTH, &error);
EXPECT_EQ(error, TOX_ERR_FRIEND_ADD_OK) << "Failed to add friend.";
EXPECT_EQ(ret, 0);
ret = tox_friend_add(tox1, address.data(), message, TOX_MAX_FRIEND_REQUEST_LENGTH, &error);
EXPECT_EQ(error, TOX_ERR_FRIEND_ADD_ALREADY_SENT) << "Adding friend twice worked.";
EXPECT_EQ(ret, UINT32_MAX);
tox_self_set_name(tox1, name.data(), name.size(), nullptr);
EXPECT_EQ(tox_self_get_name_size(tox1), name.size()) << "Can't set name of TOX_MAX_NAME_LENGTH";
tox_self_set_status_message(tox1, status_message.data(), status_message.size(), nullptr);
EXPECT_EQ(tox_self_get_status_message_size(tox1), status_message.size())
<< "Can't set status message of TOX_MAX_STATUS_MESSAGE_LENGTH";
tox_self_get_address(tox1, address.data());
std::vector<uint8_t> data(tox_get_savedata_size(tox1));
tox_get_savedata(tox1, data.data());
tox_kill(tox2);
Tox_Err_New err_n;
struct Tox_Options *options = tox_options_new(nullptr);
ASSERT_NE(options, nullptr);
tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
tox_options_set_savedata_data(options, data.data(), data.size());
tox2 = tox_new(options, &err_n);
EXPECT_EQ(err_n, TOX_ERR_NEW_OK) << "Load failed";
EXPECT_EQ(tox_self_get_name_size(tox2), sizeof name) << "Wrong name size.";
EXPECT_EQ(tox_self_get_status_message_size(tox2), sizeof status_message)
<< "Wrong status message size";
std::array<uint8_t, TOX_MAX_NAME_LENGTH> name_loaded{};
tox_self_get_name(tox2, name_loaded.data());
EXPECT_EQ(name, name_loaded) << "Wrong name.";
std::array<uint8_t, TOX_MAX_STATUS_MESSAGE_LENGTH> status_message_loaded{};
tox_self_get_status_message(tox2, status_message_loaded.data());
EXPECT_EQ(status_message, status_message_loaded) << "Wrong status message.";
std::array<uint8_t, TOX_ADDRESS_SIZE> address2{};
tox_self_get_address(tox2, address2.data());
EXPECT_EQ(address2, address) << "Wrong address.";
std::array<uint8_t, TOX_MAX_NAME_LENGTH> new_name{};
tox_self_get_name(tox2, new_name.data());
EXPECT_EQ(name, new_name) << "Wrong name";
std::array<uint8_t, TOX_SECRET_KEY_SIZE> sk;
tox_self_get_secret_key(tox2, sk.data());
tox_kill(tox2);
tox_options_default(options);
tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_SECRET_KEY);
tox_options_set_savedata_data(options, sk.data(), sk.size());
tox2 = tox_new(options, &err_n);
ASSERT_EQ(err_n, TOX_ERR_NEW_OK) << "Load failed";
tox_self_set_nospam(tox2, tox_self_get_nospam(tox1));
std::array<uint8_t, TOX_ADDRESS_SIZE> address3;
tox_self_get_address(tox2, address3.data());
EXPECT_EQ(address3, address) << "Wrong public key.";
std::array<uint8_t, TOX_PUBLIC_KEY_SIZE> pk;
tox_self_get_public_key(tox2, pk.data());
std::array<uint8_t, TOX_PUBLIC_KEY_SIZE> pk_from_addr;
std::copy(address.begin(), address.begin() + TOX_PUBLIC_KEY_SIZE, pk_from_addr.begin());
EXPECT_EQ(pk, pk_from_addr) << "Wrong public key.";
tox_options_free(options);
tox_kill(tox1);
tox_kill(tox2);
}
} // namespace