blob: 64751987e7fca0c53232e6cf729db5e6cbb2ebdd [file] [log] [blame]
// Copyright 2018 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 <hid/hid.h>
#include <hid/usages.h>
#include "garnet/bin/ui/input/inverse_keymap.h"
#include "gtest/gtest.h"
namespace input {
namespace {
// Initializes an inverse QWERTY keymap.
class InverseKeymapTest : public testing::Test {
protected:
InverseKeymapTest() : keymap_(InvertKeymap(qwerty_map)) {}
const InverseKeymap keymap_;
};
// A version of |Keystroke| with a more concise, binary shift state.
struct SimpleKeystroke {
uint32_t usage;
bool shift;
};
// Runs checks on a key sequence, using |SimpleKeystroke|s as a convenience
// representation. Null usages on the expectation indicate that no (non-shift)
// key is expected to be pressed. (Shift is governed separately.)
void CheckKeySequence(const KeySequence& actual,
const std::vector<SimpleKeystroke>& expected) {
ASSERT_EQ(actual.size(), expected.size());
for (size_t i = 0; i < actual.size(); ++i) {
const std::vector<uint32_t>& pressed_keys = actual[i]->pressed_keys;
uint32_t key = 0;
bool shift = false;
for (uint32_t usage : pressed_keys) {
EXPECT_NE(usage, 0u);
if (usage == HID_USAGE_KEY_LEFT_SHIFT) {
EXPECT_FALSE(shift) << "Duplicate shift key in report";
shift = true;
} else {
EXPECT_EQ(key, 0u) << "Multiple normal keys in report";
key = usage;
}
}
EXPECT_EQ(key, expected[i].usage);
EXPECT_EQ(shift, expected[i].shift);
}
}
} // namespace
TEST_F(InverseKeymapTest, PlainKey) {
auto it = keymap_.find('a');
ASSERT_NE(it, keymap_.end());
const Keystroke& keystroke = it->second;
EXPECT_EQ(keystroke.usage, HID_USAGE_KEY_A);
EXPECT_EQ(keystroke.shift, Keystroke::Shift::kNo);
}
TEST_F(InverseKeymapTest, ShiftKey) {
auto it = keymap_.find('A');
ASSERT_NE(it, keymap_.end());
const Keystroke& keystroke = it->second;
EXPECT_EQ(keystroke.usage, HID_USAGE_KEY_A);
EXPECT_EQ(keystroke.shift, Keystroke::Shift::kYes);
}
// The primary facility under test in the following cases is
// |DeriveKeySequence|. See the inverse_keymap.h/cc for details on expected
// behavior.
TEST_F(InverseKeymapTest, Lowercase) {
KeySequence key_sequence;
bool ok;
std::tie(key_sequence, ok) = DeriveKeySequence(keymap_, "lowercase");
ASSERT_TRUE(ok);
CheckKeySequence(key_sequence, {{HID_USAGE_KEY_L, false},
{HID_USAGE_KEY_O, false},
{HID_USAGE_KEY_W, false},
{HID_USAGE_KEY_E, false},
{HID_USAGE_KEY_R, false},
{HID_USAGE_KEY_C, false},
{HID_USAGE_KEY_A, false},
{HID_USAGE_KEY_S, false},
{HID_USAGE_KEY_E, false},
{}});
}
TEST_F(InverseKeymapTest, Sentence) {
KeySequence key_sequence;
bool ok;
std::tie(key_sequence, ok) = DeriveKeySequence(keymap_, "Hello, world!");
ASSERT_TRUE(ok);
CheckKeySequence(key_sequence, {{0, true},
{HID_USAGE_KEY_H, true},
{},
{HID_USAGE_KEY_E, false},
{HID_USAGE_KEY_L, false},
{},
{HID_USAGE_KEY_L, false},
{HID_USAGE_KEY_O, false},
{HID_USAGE_KEY_COMMA, false},
{HID_USAGE_KEY_SPACE, false},
{HID_USAGE_KEY_W, false},
{HID_USAGE_KEY_O, false},
{HID_USAGE_KEY_R, false},
{HID_USAGE_KEY_L, false},
{HID_USAGE_KEY_D, false},
{0, true},
{HID_USAGE_KEY_1, true},
{}});
}
TEST_F(InverseKeymapTest, HoldShift) {
KeySequence key_sequence;
bool ok;
std::tie(key_sequence, ok) = DeriveKeySequence(keymap_, "ALL'S WELL!");
ASSERT_TRUE(ok);
CheckKeySequence(key_sequence, {{0, true},
{HID_USAGE_KEY_A, true},
{HID_USAGE_KEY_L, true},
{0, true},
{HID_USAGE_KEY_L, true},
{},
{HID_USAGE_KEY_APOSTROPHE, false},
{0, true},
{HID_USAGE_KEY_S, true},
{HID_USAGE_KEY_SPACE, true},
{HID_USAGE_KEY_W, true},
{HID_USAGE_KEY_E, true},
{HID_USAGE_KEY_L, true},
{0, true},
{HID_USAGE_KEY_L, true},
{HID_USAGE_KEY_1, true},
{}});
}
} // namespace input