blob: b155e64f042ed6ce55b4deb46c8872eaad59510f [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/signaling/ftl_registration_manager.h"
#include "base/memory/raw_ptr.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "base/uuid.h"
#include "remoting/base/fake_oauth_token_getter.h"
#include "remoting/base/protobuf_http_status.h"
#include "remoting/proto/ftl/v1/ftl_messages.pb.h"
#include "remoting/signaling/ftl_client_uuid_device_id_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace remoting {
namespace {
using testing::_;
using SignInGaiaResponseCallback =
base::OnceCallback<void(const ProtobufHttpStatus&,
std::unique_ptr<ftl::SignInGaiaResponse>)>;
constexpr char kAuthToken[] = "auth_token";
constexpr int64_t kAuthTokenExpiresInMicroseconds = 86400000000; // = 1 day
constexpr base::TimeDelta kAuthTokenExpiration =
base::Microseconds(kAuthTokenExpiresInMicroseconds);
MATCHER_P(HasErrorCode, error_code, "") {
return arg.error_code() == error_code;
}
MATCHER(IsStatusOk, "") {
return arg.ok();
}
void VerifySignInGaiaRequest(const ftl::SignInGaiaRequest& request) {
ASSERT_EQ(ftl::SignInGaiaMode_Value_DEFAULT_CREATE_ACCOUNT, request.mode());
ASSERT_TRUE(
base::Uuid::ParseCaseInsensitive(request.register_data().device_id().id())
.is_valid());
ASSERT_LT(0, request.register_data().caps_size());
}
decltype(auto) RespondOkToSignInGaia(const std::string& registration_id) {
return [registration_id](const ftl::SignInGaiaRequest& request,
SignInGaiaResponseCallback on_done) {
VerifySignInGaiaRequest(request);
auto response = std::make_unique<ftl::SignInGaiaResponse>();
response->set_registration_id(registration_id);
response->mutable_auth_token()->set_payload(kAuthToken);
response->mutable_auth_token()->set_expires_in(
kAuthTokenExpiresInMicroseconds);
std::move(on_done).Run(ProtobufHttpStatus::OK(), std::move(response));
};
}
} // namespace
class FtlRegistrationManagerTest : public testing::Test {
protected:
class MockRegistrationClient
: public FtlRegistrationManager::RegistrationClient {
public:
MOCK_METHOD2(SignInGaia,
void(const ftl::SignInGaiaRequest&,
SignInGaiaResponseCallback));
MOCK_METHOD0(CancelPendingRequests, void());
};
const net::BackoffEntry& GetBackoff() const {
return registration_manager_.sign_in_backoff_;
}
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
FtlRegistrationManager registration_manager_{
std::make_unique<MockRegistrationClient>(),
std::make_unique<FtlClientUuidDeviceIdProvider>()};
raw_ptr<MockRegistrationClient> registration_client_ =
static_cast<MockRegistrationClient*>(
registration_manager_.registration_client_.get());
base::MockCallback<base::RepeatingCallback<void(const ProtobufHttpStatus&)>>
done_callback_;
};
TEST_F(FtlRegistrationManagerTest, SignInGaiaAndAutorefresh) {
ASSERT_FALSE(registration_manager_.IsSignedIn());
ASSERT_TRUE(registration_manager_.GetRegistrationId().empty());
ASSERT_TRUE(registration_manager_.GetFtlAuthToken().empty());
EXPECT_CALL(*registration_client_, SignInGaia(_, _))
.WillOnce(RespondOkToSignInGaia("registration_id_1"))
.WillOnce(RespondOkToSignInGaia("registration_id_2"));
EXPECT_CALL(done_callback_, Run(IsStatusOk())).Times(1);
registration_manager_.SignInGaia(done_callback_.Get());
task_environment_.FastForwardBy(GetBackoff().GetTimeUntilRelease());
ASSERT_TRUE(registration_manager_.IsSignedIn());
ASSERT_EQ("registration_id_1", registration_manager_.GetRegistrationId());
ASSERT_EQ(kAuthToken, registration_manager_.GetFtlAuthToken());
task_environment_.FastForwardBy(kAuthTokenExpiration);
task_environment_.FastForwardBy(GetBackoff().GetTimeUntilRelease());
ASSERT_EQ("registration_id_2", registration_manager_.GetRegistrationId());
}
TEST_F(FtlRegistrationManagerTest, FailedToSignIn_Backoff) {
ASSERT_FALSE(registration_manager_.IsSignedIn());
ASSERT_TRUE(registration_manager_.GetRegistrationId().empty());
ASSERT_TRUE(registration_manager_.GetFtlAuthToken().empty());
ASSERT_EQ(0, GetBackoff().failure_count());
EXPECT_CALL(*registration_client_, SignInGaia(_, _))
.WillOnce([](const ftl::SignInGaiaRequest& request,
SignInGaiaResponseCallback on_done) {
VerifySignInGaiaRequest(request);
std::move(on_done).Run(
ProtobufHttpStatus(ProtobufHttpStatus::Code::UNAVAILABLE,
"unavailable"),
{});
})
.WillOnce([](const ftl::SignInGaiaRequest& request,
SignInGaiaResponseCallback on_done) {
VerifySignInGaiaRequest(request);
std::move(on_done).Run(
ProtobufHttpStatus(ProtobufHttpStatus::Code::UNAUTHENTICATED,
"unauthenticated"),
{});
})
.WillOnce(RespondOkToSignInGaia("registration_id"));
EXPECT_CALL(done_callback_,
Run(HasErrorCode(ProtobufHttpStatus::Code::UNAVAILABLE)))
.Times(1);
registration_manager_.SignInGaia(done_callback_.Get());
task_environment_.FastForwardBy(GetBackoff().GetTimeUntilRelease());
ASSERT_FALSE(registration_manager_.IsSignedIn());
ASSERT_EQ(1, GetBackoff().failure_count());
EXPECT_CALL(done_callback_,
Run(HasErrorCode(ProtobufHttpStatus::Code::UNAUTHENTICATED)))
.Times(1);
registration_manager_.SignInGaia(done_callback_.Get());
task_environment_.FastForwardBy(GetBackoff().GetTimeUntilRelease());
ASSERT_FALSE(registration_manager_.IsSignedIn());
ASSERT_EQ(2, GetBackoff().failure_count());
EXPECT_CALL(done_callback_, Run(IsStatusOk())).Times(1);
registration_manager_.SignInGaia(done_callback_.Get());
task_environment_.FastForwardBy(GetBackoff().GetTimeUntilRelease());
ASSERT_TRUE(registration_manager_.IsSignedIn());
ASSERT_EQ("registration_id", registration_manager_.GetRegistrationId());
ASSERT_EQ(0, GetBackoff().failure_count());
}
TEST_F(FtlRegistrationManagerTest, SignOut) {
ASSERT_FALSE(registration_manager_.IsSignedIn());
ASSERT_TRUE(registration_manager_.GetRegistrationId().empty());
ASSERT_TRUE(registration_manager_.GetFtlAuthToken().empty());
EXPECT_CALL(*registration_client_, SignInGaia(_, _))
.WillOnce(RespondOkToSignInGaia("registration_id"));
EXPECT_CALL(done_callback_, Run(IsStatusOk())).Times(1);
registration_manager_.SignInGaia(done_callback_.Get());
task_environment_.FastForwardBy(GetBackoff().GetTimeUntilRelease());
ASSERT_TRUE(registration_manager_.IsSignedIn());
ASSERT_EQ("registration_id", registration_manager_.GetRegistrationId());
ASSERT_EQ(kAuthToken, registration_manager_.GetFtlAuthToken());
EXPECT_CALL(*registration_client_, CancelPendingRequests()).Times(1);
registration_manager_.SignOut();
ASSERT_FALSE(registration_manager_.IsSignedIn());
ASSERT_TRUE(registration_manager_.GetRegistrationId().empty());
ASSERT_TRUE(registration_manager_.GetFtlAuthToken().empty());
task_environment_.FastForwardUntilNoTasksRemain();
ASSERT_FALSE(registration_manager_.IsSignedIn());
}
} // namespace remoting