blob: d4a2076c12d873bee5102e71293e0402b9fdcbbd [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/on_device_translation/test/test_util.h"
#include "base/files/file_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/on_device_translation/language_pack_util.h"
#include "chrome/browser/on_device_translation/pref_names.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "components/prefs/pref_service.h"
#include "components/services/on_device_translation/test/test_util.h"
#include "content/public/test/browser_test_utils.h"
using ::testing::_;
namespace on_device_translation {
MockComponentManager::MockComponentManager(const base::FilePath& package_dir)
: package_dir_(package_dir),
mock_component_manager_(ComponentManager::SetForTesting(this)) {}
MockComponentManager::~MockComponentManager() = default;
void MockComponentManager::DoNotExpectCallRegisterTranslateKitComponent() {
EXPECT_CALL(*this, RegisterTranslateKitComponentImpl()).Times(0);
}
void MockComponentManager::ExpectCallRegisterTranslateKitComponentAndInstall() {
EXPECT_CALL(*this, RegisterTranslateKitComponentImpl()).WillOnce([&]() {
InstallMockTranslateKitComponentLater();
});
}
void MockComponentManager::DoNotExpectCallRegisterLanguagePackComponent() {
EXPECT_CALL(*this, RegisterTranslateKitLanguagePackComponent(_)).Times(0);
}
void MockComponentManager::ExpectCallRegisterLanguagePackComponentAndInstall(
const base::span<const LanguagePackKey>& language_pack_keys) {
auto& expectation =
EXPECT_CALL(*this, RegisterTranslateKitLanguagePackComponent(_));
for (const auto expected_key : language_pack_keys) {
expectation.WillOnce([&, expected_key](LanguagePackKey key) {
EXPECT_EQ(key, expected_key);
InstallMockLanguagePackLater(key);
});
}
}
void MockComponentManager::InstallMockTranslateKitComponent() {
InstallComponent(GetMockLibraryPath());
}
void MockComponentManager::InstallMockInvalidFunctionPointerLibraryComponent() {
InstallComponent(GetMockInvalidFunctionPointerLibraryPath());
}
void MockComponentManager::InstallMockFailingLibraryComponent() {
InstallComponent(GetMockFailingLibraryPath());
}
void MockComponentManager::InstallEmptyMockComponent() {
g_browser_process->local_state()->SetFilePath(
prefs::kTranslateKitBinaryPath, package_dir_.AppendASCII("fakefile"));
}
void MockComponentManager::InstallComponent(base::FilePath library_path) {
CHECK(!library_path.empty());
base::ScopedAllowBlockingForTesting allow_io;
const auto binary_path = package_dir_.Append(library_path.BaseName());
if (!base::DirectoryExists(binary_path.DirName())) {
CHECK(base::CreateDirectory(binary_path.DirName()));
}
CHECK(base::CopyFile(library_path, binary_path));
g_browser_process->local_state()->SetFilePath(prefs::kTranslateKitBinaryPath,
binary_path);
}
void MockComponentManager::InstallMockLanguagePack(
LanguagePackKey language_pack_key) {
InstallMockLanguagePack(
language_pack_key,
CreateFakeDictionaryData(GetSourceLanguageCode(language_pack_key),
GetTargetLanguageCode(language_pack_key)));
}
void MockComponentManager::RegisterLanguagePack(
LanguagePackKey language_pack_key) {
const LanguagePackComponentConfig* config =
kLanguagePackComponentConfigMap.at(language_pack_key);
g_browser_process->local_state()->SetBoolean(
GetRegisteredFlagPrefName(*config), true);
}
void MockComponentManager::InstallMockLanguagePack(
LanguagePackKey language_pack_key,
const std::string_view fake_dictionary_data) {
base::ScopedAllowBlockingForTesting allow_io;
const auto dict_dir_path =
package_dir_.AppendASCII(GetPackageInstallDirName(language_pack_key));
const auto dict_path = dict_dir_path.AppendASCII("dict.dat");
if (!base::DirectoryExists(dict_dir_path)) {
CHECK(base::CreateDirectory(dict_dir_path));
}
CHECK(base::File(dict_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE)
.WriteAndCheck(0, base::as_byte_span(fake_dictionary_data)));
const LanguagePackComponentConfig* config =
kLanguagePackComponentConfigMap.at(language_pack_key);
g_browser_process->local_state()->SetBoolean(
GetRegisteredFlagPrefName(*config), true);
g_browser_process->local_state()->SetFilePath(
GetComponentPathPrefName(*config), dict_dir_path);
}
void MockComponentManager::InstallMockTranslateKitComponentLater() {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&MockComponentManager::InstallMockTranslateKitComponent,
weak_ptr_factory_.GetWeakPtr()));
}
void MockComponentManager::InstallMockLanguagePackLater(
LanguagePackKey language_pack_key) {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(
[](base::WeakPtr<MockComponentManager> self,
LanguagePackKey language_pack_key) {
if (self) {
self->InstallMockLanguagePack(language_pack_key);
}
},
weak_ptr_factory_.GetWeakPtr(), language_pack_key));
}
MockTranslationManagerImpl::MockTranslationManagerImpl(
content::RenderProcessHost* process_host,
content::BrowserContext* browser_context,
const url::Origin& origin)
: TranslationManagerImpl(process_host, browser_context, origin),
mock_translation_manager_impl_(
TranslationManagerImpl::SetForTesting(this)) {}
MockTranslationManagerImpl::~MockTranslationManagerImpl() = default;
std::string CreateFakeDictionaryData(const std::string_view sourceLang,
const std::string_view targetLang) {
return base::StringPrintf("%s to %s: ", sourceLang, targetLang);
}
void TestSimpleTranslationWorks(Browser* browser,
LanguagePackKey language_pack_key) {
TestSimpleTranslationWorks(browser, GetSourceLanguageCode(language_pack_key),
GetTargetLanguageCode(language_pack_key));
}
void TestSimpleTranslationWorks(Browser* browser,
const std::string_view sourceLang,
const std::string_view targetLang) {
// Translate "hello" from `sourceLang` to `targetLang`.
// Note: the mock TranslateKit component returns the concatenation of the
// content of "dict.dat" in the language pack and the input text.
// See comments in mock_translate_kit_lib.cc for more details.
EXPECT_EQ(EvalJs(browser->tab_strip_model()->GetActiveWebContents(),
base::StringPrintf(R"(
(async () => {
try {
const translator = await Translator.create({
sourceLanguage: '%s',
targetLanguage: '%s',
});
return await translator.translate('hello');
} catch (e) {
return e.toString();
}
})();
)",
sourceLang, targetLang))
.ExtractString(),
base::StringPrintf("%s to %s: hello", sourceLang, targetLang));
}
void TestCreateTranslator(Browser* browser,
LanguagePackKey language_pack_key,
const std::string_view result) {
TestCreateTranslator(browser, GetSourceLanguageCode(language_pack_key),
GetTargetLanguageCode(language_pack_key), result);
}
// Tests that the createTranslator() returns the expected result.
void TestCreateTranslator(Browser* browser,
const std::string_view sourceLang,
const std::string_view targetLang,
const std::string_view result) {
ASSERT_EQ(EvalJs(browser->tab_strip_model()->GetActiveWebContents(),
base::StringPrintf(R"(
(async () => {
try {
await Translator.create({
sourceLanguage: '%s',
targetLanguage: '%s',
});
return 'OK';
} catch (e) {
return e.toString();
}
})();
)",
sourceLang, targetLang))
.ExtractString(),
result);
}
// Tests that availability() method returns the expected result for the given
// languages.
void TestTranslationAvailable(Browser* browser,
const std::string_view sourceLang,
const std::string_view targetLang,
const std::string_view result) {
ASSERT_EQ(EvalJs(browser->tab_strip_model()->GetActiveWebContents(),
base::StringPrintf(R"(
(async () => {
try {
return await Translator.availability({
sourceLanguage: '%s',
targetLanguage: '%s',
});
} catch (e) {
return e.toString();
}
})();
)",
sourceLang, targetLang))
.ExtractString(),
result);
}
} // namespace on_device_translation