Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: add httpcommon tests and add new file_handler methods #2712

Merged
merged 1 commit into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packaging/linux/flatpak/dev.lizardbyte.sunshine.yml
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ modules:
append-path: /usr/lib/sdk/node18/bin
build-args:
- --share=network
test-args:
- --share=network
env:
BUILD_VERSION: "@BUILD_VERSION@"
BRANCH: "@GITHUB_BRANCH@"
Expand Down
4 changes: 1 addition & 3 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1255,9 +1255,7 @@ namespace config {
bool config_loaded = false;
try {
// Create appdata folder if it does not exist
if (!boost::filesystem::exists(platf::appdata().string())) {
boost::filesystem::create_directories(platf::appdata().string());
}
file_handler::make_directory(platf::appdata().string());

// Create empty config file if it does not exist
if (!fs::exists(sunshine.config_file)) {
Expand Down
4 changes: 1 addition & 3 deletions src/confighttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,9 +501,7 @@ namespace confighttp {
auto url = inputTree.get("url", "");

const std::string coverdir = platf::appdata().string() + "/covers/";
if (!boost::filesystem::exists(coverdir)) {
boost::filesystem::create_directories(coverdir);
}
file_handler::make_directory(coverdir);

std::basic_string path = coverdir + http::url_escape(key) + ".png";
if (!url.empty()) {
Expand Down
31 changes: 31 additions & 0 deletions src/file_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,37 @@
#include "logging.h"

namespace file_handler {
/**
* @breif Get the parent directory of a file or directory.
* @param path The path of the file or directory.
* @return `std::string` : The parent directory.
*/
std::string
get_parent_directory(const std::string &path) {
// remove any trailing path separators
std::string trimmed_path = path;
while (!trimmed_path.empty() && trimmed_path.back() == '/') {
trimmed_path.pop_back();
}

std::filesystem::path p(trimmed_path);
return p.parent_path().string();
}

/**
* @brief Make a directory.
* @param path The path of the directory.
* @return `bool` : `true` on success, `false` on failure.
*/
bool
make_directory(const std::string &path) {
// first, check if the directory already exists
if (std::filesystem::exists(path)) {
return true;
}

return std::filesystem::create_directories(path);
}

/**
* @brief Read a file to string.
Expand Down
7 changes: 7 additions & 0 deletions src/file_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@
#include <string>

namespace file_handler {
std::string
get_parent_directory(const std::string &path);

bool
make_directory(const std::string &path);

std::string
read_file(const char *path);

int
write_file(const char *path, const std::string_view &contents);
} // namespace file_handler
8 changes: 8 additions & 0 deletions src/httpcommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@
BOOST_LOG(error) << "Couldn't create CURL instance";
return false;
}

std::string file_dir = file_handler::get_parent_directory(file);
if (!file_handler::make_directory(file_dir)) {
BOOST_LOG(error) << "Couldn't create directory ["sv << file_dir << ']';
curl_easy_cleanup(curl);
return false;

Check warning on line 208 in src/httpcommon.cpp

View check run for this annotation

Codecov / codecov/patch

src/httpcommon.cpp#L208

Added line #L208 was not covered by tests
}

FILE *fp = fopen(file.c_str(), "wb");
if (!fp) {
BOOST_LOG(error) << "Couldn't open ["sv << file << ']';
Expand Down
41 changes: 41 additions & 0 deletions tests/unit/test_file_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,47 @@

#include <tests/conftest.cpp>

class FileHandlerParentDirectoryTest: public ::testing::TestWithParam<std::tuple<std::string, std::string>> {};

TEST_P(FileHandlerParentDirectoryTest, Run) {
auto [input, expected] = GetParam();
EXPECT_EQ(file_handler::get_parent_directory(input), expected);
}

INSTANTIATE_TEST_SUITE_P(
FileHandlerTests,
FileHandlerParentDirectoryTest,
::testing::Values(
std::make_tuple("/path/to/file.txt", "/path/to"),
std::make_tuple("/path/to/directory", "/path/to"),
std::make_tuple("/path/to/directory/", "/path/to")));

class FileHandlerMakeDirectoryTest: public ::testing::TestWithParam<std::tuple<std::string, bool, bool>> {};

TEST_P(FileHandlerMakeDirectoryTest, Run) {
auto [input, expected, remove] = GetParam();
const std::string test_dir = platf::appdata().string() + "/tests/path/";
input = test_dir + input;

EXPECT_EQ(file_handler::make_directory(input), expected);
EXPECT_TRUE(std::filesystem::exists(input));

// remove test directory
if (remove) {
std::filesystem::remove_all(test_dir);
EXPECT_FALSE(std::filesystem::exists(test_dir));
}
}

INSTANTIATE_TEST_SUITE_P(
FileHandlerTests,
FileHandlerMakeDirectoryTest,
::testing::Values(
std::make_tuple("dir_123", true, false),
std::make_tuple("dir_123", true, true),
std::make_tuple("dir_123/abc", true, false),
std::make_tuple("dir_123/abc", true, true)));

class FileHandlerTests: public virtual BaseTest, public ::testing::WithParamInterface<std::tuple<int, std::string>> {
protected:
void
Expand Down
53 changes: 53 additions & 0 deletions tests/unit/test_httpcommon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* @file tests/test_httpcommon.cpp
* @brief Test src/httpcommon.*.
*/
#include <src/httpcommon.h>

#include <tests/conftest.cpp>

class UrlEscapeTest: public ::testing::TestWithParam<std::tuple<std::string, std::string>> {};

TEST_P(UrlEscapeTest, Run) {
auto [input, expected] = GetParam();
ASSERT_EQ(http::url_escape(input), expected);
}

INSTANTIATE_TEST_SUITE_P(
UrlEscapeTests,
UrlEscapeTest,
::testing::Values(
std::make_tuple("igdb_0123456789", "igdb_0123456789"),
std::make_tuple("../../../", "..%2F..%2F..%2F"),
std::make_tuple("..*\\", "..%2A%5C")));

class UrlGetHostTest: public ::testing::TestWithParam<std::tuple<std::string, std::string>> {};

TEST_P(UrlGetHostTest, Run) {
auto [input, expected] = GetParam();
ASSERT_EQ(http::url_get_host(input), expected);
}

INSTANTIATE_TEST_SUITE_P(
UrlGetHostTests,
UrlGetHostTest,
::testing::Values(
std::make_tuple("https://images.igdb.com/example.txt", "images.igdb.com"),
std::make_tuple("http://localhost:8080", "localhost"),
std::make_tuple("nonsense!!}{::", "")));

class DownloadFileTest: public ::testing::TestWithParam<std::tuple<std::string, std::string>> {};

TEST_P(DownloadFileTest, Run) {
auto [url, filename] = GetParam();
const std::string test_dir = platf::appdata().string() + "/tests/";
std::basic_string path = test_dir + filename;
ASSERT_TRUE(http::download_file(url, path));
}

INSTANTIATE_TEST_SUITE_P(
DownloadFileTests,
DownloadFileTest,
::testing::Values(
std::make_tuple("https://httpbin.org/base64/aGVsbG8h", "hello.txt"),
std::make_tuple("https://httpbin.org/redirect-to?url=/base64/aGVsbG8h", "hello-redirect.txt")));
Loading