Skip to content

Commit

Permalink
test: add extended unit tests mode (#731)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mishura4 authored Jul 19, 2023
1 parent bb5af55 commit 5895803
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 70 deletions.
127 changes: 85 additions & 42 deletions src/unittest/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,25 @@
#include <dpp/restrequest.h>
#include <dpp/json.h>

namespace {
/**
* @brief Thread emoji - https://www.compart.com/en/unicode/U+1F9F5
*/
inline const std::string THREAD_EMOJI = "\xF0\x9F\xA7\xB5";
}

/* Unit tests go here */
int main()
int main(int argc, char *argv[])
{
std::string token(get_token());

std::cout << "[" << std::fixed << std::setprecision(3) << (dpp::utility::time_f() - get_start_time()) << "]: [\u001b[36mSTART\u001b[0m] ";
if (offline) {
std::cout << "Running offline unit tests only.\n";
} else {
std::cout << "Running offline and online unit tests. Guild ID: " << TEST_GUILD_ID << " Text Channel ID: " << TEST_TEXT_CHANNEL_ID << " VC ID: " << TEST_VC_ID << " User ID: " << TEST_USER_ID << " Event ID: " << TEST_EVENT_ID << "\n";
if (argc > 1 && std::find_if(argv + 1, argv + argc, [](const char *a){ return (std::strcmp(a, "full") == 0); }) != argv + argc)
extended = true;
std::cout << "Running offline and " << (extended ? "extended" : "limited") << " online unit tests. Guild ID: " << TEST_GUILD_ID << " Text Channel ID: " << TEST_TEXT_CHANNEL_ID << " VC ID: " << TEST_VC_ID << " User ID: " << TEST_USER_ID << " Event ID: " << TEST_EVENT_ID << "\n";
}

std::string test_to_escape = "*** _This is a test_ ***\n```cpp\n\
Expand Down Expand Up @@ -800,6 +808,10 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b
}

void test_pin() {
if (!extended) {
set_pin_tested();
return;
}
set_test("MESSAGEPIN", false);
set_test("MESSAGEUNPIN", false);
bot.message_pin(channel_id, message_id, [=](const dpp::confirmation_callback_t &callback) {
Expand Down Expand Up @@ -859,12 +871,13 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b
bool members_tested = false;
bool messages_tested = false;
bool events_tested = false;
bool get_active_tested = false;
uint32_t events_tested_mask = 0;
uint32_t events_to_test_mask = 0;

void delete_if_done()
{
if (edit_tested && members_tested && messages_tested && events_tested) {
if (edit_tested && members_tested && messages_tested && events_tested && get_active_tested) {
bot.channel_delete(thread_id);
}
}
Expand Down Expand Up @@ -896,6 +909,15 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b
delete_if_done();
}

void set_get_active_tested()
{
if (get_active_tested) {
return;
}
get_active_tested = true;
delete_if_done();
}

void set_messages_tested()
{
if (messages_tested) {
Expand All @@ -912,7 +934,7 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b
}
events_tested_mask |= flag;
for (uint32_t i = 1; i < EVENT_END; i <<= 1) {
if ((events_tested_mask & i) != i)
if ((events_to_test_mask & i) && (events_tested_mask & i) != i)
return;
}
set_events_tested();
Expand Down Expand Up @@ -961,17 +983,42 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b
}
}

void test_members(const dpp::thread &thread)
{
void test_get_active(const dpp::thread &thread)
{
std::lock_guard lock{mutex};
set_test("THREAD_MEMBER_ADD", false);
set_test("THREAD_MEMBER_GET", false);
set_test("THREAD_MEMBERS_GET", false);
set_test("THREAD_MEMBER_REMOVE", false);
set_test("THREAD_MEMBERS_ADD_EVENT", false);
set_test("THREAD_MEMBERS_REMOVE_EVENT", false);

set_test("THREAD_GET_ACTIVE", false);
bot.threads_get_active(TEST_GUILD_ID, [this](const dpp::confirmation_callback_t &callback) {
std::lock_guard lock{mutex};
if (!callback.is_error()) {
const auto &threads = callback.get<dpp::active_threads>();
if (auto thread_it = threads.find(thread_id); thread_it != threads.end()) {
const auto &thread = thread_it->second.active_thread;
const auto &member = thread_it->second.bot_member;
if (thread.id == thread_id && member.has_value() && member->user_id == bot.me.id) {
set_test("THREAD_GET_ACTIVE", true);
}
}
}
set_get_active_tested();
});
}

void test_members(const dpp::thread &thread)
{
std::lock_guard lock{mutex};

if (!members_tested) {
if (!extended) {
set_members_tested();
return;
}
set_test("THREAD_MEMBER_ADD", false);
set_test("THREAD_MEMBER_GET", false);
set_test("THREAD_MEMBERS_GET", false);
set_test("THREAD_MEMBER_REMOVE", false);
set_test("THREAD_MEMBERS_ADD_EVENT", false);
set_test("THREAD_MEMBERS_REMOVE_EVENT", false);
bot.thread_member_add(thread_id, TEST_USER_ID, [this](const dpp::confirmation_callback_t &callback) {
std::lock_guard lock{mutex};
if (callback.is_error()) {
Expand All @@ -998,34 +1045,27 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b
return;
}
set_test("THREAD_MEMBERS_GET", true);
bot.threads_get_active(TEST_GUILD_ID, [this](const dpp::confirmation_callback_t &callback) {
bot.thread_member_remove(thread_id, TEST_USER_ID, [this](const dpp::confirmation_callback_t &callback) {
std::lock_guard lock{mutex};
if (!callback.is_error()) {
const auto &threads = callback.get<dpp::active_threads>();
if (auto thread_it = threads.find(thread_id); thread_it != threads.end()) {
const auto &thread = thread_it->second.active_thread;
const auto &member = thread_it->second.bot_member;
if (thread.id == thread_id && member.has_value() && member->user_id == bot.me.id) {
set_test("THREAD_GET_ACTIVE", true);
}
}
set_test("THREAD_MEMBER_REMOVE", true);
}
bot.thread_member_remove(thread_id, TEST_USER_ID, [this](const dpp::confirmation_callback_t &callback) {
std::lock_guard lock{mutex};
if (!callback.is_error()) {
set_test("THREAD_MEMBER_REMOVE", true);
}
set_members_tested();
});
set_members_tested();
});
});
});
});
}
}
}

void test_messages(const dpp::thread &thread)
{
if (!extended) {
set_messages_tested();
set_events_tested();
return;
}

std::lock_guard lock{mutex};
set_test("THREAD_MESSAGE", false);
set_test("THREAD_MESSAGE_CREATE_EVENT", false);
Expand Down Expand Up @@ -1083,14 +1123,10 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b
});
}

