From 7841ab57aff30a349edcaabfe2d1f6b70d1743e8 Mon Sep 17 00:00:00 2001
From: brain <craigedwards@brainbox.cc>
Date: Sat, 28 May 2022 15:51:28 +0100
Subject: [PATCH 1/4] change to using ctest to run tests, as this is more
 standardized

---
 .github/workflows/ci.yml          |  2 +-
 CMakeLists.txt                    | 14 +++++++++++---
 docpages/03_example_programs.md   |  2 +-
 docpages/04_advanced_reference.md |  6 ++++--
 include/dpp/dispatcher.h          |  3 +++
 src/dpp/cluster/webhook.cpp       |  6 +++++-
 6 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ec7a3adfa3..6fb4bbf9fb 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -51,7 +51,7 @@ jobs:
         run: cd build && ninja 
 
       - name: Run unit tests
-        run: cd build && ./test
+        run: cd build && ctest -VV
         env:
           DPP_UNIT_TEST_TOKEN: ${{secrets.DPP_UNIT_TEST_TOKEN}}
           TEST_GUILD_ID: ${{secrets.TEST_GUILD_ID}}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 949374be90..bbcc4b3eb7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -286,9 +286,16 @@ target_compile_features(dpp PRIVATE cxx_variadic_templates)
 target_compile_features(dpp PRIVATE cxx_attribute_deprecated)
 
 if (DPP_BUILD_TEST)
-	add_executable(test ${coresrc})
-	target_compile_features(test PRIVATE cxx_std_17)
-	target_link_libraries(test PUBLIC ${modname})
+	enable_testing(${PROJECT_SOURCE_DIR})
+	add_executable(unittest ${coresrc})
+	target_compile_features(unittest PRIVATE cxx_std_17)
+	target_link_libraries(unittest PUBLIC ${modname})
+	add_test(
+		NAME unittests
+		COMMAND unittest
+		WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
+	)
+
 endif()
 
 if(HAVE_PRCTL)
@@ -333,3 +340,4 @@ include("cmake/CPackSetup.cmake")						# Setup information for packaging and dis
 
 # CPack initialization for distribution
 include(CPack)
