blob: 2d3a9b0611f6eb61bf19905ee2645c0f716a0149 [file] [log] [blame] [edit]
#include "remote_credentials.h"
#include <array>
#include "gmock.h"
#include "gunit.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
namespace milotic {
namespace {
using ::testing::_;
using ::testing::Field;
using ::testing::InSequence;
using ::testing::MockFunction;
using ::testing::Return;
using ::testing::StrictMock;
using ::testing::status::IsOkAndHolds;
using ::testing::status::StatusIs;
struct TestManager {
public:
TestManager()
: reader(mock_reader.AsStdFunction()),
writer(mock_writer.AsStdFunction()),
manager(reader, writer) {}
StrictMock<MockFunction<CredentialsFileReader>> mock_reader;
StrictMock<MockFunction<CredentialsFileWriter>> mock_writer;
private:
CredentialsFileReader reader;
CredentialsFileWriter writer;
public:
CredentialsFileManager manager;
};
TEST(CredentialsFileManagerTest, FilesAreTriedInSequenceOnReadError) {
TestManager test_manager;
auto source_files = std::to_array({"file1", "file2"});
test_manager.manager.AddSourceFiles(source_files.begin(), source_files.end());
test_manager.manager.SetPrivateCachePath("cache/file");
InSequence seq;
EXPECT_CALL(test_manager.mock_reader, Call("cache/file", "endpoint"))
.WillOnce(Return(absl::InternalError("test error1")));
EXPECT_CALL(test_manager.mock_reader, Call("file1", "endpoint"))
.WillOnce(Return(absl::InternalError("test error2")));
EXPECT_CALL(test_manager.mock_reader, Call("file2", "endpoint"))
.WillOnce(Return(absl::InternalError("test error3")));
EXPECT_THAT(test_manager.manager.RunLogin(
"endpoint",
[](const absl::StatusOr<RemoteCredentials>& c) {
return c.status();
}),
StatusIs(absl::StatusCode::kInternal, "test error3"));
}
TEST(CredentialsFileManagerTest, FilesAreTriedInSequenceOnLoginError) {
TestManager test_manager;
auto source_files = std::to_array({"file1", "file2"});
test_manager.manager.AddSourceFiles(source_files.begin(), source_files.end());
test_manager.manager.SetPrivateCachePath("cache/file");
MockFunction<LoginFunction> mock_login_function;
InSequence seq;
EXPECT_CALL(test_manager.mock_reader, Call("cache/file", "endpoint"))
.WillOnce(Return(RemoteCredentials{.password = "test_password1"}));
EXPECT_CALL(mock_login_function,
Call(IsOkAndHolds(Field("password", &RemoteCredentials::password,
"test_password1"))))
.WillOnce(Return(absl::UnauthenticatedError("test error1")));
EXPECT_CALL(test_manager.mock_reader, Call("file1", "endpoint"))
.WillOnce(Return(RemoteCredentials{.password = "test_password2"}));
EXPECT_CALL(mock_login_function,
Call(IsOkAndHolds(Field("password", &RemoteCredentials::password,
"test_password2"))))
.WillOnce(Return(absl::UnauthenticatedError("test error2")));
EXPECT_CALL(test_manager.mock_reader, Call("file2", "endpoint"))
.WillOnce(Return(RemoteCredentials{.password = "test_password3"}));
EXPECT_CALL(mock_login_function,
Call(IsOkAndHolds(Field("password", &RemoteCredentials::password,
"test_password3"))))
.WillOnce(Return(absl::UnauthenticatedError("test error3")));
EXPECT_THAT(test_manager.manager.RunLogin(
"endpoint", mock_login_function.AsStdFunction()),
StatusIs(absl::StatusCode::kUnauthenticated, "test error3"));
}
TEST(CredentialsFileManagerTest, FirstSuccessIsUsed) {
TestManager test_manager;
auto source_files = std::to_array({"file1", "file2", "file3"});
test_manager.manager.AddSourceFiles(source_files.begin(), source_files.end());
EXPECT_CALL(test_manager.mock_reader, Call("file1", _))
.WillOnce(Return(absl::InternalError("test error1")));
EXPECT_CALL(test_manager.mock_reader, Call("file2", _))
.WillOnce(Return(RemoteCredentials{.password = "test_password"}));
EXPECT_CALL(test_manager.mock_reader, Call("file3", _)).Times(0);
MockFunction<LoginFunction> mock_login_function;
EXPECT_CALL(mock_login_function,
Call(IsOkAndHolds(Field("password", &RemoteCredentials::password,
"test_password"))))
.WillOnce(Return(absl::OkStatus()));
EXPECT_OK(test_manager.manager.RunLogin("endpoint",
mock_login_function.AsStdFunction()));
}
TEST(CredentialsFileManagerTest, WorkingCredentialsAreCached) {
TestManager test_manager;
auto source_files = std::to_array({"file1"});
test_manager.manager.AddSourceFiles(source_files.begin(), source_files.end());
test_manager.manager.SetPrivateCachePath("cache/file");
EXPECT_CALL(test_manager.mock_reader, Call("cache/file", _))
.WillOnce(Return(absl::NotFoundError("no cache")));
EXPECT_CALL(test_manager.mock_reader, Call("file1", _))
.WillOnce(Return(RemoteCredentials{.password = "test_password"}));
EXPECT_CALL(
test_manager.mock_writer,
Call("cache/file", "file1",
Field("password", &RemoteCredentials::password, "test_password"), _))
.WillOnce(Return(absl::OkStatus()));
MockFunction<LoginFunction> mock_login_function;
EXPECT_CALL(mock_login_function,
Call(IsOkAndHolds(Field("password", &RemoteCredentials::password,
"test_password"))))
.WillOnce(Return(absl::OkStatus()));
EXPECT_OK(test_manager.manager.RunLogin("endpoint",
mock_login_function.AsStdFunction()));
}
TEST(CredentialsFileManagerTest, CachedCredentialsAreNotRewritten) {
TestManager test_manager;
auto source_files = std::to_array({"file1"});
test_manager.manager.AddSourceFiles(source_files.begin(), source_files.end());
test_manager.manager.SetPrivateCachePath("cache/file");
EXPECT_CALL(test_manager.mock_reader, Call("cache/file", _))
.WillOnce(Return(RemoteCredentials{.password = "test_password"}));
EXPECT_CALL(test_manager.mock_reader, Call("file1", _)).Times(0);
EXPECT_CALL(test_manager.mock_writer, Call).Times(0);
MockFunction<LoginFunction> mock_login_function;
EXPECT_CALL(mock_login_function,
Call(IsOkAndHolds(Field("password", &RemoteCredentials::password,
"test_password"))))
.WillOnce(Return(absl::OkStatus()));
EXPECT_OK(test_manager.manager.RunLogin("endpoint",
mock_login_function.AsStdFunction()));
}
TEST(CredentialsFileManagerTest, WorkingCredentialsAreReadOnce) {
TestManager test_manager;
auto source_files = std::to_array({"file1"});
test_manager.manager.AddSourceFiles(source_files.begin(), source_files.end());
test_manager.manager.SetPrivateCachePath("cache/file");
EXPECT_CALL(test_manager.mock_reader, Call("cache/file", _))
.WillOnce(Return(RemoteCredentials{.password = "test_password"}));
MockFunction<LoginFunction> mock_login_function;
EXPECT_CALL(mock_login_function,
Call(IsOkAndHolds(Field("password", &RemoteCredentials::password,
"test_password"))))
.Times(2)
.WillRepeatedly(Return(absl::OkStatus()));
EXPECT_OK(test_manager.manager.RunLogin("endpoint",
mock_login_function.AsStdFunction()));
EXPECT_OK(test_manager.manager.RunLogin("endpoint",
mock_login_function.AsStdFunction()));
}
TEST(CredentialsFileManagerTest, CredentialsAreRefreshedIfTheyStopWorking) {
TestManager test_manager;
auto source_files = std::to_array({"file1", "file2"});
test_manager.manager.AddSourceFiles(source_files.begin(), source_files.end());
test_manager.manager.SetPrivateCachePath("cache/file");
EXPECT_CALL(test_manager.mock_reader, Call("cache/file", _))
.WillOnce(Return(absl::NotFoundError("no cache")));
EXPECT_CALL(test_manager.mock_reader, Call("file1", _))
.Times(2)
.WillRepeatedly(Return(RemoteCredentials{.password = "test_password1"}));
EXPECT_CALL(test_manager.mock_reader, Call("file2", _))
.WillOnce(Return(RemoteCredentials{.password = "test_password2"}));
EXPECT_CALL(
test_manager.mock_writer,
Call("cache/file", "file1",
Field("password", &RemoteCredentials::password, "test_password1"),
_))
.WillOnce(Return(absl::OkStatus()));
EXPECT_CALL(
test_manager.mock_writer,
Call("cache/file", "file2",
Field("password", &RemoteCredentials::password, "test_password2"),
_))
.WillOnce(Return(absl::OkStatus()));
MockFunction<LoginFunction> mock_login_function;
EXPECT_CALL(mock_login_function,
Call(IsOkAndHolds(Field("password", &RemoteCredentials::password,
"test_password1"))))
.WillOnce(Return(absl::OkStatus()))
.WillRepeatedly(Return(absl::UnauthenticatedError("test error1")));
EXPECT_CALL(mock_login_function,
Call(IsOkAndHolds(Field("password", &RemoteCredentials::password,
"test_password2"))))
.WillOnce(Return(absl::OkStatus()));
EXPECT_OK(test_manager.manager.RunLogin("endpoint",
mock_login_function.AsStdFunction()));
EXPECT_OK(test_manager.manager.RunLogin("endpoint",
mock_login_function.AsStdFunction()));
}
} // namespace
} // namespace milotic