| // 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 |