+
diff --git a/docpages/03_example_programs.md b/docpages/03_example_programs.md
index f1958d644c..7785abc1f4 100644
--- a/docpages/03_example_programs.md
+++ b/docpages/03_example_programs.md
@@ -259,7 +259,7 @@ int main() {
 
 ### 7. Compile and run your bot
 
-Compile your bot using `g++ -std=c++17 -o test test.cpp -ldpp` (if your .cpp file is called `test.cpp`) and run it with `./test`.
+Compile your bot using `g++ -std=c++17 -o bot bot.cpp -ldpp` (if your .cpp file is called `bot.cpp`) and run it with `./bot`.
 
 ### 8. Inviting your bot to your server
 
diff --git a/docpages/04_advanced_reference.md b/docpages/04_advanced_reference.md
index 8d310af3bc..cc0a9c4295 100644
--- a/docpages/04_advanced_reference.md
+++ b/docpages/04_advanced_reference.md
@@ -162,7 +162,7 @@ Before running test cases, create a test server for your test bot. You should:
 * Create at least one voice channel
 * Create at least one text channel
 
-Then, set the following variables to the appropriate values. (This uses a fake token, don't bother trying to use it.)
+Then, set the following variables to the appropriate values. (Below is a fake token, don't bother trying to use it)
 
     export DPP_UNIT_TEST_TOKEN="ODI2ZSQ4CFYyMzgxUzkzzACy.HPL5PA.9qKR4uh8po63-pjYVrPAvQQO4ln"
     export TEST_GUILD_ID="907951970017480704"
@@ -171,7 +171,9 @@ Then, set the following variables to the appropriate values. (This uses a fake t
     export TEST_USER_ID="826535422381391913"
     export TEST_EVENT_ID="909928577951203360"
 
-Then, after cloning and building DPP, run `./build/test` for unit test cases. 
+Then, after cloning and building DPP, run `cd build && ctest -VV` for unit test cases. 
+
+If you do not specify the `DPP_UNIT_TEST_TOKEN` environment variable, a subset of the tests will run which do not require discord connectivity.
 
 \page lambdas-and-locals Ownership of local variables and safely transferring into a lambda
 
diff --git a/include/dpp/dispatcher.h b/include/dpp/dispatcher.h
index 3174938307..b366c62d37 100644
--- a/include/dpp/dispatcher.h
+++ b/include/dpp/dispatcher.h
@@ -428,6 +428,9 @@ struct DPP_EXPORT interaction_create_t : public event_dispatch_t {
 	virtual ~interaction_create_t() = default;
 };
 
+/**
+ * @brief User has issued a slash command
+ */
 struct DPP_EXPORT slashcommand_t : public interaction_create_t {
 public:
 	/** Constructor
diff --git a/src/dpp/cluster/webhook.cpp b/src/dpp/cluster/webhook.cpp
index 24b227b5d1..954ce3ee46 100644
--- a/src/dpp/cluster/webhook.cpp
+++ b/src/dpp/cluster/webhook.cpp
@@ -67,7 +67,11 @@ void cluster::execute_webhook(const class webhook &wh, const struct message& m,
 		{"wait", wait},
 		{"thread_id", thread_id},
 	});
-	rest_request<message>(this, API_PATH "/webhooks", std::to_string(wh.id), utility::url_encode(!wh.token.empty() ? wh.token: token) + parameters, m_post, m.build_json(false), callback);
+	this->post_rest_multipart(API_PATH API_PATH "/webhooks", std::to_string(wh.id), utility::url_encode(!wh.token.empty() ? wh.token: token) + parameters, m_post, m.build_json(), [this, callback](json &j, const http_request_completion_t& http) {
+		if (callback) {
+			callback(confirmation_callback_t(this, message(this).fill_from_json(&j), http));
+		}
+	}, m.filename, m.filecontent);
 }
 
 

From f6687225ded93d02aab61535aeb11b3e4c5ff482 Mon Sep 17 00:00:00 2001
From: brain <craigedwards@brainbox.cc>
Date: Sat, 28 May 2022 15:52:42 +0100
Subject: [PATCH 2/4] add ctest to cspell

---
 .cspell.json | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/.cspell.json b/.cspell.json
index 73b3a08af6..02e7209f48 100644
--- a/.cspell.json
+++ b/.cspell.json
@@ -75,7 +75,8 @@
 		"clion",
 		"followup",
 		"gifv",
-		"ctls"
+		"ctls",
+		"ctest"
 	],
 	"flagWords": [
 		"hte"

From 30b32e0bf1cc348309f09686f9131298c5e07df9 Mon Sep 17 00:00:00 2001
From: es183923 <72744903+es183923@users.noreply.github.com>
Date: Sat, 28 May 2022 14:12:22 -0400
Subject: [PATCH 3/4] add template to only enable for int convertible types

---
 include/dpp/permissions.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/dpp/permissions.h b/include/dpp/permissions.h
index b2e4e4598f..276a9ac214 100644
--- a/include/dpp/permissions.h
+++ b/include/dpp/permissions.h
@@ -145,7 +145,7 @@ class DPP_EXPORT permission {
 	 *
 	 * @return permission& reference to self for chaining
 	 */
-	template <typename... T>
+	template <typename... T, typename = std::enable_if_t<std::conjunction_v<std::is_convertible<T, uint64_t>...>>>
 	permission& add(T... values) {
 		(value |= (0 | ... | values));
 		return *this;
@@ -164,7 +164,7 @@ class DPP_EXPORT permission {
 	 *
 	 * @return permission& reference to self for chaining
 	 */
-	template <typename... T>
+	template <typename... T, typename = std::enable_if_t<std::conjunction_v<std::is_convertible<T, uint64_t>...>>>
 	permission& set(T... values) {
 		(value = (0 | ... | values));
 		return *this;
@@ -184,7 +184,7 @@ class DPP_EXPORT permission {
 	 *
 	 * @return permission& reference to self for chaining
 	 */
-	template <typename... T>
+	template <typename... T, typename = std::enable_if_t<std::conjunction_v<std::is_convertible<T, uint64_t>...>>>
 	permission& remove(T... values) {
 		(value &= ~(0 | ... | values));
 		return *this;

From c4a34ff7f030f2fb5648c0d8d2a8af8e3cfee661 Mon Sep 17 00:00:00 2001
From: es183923 <72744903+es183923@users.noreply.github.com>
Date: Sat, 28 May 2022 15:11:31 -0400
Subject: [PATCH 4/4] use folding instead of conjunction

---
 include/dpp/permissions.h | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/include/dpp/permissions.h b/include/dpp/permissions.h
index 276a9ac214..68e5f2d379 100644
--- a/include/dpp/permissions.h
+++ b/include/dpp/permissions.h
@@ -145,9 +145,10 @@ class DPP_EXPORT permission {
 	 *
 	 * @return permission& reference to self for chaining
 	 */
-	template <typename... T, typename = std::enable_if_t<std::conjunction_v<std::is_convertible<T, uint64_t>...>>>
-	permission& add(T... values) {
-		(value |= (0 | ... | values));
+	template <typename... T>
+	typename std::enable_if<(std::is_convertible<T, uint64_t>::value && ...), permission&>::type
+	add(T... values) {
+		value |= (0 | ... | values);
 		return *this;
 	}
 
@@ -164,9 +165,10 @@ class DPP_EXPORT permission {
 	 *
 	 * @return permission& reference to self for chaining
 	 */
-	template <typename... T, typename = std::enable_if_t<std::conjunction_v<std::is_convertible<T, uint64_t>...>>>
-	permission& set(T... values) {
-		(value = (0 | ... | values));
+	template <typename... T>
+	typename std::enable_if<(std::is_convertible<T, uint64_t>::value && ...), permission&>::type
+	set(T... values) {
+		value = (0 | ... | values);
 		return *this;
 	}
 
@@ -184,9 +186,10 @@ class DPP_EXPORT permission {
 	 *
 	 * @return permission& reference to self for chaining
 	 */
-	template <typename... T, typename = std::enable_if_t<std::conjunction_v<std::is_convertible<T, uint64_t>...>>>
-	permission& remove(T... values) {
-		(value &= ~(0 | ... | values));
+	template <typename... T>
+	typename std::enable_if<(std::is_convertible<T, uint64_t>::value && ...), permission&>::type
+	remove(T... values) {
+		value &= ~(0 | ... | values);
 		return *this;
 	}
 };