blob: 58df55c0fa0b9b06de9f8e6941f9358e26aa0cf2 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "peridot/lib/firebase_auth/firebase_auth_impl.h"
#include <utility>
#include <fuchsia/auth/cpp/fidl.h>
#include <lib/backoff/testing/test_backoff.h>
#include <lib/callback/capture.h>
#include <lib/callback/set_when_called.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fxl/functional/make_copyable.h>
#include <lib/gtest/test_loop_fixture.h>
#include "peridot/lib/firebase_auth/testing/test_token_manager.h"
namespace firebase_auth {
namespace {
class MockCobaltLogger : public cobalt::CobaltLogger {
public:
~MockCobaltLogger() override = default;
MockCobaltLogger(int* called) : called_(called) {}
void LogEvent(uint32_t metric_id, uint32_t event_code) override {}
void LogEventCount(uint32_t metric_id, uint32_t event_code,
const std::string& component, zx::duration period_duration,
int64_t count) override {
EXPECT_EQ(4u, metric_id);
// The value should contain the client name.
EXPECT_TRUE(component.find("firebase-test") != std::string::npos);
*called_ += 1;
}
void LogElapsedTime(uint32_t metric_id, uint32_t event_code,
const std::string& component,
zx::duration elapsed_time) override {}
void LogFrameRate(uint32_t metric_id, uint32_t event_code,
const std::string& component, float fps) override {}
void LogMemoryUsage(uint32_t metric_id, uint32_t event_code,
const std::string& component, int64_t bytes) override {}
void LogString(uint32_t metric_id, const std::string& s) override {}
void StartTimer(uint32_t metric_id, uint32_t event_code,
const std::string& component, const std::string& timer_id,
zx::time timestamp, zx::duration timeout) override {}
void EndTimer(const std::string& timer_id, zx::time timestamp,
zx::duration timeout) override {}
void LogIntHistogram(
uint32_t metric_id, uint32_t event_code, const std::string& component,
std::vector<fuchsia::cobalt::HistogramBucket> histogram) override {}
void LogCustomEvent(
uint32_t metric_id,
std::vector<fuchsia::cobalt::CustomEventValue> event_values) override {}
private:
int* called_;
};
class FirebaseAuthImplTest : public gtest::TestLoopFixture {
public:
FirebaseAuthImplTest()
: token_manager_(dispatcher()),
token_manager_binding_(&token_manager_),
firebase_auth_(
{"api_key", "firebase-test", 1}, dispatcher(),
token_manager_binding_.NewBinding().Bind(), InitBackoff(),
std::make_unique<MockCobaltLogger>(&report_observation_count_)) {}
~FirebaseAuthImplTest() override {}
protected:
std::unique_ptr<backoff::Backoff> InitBackoff() {
// TODO(LE-630): Don't use a backoff duration of 0.
auto backoff = std::make_unique<backoff::TestBackoff>(zx::sec(0));
backoff_ = backoff.get();
return backoff;
}
TestTokenManager token_manager_;
fidl::Binding<fuchsia::auth::TokenManager> token_manager_binding_;
FirebaseAuthImpl firebase_auth_;
int report_observation_count_ = 0;
backoff::TestBackoff* backoff_;
private:
FXL_DISALLOW_COPY_AND_ASSIGN(FirebaseAuthImplTest);
};
TEST_F(FirebaseAuthImplTest, GetFirebaseToken) {
token_manager_.Set("this is a token", "some id", "me@example.com");
bool called;
AuthStatus auth_status;
std::string firebase_token;
firebase_auth_.GetFirebaseToken(callback::Capture(
callback::SetWhenCalled(&called), &auth_status, &firebase_token));
RunLoopUntilIdle();
EXPECT_TRUE(called);
EXPECT_EQ(AuthStatus::OK, auth_status);
EXPECT_EQ("this is a token", firebase_token);
EXPECT_EQ(0, report_observation_count_);
}
TEST_F(FirebaseAuthImplTest, GetFirebaseTokenRetryOnError) {
bool called;
AuthStatus auth_status;
std::string firebase_token;
token_manager_.SetError(fuchsia::auth::Status::NETWORK_ERROR);
backoff_->SetOnGetNext(QuitLoopClosure());
firebase_auth_.GetFirebaseToken(callback::Capture(
callback::SetWhenCalled(&called), &auth_status, &firebase_token));
RunLoopUntilIdle();
EXPECT_FALSE(called);
EXPECT_EQ(1, backoff_->get_next_count);
EXPECT_EQ(0, backoff_->reset_count);
EXPECT_EQ(0, report_observation_count_);
token_manager_.Set("this is a token", "some id", "me@example.com");
RunLoopUntilIdle();
EXPECT_TRUE(called);
EXPECT_EQ(AuthStatus::OK, auth_status);
EXPECT_EQ("this is a token", firebase_token);
EXPECT_EQ(1, backoff_->get_next_count);
EXPECT_EQ(1, backoff_->reset_count);
EXPECT_EQ(0, report_observation_count_);
}
TEST_F(FirebaseAuthImplTest, GetFirebaseUserId) {
token_manager_.Set("this is a token", "some id", "me@example.com");
bool called;
AuthStatus auth_status;
std::string firebase_user_id;
firebase_auth_.GetFirebaseUserId(callback::Capture(
callback::SetWhenCalled(&called), &auth_status, &firebase_user_id));
RunLoopUntilIdle();
EXPECT_TRUE(called);
EXPECT_EQ(AuthStatus::OK, auth_status);
EXPECT_EQ("some id", firebase_user_id);
EXPECT_EQ(0, report_observation_count_);
}
TEST_F(FirebaseAuthImplTest, GetFirebaseUserIdRetryOnError) {
bool called;
AuthStatus auth_status;
std::string firebase_id;
token_manager_.SetError(fuchsia::auth::Status::NETWORK_ERROR);
backoff_->SetOnGetNext(QuitLoopClosure());
firebase_auth_.GetFirebaseUserId(callback::Capture(
callback::SetWhenCalled(&called), &auth_status, &firebase_id));
RunLoopUntilIdle();
EXPECT_FALSE(called);
EXPECT_EQ(1, backoff_->get_next_count);
EXPECT_EQ(0, backoff_->reset_count);
EXPECT_EQ(0, report_observation_count_);
token_manager_.Set("this is a token", "some id", "me@example.com");
RunLoopUntilIdle();
EXPECT_TRUE(called);
EXPECT_EQ(AuthStatus::OK, auth_status);
EXPECT_EQ("some id", firebase_id);
EXPECT_EQ(1, backoff_->get_next_count);
EXPECT_EQ(1, backoff_->reset_count);
EXPECT_EQ(0, report_observation_count_);
}
TEST_F(FirebaseAuthImplTest, GetFirebaseUserIdMaxRetry) {
bool called;
AuthStatus auth_status;
token_manager_.SetError(fuchsia::auth::Status::NETWORK_ERROR);
backoff_->SetOnGetNext(QuitLoopClosure());
firebase_auth_.GetFirebaseUserId(callback::Capture(
callback::SetWhenCalled(&called), &auth_status, &std::ignore));
RunLoopUntilIdle();
EXPECT_FALSE(called);
EXPECT_EQ(1, backoff_->get_next_count);
EXPECT_EQ(0, backoff_->reset_count);
EXPECT_EQ(0, report_observation_count_);
// Exceeding the maximum number of retriable errors returns an error.
token_manager_.SetError(fuchsia::auth::Status::INTERNAL_ERROR);
RunLoopUntilIdle();
EXPECT_TRUE(called);
EXPECT_EQ(AuthStatus::ERROR, auth_status);
EXPECT_EQ(1, backoff_->get_next_count);
EXPECT_EQ(1, backoff_->reset_count);
EXPECT_EQ(1, report_observation_count_);
}
TEST_F(FirebaseAuthImplTest, GetFirebaseUserIdNonRetriableError) {
bool called;
AuthStatus auth_status;
token_manager_.SetError(fuchsia::auth::Status::INVALID_REQUEST);
backoff_->SetOnGetNext(QuitLoopClosure());
firebase_auth_.GetFirebaseUserId(callback::Capture(
callback::SetWhenCalled(&called), &auth_status, &std::ignore));
RunLoopUntilIdle();
EXPECT_TRUE(called);
EXPECT_EQ(AuthStatus::ERROR, auth_status);
EXPECT_EQ(0, backoff_->get_next_count);
EXPECT_EQ(1, backoff_->reset_count);
EXPECT_EQ(1, report_observation_count_);
}
} // namespace
} // namespace firebase_auth