blob: 75af2b335393d94bfcf73cf931046154f8d63ade [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 "lorgnette/sane_client_impl.h"
#include <iostream>
#include <memory>
#include <vector>
#include <chromeos/dbus/service_constants.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <lorgnette/proto_bindings/lorgnette_service.pb.h>
#include "lorgnette/manager.h"
#include "lorgnette/test_util.h"
using ::testing::ElementsAre;
namespace lorgnette {
class SaneDeviceImplTest : public testing::Test {
protected:
void SetUp() override {
client_ = SaneClientImpl::Create();
device_ = client_->ConnectToDevice(nullptr, "test");
EXPECT_TRUE(device_);
}
void ReloadOptions() {
dynamic_cast<SaneDeviceImpl*>(device_.get())->LoadOptions(nullptr);
}
std::unique_ptr<SaneClient> client_;
std::unique_ptr<SaneDevice> device_;
};
// Check that GetValidOptionValues returns correct values for the test backend.
TEST_F(SaneDeviceImplTest, GetValidOptionValuesSuccess) {
base::Optional<ValidOptionValues> values =
device_->GetValidOptionValues(nullptr);
EXPECT_TRUE(values.has_value());
ASSERT_EQ(values->resolutions.size(), 1200);
for (int i = 0; i < 1200; i++)
EXPECT_EQ(values->resolutions[i], i + 1);
EXPECT_THAT(values->sources,
ElementsAre(EqualsDocumentSource(CreateDocumentSource(
"Flatbed", SOURCE_PLATEN, 200.0, 200.0)),
EqualsDocumentSource(CreateDocumentSource(
"Automatic Document Feeder", SOURCE_ADF_SIMPLEX,
200.0, 200.0))));
EXPECT_THAT(values->color_modes,
ElementsAre(kScanPropertyModeGray, kScanPropertyModeColor));
}
// Check that SetScanResolution works for all valid values.
TEST_F(SaneDeviceImplTest, SetResolution) {
base::Optional<ValidOptionValues> values =
device_->GetValidOptionValues(nullptr);
EXPECT_TRUE(values.has_value());
for (int resolution : values->resolutions)
EXPECT_TRUE(device_->SetScanResolution(nullptr, resolution));
}
// Check the SetDocumentSource rejects invalid values and works properly for all
// valid values. Also check that GetDocumentSource returns that correct value
// after SetDocumentSource, even if we force-reload option values from scanner.
TEST_F(SaneDeviceImplTest, SetSource) {
EXPECT_FALSE(device_->SetDocumentSource(nullptr, "invalid source"));
base::Optional<ValidOptionValues> values =
device_->GetValidOptionValues(nullptr);
EXPECT_TRUE(values.has_value());
// Test both with and without reloading options after setting option, since
// it can surface different bugs.
for (bool reload_options : {true, false}) {
LOG(INFO) << "Testing " << (reload_options ? "with" : "without")
<< " option reloading.";
for (const DocumentSource& source : values->sources) {
EXPECT_TRUE(device_->SetDocumentSource(nullptr, source.name()));
if (reload_options) {
ReloadOptions();
}
base::Optional<std::string> scanner_value =
device_->GetDocumentSource(nullptr);
EXPECT_TRUE(scanner_value.has_value());
EXPECT_EQ(scanner_value.value(), source.name());
}
}
}
// Check that SetColorMode rejects invalid values, and accepts all valid values.
TEST_F(SaneDeviceImplTest, SetColorMode) {
EXPECT_FALSE(device_->SetColorMode(nullptr, MODE_UNSPECIFIED));
base::Optional<ValidOptionValues> values =
device_->GetValidOptionValues(nullptr);
EXPECT_TRUE(values.has_value());
for (const std::string& mode_string : values->color_modes) {
ColorMode mode = impl::ColorModeFromSaneString(mode_string);
EXPECT_NE(mode, MODE_UNSPECIFIED)
<< "Unexpected ColorMode string " << mode_string;
EXPECT_TRUE(device_->SetColorMode(nullptr, mode));
}
}
// Check that extra calls to StartScan fail properly.
TEST_F(SaneDeviceImplTest, DuplicateStartScan) {
EXPECT_EQ(device_->StartScan(nullptr), SANE_STATUS_GOOD);
EXPECT_EQ(device_->StartScan(nullptr), SANE_STATUS_DEVICE_BUSY);
}
// Check that GetScanParameters returns the correct values corresponding to the
// input resolution and scan region.
TEST_F(SaneDeviceImplTest, GetScanParameters) {
const int resolution = 100; /* dpi */
EXPECT_TRUE(device_->SetScanResolution(nullptr, resolution));
const double width = 187; /* mm */
const double height = 123; /* mm */
ScanRegion region;
region.set_top_left_x(0);
region.set_top_left_y(0);
region.set_bottom_right_x(width);
region.set_bottom_right_y(height);
EXPECT_TRUE(device_->SetScanRegion(nullptr, region));
base::Optional<ScanParameters> params = device_->GetScanParameters(nullptr);
EXPECT_TRUE(params.has_value());
EXPECT_TRUE(params->format == kGrayscale);
const double mms_per_inch = 25.4;
EXPECT_EQ(params->bytes_per_line,
static_cast<int>(width / mms_per_inch * resolution));
EXPECT_EQ(params->pixels_per_line,
static_cast<int>(width / mms_per_inch * resolution));
EXPECT_EQ(params->lines,
static_cast<int>(height / mms_per_inch * resolution));
EXPECT_EQ(params->depth, 8);
}
// Check that ReadScanData fails when we haven't started a scan.
TEST_F(SaneDeviceImplTest, ReadScanDataWhenNotStarted) {
std::vector<uint8_t> buf(8192);
size_t read = 0;
EXPECT_EQ(device_->ReadScanData(nullptr, buf.data(), buf.size(), &read),
SANE_STATUS_INVAL);
}
// Check that ReadScanData fails with invalid input pointers.
TEST_F(SaneDeviceImplTest, ReadScanDataBadPointers) {
std::vector<uint8_t> buf(8192);
size_t read = 0;
EXPECT_EQ(device_->StartScan(nullptr), SANE_STATUS_GOOD);
EXPECT_EQ(device_->ReadScanData(nullptr, nullptr, buf.size(), &read),
SANE_STATUS_INVAL);
EXPECT_EQ(device_->ReadScanData(nullptr, buf.data(), buf.size(), nullptr),
SANE_STATUS_INVAL);
}
// Check that we can successfully run a scan to completion.
TEST_F(SaneDeviceImplTest, RunScan) {
std::vector<uint8_t> buf(8192);
size_t read = 0;
EXPECT_EQ(device_->StartScan(nullptr), SANE_STATUS_GOOD);
SANE_Status status = SANE_STATUS_GOOD;
do {
status = device_->ReadScanData(nullptr, buf.data(), buf.size(), &read);
} while (status == SANE_STATUS_GOOD && read != 0);
EXPECT_EQ(read, 0);
EXPECT_EQ(status, SANE_STATUS_EOF);
}
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};
};
TEST_F(SaneClientTest, ScannerInfoFromDeviceListInvalidParameters) {
EXPECT_FALSE(SaneClientImpl::DeviceListToScannerInfo(NULL).has_value());
}
TEST_F(SaneClientTest, ScannerInfoFromDeviceListNoDevices) {
base::Optional<std::vector<ScannerInfo>> info =
SaneClientImpl::DeviceListToScannerInfo(empty_devices_);
EXPECT_TRUE(info.has_value());
EXPECT_EQ(info->size(), 0);
}
TEST_F(SaneClientTest, ScannerInfoFromDeviceListOneDevice) {
base::Optional<std::vector<ScannerInfo>> opt_info =
SaneClientImpl::DeviceListToScannerInfo(one_device_);
EXPECT_TRUE(opt_info.has_value());
std::vector<ScannerInfo> info = opt_info.value();
ASSERT_EQ(info.size(), 1);
EXPECT_EQ(info[0].name(), dev_.name);
EXPECT_EQ(info[0].manufacturer(), dev_.vendor);
EXPECT_EQ(info[0].model(), dev_.model);
EXPECT_EQ(info[0].type(), dev_.type);
}
TEST_F(SaneClientTest, ScannerInfoFromDeviceListNullFields) {
dev_ = CreateTestDevice();
dev_.name = NULL;
base::Optional<std::vector<ScannerInfo>> opt_info =
SaneClientImpl::DeviceListToScannerInfo(one_device_);
EXPECT_TRUE(opt_info.has_value());
EXPECT_EQ(opt_info->size(), 0);
dev_ = CreateTestDevice();
dev_.vendor = NULL;
opt_info = SaneClientImpl::DeviceListToScannerInfo(one_device_);
EXPECT_TRUE(opt_info.has_value());
std::vector<ScannerInfo> info = opt_info.value();
ASSERT_EQ(info.size(), 1);
EXPECT_EQ(info[0].name(), dev_.name);
EXPECT_EQ(info[0].manufacturer(), "");
EXPECT_EQ(info[0].model(), dev_.model);
EXPECT_EQ(info[0].type(), dev_.type);
dev_ = CreateTestDevice();
dev_.model = NULL;
opt_info = SaneClientImpl::DeviceListToScannerInfo(one_device_);
EXPECT_TRUE(opt_info.has_value());
info = opt_info.value();
ASSERT_EQ(info.size(), 1);
EXPECT_EQ(info[0].name(), dev_.name);
EXPECT_EQ(info[0].manufacturer(), dev_.vendor);
EXPECT_EQ(info[0].model(), "");
EXPECT_EQ(info[0].type(), dev_.type);
dev_ = CreateTestDevice();
dev_.type = NULL;
opt_info = SaneClientImpl::DeviceListToScannerInfo(one_device_);
EXPECT_TRUE(opt_info.has_value());
info = opt_info.value();
ASSERT_EQ(info.size(), 1);
EXPECT_EQ(info[0].name(), dev_.name);
EXPECT_EQ(info[0].manufacturer(), dev_.vendor);
EXPECT_EQ(info[0].model(), dev_.model);
EXPECT_EQ(info[0].type(), "");
}
TEST_F(SaneClientTest, ScannerInfoFromDeviceListMultipleDevices) {
base::Optional<std::vector<ScannerInfo>> opt_info =
SaneClientImpl::DeviceListToScannerInfo(two_devices_);
EXPECT_FALSE(opt_info.has_value());
dev_two_.name = "Test Device 2";
dev_two_.vendor = "Test Vendor 2";
opt_info = SaneClientImpl::DeviceListToScannerInfo(two_devices_);
EXPECT_TRUE(opt_info.has_value());
std::vector<ScannerInfo> info = opt_info.value();
ASSERT_EQ(info.size(), 2);
EXPECT_EQ(info[0].name(), dev_.name);
EXPECT_EQ(info[0].manufacturer(), dev_.vendor);
EXPECT_EQ(info[0].model(), dev_.model);
EXPECT_EQ(info[0].type(), dev_.type);
EXPECT_EQ(info[1].name(), dev_two_.name);
EXPECT_EQ(info[1].manufacturer(), dev_two_.vendor);
EXPECT_EQ(info[1].model(), dev_two_.model);
EXPECT_EQ(info[1].type(), dev_two_.type);
}
namespace {
SANE_Option_Descriptor CreateDescriptor(const char* name,
SANE_Value_Type type,
int size) {
SANE_Option_Descriptor desc;
desc.name = name;
desc.type = type;
desc.constraint_type = SANE_CONSTRAINT_NONE;
desc.size = size;
return desc;
}
} // namespace
TEST(SaneOptionIntTest, SetIntSucceeds) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_INT, sizeof(SANE_Word)), 7);
EXPECT_TRUE(option.Set(54));
EXPECT_EQ(*static_cast<SANE_Int*>(option.GetPointer()), 54);
}
TEST(SaneOptionIntTest, SetDoubleSucceeds) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_INT, sizeof(SANE_Word)), 7);
// Should round towards 0.
EXPECT_TRUE(option.Set(295.7));
EXPECT_EQ(option.Get<int>().value(), 295);
}
TEST(SaneOptionIntTest, SetStringFails) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_INT, sizeof(SANE_Word)), 7);
EXPECT_TRUE(option.Set(17));
EXPECT_FALSE(option.Set("test"));
EXPECT_EQ(option.Get<int>().value(), 17);
}
TEST(SaneOptionIntTest, GetIndex) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_INT, sizeof(SANE_Word)), 7);
EXPECT_EQ(option.GetIndex(), 7);
}
TEST(SaneOptionIntTest, GetName) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_INT, sizeof(SANE_Word)), 7);
EXPECT_EQ(option.GetName(), "Test Name");
}
TEST(SaneOptionIntTest, DisplayValue) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_INT, sizeof(SANE_Word)), 2);
EXPECT_TRUE(option.Set(247));
EXPECT_EQ(option.DisplayValue(), "247");
}
TEST(SaneOptionIntTest, CopiesDoNotAlias) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_INT, sizeof(SANE_Word)), 2);
EXPECT_TRUE(option.Set(88));
EXPECT_EQ(option.DisplayValue(), "88");
SaneOption option_two = option;
EXPECT_TRUE(option_two.Set(9));
EXPECT_EQ(option_two.DisplayValue(), "9");
EXPECT_EQ(option.DisplayValue(), "88");
}
TEST(SaneOptionFixedTest, SetIntSucceeds) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_FIXED, sizeof(SANE_Word)), 7);
EXPECT_TRUE(option.Set(54));
SANE_Fixed f = *static_cast<SANE_Fixed*>(option.GetPointer());
EXPECT_EQ(static_cast<int>(SANE_UNFIX(f)), 54);
}
TEST(SaneOptionFixedTest, SetDoubleSucceeds) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_FIXED, sizeof(SANE_Word)), 7);
EXPECT_TRUE(option.Set(436.2));
SANE_Fixed f = *static_cast<SANE_Fixed*>(option.GetPointer());
EXPECT_FLOAT_EQ(SANE_UNFIX(f), 436.2);
}
TEST(SaneOptionFixedTest, SetStringFails) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_FIXED, sizeof(SANE_Word)), 7);
EXPECT_TRUE(option.Set(17));
EXPECT_FALSE(option.Set("test"));
SANE_Fixed f = *static_cast<SANE_Fixed*>(option.GetPointer());
EXPECT_EQ(static_cast<int>(SANE_UNFIX(f)), 17);
}
TEST(SaneOptionFixedTest, GetIndex) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_FIXED, sizeof(SANE_Word)), 7);
EXPECT_EQ(option.GetIndex(), 7);
}
TEST(SaneOptionFixedTest, GetName) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_FIXED, sizeof(SANE_Word)), 7);
EXPECT_EQ(option.GetName(), "Test Name");
}
TEST(SaneOptionFixedTest, DisplayValue) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_FIXED, sizeof(SANE_Word)), 2);
EXPECT_TRUE(option.Set(247));
EXPECT_EQ(option.DisplayValue(), "247");
}
TEST(SaneOptionFixedTest, CopiesDoNotAlias) {
SaneOption option(
CreateDescriptor("Test Name", SANE_TYPE_FIXED, sizeof(SANE_Word)), 2);
EXPECT_TRUE(option.Set(88));
EXPECT_EQ(option.DisplayValue(), "88");
SaneOption option_two = option;
EXPECT_TRUE(option_two.Set(9));
EXPECT_EQ(option_two.DisplayValue(), "9");
EXPECT_EQ(option.DisplayValue(), "88");
}
TEST(SaneOptionStringTest, SetStringSucceeds) {
SaneOption option(CreateDescriptor("Test Name", SANE_TYPE_STRING, 8), 7);
EXPECT_TRUE(option.Set("test"));
EXPECT_STREQ(static_cast<char*>(option.GetPointer()), "test");
// Longest string that fits (with null terminator).
EXPECT_TRUE(option.Set("1234567"));
EXPECT_STREQ(static_cast<char*>(option.GetPointer()), "1234567");
}
TEST(SaneOptionStringTest, SetStringTooLongFails) {
SaneOption option(CreateDescriptor("Test Name", SANE_TYPE_STRING, 8), 7);
EXPECT_TRUE(option.Set("test"));
// String that is exactly one character too long.
EXPECT_FALSE(option.Set("12345678"));
// String that is many characters too long.
EXPECT_FALSE(option.Set("This is a much longer string than can fit."));
EXPECT_STREQ(static_cast<char*>(option.GetPointer()), "test");
}
TEST(SaneOptionStringTest, SetIntFails) {
SaneOption option(CreateDescriptor("Test Name", SANE_TYPE_STRING, 32), 7);
EXPECT_TRUE(option.Set("test"));
EXPECT_FALSE(option.Set(54));
EXPECT_STREQ(static_cast<char*>(option.GetPointer()), "test");
}
TEST(SaneOptionStringTest, GetIndex) {
SaneOption option(CreateDescriptor("Test Name", SANE_TYPE_STRING, 32), 7);
EXPECT_EQ(option.GetIndex(), 7);
}
TEST(SaneOptionStringTest, GetName) {
SaneOption option(CreateDescriptor("Test Name", SANE_TYPE_STRING, 32), 7);
EXPECT_EQ(option.GetName(), "Test Name");
}
TEST(SaneOptionStringTest, DisplayValue) {
SaneOption option(CreateDescriptor("Test Name", SANE_TYPE_STRING, 32), 2);
EXPECT_TRUE(option.Set("test string"));
EXPECT_EQ(option.DisplayValue(), "test string");
}
TEST(SaneOptionStringTest, CopiesDoNotAlias) {
SaneOption option(CreateDescriptor("Test Name", SANE_TYPE_STRING, 32), 2);
EXPECT_TRUE(option.Set("test string"));
EXPECT_EQ(option.DisplayValue(), "test string");
SaneOption option_two = option;
EXPECT_TRUE(option_two.Set("other value"));
EXPECT_EQ(option.DisplayValue(), "test string");
EXPECT_EQ(option_two.DisplayValue(), "other value");
}
TEST(ValidOptionValues, InvalidDescriptorWordList) {
SANE_Option_Descriptor desc;
desc.constraint_type = SANE_CONSTRAINT_STRING_LIST;
std::vector<SANE_String_Const> valid_values = {nullptr};
desc.constraint.string_list = valid_values.data();
base::Optional<std::vector<uint32_t>> values =
SaneDeviceImpl::GetValidIntOptionValues(nullptr, desc);
EXPECT_FALSE(values.has_value());
}
TEST(ValidOptionValues, EmptyWordList) {
SANE_Option_Descriptor desc;
desc.constraint_type = SANE_CONSTRAINT_WORD_LIST;
std::vector<SANE_Word> valid_values = {0};
desc.constraint.word_list = valid_values.data();
base::Optional<std::vector<uint32_t>> values =
SaneDeviceImpl::GetValidIntOptionValues(nullptr, desc);
EXPECT_TRUE(values.has_value());
EXPECT_EQ(values.value().size(), 0);
}
TEST(ValidOptionValues, NonEmptyWordList) {
SANE_Option_Descriptor desc;
desc.constraint_type = SANE_CONSTRAINT_WORD_LIST;
std::vector<SANE_Word> valid_values = {4, 0, 729, 368234, 15};
desc.constraint.word_list = valid_values.data();
base::Optional<std::vector<uint32_t>> values =
SaneDeviceImpl::GetValidIntOptionValues(nullptr, desc);
EXPECT_TRUE(values.has_value());
EXPECT_EQ(values.value().size(), 4);
EXPECT_EQ(values.value(), std::vector<uint32_t>({0, 729, 368234, 15}));
}
TEST(ValidOptionValues, InvalidDescriptorRangeList) {
SANE_Option_Descriptor desc;
desc.constraint_type = SANE_CONSTRAINT_RANGE;
SANE_Range range;
desc.constraint.range = &range;
base::Optional<std::vector<std::string>> values =
SaneDeviceImpl::GetValidStringOptionValues(nullptr, desc);
EXPECT_FALSE(values.has_value());
}
TEST(ValidOptionValues, EmptyRangeList) {
SANE_Option_Descriptor desc;
desc.constraint_type = SANE_CONSTRAINT_RANGE;
SANE_Range range;
range.min = 5;
range.max = 4;
range.quant = 1;
desc.constraint.range = &range;
base::Optional<std::vector<uint32_t>> values =
SaneDeviceImpl::GetValidIntOptionValues(nullptr, desc);
EXPECT_TRUE(values.has_value());
EXPECT_EQ(values.value().size(), 0);
}
TEST(ValidOptionValues, SingleStepRangeList) {
SANE_Option_Descriptor desc;
desc.constraint_type = SANE_CONSTRAINT_RANGE;
SANE_Range range;
range.min = 5;
range.max = 11;
range.quant = 1;
desc.constraint.range = &range;
base::Optional<std::vector<uint32_t>> values =
SaneDeviceImpl::GetValidIntOptionValues(nullptr, desc);
EXPECT_TRUE(values.has_value());
EXPECT_EQ(values.value(), std::vector<uint32_t>({5, 6, 7, 8, 9, 10, 11}));
}
TEST(ValidOptionValues, FourStepRangeList) {
SANE_Option_Descriptor desc;
desc.constraint_type = SANE_CONSTRAINT_RANGE;
SANE_Range range;
range.min = 13;
range.max = 28;
range.quant = 4;
desc.constraint.range = &range;
base::Optional<std::vector<uint32_t>> values =
SaneDeviceImpl::GetValidIntOptionValues(nullptr, desc);
EXPECT_TRUE(values.has_value());
EXPECT_EQ(values.value(), std::vector<uint32_t>({13, 17, 21, 25}));
}
TEST(ValidOptionValues, InvalidDescriptorStringList) {
SANE_Option_Descriptor desc;
desc.constraint_type = SANE_CONSTRAINT_WORD_LIST;
std::vector<SANE_Word> valid_values = {4, 0, 729, 368234, 15};
desc.constraint.word_list = valid_values.data();
base::Optional<std::vector<std::string>> values =
SaneDeviceImpl::GetValidStringOptionValues(nullptr, desc);
EXPECT_FALSE(values.has_value());
}
TEST(ValidOptionValues, EmptyStringList) {
SANE_Option_Descriptor desc;
desc.constraint_type = SANE_CONSTRAINT_STRING_LIST;
std::vector<SANE_String_Const> valid_values = {nullptr};
desc.constraint.string_list = valid_values.data();
base::Optional<std::vector<std::string>> values =
SaneDeviceImpl::GetValidStringOptionValues(nullptr, desc);
EXPECT_TRUE(values.has_value());
EXPECT_EQ(values.value().size(), 0);
}
TEST(ValidOptionValues, NonEmptyStringList) {
SANE_Option_Descriptor desc;
desc.constraint_type = SANE_CONSTRAINT_STRING_LIST;
std::vector<SANE_String_Const> valid_values = {"Color", "Gray", "Lineart",
nullptr};
desc.constraint.string_list = valid_values.data();
base::Optional<std::vector<std::string>> values =
SaneDeviceImpl::GetValidStringOptionValues(nullptr, desc);
desc.constraint.string_list = valid_values.data();
values = SaneDeviceImpl::GetValidStringOptionValues(nullptr, desc);
EXPECT_TRUE(values.has_value());
EXPECT_EQ(values.value().size(), 3);
EXPECT_EQ(values.value(),
std::vector<std::string>({"Color", "Gray", "Lineart"}));
}
TEST(GetOptionRange, InvalidConstraint) {
SANE_Option_Descriptor desc;
desc.name = "Test";
desc.constraint_type = SANE_CONSTRAINT_WORD_LIST;
EXPECT_FALSE(SaneDeviceImpl::GetOptionRange(nullptr, desc).has_value());
desc.constraint_type = SANE_CONSTRAINT_NONE;
EXPECT_FALSE(SaneDeviceImpl::GetOptionRange(nullptr, desc).has_value());
}
TEST(GetOptionRange, InvalidType) {
SANE_Option_Descriptor desc;
desc.name = "Test";
desc.constraint_type = SANE_CONSTRAINT_RANGE;
SANE_Range range;
range.min = 13;
range.max = 28;
range.quant = 4;
desc.constraint.range = &range;
desc.type = SANE_TYPE_STRING;
EXPECT_FALSE(SaneDeviceImpl::GetOptionRange(nullptr, desc).has_value());
desc.type = SANE_TYPE_BOOL;
EXPECT_FALSE(SaneDeviceImpl::GetOptionRange(nullptr, desc).has_value());
}
TEST(GetOptionRange, ValidFixedValue) {
SANE_Option_Descriptor desc;
desc.name = "Test";
desc.constraint_type = SANE_CONSTRAINT_RANGE;
SANE_Range range;
range.min = SANE_FIX(2.3);
range.max = SANE_FIX(4.9);
range.quant = SANE_FIX(0.1);
desc.constraint.range = &range;
desc.type = SANE_TYPE_FIXED;
base::Optional<OptionRange> range_result =
SaneDeviceImpl::GetOptionRange(nullptr, desc);
EXPECT_TRUE(range_result.has_value());
EXPECT_NEAR(range_result.value().start, 2.3, 1e-4);
EXPECT_NEAR(range_result.value().size, 2.6, 1e-4);
}
TEST(GetOptionRange, ValidIntValue) {
SANE_Option_Descriptor desc;
desc.name = "Test";
desc.constraint_type = SANE_CONSTRAINT_RANGE;
SANE_Range range;
range.min = 3;
range.max = 27;
range.quant = 1;
desc.constraint.range = &range;
desc.type = SANE_TYPE_INT;
base::Optional<OptionRange> range_result =
SaneDeviceImpl::GetOptionRange(nullptr, desc);
EXPECT_TRUE(range_result.has_value());
EXPECT_NEAR(range_result.value().start, 3, 1e-4);
EXPECT_NEAR(range_result.value().size, 24, 1e-4);
}
} // namespace lorgnette