blob: 293ccb234eb2f4c802c36bb5a9f5c385371fd40e [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 "src/ui/a11y/lib/configuration/color_transform_manager.h"
#include <fuchsia/accessibility/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/sys/cpp/testing/component_context_provider.h>
#include <lib/syslog/cpp/macros.h>
#include <cmath>
#include <gtest/gtest.h>
#include "src/lib/testing/loop_fixture/test_loop_fixture.h"
namespace accessibility_test {
namespace {
// clang-format off
const std::array<float, 9> kIdentityMatrix = {
1, 0, 0,
0, 1, 0,
0, 0, 1};
const std::array<float, 3> kZero3x1Vector = {0, 0, 0};
const std::array<float, 9> kColorInversionMatrix = {
0.402f, -1.174f, -0.228f,
-0.598f, -0.174f, -0.228f,
-0.599f, -1.177f, 0.771f};
const std::array<float, 3> kColorInversionPostOffset = {.999f, .999f, .999f};
const std::array<float, 9> kCorrectProtanomaly = {
0.622774, 0.377226, 0.000000,
0.264275, 0.735725, -0.000000,
0.216821, -0.216821, 1.000000};
const std::array<float, 9> kProtanomalyAndInversionMatrix = {
-0.10933889, -0.66266111, -0.228,
-0.46783789, -0.30416211, -0.228,
-0.51692431, -1.25907569, 0.771};
const std::array<float, 3> kProtanomalyAndInversionPostOffset = {.999f, .999f, .999f};
// clang-format on
class FakeColorTransformHandler : public fuchsia::accessibility::ColorTransformHandler {
public:
FakeColorTransformHandler() = default;
~FakeColorTransformHandler() = default;
fidl::InterfaceHandle<fuchsia::accessibility::ColorTransformHandler> GetHandle() {
return bindings_.AddBinding(this);
}
// |fuchsia.accessibility.ColorTransformHandler|
void SetColorTransformConfiguration(
fuchsia::accessibility::ColorTransformConfiguration configuration,
SetColorTransformConfigurationCallback callback) {
transform_ = configuration.has_color_adjustment_matrix()
? configuration.color_adjustment_matrix()
: kIdentityMatrix;
pre_offset_ = configuration.has_color_adjustment_pre_offset()
? configuration.color_adjustment_pre_offset()
: kZero3x1Vector;
post_offset_ = configuration.has_color_adjustment_post_offset()
? configuration.color_adjustment_post_offset()
: kZero3x1Vector;
color_inversion_enabled_ = configuration.has_color_inversion_enabled()
? configuration.color_inversion_enabled()
: false;
color_correction_mode_ = configuration.has_color_correction()
? configuration.color_correction()
: fuchsia::accessibility::ColorCorrectionMode::DISABLED;
callback();
}
bool hasTransform(std::array<float, 9> transform_to_compare) const {
return FloatArraysAreEqual(transform_, transform_to_compare);
}
bool hasPostOffset(std::array<float, 3> offset_to_compare) const {
return FloatArraysAreEqual(post_offset_, offset_to_compare);
}
fidl::BindingSet<fuchsia::accessibility::ColorTransformHandler> bindings_;
std::array<float, 9> transform_;
std::array<float, 3> pre_offset_;
std::array<float, 3> post_offset_;
// These fields `has_value()` iff SetColorTransformConfiguration() has been called.
std::optional<bool> color_inversion_enabled_;
std::optional<fuchsia::accessibility::ColorCorrectionMode> color_correction_mode_;
private:
template <size_t N>
static bool FloatArraysAreEqual(const std::array<float, N>& a, const std::array<float, N>& b) {
const float float_comparison_epsilon = 0.00001;
for (size_t i = 0; i < N; i++) {
if ((std::fabs(a[i] - b[i]) > float_comparison_epsilon)) {
return false;
}
}
return true;
}
};
class ColorTransformManagerTest : public gtest::TestLoopFixture {
public:
ColorTransformManagerTest() = default;
~ColorTransformManagerTest() override = default;
void SetUp() override {
TestLoopFixture::SetUp();
startup_context_ = sys::ComponentContext::CreateAndServeOutgoingDirectory();
color_transform_manager_ =
std::make_unique<a11y::ColorTransformManager>(startup_context_.get());
RunLoopUntilIdle();
}
std::unique_ptr<sys::ComponentContext> startup_context_;
std::unique_ptr<a11y::ColorTransformManager> color_transform_manager_;
FakeColorTransformHandler color_transform_handler_;
fidl::BindingSet<fuchsia::accessibility::ColorTransform> color_transform_bindings_;
};
TEST_F(ColorTransformManagerTest, NoHandler) {
// change a setting
color_transform_manager_->ChangeColorTransform(
false, fuchsia::accessibility::ColorCorrectionMode::DISABLED);
RunLoopUntilIdle();
// This test is verifying that nothing crashes.
}
TEST_F(ColorTransformManagerTest, SetColorTransformDefault) {
// register a (fake) handler
color_transform_manager_->RegisterColorTransformHandler(color_transform_handler_.GetHandle());
// change a setting
color_transform_manager_->ChangeColorTransform(
false, fuchsia::accessibility::ColorCorrectionMode::DISABLED);
RunLoopUntilIdle();
// Verify handler gets sent the correct settings.
ASSERT_TRUE(color_transform_handler_.color_inversion_enabled_.has_value());
EXPECT_FALSE(color_transform_handler_.color_inversion_enabled_.value());
ASSERT_TRUE(color_transform_handler_.color_correction_mode_.has_value());
EXPECT_EQ(color_transform_handler_.color_correction_mode_.value(),
fuchsia::accessibility::ColorCorrectionMode::DISABLED);
EXPECT_TRUE(color_transform_handler_.hasTransform(kIdentityMatrix));
}
TEST_F(ColorTransformManagerTest, SetColorInversionEnabled) {
// register a (fake) handler
color_transform_manager_->RegisterColorTransformHandler(color_transform_handler_.GetHandle());
// change a setting
color_transform_manager_->ChangeColorTransform(
true, fuchsia::accessibility::ColorCorrectionMode::DISABLED);
RunLoopUntilIdle();
// Verify handler gets sent the correct settings.
ASSERT_TRUE(color_transform_handler_.color_inversion_enabled_.has_value());
EXPECT_TRUE(color_transform_handler_.color_inversion_enabled_.value());
ASSERT_TRUE(color_transform_handler_.color_correction_mode_.has_value());
EXPECT_EQ(color_transform_handler_.color_correction_mode_.value(),
fuchsia::accessibility::ColorCorrectionMode::DISABLED);
EXPECT_TRUE(color_transform_handler_.hasTransform(kColorInversionMatrix));
EXPECT_TRUE(color_transform_handler_.hasPostOffset(kColorInversionPostOffset));
}
TEST_F(ColorTransformManagerTest, SetColorCorrection) {
// register a (fake) handler
color_transform_manager_->RegisterColorTransformHandler(color_transform_handler_.GetHandle());
// change a setting
color_transform_manager_->ChangeColorTransform(
false, fuchsia::accessibility::ColorCorrectionMode::CORRECT_PROTANOMALY);
RunLoopUntilIdle();
// Verify handler gets sent the correct settings.
ASSERT_TRUE(color_transform_handler_.color_inversion_enabled_.has_value());
EXPECT_FALSE(color_transform_handler_.color_inversion_enabled_.value());
ASSERT_TRUE(color_transform_handler_.color_correction_mode_.has_value());
EXPECT_EQ(color_transform_handler_.color_correction_mode_.value(),
fuchsia::accessibility::ColorCorrectionMode::CORRECT_PROTANOMALY);
EXPECT_TRUE(color_transform_handler_.hasTransform(kCorrectProtanomaly));
}
TEST_F(ColorTransformManagerTest, SetColorCorrectionAndInversion) {
// register a (fake) handler
color_transform_manager_->RegisterColorTransformHandler(color_transform_handler_.GetHandle());
// change a setting
color_transform_manager_->ChangeColorTransform(
true, fuchsia::accessibility::ColorCorrectionMode::CORRECT_PROTANOMALY);
RunLoopUntilIdle();
// Verify handler gets sent the correct settings.
ASSERT_TRUE(color_transform_handler_.color_inversion_enabled_.has_value());
EXPECT_TRUE(color_transform_handler_.color_inversion_enabled_.value());
ASSERT_TRUE(color_transform_handler_.color_correction_mode_.has_value());
EXPECT_EQ(color_transform_handler_.color_correction_mode_.value(),
fuchsia::accessibility::ColorCorrectionMode::CORRECT_PROTANOMALY);
EXPECT_TRUE(color_transform_handler_.hasTransform(kProtanomalyAndInversionMatrix));
EXPECT_TRUE(color_transform_handler_.hasPostOffset(kProtanomalyAndInversionPostOffset));
}
TEST_F(ColorTransformManagerTest, BuffersChangeBeforeHandlerRegistered) {
// Enable color inversion and color correction.
color_transform_manager_->ChangeColorTransform(
true, fuchsia::accessibility::ColorCorrectionMode::CORRECT_DEUTERANOMALY);
RunLoopUntilIdle();
// Register the (fake) handler.
color_transform_manager_->RegisterColorTransformHandler(color_transform_handler_.GetHandle());
RunLoopUntilIdle();
// Verify handler gets sent the correct settings.
ASSERT_TRUE(color_transform_handler_.color_inversion_enabled_.has_value());
EXPECT_TRUE(color_transform_handler_.color_inversion_enabled_.value());
ASSERT_TRUE(color_transform_handler_.color_correction_mode_.has_value());
EXPECT_EQ(color_transform_handler_.color_correction_mode_.value(),
fuchsia::accessibility::ColorCorrectionMode::CORRECT_DEUTERANOMALY);
}
TEST_F(ColorTransformManagerTest, ReappliesSettingOnHandlerChange) {
// Enable color inversion and color correction.
color_transform_manager_->ChangeColorTransform(
true, fuchsia::accessibility::ColorCorrectionMode::CORRECT_DEUTERANOMALY);
RunLoopUntilIdle();
// Register the (fake) handler.
color_transform_manager_->RegisterColorTransformHandler(color_transform_handler_.GetHandle());
RunLoopUntilIdle();
// Create and register a new (fake) handler.
FakeColorTransformHandler new_handler;
color_transform_manager_->RegisterColorTransformHandler(new_handler.GetHandle());
RunLoopUntilIdle();
// Verify the new handler gets sent the correct settings.
ASSERT_TRUE(new_handler.color_inversion_enabled_.has_value());
EXPECT_TRUE(new_handler.color_inversion_enabled_.value());
ASSERT_TRUE(new_handler.color_correction_mode_.has_value());
EXPECT_EQ(new_handler.color_correction_mode_.value(),
fuchsia::accessibility::ColorCorrectionMode::CORRECT_DEUTERANOMALY);
}
} // namespace
} // namespace accessibility_test