1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chromeos/ime/xkeyboard.h" 6 7 #include <algorithm> 8 #include <set> 9 #include <string> 10 11 #include "base/logging.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/message_loop/message_loop.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 #include <X11/Xlib.h> 17 18 namespace chromeos { 19 namespace input_method { 20 21 namespace { 22 23 class XKeyboardTest : public testing::Test { 24 public: 25 XKeyboardTest() { 26 } 27 28 virtual void SetUp() { 29 xkey_.reset(XKeyboard::Create()); 30 } 31 32 virtual void TearDown() { 33 xkey_.reset(); 34 } 35 36 scoped_ptr<XKeyboard> xkey_; 37 38 base::MessageLoopForUI message_loop_; 39 }; 40 41 // Returns true if X display is available. 42 bool DisplayAvailable() { 43 return (base::MessagePumpForUI::GetDefaultXDisplay() != NULL); 44 } 45 46 } // namespace 47 48 // Tests CheckLayoutName() function. 49 TEST_F(XKeyboardTest, TestCheckLayoutName) { 50 // CheckLayoutName should not accept non-alphanumeric characters 51 // except "()-_". 52 EXPECT_FALSE(XKeyboard::CheckLayoutNameForTesting("us!")); 53 EXPECT_FALSE(XKeyboard::CheckLayoutNameForTesting("us; /bin/sh")); 54 EXPECT_TRUE(XKeyboard::CheckLayoutNameForTesting("ab-c_12")); 55 56 // CheckLayoutName should not accept upper-case ascii characters. 57 EXPECT_FALSE(XKeyboard::CheckLayoutNameForTesting("US")); 58 59 // CheckLayoutName should accept lower-case ascii characters. 60 for (int c = 'a'; c <= 'z'; ++c) { 61 EXPECT_TRUE(XKeyboard::CheckLayoutNameForTesting(std::string(3, c))); 62 } 63 64 // CheckLayoutName should accept numbers. 65 for (int c = '0'; c <= '9'; ++c) { 66 EXPECT_TRUE(XKeyboard::CheckLayoutNameForTesting(std::string(3, c))); 67 } 68 69 // CheckLayoutName should accept a layout with a variant name. 70 EXPECT_TRUE(XKeyboard::CheckLayoutNameForTesting("us(dvorak)")); 71 EXPECT_TRUE(XKeyboard::CheckLayoutNameForTesting("jp")); 72 } 73 74 TEST_F(XKeyboardTest, TestSetCapsLockEnabled) { 75 if (!DisplayAvailable()) { 76 // Do not fail the test to allow developers to run unit_tests without an X 77 // server (e.g. via ssh). Note that both try bots and waterfall always have 78 // an X server for running browser_tests. 79 DVLOG(1) << "X server is not available. Skip the test."; 80 return; 81 } 82 const bool initial_lock_state = xkey_->CapsLockIsEnabled(); 83 xkey_->SetCapsLockEnabled(true); 84 EXPECT_TRUE(xkey_->CapsLockIsEnabled()); 85 xkey_->SetCapsLockEnabled(false); 86 EXPECT_FALSE(xkey_->CapsLockIsEnabled()); 87 xkey_->SetCapsLockEnabled(true); 88 EXPECT_TRUE(xkey_->CapsLockIsEnabled()); 89 xkey_->SetCapsLockEnabled(false); 90 EXPECT_FALSE(xkey_->CapsLockIsEnabled()); 91 xkey_->SetCapsLockEnabled(initial_lock_state); 92 } 93 94 TEST_F(XKeyboardTest, TestSetNumLockEnabled) { 95 if (!DisplayAvailable()) { 96 DVLOG(1) << "X server is not available. Skip the test."; 97 return; 98 } 99 const unsigned int num_lock_mask = xkey_->GetNumLockMask(); 100 ASSERT_NE(0U, num_lock_mask); 101 102 const bool initial_lock_state = xkey_->NumLockIsEnabled(); 103 xkey_->SetNumLockEnabled(true); 104 EXPECT_TRUE(xkey_->NumLockIsEnabled()); 105 xkey_->SetNumLockEnabled(false); 106 EXPECT_FALSE(xkey_->NumLockIsEnabled()); 107 xkey_->SetNumLockEnabled(true); 108 EXPECT_TRUE(xkey_->NumLockIsEnabled()); 109 xkey_->SetNumLockEnabled(false); 110 EXPECT_FALSE(xkey_->NumLockIsEnabled()); 111 xkey_->SetNumLockEnabled(initial_lock_state); 112 } 113 114 TEST_F(XKeyboardTest, TestSetCapsLockAndNumLockAtTheSameTime) { 115 if (!DisplayAvailable()) { 116 DVLOG(1) << "X server is not available. Skip the test."; 117 return; 118 } 119 const unsigned int num_lock_mask = xkey_->GetNumLockMask(); 120 ASSERT_NE(0U, num_lock_mask); 121 122 const bool initial_caps_lock_state = xkey_->CapsLockIsEnabled(); 123 const bool initial_num_lock_state = xkey_->NumLockIsEnabled(); 124 125 // Flip both. 126 xkey_->SetLockedModifiers( 127 initial_caps_lock_state ? kDisableLock : kEnableLock, 128 initial_num_lock_state ? kDisableLock : kEnableLock); 129 EXPECT_EQ(!initial_caps_lock_state, xkey_->CapsLockIsEnabled()); 130 EXPECT_EQ(!initial_num_lock_state, xkey_->NumLockIsEnabled()); 131 132 // Flip Caps Lock. 133 xkey_->SetLockedModifiers( 134 initial_caps_lock_state ? kEnableLock : kDisableLock, 135 kDontChange); 136 // Use GetLockedModifiers() for verifying the result. 137 bool c, n; 138 xkey_->GetLockedModifiers(&c, &n); 139 EXPECT_EQ(initial_caps_lock_state, c); 140 EXPECT_EQ(!initial_num_lock_state, n); 141 142 // Flip both. 143 xkey_->SetLockedModifiers( 144 initial_caps_lock_state ? kDisableLock : kEnableLock, 145 initial_num_lock_state ? kEnableLock : kDisableLock); 146 EXPECT_EQ(!initial_caps_lock_state, xkey_->CapsLockIsEnabled()); 147 EXPECT_EQ(initial_num_lock_state, xkey_->NumLockIsEnabled()); 148 149 // Flip Num Lock. 150 xkey_->SetLockedModifiers( 151 kDontChange, 152 initial_num_lock_state ? kDisableLock : kEnableLock); 153 xkey_->GetLockedModifiers(&c, &n); 154 EXPECT_EQ(!initial_caps_lock_state, c); 155 EXPECT_EQ(!initial_num_lock_state, n); 156 157 // Flip both to restore the initial state. 158 xkey_->SetLockedModifiers( 159 initial_caps_lock_state ? kEnableLock : kDisableLock, 160 initial_num_lock_state ? kEnableLock : kDisableLock); 161 EXPECT_EQ(initial_caps_lock_state, xkey_->CapsLockIsEnabled()); 162 EXPECT_EQ(initial_num_lock_state, xkey_->NumLockIsEnabled()); 163 164 // No-op SetLockedModifiers call. 165 xkey_->SetLockedModifiers(kDontChange, kDontChange); 166 EXPECT_EQ(initial_caps_lock_state, xkey_->CapsLockIsEnabled()); 167 EXPECT_EQ(initial_num_lock_state, xkey_->NumLockIsEnabled()); 168 169 // No-op GetLockedModifiers call. Confirm it does not crash. 170 xkey_->GetLockedModifiers(NULL, NULL); 171 } 172 173 TEST_F(XKeyboardTest, TestSetAutoRepeatEnabled) { 174 if (!DisplayAvailable()) { 175 DVLOG(1) << "X server is not available. Skip the test."; 176 return; 177 } 178 const bool state = XKeyboard::GetAutoRepeatEnabledForTesting(); 179 XKeyboard::SetAutoRepeatEnabled(!state); 180 EXPECT_EQ(!state, XKeyboard::GetAutoRepeatEnabledForTesting()); 181 // Restore the initial state. 182 XKeyboard::SetAutoRepeatEnabled(state); 183 EXPECT_EQ(state, XKeyboard::GetAutoRepeatEnabledForTesting()); 184 } 185 186 TEST_F(XKeyboardTest, TestSetAutoRepeatRate) { 187 if (!DisplayAvailable()) { 188 DVLOG(1) << "X server is not available. Skip the test."; 189 return; 190 } 191 AutoRepeatRate rate; 192 EXPECT_TRUE(XKeyboard::GetAutoRepeatRateForTesting(&rate)); 193 194 AutoRepeatRate tmp(rate); 195 ++tmp.initial_delay_in_ms; 196 ++tmp.repeat_interval_in_ms; 197 EXPECT_TRUE(XKeyboard::SetAutoRepeatRate(tmp)); 198 EXPECT_TRUE(XKeyboard::GetAutoRepeatRateForTesting(&tmp)); 199 EXPECT_EQ(rate.initial_delay_in_ms + 1, tmp.initial_delay_in_ms); 200 EXPECT_EQ(rate.repeat_interval_in_ms + 1, tmp.repeat_interval_in_ms); 201 202 // Restore the initial state. 203 EXPECT_TRUE(XKeyboard::SetAutoRepeatRate(rate)); 204 EXPECT_TRUE(XKeyboard::GetAutoRepeatRateForTesting(&tmp)); 205 EXPECT_EQ(rate.initial_delay_in_ms, tmp.initial_delay_in_ms); 206 EXPECT_EQ(rate.repeat_interval_in_ms, tmp.repeat_interval_in_ms); 207 } 208 209 } // namespace input_method 210 } // namespace chromeos 211