Skip to content

Commit

Permalink
Added unit tests for special file names
Browse files Browse the repository at this point in the history
  • Loading branch information
COM8 committed Aug 3, 2023
1 parent eb2d418 commit ad5cda8
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 2 deletions.
5 changes: 5 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ add_cpr_test(interceptor_multi)
add_cpr_test(multiperform)
add_cpr_test(resolve)
add_cpr_test(multiasync)
add_cpr_test(file_upload)

if (ENABLE_SSL_TESTS)
add_cpr_test(ssl)
Expand All @@ -79,4 +80,8 @@ if (ENABLE_SSL_TESTS)
add_custom_command(TARGET ssl_tests POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/data/keys/server.pub $<TARGET_FILE_DIR:ssl_tests>/data/keys/server.pub)
endif()

add_custom_command(TARGET file_upload_tests POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/data/test_file_hello_äüöp_2585_你好.txt $<TARGET_FILE_DIR:file_upload_tests>/data/test_file_hello_äüöp_2585_你好.txt)
add_custom_command(TARGET file_upload_tests POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/data/test_file_hello_äüöp_2585.txt $<TARGET_FILE_DIR:file_upload_tests>/data/test_file_hello_äüöp_2585.txt)
add_custom_command(TARGET file_upload_tests POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/data/test_file.txt $<TARGET_FILE_DIR:file_upload_tests>/data/test_file.txt)

file(INSTALL data DESTINATION data)
1 change: 1 addition & 0 deletions test/data/test_file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test content: hello_äüöp_2585_你好
1 change: 1 addition & 0 deletions test/data/test_file_hello_äüöp_2585.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test content: hello_äüöp_2585_你好
1 change: 1 addition & 0 deletions test/data/test_file_hello_äüöp_2585_你好.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test content: hello_äüöp_2585_你好
100 changes: 100 additions & 0 deletions test/file_upload_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include <gtest/gtest.h>

#include <fstream>
#include <optional>
#include <string>

#include <cpr/cpr.h>
#include <cpr/filesystem.h>

#include "cpr/api.h"
#include "cpr/file.h"
#include "cpr/multipart.h"
#include "httpServer.hpp"

namespace {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables, cert-err58-cpp)
cpr::HttpServer* server = new cpr::HttpServer();
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
std::optional<cpr::fs::path> baseDirPath{std::nullopt};
} // namespace

cpr::fs::path GetBasePath(const std::string& execPath) {
return cpr::fs::path(cpr::fs::path{execPath}.parent_path().string() + "/").make_preferred();
}


TEST(FileUploadTests, AsciiFileName) {
// Ensure 'baseDirPath' has been set
EXPECT_NE(baseDirPath, std::nullopt);

// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
cpr::fs::path filePath = baseDirPath->append("test_file.txt");

cpr::Multipart mp{{cpr::Part("file_name", cpr::File(filePath.string()))}};
cpr::Url url{server->GetBaseUrl() + "/post_file_upload.html"};
cpr::Response response = cpr::Post(url, mp);

// Expected file content
std::ifstream ifs(filePath.string());
std::string expected_text = "{\n \"file_name\": \"" + filePath.filename().string() + "=" + std::string((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>())) + "\"\n}";

EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(cpr::Url{server->GetBaseUrl() + "/post_file_upload.html"}, response.url);
EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
EXPECT_EQ(201, response.status_code);
EXPECT_EQ(cpr::ErrorCode::OK, response.error.code);
}

TEST(FileUploadTests, NonAsciiFileName) {
// Ensure 'baseDirPath' has been set
EXPECT_NE(baseDirPath, std::nullopt);

// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
cpr::fs::path filePath = baseDirPath->append("test_file_hello_äüöp_2585.txt");

cpr::Multipart mp{{cpr::Part("file_name", cpr::File(filePath.string()))}};
cpr::Url url{server->GetBaseUrl() + "/post_file_upload.html"};
cpr::Response response = cpr::Post(url, mp);

// Expected file content
std::ifstream ifs(filePath.string());
std::string expected_text = "{\n \"file_name\": \"" + filePath.filename().string() + "=" + std::string((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>())) + "\"\n}";

EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(cpr::Url{server->GetBaseUrl() + "/post_file_upload.html"}, response.url);
EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
EXPECT_EQ(201, response.status_code);
EXPECT_EQ(cpr::ErrorCode::OK, response.error.code);
}

