blob: 97be4722ac82e3684e7cee0d20cd14ff1bef64bc [file] [log] [blame]
// Copyright 2021 The Chromium 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 "chrome/browser/ui/ash/projector/projector_client_impl.h"
#include <memory>
#include "ash/constants/ash_features.h"
#include "ash/public/cpp/projector/projector_client.h"
#include "ash/public/cpp/projector/projector_controller.h"
#include "ash/public/cpp/test/mock_projector_controller.h"
#include "ash/webui/projector_app/public/cpp/projector_app_constants.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/speech/cros_speech_recognition_service_factory.h"
#include "chrome/browser/speech/fake_speech_recognition_service.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/prefs/pref_service.h"
#include "components/soda/soda_installer.h"
#include "components/soda/soda_installer_impl_chromeos.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace ash {
namespace {
const char kFirstSpeechResult[] = "the brown fox";
const char kSecondSpeechResult[] = "the brown fox jumped over the lazy dog";
const char kEnglishLocale[] = "en-US";
inline void SetLocale(const std::string& locale) {
g_browser_process->SetApplicationLocale(locale);
}
// A mocked version instance of SodaInstaller for testing purposes.
class MockSodaInstaller : public speech::SodaInstaller {
public:
MockSodaInstaller() = default;
MockSodaInstaller(const MockSodaInstaller&) = delete;
MockSodaInstaller& operator=(const MockSodaInstaller&) = delete;
~MockSodaInstaller() override = default;
MOCK_CONST_METHOD0(GetSodaBinaryPath, base::FilePath());
MOCK_CONST_METHOD1(GetLanguagePath, base::FilePath(const std::string&));
MOCK_METHOD2(InstallLanguage, void(const std::string&, PrefService*));
MOCK_CONST_METHOD0(GetAvailableLanguages, std::vector<std::string>());
MOCK_METHOD1(InstallSoda, void(PrefService*));
MOCK_METHOD1(UninstallSoda, void(PrefService*));
};
} // namespace
class ProjectorClientImplUnitTest : public testing::Test {
public:
ProjectorClientImplUnitTest() {
scoped_feature_list_.InitWithFeatures(
{features::kProjector, features::kOnDeviceSpeechRecognition}, {});
}
ProjectorClientImplUnitTest(const ProjectorClientImplUnitTest&) = delete;
ProjectorClientImplUnitTest& operator=(const ProjectorClientImplUnitTest&) =
delete;
~ProjectorClientImplUnitTest() override = default;
Profile* profile() { return testing_profile_; }
MockProjectorController& projector_controller() {
return projector_controller_;
}
ProjectorClient* client() { return projector_client_.get(); }
// testing::Test:
void SetUp() override {
testing::Test::SetUp();
ASSERT_TRUE(testing_profile_manager_.SetUp());
testing_profile_ = ProfileManager::GetPrimaryUserProfile();
ASSERT_TRUE(testing_profile_);
CrosSpeechRecognitionServiceFactory::GetInstanceForTest()
->SetTestingFactoryAndUse(
profile(),
base::BindRepeating(&ProjectorClientImplUnitTest::
CreateTestSpeechRecognitionService,
base::Unretained(this)));
SetLocale(kEnglishLocale);
soda_installer_ = std::make_unique<MockSodaInstaller>();
soda_installer_->NotifySodaInstalledForTesting();
soda_installer_->NotifySodaInstalledForTesting(speech::LanguageCode::kEnUs);
projector_client_ =
std::make_unique<ProjectorClientImpl>(&projector_controller_);
}
std::unique_ptr<KeyedService> CreateTestSpeechRecognitionService(
content::BrowserContext* context) {
std::unique_ptr<speech::FakeSpeechRecognitionService> fake_service =
std::make_unique<speech::FakeSpeechRecognitionService>();
fake_service_ = fake_service.get();
return std::move(fake_service);
}
void SendSpeechResult(const char* result, bool is_final) {
EXPECT_TRUE(fake_service_->is_capturing_audio());
base::RunLoop loop;
fake_service_->SendSpeechRecognitionResult(
media::SpeechRecognitionResult(result, is_final));
loop.RunUntilIdle();
}
void SendTranscriptionError() {
EXPECT_TRUE(fake_service_->is_capturing_audio());
base::RunLoop loop;
fake_service_->SendSpeechRecognitionError();
loop.RunUntilIdle();
}
protected:
content::BrowserTaskEnvironment task_environment_;
Profile* testing_profile_ = nullptr;
TestingProfileManager testing_profile_manager_{
TestingBrowserProcess::GetGlobal()};
MockProjectorController projector_controller_;
std::unique_ptr<ProjectorClient> projector_client_;
std::unique_ptr<MockSodaInstaller> soda_installer_;
speech::FakeSpeechRecognitionService* fake_service_;
base::test::ScopedFeatureList scoped_feature_list_;
};
TEST_F(ProjectorClientImplUnitTest, SpeechRecognitionResults) {
client()->StartSpeechRecognition();
fake_service_->WaitForRecognitionStarted();
EXPECT_CALL(projector_controller(),
OnTranscription(
media::SpeechRecognitionResult(kFirstSpeechResult, false)));
SendSpeechResult(kFirstSpeechResult, /*is_final=*/false);
EXPECT_CALL(projector_controller(),
OnTranscription(
media::SpeechRecognitionResult(kSecondSpeechResult, false)));
SendSpeechResult(kSecondSpeechResult, /*is_final=*/false);
EXPECT_CALL(projector_controller(), OnTranscriptionError());
SendTranscriptionError();
}
} // namespace ash