blob: 1e0595e56e7b886c5ee8878e0a2205e5428aa446 [file] [log] [blame]
// Copyright 2020 The Chromium OS 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 <fcntl.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/bind.h>
#include <base/files/file_path.h>
#include <base/files/scoped_file.h>
#include <base/files/scoped_temp_dir.h>
#include <base/message_loop/message_pump_type.h>
#include <base/posix/eintr_wrapper.h>
#include <base/run_loop.h>
#include <base/task/single_thread_task_executor.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <mojo/core/embedder/embedder.h>
#include <mojo/public/cpp/system/handle.h>
#include <mojo/public/cpp/bindings/pending_receiver.h>
#include <mojo/public/cpp/system/platform_handle.h>
#include <mojo/public/cpp/bindings/remote.h>
#include "ocr/mojo/ocr_service.mojom.h"
#include "ocr/ocr_service_impl.h"
namespace ocr {
namespace {
namespace mojo_ipc = chromeos::ocr::mojom;
// The relative path of the input test image.
constexpr char kTestImageRelativePath[] = "./test_images/phototest.tif";
// The name of the output pdf file.
constexpr char kOutputPdfFilename[] = "phototest.pdf";
mojo::ScopedHandle GetInputFileHandle(const std::string& input_filename) {
base::ScopedFD input_fd(HANDLE_EINTR(
open(input_filename.c_str(), O_RDONLY | O_NOFOLLOW | O_NOCTTY)));
return mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(input_fd)));
}
mojo::ScopedHandle GetOutputFileHandle(const std::string& output_filename) {
base::ScopedFD out_fd(
HANDLE_EINTR(open(output_filename.c_str(), O_CREAT | O_WRONLY, 0644)));
return mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(out_fd)));
}
} // namespace
class OcrServiceImplTest : public testing::Test {
protected:
OcrServiceImplTest() { mojo::core::Init(); }
void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
OcrServiceImpl* ocr_service() { return &ocr_service_impl_; }
const base::FilePath& temp_dir_path() const { return temp_dir_.GetPath(); }
private:
OcrServiceImpl ocr_service_impl_;
base::SingleThreadTaskExecutor executor_{base::MessagePumpType::IO};
base::ScopedTempDir temp_dir_;
};
// Tests OCR on a valid input image and with valid parameters.
TEST_F(OcrServiceImplTest, GenerateSearchablePdfFromImageSuccess) {
mojo::Remote<mojo_ipc::OpticalCharacterRecognitionService> remote;
EXPECT_FALSE(remote);
ocr_service()->AddReceiver(remote.BindNewPipeAndPassReceiver(),
false /* should_quit */);
ASSERT_TRUE(remote);
// Construct request.
const std::string input_image_filename =
base::FilePath(kTestImageRelativePath).value();
mojo::ScopedHandle input_fd_handle = GetInputFileHandle(input_image_filename);
const std::string output_filename =
temp_dir_path().Append(kOutputPdfFilename).value();
mojo::ScopedHandle output_fd_handle = GetOutputFileHandle(output_filename);
mojo_ipc::OcrConfigPtr ocr_config = mojo_ipc::OcrConfig::New();
mojo_ipc::PdfRendererConfigPtr pdf_renderer_config =
mojo_ipc::PdfRendererConfig::New();
// Perform OCR.
bool ocr_callback_done = false;
// Ensure that remote is bound.
remote->GenerateSearchablePdfFromImage(
std::move(input_fd_handle), std::move(output_fd_handle),
std::move(ocr_config), std::move(pdf_renderer_config),
base::BindOnce(
[](bool* ocr_callback_done,
const mojo_ipc::OpticalCharacterRecognitionServiceResponsePtr
response) {
EXPECT_EQ(response->result, mojo_ipc::OcrResultEnum::SUCCESS);
*ocr_callback_done = true;
},
&ocr_callback_done));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(ocr_callback_done);
}
TEST_F(OcrServiceImplTest, OcrFailToLoadLanguage) {
// Construct request.
const std::string input_image_filename =
base::FilePath(kTestImageRelativePath).value();
mojo::ScopedHandle input_fd_handle = GetInputFileHandle(input_image_filename);
const std::string output_filename =
temp_dir_path().Append(kOutputPdfFilename).value();
mojo::ScopedHandle output_fd_handle = GetOutputFileHandle(output_filename);
mojo_ipc::OcrConfigPtr ocr_config = mojo_ipc::OcrConfig::New();
ocr_config->language = "deu";
mojo_ipc::PdfRendererConfigPtr pdf_renderer_config =
mojo_ipc::PdfRendererConfig::New();
// Perform OCR.
bool ocr_callback_done = false;
// Ensure that remote is bound.
ocr_service()->GenerateSearchablePdfFromImage(
std::move(input_fd_handle), std::move(output_fd_handle),
std::move(ocr_config), std::move(pdf_renderer_config),
base::BindOnce(
[](bool* ocr_callback_done,
const mojo_ipc::OpticalCharacterRecognitionServiceResponsePtr
response) {
EXPECT_EQ(response->result,
mojo_ipc::OcrResultEnum::LANGUAGE_NOT_SUPPORTED_ERROR);
*ocr_callback_done = true;
},
&ocr_callback_done));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(ocr_callback_done);
}
TEST_F(OcrServiceImplTest, OcrInvalidInputImageFileHandle) {
// Construct request.
mojo::ScopedHandle input_fd_handle = mojo::ScopedHandle();
const std::string output_filename =
temp_dir_path().Append(kOutputPdfFilename).value();
mojo::ScopedHandle output_fd_handle = GetOutputFileHandle(output_filename);
mojo_ipc::OcrConfigPtr ocr_config = mojo_ipc::OcrConfig::New();
mojo_ipc::PdfRendererConfigPtr pdf_renderer_config =
mojo_ipc::PdfRendererConfig::New();
// Perform OCR.
bool ocr_callback_done = false;
// Ensure that remote is bound.
ocr_service()->GenerateSearchablePdfFromImage(
std::move(input_fd_handle), std::move(output_fd_handle),
std::move(ocr_config), std::move(pdf_renderer_config),
base::BindOnce(
[](bool* ocr_callback_done,
const mojo_ipc::OpticalCharacterRecognitionServiceResponsePtr
response) {
EXPECT_EQ(response->result,
mojo_ipc::OcrResultEnum::INPUT_FILE_ERROR);
*ocr_callback_done = true;
},
&ocr_callback_done));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(ocr_callback_done);
}
TEST_F(OcrServiceImplTest, OcrInvalidOutputPdfFileHandle) {
// Construct request.
const std::string input_image_filename =
base::FilePath(kTestImageRelativePath).value();
mojo::ScopedHandle input_fd_handle = GetInputFileHandle(input_image_filename);
mojo::ScopedHandle output_fd_handle = mojo::ScopedHandle();
mojo_ipc::OcrConfigPtr ocr_config = mojo_ipc::OcrConfig::New();
mojo_ipc::PdfRendererConfigPtr pdf_renderer_config =
mojo_ipc::PdfRendererConfig::New();
// Perform OCR.
bool ocr_callback_done = false;
// Ensure that remote is bound.
ocr_service()->GenerateSearchablePdfFromImage(
std::move(input_fd_handle), std::move(output_fd_handle),
std::move(ocr_config), std::move(pdf_renderer_config),
base::BindOnce(
[](bool* ocr_callback_done,
const mojo_ipc::OpticalCharacterRecognitionServiceResponsePtr
response) {
EXPECT_EQ(response->result,
mojo_ipc::OcrResultEnum::OUTPUT_FILE_ERROR);
*ocr_callback_done = true;
},
&ocr_callback_done));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(ocr_callback_done);
}
} // namespace ocr