Skip to content

Commit 9cd8ccc

Browse files
Add modules unit test
1 parent 6e4944e commit 9cd8ccc

File tree

10 files changed

+194
-50
lines changed

10 files changed

+194
-50
lines changed

.github/workflows/test-docs-examples.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,17 @@ jobs:
3535
submodules: recursive
3636

3737
- name: Install apt packages
38-
run: sudo sed -i 's/azure\.//' /etc/apt/sources.list && sudo apt-get update && sudo apt-get install -y g++-12 libopus-dev zlib1g-dev libmpg123-dev liboggz-dev cmake libfmt-dev libopusfile-dev
38+
run: sudo sed -i 's/azure\.//' /etc/apt/sources.list && sudo apt-get update && sudo apt-get install -y g++-12 libopus-dev ninja-build zlib1g-dev libmpg123-dev liboggz-dev cmake libfmt-dev libopusfile-dev
3939

4040
- name: Generate CMake
41-
run: mkdir build && cd build && cmake -DDPP_NO_VCPKG=ON -DAVX_TYPE=T_fallback -DDPP_CORO=ON -DCMAKE_BUILD_TYPE=Debug ..
41+
run: mkdir build && cd build && cmake -G Ninja -DDPP_NO_VCPKG=ON -DDPP_MODULES=ON -DAVX_TYPE=T_fallback -DDPP_CORO=ON -DCMAKE_BUILD_TYPE=Debug ..
4242
env:
4343
CXX: g++-12
4444

4545
- name: Build Project
46-
run: cd build && make -j2 && sudo make install
46+
run: cd build && ninja && sudo ninja install
4747

4848
- name: Test compile examples
49-
run: cd docpages/example_code && mkdir build && cd build && cmake .. && make -j2
49+
run: cd docpages/example_code && mkdir build && cd build && cmake -G Ninja .. && ninja
5050
env:
5151
CXX: g++-12

CMakeLists.txt

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -161,38 +161,3 @@ if (NOT WIN32)
161161
target_link_libraries(dpp PRIVATE std::filesystem)
162162
endif()
163163

164-
if (DPP_MODULES)
165-
message("-- C++20 Modules support: ${Green}ENABLED${ColourReset}")
166-
add_library(dpp_module)
167-
168-
target_sources(dpp_module
169-
PUBLIC
170-
FILE_SET CXX_MODULES
171-
FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/dpp/dpp.cppm"
172-
)
173-
174-
target_compile_features(dpp_module PUBLIC cxx_std_20)
175-
176-
target_include_directories(dpp_module PUBLIC
177-
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
178-
$<INSTALL_INTERFACE:include>
179-
)
180-
181-
target_link_libraries(dpp_module PUBLIC dpp)
182-
183-
add_library(dpp::module ALIAS dpp_module)
184-
185-
# Installation
186-
install(TARGETS dpp_module
187-
EXPORT ${PROJECT_NAME}Targets
188-
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
189-
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
190-
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
191-
FILE_SET CXX_MODULES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dpp/include
192-
)
193-
194-
target_compile_definitions(dpp PUBLIC DPP_MODULES)
195-
else()
196-
message("-- C++20 Modules support: ${Red}DISABLED${ColourReset} (enable with -DDPP_MODULES=ON)")
197-
endif()
198-
Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
1-
/* If import std; is supported, use it instead */
2-
#include <cstdlib>
3-
41
import dpp;
52

63
using dpp::cluster;
4+
using std::ready_t;
75
using dpp::slashcommand;
6+
using dpp::slashcommand_t;
87
using dpp::start_type;
98

