chromium/ash/in_session_auth/webauthn_dialog_controller_impl_unittest.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/in_session_auth/webauthn_dialog_controller_impl.h"

#include <memory>
#include <string>
#include <utility>

#include "ash/in_session_auth/mock_in_session_auth_dialog_client.h"
#include "ash/public/cpp/webauthn_dialog_controller.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "base/functional/callback.h"
#include "base/test/bind.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;

namespace ash {
namespace {

using WebAuthNDialogControllerImplTest = AshTestBase;

TEST_F(WebAuthNDialogControllerImplTest, PinAuthSuccess) {
  WebAuthNDialogController* controller =
      Shell::Get()->webauthn_dialog_controller();
  auto client = std::make_unique<MockInSessionAuthDialogClient>();

  std::string pin = "123456";

  EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin(
                           pin, /* authenticated_by_pin = */ true, _))
      .WillOnce([](const std::string& pin, bool authenticated_by_pin,
                   base::OnceCallback<void(bool success)> controller_callback) {
        std::move(controller_callback).Run(true);
      });

  bool result_success = false;
  controller->AuthenticateUserWithPasswordOrPin(
      pin,
      /*authenticated_by_password=*/true,
      /* View callback will be executed during controller callback. */
      base::BindLambdaForTesting(
          [&result_success](bool success, bool can_use_pin) {
            result_success = success;
          }));

  EXPECT_TRUE(result_success);
}

TEST_F(WebAuthNDialogControllerImplTest, PinAuthFail) {
  WebAuthNDialogController* controller =
      Shell::Get()->webauthn_dialog_controller();
  auto client = std::make_unique<MockInSessionAuthDialogClient>();

  std::string pin = "123456";

  EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin(
                           pin, /* authenticated_by_pin = */ true, _))
      .WillOnce([](const std::string& pin, bool authenticated_by_pin,
                   base::OnceCallback<void(bool success)> controller_callback) {
        std::move(controller_callback).Run(false);
      });
  EXPECT_CALL(*client, CheckPinAuthAvailability(_, _))
      .WillOnce([](const AccountId& account_id,
                   base::OnceCallback<void(bool success)> controller_callback) {
        std::move(controller_callback).Run(true);
      });

  bool result_success = false;
  bool result_can_use_pin = false;
  controller->AuthenticateUserWithPasswordOrPin(
      pin,
      /*authenticated_by_password=*/true,
      /* View callback will be executed during controller callback. */
      base::BindLambdaForTesting([&result_success, &result_can_use_pin](
                                     bool success, bool can_use_pin) {
        result_success = success;
        result_can_use_pin = can_use_pin;
      }));

  EXPECT_FALSE(result_success);
  EXPECT_TRUE(result_can_use_pin);
}

TEST_F(WebAuthNDialogControllerImplTest, PinAuthFailLockout) {
  WebAuthNDialogController* controller =
      Shell::Get()->webauthn_dialog_controller();
  auto client = std::make_unique<MockInSessionAuthDialogClient>();

  std::string pin = "123456";

  EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin(
                           pin, /* authenticated_by_pin = */ true, _))
      .WillOnce([](const std::string& pin, bool authenticated_by_pin,
                   base::OnceCallback<void(bool success)> controller_callback) {
        std::move(controller_callback).Run(false);
      });
  EXPECT_CALL(*client, CheckPinAuthAvailability(_, _))
      .WillOnce([](const AccountId& account_id,
                   base::OnceCallback<void(bool success)> controller_callback) {
        std::move(controller_callback).Run(false);
      });

  bool result_success = false;
  bool result_can_use_pin = false;
  controller->AuthenticateUserWithPasswordOrPin(
      pin,
      /*authenticated_by_password=*/true,
      /* View callback will be executed during controller callback. */
      base::BindLambdaForTesting([&result_success, &result_can_use_pin](
                                     bool success, bool can_use_pin) {
        result_success = success;
        result_can_use_pin = can_use_pin;
      }));

  EXPECT_FALSE(result_success);
  EXPECT_FALSE(result_can_use_pin);
}

TEST_F(WebAuthNDialogControllerImplTest, PasswordAuthSuccess) {
  WebAuthNDialogController* controller =
      Shell::Get()->webauthn_dialog_controller();
  auto client = std::make_unique<MockInSessionAuthDialogClient>();

  std::string password = "abcdef";

  EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin(
                           password, /* authenticated_by_pin = */ false, _))
      .WillOnce([](const std::string& password, bool authenticated_by_pin,
                   base::OnceCallback<void(bool success)> controller_callback) {
        std::move(controller_callback).Run(true);
      });

  bool result_success = false;
  controller->AuthenticateUserWithPasswordOrPin(
      password,
      /*authenticated_by_password=*/false,
      /* View callback will be executed during controller callback. */
      base::BindLambdaForTesting(
          [&result_success](bool success, bool can_use_pin) {
            result_success = success;
          }));

  EXPECT_TRUE(result_success);
}

TEST_F(WebAuthNDialogControllerImplTest, PasswordAuthFail) {
  WebAuthNDialogController* controller =
      Shell::Get()->webauthn_dialog_controller();
  auto client = std::make_unique<MockInSessionAuthDialogClient>();

  std::string password = "abcdef";

  EXPECT_CALL(*client, AuthenticateUserWithPasswordOrPin(
                           password, /* authenticated_by_pin = */ false, _))
      .WillOnce([](const std::string& password, bool authenticated_by_pin,
                   base::OnceCallback<void(bool success)> controller_callback) {
        std::move(controller_callback).Run(false);
      });
  EXPECT_CALL(*client, CheckPinAuthAvailability(_, _))
      .WillOnce([](const AccountId& account_id,
                   base::OnceCallback<void(bool success)> controller_callback) {
        std::move(controller_callback).Run(false);
      });

  bool result_success = false;
  controller->AuthenticateUserWithPasswordOrPin(
      password,
      /*authenticated_by_password=*/false,
      /* View callback will be executed during controller callback. */
      base::BindLambdaForTesting(
          [&result_success](bool success, bool can_use_pin) {
            result_success = success;
          }));

  EXPECT_FALSE(result_success);
}

}  // namespace
}  // namespace ash