blob: 11149a121a288c9e420279319cb0a74afe7d4806 [file] [log] [blame]
// Copyright (c) 2013 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 "lorgnette/manager.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <base/files/file.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/files/scoped_temp_dir.h>
#include <brillo/process.h>
#include <brillo/variant_dictionary.h>
#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest.h>
#include <metrics/metrics_library_mock.h>
#include <sane/sane.h>
#include "lorgnette/sane_client_fake.h"
#include "lorgnette/sane_client_impl.h"
using base::ScopedFD;
using brillo::VariantDictionary;
namespace lorgnette {
class ManagerTest : public testing::Test {
protected:
ManagerTest()
: sane_client_(new SaneClientFake()),
manager_(base::Callback<void()>(),
std::unique_ptr<SaneClient>(sane_client_)),
metrics_library_(new MetricsLibraryMock) {
manager_.metrics_library_.reset(metrics_library_);
}
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
output_path_ = temp_dir_.GetPath().Append("scan_data.png");
}
void ExpectScanSuccess() {
EXPECT_CALL(*metrics_library_, SendEnumToUMA(Manager::kMetricScanResult,
Manager::kBooleanMetricSuccess,
Manager::kBooleanMetricMax));
}
void ExpectScanFailure() {
EXPECT_CALL(*metrics_library_, SendEnumToUMA(Manager::kMetricScanResult,
Manager::kBooleanMetricFailure,
Manager::kBooleanMetricMax));
}
void ExpectConverterSuccess() {
EXPECT_CALL(*metrics_library_,
SendEnumToUMA(Manager::kMetricConverterResult,
Manager::kBooleanMetricSuccess,
Manager::kBooleanMetricMax));
}
bool CompareImages(const std::string& path_a, const std::string& path_b) {
brillo::ProcessImpl diff;
diff.AddArg("/usr/bin/perceptualdiff");
diff.AddArg("-verbose");
diff.AddIntOption("-threshold", 1);
diff.AddArg(path_a);
diff.AddArg(path_b);
return diff.Run() == 0;
}
SaneClientFake* sane_client_;
Manager manager_;
MetricsLibraryMock* metrics_library_; // Owned by manager_.
base::ScopedTempDir temp_dir_;
base::FilePath output_path_;
};
TEST_F(ManagerTest, ScanBlackAndWhiteSuccess) {
std::string contents;
ASSERT_TRUE(base::ReadFileToString(base::FilePath("./test_images/bw.pnm"),
&contents));
std::vector<uint8_t> image_data(contents.begin(), contents.end());
std::unique_ptr<SaneDeviceFake> device = std::make_unique<SaneDeviceFake>();
device->SetScanData(image_data);
ScanParameters parameters;
parameters.format = kGrayscale;
parameters.pixels_per_line = 85;
parameters.lines = 29;
parameters.depth = 1;
device->SetScanParameters(parameters);
sane_client_->SetDeviceForName("TestDevice", std::move(device));
base::File scan(output_path_,
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(scan.IsValid());
base::ScopedFD scan_fd(scan.TakePlatformFile());
ExpectScanSuccess();
ExpectConverterSuccess();
EXPECT_TRUE(manager_.ScanImage(nullptr, "TestDevice", scan_fd,
brillo::VariantDictionary()));
EXPECT_TRUE(CompareImages("./test_images/bw.png", output_path_.value()));
}
TEST_F(ManagerTest, ScanColorSuccess) {
std::string contents;
ASSERT_TRUE(base::ReadFileToString(base::FilePath("./test_images/color.pnm"),
&contents));
std::vector<uint8_t> image_data(contents.begin(), contents.end());
std::unique_ptr<SaneDeviceFake> device = std::make_unique<SaneDeviceFake>();
device->SetScanData(image_data);
ScanParameters parameters;
parameters.format = kRGB;
parameters.pixels_per_line = 98;
parameters.lines = 50;
parameters.depth = 8;
device->SetScanParameters(parameters);
sane_client_->SetDeviceForName("TestDevice", std::move(device));
base::File scan(output_path_,
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(scan.IsValid());
base::ScopedFD scan_fd(scan.TakePlatformFile());
ExpectScanSuccess();
ExpectConverterSuccess();
EXPECT_TRUE(manager_.ScanImage(nullptr, "TestDevice", scan_fd,
brillo::VariantDictionary()));
EXPECT_TRUE(CompareImages("./test_images/color.png", output_path_.value()));
}
TEST_F(ManagerTest, ScanFailNoDevice) {
std::string contents;
ASSERT_TRUE(base::ReadFileToString(base::FilePath("./test_images/color.pnm"),
&contents));
std::vector<uint8_t> image_data(contents.begin(), contents.end());
base::File scan(output_path_,
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(scan.IsValid());
base::ScopedFD scan_fd(scan.TakePlatformFile());
EXPECT_FALSE(manager_.ScanImage(nullptr, "TestDevice", scan_fd,
brillo::VariantDictionary()));
}
TEST_F(ManagerTest, ScanFailToStart) {
std::string contents;
ASSERT_TRUE(base::ReadFileToString(base::FilePath("./test_images/color.pnm"),
&contents));
std::vector<uint8_t> image_data(contents.begin(), contents.end());
std::unique_ptr<SaneDeviceFake> device = std::make_unique<SaneDeviceFake>();
device->SetScanData(image_data);
device->SetStartScanResult(false);
sane_client_->SetDeviceForName("TestDevice", std::move(device));
base::File scan(output_path_,
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(scan.IsValid());
base::ScopedFD scan_fd(scan.TakePlatformFile());
ExpectScanFailure();
EXPECT_FALSE(manager_.ScanImage(nullptr, "TestDevice", scan_fd,
brillo::VariantDictionary()));
}
TEST_F(ManagerTest, ScanFailToRead) {
std::string contents;
ASSERT_TRUE(base::ReadFileToString(base::FilePath("./test_images/color.pnm"),
&contents));
std::vector<uint8_t> image_data(contents.begin(), contents.end());
std::unique_ptr<SaneDeviceFake> device = std::make_unique<SaneDeviceFake>();
device->SetScanData(image_data);
device->SetReadScanDataResult(false);
sane_client_->SetDeviceForName("TestDevice", std::move(device));
base::File scan(output_path_,
base::File::FLAG_CREATE | base::File::FLAG_WRITE);
ASSERT_TRUE(scan.IsValid());
base::ScopedFD scan_fd(scan.TakePlatformFile());
ExpectScanFailure();
EXPECT_FALSE(manager_.ScanImage(nullptr, "TestDevice", scan_fd,
brillo::VariantDictionary()));
}
class SaneClientTest : public testing::Test {
protected:
void SetUp() override {
dev_ = CreateTestDevice();
dev_two_ = CreateTestDevice();
}
static SANE_Device CreateTestDevice() {
SANE_Device dev;
dev.name = "Test Name";
dev.vendor = "Test Vendor";
dev.model = "Test Model";
dev.type = "film scanner";
return dev;
}
SANE_Device dev_;
SANE_Device dev_two_;
const SANE_Device* empty_devices_[1] = {NULL};
const SANE_Device* one_device_[2] = {&dev_, NULL};
const SANE_Device* two_devices_[3] = {&dev_, &dev_two_, NULL};
Manager::ScannerInfo info_;
};
TEST_F(SaneClientTest, ScannerInfoFromDeviceListInvalidParameters) {
EXPECT_FALSE(SaneClientImpl::DeviceListToScannerInfo(NULL, NULL));
EXPECT_FALSE(SaneClientImpl::DeviceListToScannerInfo(one_device_, NULL));
EXPECT_FALSE(SaneClientImpl::DeviceListToScannerInfo(NULL, &info_));
}
TEST_F(SaneClientTest, ScannerInfoFromDeviceListNoDevices) {
EXPECT_TRUE(SaneClientImpl::DeviceListToScannerInfo(empty_devices_, &info_));
EXPECT_EQ(info_.size(), 0);
}
TEST_F(SaneClientTest, ScannerInfoFromDeviceListOneDevice) {
EXPECT_TRUE(SaneClientImpl::DeviceListToScannerInfo(one_device_, &info_));
EXPECT_EQ(info_.size(), 1);
EXPECT_EQ(info_.count(dev_.name), 1);
EXPECT_EQ(info_[dev_.name]["Manufacturer"], dev_.vendor);
EXPECT_EQ(info_[dev_.name]["Model"], dev_.model);
EXPECT_EQ(info_[dev_.name]["Type"], dev_.type);
}
TEST_F(SaneClientTest, ScannerInfoFromDeviceListNullFields) {
dev_ = CreateTestDevice();
dev_.name = NULL;
EXPECT_TRUE(SaneClientImpl::DeviceListToScannerInfo(one_device_, &info_));
EXPECT_EQ(info_.size(), 0);
dev_ = CreateTestDevice();
dev_.vendor = NULL;
EXPECT_TRUE(SaneClientImpl::DeviceListToScannerInfo(one_device_, &info_));
EXPECT_EQ(info_.size(), 1);
EXPECT_EQ(info_.count(dev_.name), 1);
EXPECT_EQ(info_[dev_.name]["Manufacturer"], "");
EXPECT_EQ(info_[dev_.name]["Model"], dev_.model);
EXPECT_EQ(info_[dev_.name]["Type"], dev_.type);
dev_ = CreateTestDevice();
dev_.model = NULL;
EXPECT_TRUE(SaneClientImpl::DeviceListToScannerInfo(one_device_, &info_));
EXPECT_EQ(info_.size(), 1);
EXPECT_EQ(info_.count(dev_.name), 1);
EXPECT_EQ(info_[dev_.name]["Manufacturer"], dev_.vendor);
EXPECT_EQ(info_[dev_.name]["Model"], "");
EXPECT_EQ(info_[dev_.name]["Type"], dev_.type);
dev_ = CreateTestDevice();
dev_.type = NULL;
EXPECT_TRUE(SaneClientImpl::DeviceListToScannerInfo(one_device_, &info_));
EXPECT_EQ(info_.size(), 1);
EXPECT_EQ(info_.count(dev_.name), 1);
EXPECT_EQ(info_[dev_.name]["Manufacturer"], dev_.vendor);
EXPECT_EQ(info_[dev_.name]["Model"], dev_.model);
EXPECT_EQ(info_[dev_.name]["Type"], "");
}
TEST_F(SaneClientTest, ScannerInfoFromDeviceListMultipleDevices) {
EXPECT_FALSE(SaneClientImpl::DeviceListToScannerInfo(two_devices_, &info_));
dev_two_.name = "Test Device 2";
dev_two_.vendor = "Test Vendor 2";
EXPECT_TRUE(SaneClientImpl::DeviceListToScannerInfo(two_devices_, &info_));
EXPECT_EQ(info_.size(), 2);
EXPECT_EQ(info_.count(dev_.name), 1);
EXPECT_EQ(info_[dev_.name]["Manufacturer"], dev_.vendor);
EXPECT_EQ(info_[dev_.name]["Model"], dev_.model);
EXPECT_EQ(info_[dev_.name]["Type"], dev_.type);
EXPECT_EQ(info_.count(dev_two_.name), 1);
EXPECT_EQ(info_[dev_two_.name]["Manufacturer"], dev_two_.vendor);
EXPECT_EQ(info_[dev_two_.name]["Model"], dev_two_.model);
EXPECT_EQ(info_[dev_two_.name]["Type"], dev_.type);
}
} // namespace lorgnette