109
int main() {
11-
cluster bot(std::getenv("BOT_TOKEN"));
10+
cluster bot("YOUR_BOT_TOKEN_HERE");
1211

13-
bot.on_slashcommand([](auto event) {
12+
bot.on_slashcommand([](const slashcommand_t& event) -> void {
1413
if (event.command.get_command_name() == "ping") {
1514
event.reply("Pong!");
1615
}
1716
});
1817

19-
bot.on_ready([&bot](auto event) {
18+
bot.on_ready([&bot](const ready_t& event) -> void {
2019
if (dpp::run_once<struct register_bot_commands>()) {
2120
bot.global_command_create(
2221
slashcommand("ping", "Ping pong!", bot.me.id)
@@ -26,4 +25,4 @@ int main() {
2625

2726
bot.start(start_type::st_wait);
2827
return 0;
29-
}
28+
}

docpages/example_programs/misc/using_modules.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
D++ is offered as a C++ module, which offers improved compile times over a traditional header.
44

5-
In order to enable support, you should be using C++20+ with any module-supporting compiler. To activate the feature, pass the `DPP_MODULES` flag to CMake. Ensure that the generated build system supports modules (for CMake, this is usually Ninja).
5+
In order to enable support, you must use C++20 (or later) with any module-supporting compiler. To activate the feature, pass the `DPP_MODULES` flag to CMake. Ensure that the generated build system supports modules (for CMake, this is usually Ninja; note CMake does not currently support modules with Makefile).
66

77
Once this is done, simply `import dpp;` and we're good to go!
88

library/CMakeLists.txt

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,42 @@ if (NOT BUILD_SHARED_LIBS)
459459
endif()
460460
endif()
461461

462+
if (DPP_MODULES)
463+
message("-- ${Green}Modules are enabled!${ColourReset}")
464+
add_library(dpp_module)
465+
466+
target_sources(dpp_module
467+
PUBLIC
468+
FILE_SET CXX_MODULES
469+
BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../include"
470+
FILES "${CMAKE_CURRENT_SOURCE_DIR}/../include/dpp/dpp.cppm"
471+
)
472+
473+
target_compile_features(dpp_module PUBLIC cxx_std_20)
474+
475+
target_include_directories(dpp_module PUBLIC
476+
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
477+
$<INSTALL_INTERFACE:include>
478+
)
479+
480+
target_link_libraries(dpp_module PUBLIC dpp)
481+
482+
add_library(dpp::module ALIAS dpp_module)
483+
484+
target_compile_definitions(dpp PUBLIC DPP_MODULES)
485+
486+
# Installation
487+
install(TARGETS dpp_module
488+
EXPORT ${PROJECT_NAME}Targets
489+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
490+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
491+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
492+
FILE_SET CXX_MODULES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dpp/include
493+
)
494+
else()
495+
message("-- ${Yellow}Modules are disabled.${ColourReset}")
496+
endif()
497+
462498
if (DPP_BUILD_TEST)
463499
enable_testing(${CMAKE_CURRENT_SOURCE_DIR}/..)
464500
file(GLOB testnamelist "${CMAKE_CURRENT_SOURCE_DIR}/../src/*")
@@ -469,15 +505,24 @@ if (DPP_BUILD_TEST)
469505
set (testsrc "")
470506
file(GLOB testsrc "${modules_dir}/${testname}/*.cpp")
471507
add_executable(${testname} ${testsrc})
472-
if ((NOT DPP_NO_CORO) OR DPP_FORMATTERS)
508+
if ((NOT DPP_NO_CORO) OR DPP_FORMATTERS OR DPP_MODULES)
473509
target_compile_features(${testname} PRIVATE cxx_std_20)
474510
else()
475511
target_compile_features(${testname} PRIVATE cxx_std_17)
476512
endif()
477513
if (MSVC)
478514
target_compile_options(${testname} PRIVATE /utf-8)
479515
endif()
480-
if(BUILD_SHARED_LIBS)
516+
if (DPP_MODULES)
517+
target_link_libraries(${testname} PUBLIC dpp_module)
518+
add_dependencies(${testname} dpp_module)
519+
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
520+
target_compile_options(${testname} PRIVATE -fmodules-ts)
521+
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
522+
target_compile_options(${testname} PRIVATE -fmodules)
523+
endif()
524+
set_target_properties(${testname} PROPERTIES CXX_SCAN_FOR_MODULES ON)
525+
elseif(BUILD_SHARED_LIBS)
481526
target_link_libraries(${testname} PUBLIC ${modname})
482527
else()
483528
target_link_libraries(${testname} PUBLIC dppstatic)

src/dpp/sslconnection.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ void ssl_connection::on_buffer_drained() {
277277
/* SSL Client constructor throws std::runtime_error if it can't allocate a socket or call connect() */
278278
void ssl_connection::connect() {
279279
/* Resolve hostname to IP */
280+
int err = 0;
280281
const dns_cache_entry* addr = resolve_hostname(hostname, port);
281282
sfd = addr->make_connecting_socket();
282283
address_t destination = addr->get_connecting_address(from_string<uint16_t>(this->port, std::dec));

src/dpp/utility.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ void exec(const std::string& cmd, std::vector<std::string> parameters, cmd_resul
465465
}
466466
/* Capture stderr */
467467
cmd_and_parameters << " 2>&1";
468-
std::unique_ptr<FILE, int(*)(FILE*)> pipe(popen(cmd_and_parameters.str().c_str(), "r"), pclose);
468+
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd_and_parameters.str().c_str(), "r"), pclose);
469469
if (!pipe) {
470470
return;
471471
}

src/unittest/module_test.cpp

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/************************************************************************************
2+
*
3+
* D++, A Lightweight C++ library for Discord
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
* Copyright 2021 Craig Edwards and D++ contributors
7+
* (https://github.com/brainboxdotcc/DPP/graphs/contributors)
8+
*
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
*
21+
************************************************************************************/
22+
23+
#include "test.h"
24+
25+
import dpp;
26+
27+
/**
28+
* @brief Test basic dpp types and functionality via module import
29+
*/
30+
void test_dpp_module_basic() {
31+
start_test(MODULE_IMPORT_BASIC);
32+
33+
// Snowflake creation test
34+
dpp::snowflake test_id = 123456789;
35+
if (test_id.empty() || test_id != 123456789) {
36+
set_status(MODULE_IMPORT_BASIC, ts_failed, "snowflake creation");
37+
return;
38+
}
39+
40+
// User object creation test
41+
dpp::user test_user;
42+
test_user.id = 987654321;
43+
test_user.username = "ModuleTestUser";
44+
if (test_user.id != 987654321 || test_user.username != "ModuleTestUser") {
45+
set_status(MODULE_IMPORT_BASIC, ts_failed, "user object creation");
46+
return;
47+
}
48+
49+
// Testing ts_to_string
50+
std::string test_time = dpp::ts_to_string(1642611864);
51+
if (test_time != "2022-01-19T17:04:24Z") {
52+
set_status(MODULE_IMPORT_BASIC, ts_failed, "timestamp conversion");
53+
return;
54+
}
55+
56+
// Message object creation test
57+
dpp::message test_msg;
58+
test_msg.content = "Test message from module";
59+
test_msg.id = 111222333;
60+
if (test_msg.content != "Test message from module" || test_msg.id != 111222333) {
61+
set_status(MODULE_IMPORT_BASIC, ts_failed, "message object creation");
62+
return;
63+
}
64+
65+
// URL encoding test
66+
std::string encoded = dpp::utility::url_encode("test value");
67+
if (encoded != "test%20value") {
68+
set_status(MODULE_IMPORT_BASIC, ts_failed, "URL encoding");
69+
return;
70+
}
71+
72+
// Markdown escaping test
73+
std::string markdown = "**bold** _italic_";
74+
std::string escaped = dpp::utility::markdown_escape(markdown);
75+
if (escaped != "\\*\\*bold\\*\\* \\_italic\\_") {
76+
set_status(MODULE_IMPORT_BASIC, ts_failed, "markdown escaping");
77+
return;
78+
}
79+
80+
// Role comparison test
81+
dpp::role r1;
82+
dpp::role r2;
83+
r1.id = 100;
84+
r1.position = 1;
85+
r1.guild_id = 500;
86+
r2.id = 200;
87+
r2.position = 2;
88+
r2.guild_id = 500;
89+
if (!(r1 < r2) || (r1 > r2)) {
90+
set_status(MODULE_IMPORT_BASIC, ts_failed, "role comparison");
91+
return;
92+
}
93+
94+
set_status(MODULE_IMPORT_BASIC, ts_success);
95+
}
96+
97+
/**
98+
* @brief Test dpp module coroutine support (if enabled)
99+
*/
100+
void test_dpp_module_coro() {
101+
start_test(MODULE_IMPORT_CORO);
102+
103+
#ifndef DPP_NO_CORO
104+
dpp::promise<int> test_promise;
105+
test_promise.set_value(42);
106+
107+
if constexpr (!requires { dpp::task<void>{}; }) {
108+
set_status(MODULE_IMPORT_CORO, ts_failed, "coroutine types not accessible");
109+
return;
110+
}
111+
112+
set_status(MODULE_IMPORT_CORO, ts_success);
113+
#else
114+
set_status(MODULE_IMPORT_CORO, ts_skipped, "coroutines disabled");
115+
#endif
116+
}
117+
118+
/**
119+
* @brief Main entry point for module tests
120+
*/
121+
void run_module_tests() {
122+
test_dpp_module_basic();
123+
test_dpp_module_coro();
124+
}

src/unittest/test.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,9 @@ Markdown lol \\|\\|spoiler\\|\\| \\~\\~strikethrough\\~\\~ \\`small \\*code\\* b
334334
set_test(WEBHOOK, false);
335335
}
336336

337+
// Test C++ module import
338+
run_module_tests();
339+
337340
{ // test dpp::snowflake
338341
start_test(SNOWFLAKE);
339342
bool success = true;

src/unittest/test.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ DPP_TEST(FORUM_CHANNEL_GET, "retrieve the created forum channel", tf_online);
156156
DPP_TEST(FORUM_CHANNEL_DELETE, "delete the created forum channel", tf_online);
157157
DPP_TEST(ERRORS, "Human readable error translation", tf_offline);
158158
DPP_TEST(INVALIDUTF8, "Invalid UTF-8 handling", tf_online);
159+
DPP_TEST(MODULE_IMPORT_BASIC, "C++ module import: basic types", tf_offline);
160+
DPP_TEST(MODULE_IMPORT_CORO, "C++ module import: coroutines", tf_offline);
159161

160162
DPP_TEST(GUILD_EDIT, "cluster::guild_edit", tf_online);
161163
DPP_TEST(GUILD_BAN_CREATE, "cluster::guild_ban_add ban three well-known discord accounts", tf_online);
@@ -570,6 +572,11 @@ inline constexpr auto is_owner = [](auto &&user) noexcept {
570572
return get_user_snowflake(user) == TEST_USER_ID;
571573
};
572574

575+
/**
576+
* @brief Main entry point for module tests
577+
*/
578+
void run_module_tests();
579+
573580
#define DPP_RUNTIME_CHECK(test, check, var) if (!check) { var = false; set_status(test, ts_failed, "check failed: " #check); }
574581
#define DPP_COMPILETIME_CHECK(test, check, var) static_assert(check, #test ": " #check)
575582

0 commit comments

Comments
 (0)