void confirm_message_receive()
{
std::lock_guard lock{mutex};
}

void run(const dpp::thread &thread)
{
thread_id = thread.id;
test_get_active(thread);
test_edit(thread);
test_members(thread);
test_messages(thread);
Expand Down Expand Up @@ -1357,18 +1393,25 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b
}

bot.invite_get(created.code, [&bot, created](const dpp::confirmation_callback_t &event) {
if (event.is_error()) return;
if (!event.is_error()) {
auto retrieved = event.get<dpp::invite>();
if (retrieved.code == created.code && retrieved.guild_id == created.guild_id && retrieved.channel_id == created.channel_id && retrieved.inviter.id == created.inviter.id) {
if (retrieved.destination_guild.flags & dpp::g_community)
set_test("INVITE_GET", retrieved.expires_at == 0);
else
set_test("INVITE_GET", true);

auto retrieved = event.get<dpp::invite>();
if (retrieved.code == created.code && retrieved.expires_at == 0 && retrieved.guild_id == created.guild_id && retrieved.channel_id == created.channel_id && retrieved.inviter.id == created.inviter.id) {
set_test("INVITE_GET", true);
}
else {
set_test("INVITE_GET", false);
}
} else {
set_test("INVITE_GET", false);
}

set_test("INVITE_DELETE_EVENT", false);
bot.invite_delete(retrieved.code, [](const dpp::confirmation_callback_t &event) {
if (!event.is_error()) {
set_test("INVITE_DELETE", true);
}
bot.invite_delete(created.code, [](const dpp::confirmation_callback_t &event) {
set_test("INVITE_DELETE", !event.is_error());
});
});
});
Expand Down
8 changes: 3 additions & 5 deletions src/unittest/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ enum test_type_t {
tt_offline,
/* A test that requires discord connectivity */
tt_online,
/* A test that requires both online and full tests to be enabled */
tt_extended
};

/* Represents a test case */
Expand Down Expand Up @@ -75,6 +77,7 @@ extern dpp::snowflake TEST_EVENT_ID;

/* True if we skip tt_online tests */
extern bool offline;
extern bool extended;

/**
* @brief Perform a test of a REST base API call with one parameter
Expand Down Expand Up @@ -314,8 +317,3 @@ inline constexpr user_project_id_t get_user_snowflake;
inline constexpr auto is_owner = [](auto &&user) noexcept {
return get_user_snowflake(user) == TEST_USER_ID;
};

/**
* @brief Thread emoji - https://www.compart.com/en/unicode/U+1F9F5
*/
inline const std::string THREAD_EMOJI = "\xF0\x9F\xA7\xB5";
65 changes: 42 additions & 23 deletions src/unittest/unittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ std::map<std::string, test_t> tests = {
{"MESSAGECREATE", {tt_online, "Creation of a channel message", false, false}},
{"MESSAGEEDIT", {tt_online, "Editing a channel message", false, false}},
{"EDITEVENT", {tt_online, "Message edit event", false, false}},
{"MESSAGEPIN", {tt_online, "Pinning a channel message", false, false}},
{"MESSAGEUNPIN", {tt_online, "Unpinning a channel message", false, false}},
{"MESSAGEDELETE", {tt_online, "Deletion of a channel message", false, false}},
{"MESSAGERECEIVE", {tt_online, "Receipt of a created message", false, false}},
{"MESSAGEFILE", {tt_online, "Message attachment send and check", false, false}},
Expand Down Expand Up @@ -103,22 +101,8 @@ std::map<std::string, test_t> tests = {
{"THREAD_DELETE_EVENT", {tt_online, "cluster::on_thread_delete event", false, false}},
{"THREAD_EDIT", {tt_online, "cluster::thread_edit", false, false}},
{"THREAD_UPDATE_EVENT", {tt_online, "cluster::on_thread_update event", false, false}},
{"THREAD_MEMBER_ADD", {tt_online, "cluster::thread_member_add", false, false}},
{"THREAD_MEMBER_GET", {tt_online, "cluster::thread_member_get", false, false}},
{"THREAD_MEMBERS_GET", {tt_online, "cluster::thread_members_get", false, false}},
{"THREAD_MEMBER_REMOVE", {tt_online, "cluster::thread_member_remove", false, false}},
{"THREAD_MEMBERS_ADD_EVENT", {tt_online, "cluster::on_thread_members_update event with member addition", false, false}},
{"THREAD_MEMBERS_REMOVE_EVENT", {tt_online, "cluster::on_thread_members_update event with member removal", false, false}},
{"THREAD_CREATE_MESSAGE", {tt_online, "cluster::thread_create_with_message", false, false}},
{"THREAD_GET_ACTIVE", {tt_online, "cluster::threads_get_active", false, false}},

{"THREAD_MESSAGE", {tt_online, "message manipulation in thread", false, false}},
{"THREAD_MESSAGE_CREATE_EVENT", {tt_online, "cluster::on_message_create in thread", false, false}},
{"THREAD_MESSAGE_EDIT_EVENT", {tt_online, "cluster::on_message_edit in thread", false, false}},
{"THREAD_MESSAGE_DELETE_EVENT", {tt_online, "cluster::on_message_delete in thread", false, false}},
{"THREAD_MESSAGE_REACT_ADD_EVENT", {tt_online, "cluster::on_reaction_add in thread", false, false}},
{"THREAD_MESSAGE_REACT_REMOVE_EVENT", {tt_online, "cluster::on_reaction_remove in thread", false, false}},

{"VOICE_CHANNEL_CREATE", {tt_online, "creating a voice channel", false, false}},
{"VOICE_CHANNEL_EDIT", {tt_online, "editing the created voice channel", false, false}},
{"VOICE_CHANNEL_DELETE", {tt_online, "deleting the created voice channel", false, false}},
Expand Down Expand Up @@ -169,10 +153,31 @@ std::map<std::string, test_t> tests = {
{"INVITE_CREATE", {tt_online, "cluster::channel_invite_create", false, false}},
{"INVITE_GET", {tt_online, "cluster::invite_get", false, false}},
{"INVITE_DELETE", {tt_online, "cluster::invite_delete", false, false}},

/* Extended set -- Less important, skipped on the master branch due to rate limits and GitHub actions limitations*/
/* To execute, run unittests with "full" command line argument */
{"MESSAGEPIN", {tt_extended, "Pinning a channel message", false, false}},
{"MESSAGEUNPIN", {tt_extended, "Unpinning a channel message", false, false}},

{"THREAD_MEMBER_ADD", {tt_extended, "cluster::thread_member_add", false, false}},
{"THREAD_MEMBER_GET", {tt_extended, "cluster::thread_member_get", false, false}},
{"THREAD_MEMBERS_GET", {tt_extended, "cluster::thread_members_get", false, false}},
{"THREAD_MEMBER_REMOVE", {tt_extended, "cluster::thread_member_remove", false, false}},
{"THREAD_MEMBERS_ADD_EVENT", {tt_extended, "cluster::on_thread_members_update event with member addition", false, false}},
{"THREAD_MEMBERS_REMOVE_EVENT", {tt_extended, "cluster::on_thread_members_update event with member removal", false, false}},
{"THREAD_CREATE_MESSAGE", {tt_extended, "cluster::thread_create_with_message", false, false}},

{"THREAD_MESSAGE", {tt_extended, "message manipulation in thread", false, false}},
{"THREAD_MESSAGE_CREATE_EVENT", {tt_extended, "cluster::on_message_create in thread", false, false}},
{"THREAD_MESSAGE_EDIT_EVENT", {tt_extended, "cluster::on_message_edit in thread", false, false}},
{"THREAD_MESSAGE_DELETE_EVENT", {tt_extended, "cluster::on_message_delete in thread", false, false}},
{"THREAD_MESSAGE_REACT_ADD_EVENT", {tt_extended, "cluster::on_reaction_add in thread", false, false}},
{"THREAD_MESSAGE_REACT_REMOVE_EVENT", {tt_extended, "cluster::on_reaction_remove in thread", false, false}},
};

double start = dpp::utility::time_f();
bool offline = false;
bool extended = false;

dpp::snowflake TEST_GUILD_ID = std::stoull(SAFE_GETENV("TEST_GUILD_ID"));
dpp::snowflake TEST_TEXT_CHANNEL_ID = std::stoull(SAFE_GETENV("TEST_TEXT_CHANNEL_ID"));
Expand Down Expand Up @@ -216,7 +221,7 @@ int test_summary() {
std::cout << "\u001b[37;1m\n\nUNIT TEST SUMMARY\n==================\n\u001b[0m";
for (auto & t : tests) {
bool test_skipped = false;
if (t.second.type == tt_online && offline) {
if ((t.second.type == tt_online && offline) || (t.second.type == tt_extended && !extended)) {
skipped++;
test_skipped = true;
} else {
Expand All @@ -232,9 +237,18 @@ int test_summary() {
return failed;
}

namespace {
std::string get_testdata_dir() {
char *env_var = getenv("TEST_DATA_DIR");

return (env_var ? env_var : "../../testdata/");
}
}

std::vector<uint8_t> load_test_audio() {
std::vector<uint8_t> testaudio;
std::ifstream input ("../../testdata/Robot.pcm", std::ios::in|std::ios::binary|std::ios::ate);
std::string dir = get_testdata_dir();
std::ifstream input (dir + "Robot.pcm", std::ios::in|std::ios::binary|std::ios::ate);
if (input.is_open()) {
size_t testaudio_size = input.tellg();
testaudio.resize(testaudio_size);
Expand All @@ -243,15 +257,16 @@ std::vector<uint8_t> load_test_audio() {
input.close();
}
else {
std::cout << "ERROR: Can't load ../../testdata/Robot.pcm\n";
std::cout << "ERROR: Can't load " + dir + "Robot.pcm\n";
exit(1);
}
return testaudio;
}

std::vector<uint8_t> load_test_image() {
std::vector<uint8_t> testimage;
std::ifstream input ("../../testdata/DPP-Logo.png", std::ios::in|std::ios::binary|std::ios::ate);
std::string dir = get_testdata_dir();
std::ifstream input (dir + "DPP-Logo.png", std::ios::in|std::ios::binary|std::ios::ate);
if (input.is_open()) {
size_t testimage_size = input.tellg();
testimage.resize(testimage_size);
Expand All @@ -260,7 +275,7 @@ std::vector<uint8_t> load_test_image() {
input.close();
}
else {
std::cout << "ERROR: Can't load ../../testdata/DPP-Logo.png\n";
std::cout << "ERROR: Can't load " + dir + "DPP-Logo.png\n";
exit(1);
}
return testimage;
Expand All @@ -287,9 +302,9 @@ void wait_for_tests() {
for (auto & t : tests) {
if (t.second.executed == true) {
executed++;
} else if (offline && t.second.type == tt_online && !t.second.executed) {
} else if (!t.second.executed && ((offline && t.second.type == tt_online) || (!extended && t.second.type == tt_extended))) {
executed++;
t.second.success = true;
t.second.executed = true;
std::cout << "[" << std::fixed << std::setprecision(3) << get_time() << "]: " << "[\u001b[33mSKIPPED\u001b[0m] " << t.second.description << "\n";
}
}
Expand All @@ -300,4 +315,8 @@ void wait_for_tests() {
std::this_thread::sleep_for(std::chrono::seconds(1));
ticks++;
}
for (auto &t : tests) {
if (!t.second.executed)
std::cout << "[" << std::fixed << std::setprecision(3) << get_time() << "]: " << "[\u001b[31mTIMEOUT\u001b[0m] " << t.second.description << "\n";
}
}

0 comments on commit 5895803

Please sign in to comment.