TEST(FileUploadTests, ChineseFileName) {
// Ensure 'baseDirPath' has been set
EXPECT_NE(baseDirPath, std::nullopt);

// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
cpr::fs::path filePath = baseDirPath->append("test_file_hello_äüöp_2585_你好.txt");

cpr::Multipart mp{{cpr::Part("file_name", cpr::File(filePath.string()))}};
cpr::Url url{server->GetBaseUrl() + "/post_file_upload.html"};
cpr::Response response = cpr::Post(url, mp);

// Expected file content
std::ifstream ifs(filePath.string());
std::string expected_text = "{\n \"file_name\": \"" + filePath.filename().string() + "=" + std::string((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>())) + "\"\n}";

EXPECT_EQ(expected_text, response.text);
EXPECT_EQ(cpr::Url{server->GetBaseUrl() + "/post_file_upload.html"}, response.url);
EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
EXPECT_EQ(201, response.status_code);
EXPECT_EQ(cpr::ErrorCode::OK, response.error.code);
}

int main(int argc, char** argv) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
baseDirPath = std::make_optional<cpr::fs::path>(cpr::fs::path{GetBasePath(argv[0]).string() + "data/"});

::testing::InitGoogleTest(&argc, argv);
::testing::AddGlobalTestEnvironment(server);
return RUN_ALL_TESTS();
}
22 changes: 22 additions & 0 deletions test/httpServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,26 @@ void HttpServer::OnRequestFormPost(mg_connection* conn, mg_http_message* msg) {
mg_http_reply(conn, 201, headers.c_str(), response.c_str());
}

void HttpServer::OnRequestFileUploadPost(mg_connection* conn, mg_http_message* msg) {
size_t pos{0};
mg_http_part part{};

std::string headers = "Content-Type: application/json\r\n";
std::string response{};
response += "{\n";
while ((pos = mg_http_next_multipart(msg->body, pos, &part)) > 0) {
response += " \"" + std::string(part.name.ptr, part.name.len) + "\": \"";
if (!std::string(part.filename.ptr, part.filename.len).empty()) {
response += std::string(part.filename.ptr, part.filename.len) + "=";
}
response += std::string(part.body.ptr, part.body.len) + "\",\n";
}
response.erase(response.find_last_not_of(",\n") + 1);
response += "\n}";

mg_http_reply(conn, 201, headers.c_str(), response.c_str());
}

void HttpServer::OnRequestDelete(mg_connection* conn, mg_http_message* msg) {
bool has_json_header = false;
for (mg_http_header& header : msg->headers) {
Expand Down Expand Up @@ -887,6 +907,8 @@ void HttpServer::OnRequest(mg_connection* conn, mg_http_message* msg) {
OnRequestJsonPost(conn, msg);
} else if (uri == "/form_post.html") {
OnRequestFormPost(conn, msg);
} else if (uri == "/post_file_upload.html") {
OnRequestFileUploadPost(conn, msg);
} else if (uri == "/post_reflect.html") {
OnRequestPostReflect(conn, msg);
} else if (uri == "/delete.html") {
Expand Down
1 change: 1 addition & 0 deletions test/httpServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class HttpServer : public AbstractServer {
static void OnRequestBodyGet(mg_connection* conn, mg_http_message* msg);
static void OnRequestJsonPost(mg_connection* conn, mg_http_message* msg);
static void OnRequestFormPost(mg_connection* conn, mg_http_message* msg);
static void OnRequestFileUploadPost(mg_connection* conn, mg_http_message* msg);
static void OnRequestDelete(mg_connection* conn, mg_http_message* msg);
static void OnRequestDeleteNotAllowed(mg_connection* conn, mg_http_message* msg);
static void OnRequestPut(mg_connection* conn, mg_http_message* msg);
Expand Down
4 changes: 2 additions & 2 deletions test/ssl_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,13 @@ TEST(SslTests, LoadCertFromBufferTestSimpel) {
}
#endif

fs::path getBasePath(const std::string& execPath) {
fs::path GetBasePath(const std::string& execPath) {
return fs::path(fs::path{execPath}.parent_path().string() + "/").make_preferred();
}

int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
fs::path baseDirPath = fs::path{getBasePath(argv[0]).string() + "data/"};
fs::path baseDirPath = fs::path{GetBasePath(argv[0]).string() + "data/"};
fs::path serverCertPath = fs::path{baseDirPath}.append("certificates/server.crt");
fs::path serverKeyPath = fs::path{baseDirPath}.append("keys/server.key");
server = new HttpsServer(std::move(baseDirPath), std::move(serverCertPath), std::move(serverKeyPath));
Expand Down

0 comments on commit ad5cda8

Please sign in to comment.