blob: d2234d23842d6b4858f39e6e5fe8e67708871aeb [file]
// Copyright 2018 The Chromium 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 <string>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/keycodes/dom/dom_key.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout_manager.h"
#include "ui/events/keycodes/dom/dom_keyboard_layout_map_base.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
namespace ui {
namespace {
// Represents a keyboard layout where every key is ASCII capable.
constexpr uint32_t kKeyboardLayoutWithAllValidKeys = 1;
// Layout contains all valid keys so this number represents a complete layout.
constexpr uint32_t kKeyboardLayoutWithAllValidKeysCount = 50;
// Represents a keyboard layout where every alpha key is ASCII capable.
constexpr uint32_t kKeyboardLayoutWithAllValidAlphaKeys = 2;
// Layout contains all valid alpha keys so this number represents a complete
// layout minus two INTL keys which are subbed.
constexpr uint32_t kKeyboardLayoutWithAllValidAlphaKeysCount = 48;
// Represents a keyboard layout where some alpha keys are ASCII capable.
constexpr uint32_t kKeyboardLayoutWithSomeValidKeys = 3;
// The mostly valid keyboard does not pass the 'IsAsciiCapable()' test however
// the DomKeyboardLayoutManager will pass the first layout it has if it doesn't
// find an ASCII capable layout first.
constexpr uint32_t kKeyboardLayoutWithSomeValidKeysCount = 47;
// Represents a keyboard layout where no alpha keys are ASCII capable.
constexpr uint32_t kKeyboardLayoutWithNoValidKeys = 4;
constexpr uint32_t kKeyboardLayoutWithNoValidKeysCount = 0;
DomKey GetKeyFromFullLookupTable(DomCode dom_code) {
// Includes all DomCodes used in |writing_system_key_domcodes|. Tests can
// use this table to retrieve valid DomKeys for each DomCode to simulate a
// 'complete' keyboard layout. They can also use this to construct a partial
// layout with valid DomKey values for the populated entries.
static base::flat_map<DomCode, DomKey> kFullLookupTable(
{{DomCode::DIGIT0, DomKey::Constant<'0'>::Character},
{DomCode::DIGIT1, DomKey::Constant<'1'>::Character},
{DomCode::DIGIT2, DomKey::Constant<'2'>::Character},
{DomCode::DIGIT3, DomKey::Constant<'3'>::Character},
{DomCode::DIGIT4, DomKey::Constant<'4'>::Character},
{DomCode::DIGIT5, DomKey::Constant<'5'>::Character},
{DomCode::DIGIT6, DomKey::Constant<'6'>::Character},
{DomCode::DIGIT7, DomKey::Constant<'7'>::Character},
{DomCode::DIGIT8, DomKey::Constant<'8'>::Character},
{DomCode::DIGIT9, DomKey::Constant<'9'>::Character},
{DomCode::US_A, DomKey::Constant<'a'>::Character},
{DomCode::US_B, DomKey::Constant<'b'>::Character},
{DomCode::US_C, DomKey::Constant<'c'>::Character},
{DomCode::US_D, DomKey::Constant<'d'>::Character},
{DomCode::US_E, DomKey::Constant<'e'>::Character},
{DomCode::US_F, DomKey::Constant<'f'>::Character},
{DomCode::US_G, DomKey::Constant<'g'>::Character},
{DomCode::US_H, DomKey::Constant<'h'>::Character},
{DomCode::US_I, DomKey::Constant<'i'>::Character},
{DomCode::US_J, DomKey::Constant<'j'>::Character},
{DomCode::US_K, DomKey::Constant<'k'>::Character},
{DomCode::US_L, DomKey::Constant<'l'>::Character},
{DomCode::US_M, DomKey::Constant<'m'>::Character},
{DomCode::US_N, DomKey::Constant<'n'>::Character},
{DomCode::US_O, DomKey::Constant<'o'>::Character},
{DomCode::US_P, DomKey::Constant<'p'>::Character},
{DomCode::US_Q, DomKey::Constant<'q'>::Character},
{DomCode::US_R, DomKey::Constant<'r'>::Character},
{DomCode::US_S, DomKey::Constant<'s'>::Character},
{DomCode::US_T, DomKey::Constant<'t'>::Character},
{DomCode::US_U, DomKey::Constant<'u'>::Character},
{DomCode::US_V, DomKey::Constant<'v'>::Character},
{DomCode::US_W, DomKey::Constant<'w'>::Character},
{DomCode::US_X, DomKey::Constant<'x'>::Character},
{DomCode::US_Y, DomKey::Constant<'y'>::Character},
{DomCode::US_Z, DomKey::Constant<'z'>::Character},
{DomCode::BACKQUOTE, DomKey::Constant<'`'>::Character},
{DomCode::MINUS, DomKey::Constant<'-'>::Character},
{DomCode::EQUAL, DomKey::Constant<'='>::Character},
{DomCode::INTL_YEN, DomKey::Constant<0x00A5>::Dead},
{DomCode::BRACKET_LEFT, DomKey::Constant<'{'>::Character},
{DomCode::BRACKET_RIGHT, DomKey::Constant<'}'>::Character},
{DomCode::BACKSLASH, DomKey::Constant<'\\'>::Character},
{DomCode::SEMICOLON, DomKey::Constant<';'>::Character},
{DomCode::QUOTE, DomKey::Constant<'\''>::Character},
{DomCode::INTL_BACKSLASH, DomKey::Constant<'/'>::Character},
{DomCode::COMMA, DomKey::Constant<','>::Character},
{DomCode::PERIOD, DomKey::Constant<'.'>::Character},
{DomCode::SLASH, DomKey::Constant<'/'>::Character},
{DomCode::INTL_RO, DomKey::Constant<0x308D>::Dead}});
// Ensure the 'full' lookup table contains the same number of elements as the
// writing system table used by the class under test. Ideally this would be a
// static assert however that doesn't work since the other table is in a
// different compilation unit.
DCHECK_EQ(base::size(kFullLookupTable), kWritingSystemKeyDomCodeEntries);
if (kFullLookupTable.count(dom_code) == 0)
return DomKey::NONE;
return kFullLookupTable[dom_code];
}
DomKey GetKeyFromCombiningLayoutTable(DomCode dom_code) {
// Used for testing combining keys in both printable and combining forms.
static base::flat_map<DomCode, DomKey> kCombiningLayoutTable({
// Grave, combining.
{DomCode::DIGIT0, DomKey::Constant<0x0300>::Dead},
// Grave, printable.
{DomCode::DIGIT1, DomKey::Constant<0x0060>::Character},
// Acute, combining.
{DomCode::DIGIT2, DomKey::Constant<0x0301>::Dead},
// Acute, printable.
{DomCode::DIGIT3, DomKey::Constant<0x0027>::Character},
// Circumflex, combining.
{DomCode::DIGIT4, DomKey::Constant<0x0302>::Dead},
// Circumflex, printable.
{DomCode::DIGIT5, DomKey::Constant<0x005e>::Character},
// Tilde, combining.
{DomCode::DIGIT6, DomKey::Constant<0x0303>::Dead},
// Tilde, printable.
{DomCode::DIGIT7, DomKey::Constant<0x007e>::Character},
// Diaeresis, combining.
{DomCode::DIGIT8, DomKey::Constant<0x0308>::Dead},
// Diaeresis, printable.
{DomCode::DIGIT9, DomKey::Constant<0x00a8>::Character},
});
if (kCombiningLayoutTable.count(dom_code) == 0)
return DomKey::NONE;
return kCombiningLayoutTable[dom_code];
}
} // namespace
class TestDomKeyboardLayoutMap : public DomKeyboardLayoutMapBase {
public:
TestDomKeyboardLayoutMap();
~TestDomKeyboardLayoutMap() override;
// DomKeyboardLayoutMapBase overrides.
uint32_t GetKeyboardLayoutCount() override;
DomKey GetDomKeyFromDomCodeForLayout(DomCode dom_code,
uint32_t keyboard_layout_id) override;
// Adds a new keyboard layout in FIFO order.
void AddKeyboardLayout(uint32_t test_layout_id);
private:
// Helper methods used to populate a layout for testing.
DomKey GetDomKeyForLayoutWithAllValidKeys(DomCode dom_code);
DomKey GetDomKeyForLayoutWithAllValidAlphaKeys(DomCode dom_code);
DomKey GetDomKeyForLayoutWithSomeValidKeys(DomCode dom_code);
DomKey GetDomKeyForLayoutWithNoValidKeys();
std::vector<uint32_t> test_keyboard_layouts_;
DISALLOW_COPY_AND_ASSIGN(TestDomKeyboardLayoutMap);
};
TestDomKeyboardLayoutMap::TestDomKeyboardLayoutMap() = default;
TestDomKeyboardLayoutMap::~TestDomKeyboardLayoutMap() = default;
uint32_t TestDomKeyboardLayoutMap::GetKeyboardLayoutCount() {
return test_keyboard_layouts_.size();
}
DomKey TestDomKeyboardLayoutMap::GetDomKeyFromDomCodeForLayout(
DomCode dom_code,
uint32_t keyboard_layout_id) {
uint32_t test_layout_id = test_keyboard_layouts_[keyboard_layout_id];
if (test_layout_id == kKeyboardLayoutWithAllValidKeys)
return GetDomKeyForLayoutWithAllValidKeys(dom_code);
if (test_layout_id == kKeyboardLayoutWithAllValidAlphaKeys)
return GetDomKeyForLayoutWithAllValidAlphaKeys(dom_code);
if (test_layout_id == kKeyboardLayoutWithSomeValidKeys)
return GetDomKeyForLayoutWithSomeValidKeys(dom_code);
if (test_layout_id == kKeyboardLayoutWithNoValidKeys)
return GetDomKeyForLayoutWithNoValidKeys();
NOTREACHED();
return DomKey::NONE;
}
void TestDomKeyboardLayoutMap::AddKeyboardLayout(uint32_t test_layout_id) {
test_keyboard_layouts_.push_back(test_layout_id);
}
DomKey TestDomKeyboardLayoutMap::GetDomKeyForLayoutWithAllValidKeys(
DomCode dom_code) {
return GetKeyFromFullLookupTable(dom_code);
}
DomKey TestDomKeyboardLayoutMap::GetDomKeyForLayoutWithAllValidAlphaKeys(
DomCode dom_code) {
// If the number of excluded keys changes, please modify
// |kKeyboardLayoutWithAllValidAlphaKeysCount| to match the new value.
if (dom_code == DomCode::INTL_RO || dom_code == DomCode::INTL_YEN)
return DomKey::NONE;
// DIGIT 0 - 9 are overridden for combining char tests so use those here since
// this method only ensures the alpha keys are valid.
if (GetKeyFromCombiningLayoutTable(dom_code) != DomKey::NONE)
return GetKeyFromCombiningLayoutTable(dom_code);
return GetKeyFromFullLookupTable(dom_code);
}
DomKey TestDomKeyboardLayoutMap::GetDomKeyForLayoutWithSomeValidKeys(
DomCode dom_code) {
if (dom_code == DomCode::US_A || dom_code == DomCode::US_Z ||
dom_code == DomCode::BACKQUOTE)
return DomKey::NONE;
return GetKeyFromFullLookupTable(dom_code);
}
DomKey TestDomKeyboardLayoutMap::GetDomKeyForLayoutWithNoValidKeys() {
return DomKey::NONE;
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithZeroLayouts) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(0UL, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithCompletelyValidLayout) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithAllValidKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithAllValidKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithValidAlphaKeys) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(
kKeyboardLayoutWithAllValidAlphaKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithAllValidAlphaKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithMostlyValidAlphaKeys) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithSomeValidKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithSomeValidKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithNoValidKeys) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithNoValidKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithNoValidKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithValidLayoutFirst) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithAllValidKeys);
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithSomeValidKeys);
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithNoValidKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithAllValidKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithValidLayoutLast) {
TestDomKeyboardLayoutMap test_keyboard_layout_map;
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithSomeValidKeys);
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithNoValidKeys);
test_keyboard_layout_map.AddKeyboardLayout(kKeyboardLayoutWithAllValidKeys);
auto map = test_keyboard_layout_map.Generate();
ASSERT_EQ(kKeyboardLayoutWithAllValidKeysCount, map.size());
}
TEST(DomKeyboardLayoutMapTest, MapGenerationWithTwoValidLayouts) {
TestDomKeyboardLayoutMap test_keyboard_layout_map_1;
test_keyboard_layout_map_1.AddKeyboardLayout(kKeyboardLayoutWithAllValidKeys);
test_keyboard_layout_map_1.AddKeyboardLayout(
kKeyboardLayoutWithAllValidAlphaKeys);
auto map_1 = test_keyboard_layout_map_1.Generate();
EXPECT_EQ(kKeyboardLayoutWithAllValidKeysCount, map_1.size());
TestDomKeyboardLayoutMap test_keyboard_layout_map_2;
test_keyboard_layout_map_2.AddKeyboardLayout(
kKeyboardLayoutWithAllValidAlphaKeys);
test_keyboard_layout_map_2.AddKeyboardLayout(kKeyboardLayoutWithAllValidKeys);
auto map_2 = test_keyboard_layout_map_2.Generate();
EXPECT_EQ(kKeyboardLayoutWithAllValidAlphaKeysCount, map_2.size());
}
} // namespace ui