910e62b5创建于 1月15日历史提交
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/accessibility/ax_enum_util.h"

#include <string>
#include <vector>

#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"

namespace ui {

// Templatized function that tests that for a mojom enum
// such as ax::mojom::Role, ax::mojom::Event, etc. we can
// call ToString() on the enum to get a string, and then
// ParseAXEnum() on the string to get back the original
// value. Also tests what happens when we call ToString
// or ParseAXEnum on a bogus value.
template <typename T>
void TestEnumStringConversion(
    int32_t(step)(int32_t) = [](int32_t val) { return val + 1; }) {
  // Check every valid enum value.
  for (int i = static_cast<int>(T::kMinValue);
       i <= static_cast<int>(T::kMaxValue); i = step(i)) {
    T src = static_cast<T>(i);
    std::string str = ToString(src);
    auto dst = ParseAXEnum<T>(str.c_str());
    EXPECT_EQ(src, dst);
  }

  // Trying to parse a bogus string should crash.
  // TODO(http://crbug.com/1129919) - try to re-enable this death test.
  // EXPECT_DEATH_IF_SUPPORTED(ParseAXEnum<T>("bogus"), "Check failed");

  // Parse the empty string.
  EXPECT_EQ(T::kNone, ParseAXEnum<T>(""));

  // Convert a bogus value to a string.
  int out_of_range_value = static_cast<int>(T::kMaxValue) + 1;
  EXPECT_STREQ("", ToString(static_cast<T>(out_of_range_value)));
}

// Templatized function that tries calling a setter on AXNodeData
// such as AddIntAttribute, AddFloatAttribute - with each possible
// enum value.
//
// This variant is for cases where the value type is an object.
template <typename T, typename U>
void TestAXNodeDataSetter(void (AXNodeData::*Setter)(T, const U&),
                          const U& value) {
  AXNodeData node_data;
  for (int i = static_cast<int>(T::kMinValue) + 1;
       i <= static_cast<int>(T::kMaxValue); ++i) {
    T attr = static_cast<T>(i);
    ((node_data).*(Setter))(attr, value);
  }
  EXPECT_TRUE(!node_data.ToString().empty());
}

// Same as TextAXNodeData, above, but This variant is for
// cases where the value type is POD.
template <typename T, typename U>
void TestAXNodeDataSetter(void (AXNodeData::*Setter)(T, U), U value) {
  AXNodeData node_data;
  for (int i = static_cast<int>(T::kMinValue) + 1;
       i <= static_cast<int>(T::kMaxValue); ++i) {
    T attr = static_cast<T>(i);
    ((node_data).*(Setter))(attr, value);
  }
  EXPECT_TRUE(!node_data.ToString().empty());
}

TEST(AXEnumUtilTest, Event) {
  TestEnumStringConversion<ax::mojom::Event>();
}

TEST(AXEnumUtilTest, Role) {
  TestEnumStringConversion<ax::mojom::Role>();
}

TEST(AXEnumUtilTest, State) {
  TestEnumStringConversion<ax::mojom::State>();
}

TEST(AXEnumUtilTest, Action) {
  TestEnumStringConversion<ax::mojom::Action>();
}

TEST(AXEnumUtilTest, ActionFlags) {
  TestEnumStringConversion<ax::mojom::ActionFlags>();
}

TEST(AXEnumUtilTest, DefaultActionVerb) {
  TestEnumStringConversion<ax::mojom::DefaultActionVerb>();
}

TEST(AXEnumUtilTest, Mutation) {
  TestEnumStringConversion<ax::mojom::Mutation>();
}

TEST(AXEnumUtilTest, StringAttribute) {
  TestEnumStringConversion<ax::mojom::StringAttribute>();

  AXNodeData node_data;
  for (int i = static_cast<int>(ax::mojom::StringAttribute::kMinValue) + 1;
       i <= static_cast<int>(ax::mojom::StringAttribute::kMaxValue); ++i) {
    ax::mojom::StringAttribute attr =
        static_cast<ax::mojom::StringAttribute>(i);
    if (attr == ax::mojom::StringAttribute::kChildTreeId)
      continue;
    node_data.AddStringAttribute(attr, std::string());
  }
  EXPECT_TRUE(!node_data.ToString().empty());
}

TEST(AXEnumUtilTest, IntAttribute) {
  TestEnumStringConversion<ax::mojom::IntAttribute>();
  TestAXNodeDataSetter<ax::mojom::IntAttribute>(&AXNodeData::AddIntAttribute,
                                                0);
}

TEST(AXEnumUtilTest, FloatAttribute) {
  TestEnumStringConversion<ax::mojom::FloatAttribute>();
  TestAXNodeDataSetter<ax::mojom::FloatAttribute>(
      &AXNodeData::AddFloatAttribute, 0.0f);
}

TEST(AXEnumUtilTest, BoolAttribute) {
  TestEnumStringConversion<ax::mojom::BoolAttribute>();
  TestAXNodeDataSetter<ax::mojom::BoolAttribute>(&AXNodeData::AddBoolAttribute,
                                                 false);
}

TEST(AXEnumUtilTest, IntListAttribute) {
  TestEnumStringConversion<ax::mojom::IntListAttribute>();
  TestAXNodeDataSetter<ax::mojom::IntListAttribute>(
      &AXNodeData::AddIntListAttribute, std::vector<int32_t>());
}

TEST(AXEnumUtilTest, StringListAttribute) {
  TestEnumStringConversion<ax::mojom::StringListAttribute>();
  TestAXNodeDataSetter<ax::mojom::StringListAttribute>(
      &AXNodeData::AddStringListAttribute, std::vector<std::string>());
}

TEST(AXEnumUtilTest, MarkerType) {
  TestEnumStringConversion<ax::mojom::MarkerType>(
      [](int32_t val) {
        return val == 0 ? 1 :
                        // 8 (Composition) is
                        // explicitly skipped in
                        // ax_enums.mojom.
                   val == 4 ? 16 : val * 2;
      });
}

TEST(AXEnumUtilTest, Text_Decoration_Style) {
  TestEnumStringConversion<ax::mojom::TextDecorationStyle>();
}

TEST(AXEnumUtilTest, ListStyle) {
  TestEnumStringConversion<ax::mojom::ListStyle>();
}

TEST(AXEnumUtilTest, MoveDirection) {
  TestEnumStringConversion<ax::mojom::MoveDirection>();
}

TEST(AXEnumUtilTest, Command) {
  TestEnumStringConversion<ax::mojom::Command>();
}

TEST(AXEnumUtilTest, InputEventType) {
  TestEnumStringConversion<ax::mojom::InputEventType>();
}

TEST(AXEnumUtilTest, TextBoundary) {
  TestEnumStringConversion<ax::mojom::TextBoundary>();
}

TEST(AXEnumUtilTest, TextAlign) {
  TestEnumStringConversion<ax::mojom::TextAlign>();
}

TEST(AXEnumUtilTest, WritingDirection) {
  TestEnumStringConversion<ax::mojom::WritingDirection>();
}

TEST(AXEnumUtilTest, TextPosition) {
  TestEnumStringConversion<ax::mojom::TextPosition>();
}

TEST(AXEnumUtilTest, TextStyle) {
  TestEnumStringConversion<ax::mojom::TextStyle>();
}

TEST(AXEnumUtilTest, AriaCurrentState) {
  TestEnumStringConversion<ax::mojom::AriaCurrentState>();
}

TEST(AXEnumUtilTest, HasPopup) {
  TestEnumStringConversion<ax::mojom::HasPopup>();
}

TEST(AXEnumUtilTest, InvalidState) {
  TestEnumStringConversion<ax::mojom::InvalidState>();
}

TEST(AXEnumUtilTest, Restriction) {
  TestEnumStringConversion<ax::mojom::Restriction>();
}

TEST(AXEnumUtilTest, CheckedState) {
  TestEnumStringConversion<ax::mojom::CheckedState>();
}

TEST(AXEnumUtilTest, SortDirection) {
  TestEnumStringConversion<ax::mojom::SortDirection>();
}

TEST(AXEnumUtilTest, NameFrom) {
  TestEnumStringConversion<ax::mojom::NameFrom>();
}

TEST(AXEnumUtilTest, DescriptionFrom) {
  TestEnumStringConversion<ax::mojom::DescriptionFrom>();
}

TEST(AXEnumUtilTest, EventFrom) {
  TestEnumStringConversion<ax::mojom::EventFrom>();
}

TEST(AXEnumUtilTest, Gesture) {
  TestEnumStringConversion<ax::mojom::Gesture>();
}

TEST(AXEnumUtilTest, TextAffinity) {
  TestEnumStringConversion<ax::mojom::TextAffinity>();
}

TEST(AXEnumUtilTest, TreeOrder) {
  TestEnumStringConversion<ax::mojom::TreeOrder>();
}

TEST(AXEnumUtilTest, ImageAnnotationStatus) {
  TestEnumStringConversion<ax::mojom::ImageAnnotationStatus>();
}

}  // namespace ui