chromium/chrome/browser/lacros/machine_learning_service_lacros_browsertest.cc

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

#include <string>

#include "chrome/test/base/in_process_browser_test.h"
#include "chromeos/lacros/lacros_service.h"
#include "chromeos/services/machine_learning/public/cpp/fake_service_connection.h"
#include "chromeos/services/machine_learning/public/cpp/service_connection.h"
#include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom-shared.h"
#include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom-test-utils.h"
#include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
#include "chromeos/services/machine_learning/public/mojom/model.mojom-forward.h"
#include "chromeos/services/machine_learning/public/mojom/model.mojom-shared.h"
#include "content/public/test/browser_test.h"

namespace {
using chromeos::machine_learning::mojom::BuiltinModelId;
using chromeos::machine_learning::mojom::BuiltinModelSpec;
using chromeos::machine_learning::mojom::LoadModelResult;
using chromeos::machine_learning::mojom::MachineLearningService;
using chromeos::machine_learning::mojom::MachineLearningServiceAsyncWaiter;
using chromeos::machine_learning::mojom::Model;

using MachineLearningServiceLacrosBrowserTest = InProcessBrowserTest;
}  // namespace

// Tests chromeos::LacrosService::GetRemote<c::m::mojom::MachineLearningService>
// works. This should not be used by the customers directly, instead they should
// use
//   chromeos::machine_learning::ServiceConnection::GetInstance()
//       ->GetMachineLearningService();
// But we should keep this test because it initializes LacrosService, which is
// necessary before calling ServiceConnection::GetInstance().
IN_PROC_BROWSER_TEST_F(MachineLearningServiceLacrosBrowserTest,
                       CallViaLacrosService) {
  uint32_t interface_version =
      chromeos::LacrosService::Get()
          ->GetInterfaceVersion<MachineLearningService>();

  // LoadBuiltinModel doesn't have MinVersion tag in mojom, so it gets 0 as min
  // version implicitly.
  EXPECT_EQ(MachineLearningService::kLoadBuiltinModelMinVersion, 0u);
  ASSERT_GE(interface_version,
            MachineLearningService::kLoadBuiltinModelMinVersion);

  MachineLearningServiceAsyncWaiter async_waiter(
      chromeos::LacrosService::Get()
          ->GetRemote<
              chromeos::machine_learning::mojom::MachineLearningService>()
          .get());

  mojo::Remote<Model> model_remote;
  LoadModelResult result;
  async_waiter.LoadBuiltinModel(
      BuiltinModelSpec::New(BuiltinModelId::TEST_MODEL),
      model_remote.BindNewPipeAndPassReceiver(), &result);
  EXPECT_EQ(result, LoadModelResult::OK);
}

// Tests the pre-established MachineLearningService works.
IN_PROC_BROWSER_TEST_F(MachineLearningServiceLacrosBrowserTest,
                       GetMachineLearningService) {
  auto* service_connection =
      chromeos::machine_learning::ServiceConnection::GetInstance();
  MachineLearningServiceAsyncWaiter async_waiter(
      &service_connection->GetMachineLearningService());

  mojo::Remote<Model> model_remote;
  LoadModelResult result;
  async_waiter.LoadBuiltinModel(
      BuiltinModelSpec::New(BuiltinModelId::TEST_MODEL),
      model_remote.BindNewPipeAndPassReceiver(), &result);
  EXPECT_EQ(result, LoadModelResult::OK);
}

// Tests a new remote bound with BindMachineLearningService works.
IN_PROC_BROWSER_TEST_F(MachineLearningServiceLacrosBrowserTest,
                       BindMachineLearningService) {
  mojo::Remote<MachineLearningService> ml_service;
  ASSERT_FALSE(ml_service.is_bound());

  auto* service_connection =
      chromeos::machine_learning::ServiceConnection::GetInstance();
  service_connection->BindMachineLearningService(
      ml_service.BindNewPipeAndPassReceiver());
  ASSERT_TRUE(ml_service.is_bound());

  MachineLearningServiceAsyncWaiter async_waiter(ml_service.get());

  mojo::Remote<Model> model_remote;
  LoadModelResult result;
  async_waiter.LoadBuiltinModel(
      BuiltinModelSpec::New(BuiltinModelId::TEST_MODEL),
      model_remote.BindNewPipeAndPassReceiver(), &result);
  EXPECT_EQ(result, LoadModelResult::OK);
}

// Tests FakeServiceConnectionImpl works. This doesn't require crosapi.
IN_PROC_BROWSER_TEST_F(MachineLearningServiceLacrosBrowserTest,
                       FakeServiceConnecctionImpl) {
  chromeos::machine_learning::FakeServiceConnectionImpl fake_service_connection;
  chromeos::machine_learning::ServiceConnection::
      UseFakeServiceConnectionForTesting(&fake_service_connection);

  auto* service_connection =
      chromeos::machine_learning::ServiceConnection::GetInstance();
  service_connection->Initialize();

  mojo::Remote<MachineLearningService> ml_service;
  ASSERT_FALSE(ml_service.is_bound());

  service_connection->BindMachineLearningService(
      ml_service.BindNewPipeAndPassReceiver());
  ASSERT_TRUE(ml_service.is_bound());

  MachineLearningServiceAsyncWaiter async_waiter(ml_service.get());

  // By default, the FakeServiceConnectionImpl responds to all method calls with
  // success.
  mojo::Remote<Model> model_remote;
  LoadModelResult result;
  async_waiter.LoadBuiltinModel(
      BuiltinModelSpec::New(BuiltinModelId::TEST_MODEL),
      model_remote.BindNewPipeAndPassReceiver(), &result);
  EXPECT_EQ(result, LoadModelResult::OK);

  // It can also simulate failure.
  model_remote.reset();
  fake_service_connection.SetLoadModelFailure();
  async_waiter.LoadBuiltinModel(
      BuiltinModelSpec::New(BuiltinModelId::TEST_MODEL),
      model_remote.BindNewPipeAndPassReceiver(), &result);
  EXPECT_EQ(result, LoadModelResult::LOAD_MODEL_ERROR);
}