|  | // Copyright 2013 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 "ui/events/keycodes/dom/keycode_converter.h" | 
|  |  | 
|  | #include <map> | 
|  |  | 
|  | #include "base/basictypes.h" | 
|  | #include "testing/gtest/include/gtest/gtest.h" | 
|  | #include "ui/events/keycodes/dom/dom_code.h" | 
|  | #include "ui/events/keycodes/dom/dom_key.h" | 
|  |  | 
|  | using ui::KeycodeConverter; | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  | const size_t kExpectedMappedKeyCount = 138; | 
|  | #elif defined(OS_LINUX) | 
|  | const size_t kExpectedMappedKeyCount = 168; | 
|  | #elif defined(OS_MACOSX) | 
|  | const size_t kExpectedMappedKeyCount = 118; | 
|  | #else | 
|  | const size_t kExpectedMappedKeyCount = 0; | 
|  | #endif | 
|  |  | 
|  | const uint32_t kUsbNonExistentKeycode = 0xffffff; | 
|  | const uint32_t kUsbUsBackslash =        0x070031; | 
|  | const uint32_t kUsbNonUsHash =          0x070032; | 
|  |  | 
|  | TEST(UsbKeycodeMap, Basic) { | 
|  | // Verify that the first element in the table is the "invalid" code. | 
|  | const ui::KeycodeMapEntry* keycode_map = | 
|  | ui::KeycodeConverter::GetKeycodeMapForTest(); | 
|  | EXPECT_EQ(ui::KeycodeConverter::InvalidUsbKeycode(), | 
|  | keycode_map[0].usb_keycode); | 
|  | EXPECT_EQ(ui::KeycodeConverter::InvalidNativeKeycode(), | 
|  | keycode_map[0].native_keycode); | 
|  | EXPECT_EQ(ui::KeycodeConverter::InvalidNativeKeycode(), | 
|  | ui::KeycodeConverter::DomCodeToNativeKeycode(ui::DomCode::NONE)); | 
|  |  | 
|  | // Verify that there are no duplicate entries in the mapping. | 
|  | std::map<uint32_t, uint16_t> usb_to_native; | 
|  | std::map<uint16_t, uint32_t> native_to_usb; | 
|  | size_t numEntries = ui::KeycodeConverter::NumKeycodeMapEntriesForTest(); | 
|  | for (size_t i = 0; i < numEntries; ++i) { | 
|  | const ui::KeycodeMapEntry* entry = &keycode_map[i]; | 
|  | // Don't test keys with no native keycode mapping on this platform. | 
|  | if (entry->native_keycode == ui::KeycodeConverter::InvalidNativeKeycode()) | 
|  | continue; | 
|  |  | 
|  | // Verify UsbKeycodeToNativeKeycode works for this key. | 
|  | EXPECT_EQ( | 
|  | entry->native_keycode, | 
|  | ui::KeycodeConverter::UsbKeycodeToNativeKeycode(entry->usb_keycode)); | 
|  |  | 
|  | // Verify DomCodeToNativeKeycode works correctly. | 
|  | ui::DomCode dom_code = | 
|  | ui::KeycodeConverter::CodeStringToDomCode(entry->code); | 
|  | if (entry->code) { | 
|  | EXPECT_EQ(entry->native_keycode, | 
|  | ui::KeycodeConverter::DomCodeToNativeKeycode(dom_code)); | 
|  | } else { | 
|  | EXPECT_EQ(ui::DomCode::NONE, dom_code); | 
|  | } | 
|  |  | 
|  | // Verify that the USB or native codes aren't duplicated. | 
|  | EXPECT_EQ(0U, usb_to_native.count(entry->usb_keycode)) | 
|  | << " duplicate of USB code 0x" << std::hex << std::setfill('0') | 
|  | << std::setw(6) << entry->usb_keycode | 
|  | << " to native 0x" | 
|  | << std::setw(4) << entry->native_keycode | 
|  | << " (previous was 0x" | 
|  | << std::setw(4) << usb_to_native[entry->usb_keycode] | 
|  | << ")"; | 
|  | usb_to_native[entry->usb_keycode] = entry->native_keycode; | 
|  | EXPECT_EQ(0U, native_to_usb.count(entry->native_keycode)) | 
|  | << " duplicate of native code 0x" << std::hex << std::setfill('0') | 
|  | << std::setw(4) << entry->native_keycode | 
|  | << " to USB 0x" | 
|  | << std::setw(6) << entry->usb_keycode | 
|  | << " (previous was 0x" | 
|  | << std::setw(6) << native_to_usb[entry->native_keycode] | 
|  | << ")"; | 
|  | native_to_usb[entry->native_keycode] = entry->usb_keycode; | 
|  | } | 
|  | ASSERT_EQ(usb_to_native.size(), native_to_usb.size()); | 
|  |  | 
|  | // Verify that the number of mapped keys is what we expect, i.e. we haven't | 
|  | // lost any, and if we've added some then the expectation has been updated. | 
|  | EXPECT_EQ(kExpectedMappedKeyCount, usb_to_native.size()); | 
|  | } | 
|  |  | 
|  | TEST(UsbKeycodeMap, NonExistent) { | 
|  | // Verify that UsbKeycodeToNativeKeycode works for a non-existent USB keycode. | 
|  | EXPECT_EQ( | 
|  | ui::KeycodeConverter::InvalidNativeKeycode(), | 
|  | ui::KeycodeConverter::UsbKeycodeToNativeKeycode(kUsbNonExistentKeycode)); | 
|  | } | 
|  |  | 
|  | TEST(UsbKeycodeMap, UsBackslashIsNonUsHash) { | 
|  | // Verify that UsbKeycodeToNativeKeycode treats the non-US "hash" key | 
|  | // as equivalent to the US "backslash" key. | 
|  | EXPECT_EQ(ui::KeycodeConverter::UsbKeycodeToNativeKeycode(kUsbUsBackslash), | 
|  | ui::KeycodeConverter::UsbKeycodeToNativeKeycode(kUsbNonUsHash)); | 
|  | } | 
|  |  | 
|  | TEST(KeycodeConverter, DomCode) { | 
|  | // Test invalid and unknown arguments to CodeStringToDomCode() | 
|  | EXPECT_EQ(ui::DomCode::NONE, | 
|  | ui::KeycodeConverter::CodeStringToDomCode(nullptr)); | 
|  | EXPECT_EQ(ui::DomCode::NONE, ui::KeycodeConverter::CodeStringToDomCode("-")); | 
|  | EXPECT_EQ(ui::DomCode::NONE, ui::KeycodeConverter::CodeStringToDomCode("")); | 
|  | // Round-trip test DOM Level 3 .code strings. | 
|  | const ui::KeycodeMapEntry* keycode_map = | 
|  | ui::KeycodeConverter::GetKeycodeMapForTest(); | 
|  | size_t numEntries = ui::KeycodeConverter::NumKeycodeMapEntriesForTest(); | 
|  | for (size_t i = 0; i < numEntries; ++i) { | 
|  | SCOPED_TRACE(i); | 
|  | const ui::KeycodeMapEntry* entry = &keycode_map[i]; | 
|  | ui::DomCode code = ui::KeycodeConverter::CodeStringToDomCode(entry->code); | 
|  | if (entry->code) { | 
|  | EXPECT_STREQ(entry->code, | 
|  | ui::KeycodeConverter::DomCodeToCodeString(code)); | 
|  | } else { | 
|  | EXPECT_EQ(static_cast<int>(ui::DomCode::NONE), | 
|  | static_cast<int>(code)); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | TEST(KeycodeConverter, DomKey) { | 
|  | // Test invalid and unknown arguments to KeyStringToDomKey() | 
|  | EXPECT_EQ(ui::DomKey::NONE, ui::KeycodeConverter::KeyStringToDomKey(nullptr)); | 
|  | EXPECT_EQ(ui::DomKey::NONE, ui::KeycodeConverter::KeyStringToDomKey("-")); | 
|  | // Round-trip test DOM Level 3 .key strings. | 
|  | const char* s = nullptr; | 
|  | for (size_t i = 0; | 
|  | (s = ui::KeycodeConverter::DomKeyStringForTest(i)) != nullptr; | 
|  | ++i) { | 
|  | SCOPED_TRACE(i); | 
|  | ui::DomKey key = ui::KeycodeConverter::KeyStringToDomKey(s); | 
|  | if (s) { | 
|  | EXPECT_STREQ(s, ui::KeycodeConverter::DomKeyToKeyString(key)); | 
|  | } else { | 
|  | EXPECT_EQ(ui::DomKey::NONE, key); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace |