This commit is contained in:
531
repertory/repertory_test/include/fixtures/drive_fixture.hpp
Normal file
531
repertory/repertory_test/include/fixtures/drive_fixture.hpp
Normal file
@@ -0,0 +1,531 @@
|
||||
/*
|
||||
Copyright <2018-2025> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef REPERTORY_TEST_INCLUDE_FIXTURES_PLATFORM_FIXTURE_HPP
|
||||
#define REPERTORY_TEST_INCLUDE_FIXTURES_PLATFORM_FIXTURE_HPP
|
||||
|
||||
#include "test_common.hpp"
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/file_utils.hpp"
|
||||
#include "utils/path.hpp"
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "drives/winfsp/remotewinfsp/remote_winfsp_drive.hpp"
|
||||
#include "drives/winfsp/winfsp_drive.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "providers/s3/s3_provider.hpp"
|
||||
#include "providers/sia/sia_provider.hpp"
|
||||
#else
|
||||
#include "comm/curl/curl_comm.hpp"
|
||||
#include "db/i_meta_db.hpp"
|
||||
#include "db/meta_db.hpp"
|
||||
#include "drives/fuse/fuse_drive.hpp"
|
||||
#include "providers/encrypt/encrypt_provider.hpp"
|
||||
#include "providers/s3/s3_provider.hpp"
|
||||
#include "providers/sia/sia_provider.hpp"
|
||||
#if !defined(ACCESSPERMS)
|
||||
#define ACCESSPERMS (S_IRWXU | S_IRWXG | S_IRWXO) /* 0777 */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
std::atomic<std::size_t> provider_idx{0U};
|
||||
constexpr auto SLEEP_SECONDS{1.5s};
|
||||
} // namespace
|
||||
|
||||
namespace repertory {
|
||||
struct local_s3_no_encryption final {
|
||||
static constexpr provider_type type{provider_type::s3};
|
||||
static constexpr provider_type type2{provider_type::s3};
|
||||
static constexpr std::uint16_t remote_port{41000U};
|
||||
static constexpr bool force_legacy_encryption{false};
|
||||
static constexpr std::string_view encryption_token{""};
|
||||
};
|
||||
struct local_s3_encryption final {
|
||||
static constexpr provider_type type{provider_type::s3};
|
||||
static constexpr provider_type type2{provider_type::s3};
|
||||
static constexpr std::uint16_t remote_port{41000U};
|
||||
static constexpr bool force_legacy_encryption{false};
|
||||
static constexpr std::string_view encryption_token{"encryption_token"};
|
||||
};
|
||||
struct local_s3_legacy_encryption final {
|
||||
static constexpr provider_type type{provider_type::s3};
|
||||
static constexpr provider_type type2{provider_type::s3};
|
||||
static constexpr std::uint16_t remote_port{41000U};
|
||||
static constexpr bool force_legacy_encryption{true};
|
||||
static constexpr std::string_view encryption_token{"encryption_token"};
|
||||
};
|
||||
struct remote_s3_no_encryption final {
|
||||
static constexpr provider_type type{provider_type::remote};
|
||||
static constexpr provider_type type2{provider_type::s3};
|
||||
static constexpr std::uint16_t remote_port{41000U};
|
||||
static constexpr bool force_legacy_encryption{false};
|
||||
static constexpr std::string_view encryption_token{""};
|
||||
};
|
||||
struct remote_s3_encryption final {
|
||||
static constexpr provider_type type{provider_type::remote};
|
||||
static constexpr provider_type type2{provider_type::s3};
|
||||
static constexpr std::uint16_t remote_port{41000U};
|
||||
static constexpr bool force_legacy_encryption{false};
|
||||
static constexpr std::string_view encryption_token{"encryption_token"};
|
||||
};
|
||||
struct remote_s3_legacy_encryption final {
|
||||
static constexpr provider_type type{provider_type::remote};
|
||||
static constexpr provider_type type2{provider_type::s3};
|
||||
static constexpr std::uint16_t remote_port{41000U};
|
||||
static constexpr bool force_legacy_encryption{true};
|
||||
static constexpr std::string_view encryption_token{"encryption_token"};
|
||||
};
|
||||
struct local_sia final {
|
||||
static constexpr provider_type type{provider_type::sia};
|
||||
static constexpr provider_type type2{provider_type::sia};
|
||||
static constexpr std::uint16_t remote_port{41001U};
|
||||
static constexpr bool force_legacy_encryption{false};
|
||||
static constexpr std::string_view encryption_token{""};
|
||||
};
|
||||
struct remote_sia final {
|
||||
static constexpr provider_type type{provider_type::remote};
|
||||
static constexpr provider_type type2{provider_type::sia};
|
||||
static constexpr std::uint16_t remote_port{41001U};
|
||||
static constexpr bool force_legacy_encryption{false};
|
||||
static constexpr std::string_view encryption_token{""};
|
||||
};
|
||||
struct remote_winfsp_to_linux final {
|
||||
static constexpr provider_type type{provider_type::remote};
|
||||
static constexpr provider_type type2{provider_type::unknown};
|
||||
static constexpr std::uint16_t remote_port{41002U};
|
||||
static constexpr bool force_legacy_encryption{false};
|
||||
static constexpr std::string_view encryption_token{""};
|
||||
};
|
||||
struct remote_linux_to_winfsp final {
|
||||
static constexpr provider_type type{provider_type::remote};
|
||||
static constexpr provider_type type2{provider_type::unknown};
|
||||
static constexpr std::uint16_t remote_port{41002U};
|
||||
static constexpr bool force_legacy_encryption{false};
|
||||
static constexpr std::string_view encryption_token{""};
|
||||
};
|
||||
|
||||
struct platform_ops {
|
||||
static void ensure_process_cwd() {
|
||||
#if !defined(_WIN32)
|
||||
EXPECT_TRUE(utils::file::change_to_process_directory());
|
||||
#endif // !defined(_WIN32)
|
||||
}
|
||||
|
||||
static std::string build_cmd(const std::string &args_joined, bool is_mount) {
|
||||
#if defined(_WIN32)
|
||||
if (is_mount) {
|
||||
return "start .\\repertory.exe -f " + args_joined;
|
||||
}
|
||||
return ".\\repertory.exe " + args_joined;
|
||||
#else // !defined(_WIN32)
|
||||
#if defined(__APPLE__)
|
||||
constexpr const char *kBin = "./repertory.app/Contents/MacOS/repertory ";
|
||||
#else // !defined(__APPLE__)
|
||||
constexpr const char *kBin = "./repertory ";
|
||||
#endif // defined(__APPLE__)
|
||||
return std::string(kBin) + args_joined;
|
||||
#endif // defined(_WIN32)
|
||||
}
|
||||
|
||||
static void execute_mount(std::vector<std::string> args_without_location,
|
||||
const std::string &location) {
|
||||
ensure_process_cwd();
|
||||
args_without_location.emplace_back(location);
|
||||
|
||||
const auto cmd = build_cmd(utils::string::join(args_without_location, ' '),
|
||||
/*is_mount*/ true);
|
||||
std::cout << "mount command: " << cmd << std::endl;
|
||||
|
||||
ASSERT_EQ(0, system(cmd.c_str()));
|
||||
std::this_thread::sleep_for(5s);
|
||||
ASSERT_TRUE(utils::file::directory{location}.exists());
|
||||
}
|
||||
|
||||
static void execute_unmount(std::vector<std::string> args_without_unmount,
|
||||
const std::string &location) {
|
||||
ensure_process_cwd();
|
||||
args_without_unmount.emplace_back("-unmount");
|
||||
|
||||
const auto cmd = build_cmd(utils::string::join(args_without_unmount, ' '),
|
||||
/*is_mount*/ false);
|
||||
std::cout << "unmount command: " << cmd << std::endl;
|
||||
|
||||
#if defined(_WIN32)
|
||||
std::this_thread::sleep_for(10s);
|
||||
bool unmounted = false;
|
||||
for (int i = 0; !unmounted && i < 6; ++i) {
|
||||
(void)system(cmd.c_str());
|
||||
unmounted = !utils::file::directory{location}.exists();
|
||||
if (!unmounted)
|
||||
std::this_thread::sleep_for(5s);
|
||||
}
|
||||
ASSERT_TRUE(unmounted);
|
||||
#else // !defined(_WIN32)
|
||||
auto res = system(cmd.c_str());
|
||||
EXPECT_EQ(0, res);
|
||||
#endif // defined(_WIN32)
|
||||
}
|
||||
};
|
||||
|
||||
template <typename provider_t> class drive_fixture : public ::testing::Test {
|
||||
public:
|
||||
#if !defined(_WIN32)
|
||||
static std::unique_ptr<app_config> config;
|
||||
static std::unique_ptr<i_meta_db> meta;
|
||||
#endif // !defined(_WIN32)
|
||||
static std::filesystem::path current_directory;
|
||||
static provider_type current_provider;
|
||||
static std::vector<std::string> drive_args;
|
||||
static std::vector<std::string> drive_args2;
|
||||
static std::string mount_location;
|
||||
static std::string mount_location2;
|
||||
|
||||
protected:
|
||||
static void SetUpTestCase() {
|
||||
current_directory = std::filesystem::current_path();
|
||||
|
||||
const auto make_test_dir = [](std::string_view suite,
|
||||
std::string_view sub) {
|
||||
return utils::path::combine(test::get_test_output_dir(),
|
||||
{std::string(suite), std::string(sub)});
|
||||
};
|
||||
|
||||
const auto make_cfg_dir = [](const std::string &root,
|
||||
std::string_view name) {
|
||||
auto cfg = utils::path::combine(root, {std::string(name)});
|
||||
ASSERT_TRUE(utils::file::directory(cfg).create_directory());
|
||||
return cfg;
|
||||
};
|
||||
|
||||
const auto configure_s3 = [](app_config &cfg_obj) {
|
||||
app_config src_cfg{
|
||||
provider_type::s3,
|
||||
utils::path::combine(test::get_test_config_dir(), {"s3"})};
|
||||
auto cfg = src_cfg.get_s3_config();
|
||||
cfg.force_legacy_encryption = provider_t::force_legacy_encryption;
|
||||
cfg.encryption_token = provider_t::encryption_token;
|
||||
|
||||
cfg_obj.set_enable_drive_events(true);
|
||||
cfg_obj.set_event_level(event_level::trace);
|
||||
cfg_obj.set_s3_config(cfg);
|
||||
|
||||
auto r = cfg_obj.get_remote_mount();
|
||||
r.enable = true;
|
||||
r.api_port = provider_t::remote_port;
|
||||
cfg_obj.set_remote_mount(r);
|
||||
};
|
||||
|
||||
const auto configure_sia = [](app_config &cfg_obj) {
|
||||
app_config src_cfg{
|
||||
provider_type::sia,
|
||||
utils::path::combine(test::get_test_config_dir(), {"sia"})};
|
||||
|
||||
cfg_obj.set_enable_drive_events(true);
|
||||
cfg_obj.set_event_level(event_level::trace);
|
||||
cfg_obj.set_host_config(src_cfg.get_host_config());
|
||||
cfg_obj.set_sia_config(src_cfg.get_sia_config());
|
||||
|
||||
auto r = cfg_obj.get_remote_mount();
|
||||
r.enable = true;
|
||||
r.api_port = provider_t::remote_port;
|
||||
cfg_obj.set_remote_mount(r);
|
||||
};
|
||||
|
||||
const auto mount_local_s3 = [&](bool as_remote) {
|
||||
const auto test_dir = make_test_dir(
|
||||
#if defined(_WIN32)
|
||||
"winfsp_test",
|
||||
#else // !defined(_WIN32)
|
||||
"fuse_test",
|
||||
#endif // defined(_WIN32)
|
||||
fmt::format("{}_{}", app_config::get_provider_name(current_provider),
|
||||
as_remote));
|
||||
#if defined(_WIN32)
|
||||
mount_location = utils::string::to_lower(std::string{"U:"});
|
||||
#else // !defined(_WIN32)
|
||||
mount_location = utils::path::combine(test_dir, {"mount"});
|
||||
ASSERT_TRUE(utils::file::directory(mount_location).create_directory());
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
auto cfg_dir = make_cfg_dir(test_dir, "cfg");
|
||||
auto cfg = std::make_unique<app_config>(provider_type::s3, cfg_dir);
|
||||
configure_s3(*cfg);
|
||||
|
||||
drive_args = {"-dd", cfg->get_data_directory(), "-s3", "-na", "s3"};
|
||||
|
||||
#if !defined(_WIN32)
|
||||
cfg->set_database_type(database_type::sqlite);
|
||||
config = std::move(cfg);
|
||||
meta = create_meta_db(*config);
|
||||
#endif // !defined(_WIN32)
|
||||
|
||||
platform_ops::execute_mount(drive_args, mount_location);
|
||||
};
|
||||
|
||||
const auto mount_local_sia = [&](bool as_remote) {
|
||||
const auto test_dir = make_test_dir(
|
||||
#if defined(_WIN32)
|
||||
"winfsp_test",
|
||||
#else // !defined(_WIN32)
|
||||
"fuse_test",
|
||||
#endif // defined(_WIN32)
|
||||
fmt::format("{}_{}", app_config::get_provider_name(current_provider),
|
||||
as_remote));
|
||||
#if defined(_WIN32)
|
||||
mount_location = utils::string::to_lower(std::string{"U:"});
|
||||
#else // !defined(_WIN32)
|
||||
mount_location = utils::path::combine(test_dir, {"mount"});
|
||||
ASSERT_TRUE(utils::file::directory(mount_location).create_directory());
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
auto cfg_dir = make_cfg_dir(test_dir, "cfg");
|
||||
auto cfg = std::make_unique<app_config>(provider_type::sia, cfg_dir);
|
||||
configure_sia(*cfg);
|
||||
|
||||
drive_args = {"-dd", cfg->get_data_directory(), "-na", "sia"};
|
||||
|
||||
#if !defined(_WIN32)
|
||||
cfg->set_database_type(database_type::sqlite);
|
||||
config = std::move(cfg);
|
||||
meta = create_meta_db(*config);
|
||||
#endif // !defined(_WIN32)
|
||||
|
||||
platform_ops::execute_mount(drive_args, mount_location);
|
||||
};
|
||||
|
||||
const auto mount_remote = [&] {
|
||||
const auto test_dir = make_test_dir(
|
||||
#if defined(_WIN32)
|
||||
"winfsp_test",
|
||||
#else // !defined(_WIN32)
|
||||
"fuse_test",
|
||||
#endif // defined(_WIN32)
|
||||
fmt::format("{}_{}_{}",
|
||||
app_config::get_provider_name(provider_t::type),
|
||||
app_config::get_provider_name(provider_t::type2),
|
||||
provider_t::remote_port));
|
||||
|
||||
mount_location2 = mount_location;
|
||||
|
||||
#if defined(_WIN32)
|
||||
mount_location = utils::string::to_lower(std::string{"V:"});
|
||||
#else // !defined(_WIN32)
|
||||
mount_location = utils::path::combine(test_dir, {"mount"});
|
||||
ASSERT_TRUE(utils::file::directory(mount_location).create_directory());
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
auto cfg_dir2 = make_cfg_dir(test_dir, "cfg2");
|
||||
auto cfg2 = std::make_unique<app_config>(provider_type::remote, cfg_dir2);
|
||||
cfg2->set_enable_drive_events(true);
|
||||
cfg2->set_event_level(event_level::trace);
|
||||
#if !defined(_WIN32)
|
||||
cfg2->set_database_type(database_type::sqlite);
|
||||
#endif // !defined(_WIN32)
|
||||
|
||||
drive_args2 = {"-dd", cfg2->get_data_directory(), "-rm",
|
||||
fmt::format("localhost:{}", provider_t::remote_port)};
|
||||
|
||||
platform_ops::execute_mount(drive_args2, mount_location);
|
||||
};
|
||||
|
||||
switch (provider_t::type) {
|
||||
case provider_type::s3: {
|
||||
mount_local_s3(false);
|
||||
} break;
|
||||
case provider_type::sia: {
|
||||
mount_local_sia(false);
|
||||
} break;
|
||||
case provider_type::remote: {
|
||||
switch (provider_t::type2) {
|
||||
case provider_type::s3:
|
||||
mount_local_s3(true);
|
||||
break;
|
||||
case provider_type::sia:
|
||||
mount_local_sia(true);
|
||||
break;
|
||||
case provider_type::unknown:
|
||||
mount_remote();
|
||||
return;
|
||||
default:
|
||||
throw std::runtime_error("remote provider type is not implemented");
|
||||
}
|
||||
mount_remote();
|
||||
} break;
|
||||
default:
|
||||
throw std::runtime_error("provider type is not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
static void TearDownTestCase() {
|
||||
if (provider_t::type == provider_type::remote) {
|
||||
platform_ops::execute_unmount(drive_args2, mount_location);
|
||||
if (provider_t::type2 != provider_type::unknown) {
|
||||
platform_ops::execute_unmount(drive_args, mount_location2);
|
||||
}
|
||||
} else {
|
||||
platform_ops::execute_unmount(drive_args, mount_location);
|
||||
}
|
||||
|
||||
#if !defined(_WIN32)
|
||||
meta.reset();
|
||||
config.reset();
|
||||
#endif // !defined(_WIN32)
|
||||
std::filesystem::current_path(current_directory);
|
||||
}
|
||||
|
||||
#if !defined(_WIN32)
|
||||
public:
|
||||
static auto create_file_path(std::string &file_name) {
|
||||
file_name += std::to_string(++provider_idx);
|
||||
return utils::path::combine(mount_location, {file_name});
|
||||
}
|
||||
|
||||
static auto create_file_and_test(std::string &file_name, mode_t perms)
|
||||
-> std::string {
|
||||
file_name += std::to_string(++provider_idx);
|
||||
auto file_path = utils::path::combine(mount_location, {file_name});
|
||||
|
||||
auto handle = open(file_path.c_str(), O_CREAT | O_EXCL | O_RDWR, perms);
|
||||
EXPECT_LE(1, handle);
|
||||
|
||||
auto opt_size = utils::file::file{file_path}.size();
|
||||
EXPECT_TRUE(opt_size.has_value());
|
||||
if (opt_size.has_value()) {
|
||||
EXPECT_EQ(0U, opt_size.value());
|
||||
}
|
||||
|
||||
EXPECT_EQ(0, close(handle));
|
||||
|
||||
EXPECT_TRUE(utils::file::file(file_path).exists());
|
||||
EXPECT_FALSE(utils::file::directory(file_path).exists());
|
||||
|
||||
struct stat64 u_stat{};
|
||||
EXPECT_EQ(0, stat64(file_path.c_str(), &u_stat));
|
||||
EXPECT_EQ(getgid(), u_stat.st_gid);
|
||||
EXPECT_EQ(getuid(), u_stat.st_uid);
|
||||
|
||||
return file_path;
|
||||
}
|
||||
|
||||
static auto create_file_and_test(std::string &file_name) -> std::string {
|
||||
return create_file_and_test(file_name, ACCESSPERMS);
|
||||
}
|
||||
|
||||
static auto create_directory_and_test(std::string &dir_name, mode_t perms)
|
||||
-> std::string {
|
||||
dir_name += std::to_string(++provider_idx);
|
||||
|
||||
auto dir_path = utils::path::combine(mount_location, {dir_name});
|
||||
mkdir(dir_path.c_str(), perms);
|
||||
|
||||
EXPECT_TRUE(utils::file::directory(dir_path).exists());
|
||||
EXPECT_EQ(0U, utils::file::directory(dir_path).count(false));
|
||||
EXPECT_EQ(0U, utils::file::directory(dir_path).count(true));
|
||||
EXPECT_FALSE(utils::file::file(dir_path).exists());
|
||||
|
||||
struct stat64 u_stat{};
|
||||
EXPECT_EQ(0, stat64(dir_path.c_str(), &u_stat));
|
||||
EXPECT_EQ(getgid(), u_stat.st_gid);
|
||||
EXPECT_EQ(getuid(), u_stat.st_uid);
|
||||
|
||||
return dir_path;
|
||||
}
|
||||
|
||||
static auto create_directory_and_test(std::string &dir_name) -> std::string {
|
||||
return create_directory_and_test(dir_name, ACCESSPERMS);
|
||||
}
|
||||
|
||||
static auto create_root_file(std::string &file_name) -> std::string {
|
||||
auto file_path = create_file_and_test(file_name);
|
||||
auto api_path = utils::path::create_api_path(file_name);
|
||||
|
||||
[[maybe_unused]] auto res =
|
||||
meta->set_item_meta(api_path, {{META_UID, "0"}, {META_GID, "0"}});
|
||||
std::this_thread::sleep_for(SLEEP_SECONDS);
|
||||
|
||||
return file_path;
|
||||
}
|
||||
|
||||
static void rmdir_and_test(std::string_view dir_path) {
|
||||
EXPECT_TRUE(utils::file::directory(dir_path).remove());
|
||||
EXPECT_FALSE(utils::file::directory(dir_path).exists());
|
||||
EXPECT_FALSE(utils::file::file(dir_path).exists());
|
||||
}
|
||||
|
||||
static void unlink_file_and_test(std::string_view file_path) {
|
||||
EXPECT_TRUE(utils::file::file(file_path).remove());
|
||||
EXPECT_FALSE(utils::file::file(file_path).exists());
|
||||
EXPECT_FALSE(utils::file::directory(file_path).exists());
|
||||
}
|
||||
|
||||
static void unlink_root_file(const std::string &file_path) {
|
||||
auto api_path = utils::path::create_api_path(
|
||||
utils::path::strip_to_file_name(file_path));
|
||||
|
||||
[[maybe_unused]] auto res =
|
||||
meta->set_item_meta(api_path, {{META_UID, std::to_string(getuid())},
|
||||
{ META_GID,
|
||||
std::to_string(getgid()) }});
|
||||
std::this_thread::sleep_for(SLEEP_SECONDS);
|
||||
|
||||
unlink_file_and_test(file_path);
|
||||
}
|
||||
#endif // !defined(_WIN32)
|
||||
};
|
||||
|
||||
#if !defined(_WIN32)
|
||||
template <typename provider_t>
|
||||
std::unique_ptr<app_config> drive_fixture<provider_t>::config;
|
||||
template <typename provider_t>
|
||||
std::unique_ptr<i_meta_db> drive_fixture<provider_t>::meta{};
|
||||
#endif // !defined(_WIN32)
|
||||
|
||||
template <typename provider_t>
|
||||
std::filesystem::path drive_fixture<provider_t>::current_directory;
|
||||
template <typename provider_t>
|
||||
provider_type drive_fixture<provider_t>::current_provider{provider_t::type2};
|
||||
template <typename provider_t>
|
||||
std::vector<std::string> drive_fixture<provider_t>::drive_args;
|
||||
template <typename provider_t>
|
||||
std::vector<std::string> drive_fixture<provider_t>::drive_args2;
|
||||
template <typename provider_t>
|
||||
std::string drive_fixture<provider_t>::mount_location;
|
||||
template <typename provider_t>
|
||||
std::string drive_fixture<provider_t>::mount_location2;
|
||||
|
||||
using platform_provider_types =
|
||||
::testing::Types<local_s3_no_encryption, local_s3_encryption,
|
||||
local_s3_legacy_encryption, remote_s3_no_encryption,
|
||||
remote_s3_encryption, remote_s3_legacy_encryption,
|
||||
local_sia, remote_sia>;
|
||||
#if defined(_WIN32)
|
||||
using winfsp_test = drive_fixture;
|
||||
#else
|
||||
using fuse_test = drive_fixture;
|
||||
#endif
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_TEST_INCLUDE_FIXTURES_PLATFORM_FIXTURE_HPP
|
@@ -60,12 +60,7 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||
return;
|
||||
}
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Invalid username or password'),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
displayErrorMessage(context, 'Invalid username or password', clear: true);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
|
@@ -116,6 +116,7 @@ class AppDropdownFormField<T> extends StatelessWidget {
|
||||
decoration: createCommonDecoration(
|
||||
scheme,
|
||||
labelText ?? "",
|
||||
filled: true,
|
||||
icon: prefixIcon,
|
||||
),
|
||||
dropdownColor: dropdownColor ?? effectiveFill,
|
||||
|
Reference in New Issue
Block a user