• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
XKeyboardTest()25   XKeyboardTest() {
26   }
27 
SetUp()28   virtual void SetUp() {
29     xkey_.reset(XKeyboard::Create());
30   }
31 
TearDown()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.
DisplayAvailable()42 bool DisplayAvailable() {
43   return (base::MessagePumpForUI::GetDefaultXDisplay() != NULL);
44 }
45 
46 }  // namespace
47 
48 // Tests CheckLayoutName() function.
TEST_F(XKeyboardTest,TestCheckLayoutName)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 
TEST_F(XKeyboardTest,TestSetCapsLockEnabled)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 
TEST_F(XKeyboardTest,TestSetNumLockEnabled)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 
TEST_F(XKeyboardTest,TestSetCapsLockAndNumLockAtTheSameTime)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 
TEST_F(XKeyboardTest,TestSetAutoRepeatEnabled)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 
TEST_F(XKeyboardTest,TestSetAutoRepeatRate)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