普通文本  |  211行  |  6.84 KB

// 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 "chromeos/ime/xkeyboard.h"

#include <algorithm>
#include <set>
#include <string>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "testing/gtest/include/gtest/gtest.h"

#include <X11/Xlib.h>

namespace chromeos {
namespace input_method {

namespace {

class XKeyboardTest : public testing::Test {
 public:
  XKeyboardTest() {
  }

  virtual void SetUp() {
    xkey_.reset(XKeyboard::Create());
  }

  virtual void TearDown() {
    xkey_.reset();
  }

  scoped_ptr<XKeyboard> xkey_;

  base::MessageLoopForUI message_loop_;
};

// Returns true if X display is available.
bool DisplayAvailable() {
  return (base::MessagePumpForUI::GetDefaultXDisplay() != NULL);
}

}  // namespace

// Tests CheckLayoutName() function.
TEST_F(XKeyboardTest, TestCheckLayoutName) {
  // CheckLayoutName should not accept non-alphanumeric characters
  // except "()-_".
  EXPECT_FALSE(XKeyboard::CheckLayoutNameForTesting("us!"));
  EXPECT_FALSE(XKeyboard::CheckLayoutNameForTesting("us; /bin/sh"));
  EXPECT_TRUE(XKeyboard::CheckLayoutNameForTesting("ab-c_12"));

  // CheckLayoutName should not accept upper-case ascii characters.
  EXPECT_FALSE(XKeyboard::CheckLayoutNameForTesting("US"));

  // CheckLayoutName should accept lower-case ascii characters.
  for (int c = 'a'; c <= 'z'; ++c) {
    EXPECT_TRUE(XKeyboard::CheckLayoutNameForTesting(std::string(3, c)));
  }

  // CheckLayoutName should accept numbers.
  for (int c = '0'; c <= '9'; ++c) {
    EXPECT_TRUE(XKeyboard::CheckLayoutNameForTesting(std::string(3, c)));
  }

  // CheckLayoutName should accept a layout with a variant name.
  EXPECT_TRUE(XKeyboard::CheckLayoutNameForTesting("us(dvorak)"));
  EXPECT_TRUE(XKeyboard::CheckLayoutNameForTesting("jp"));
}

TEST_F(XKeyboardTest, TestSetCapsLockEnabled) {
  if (!DisplayAvailable()) {
    // Do not fail the test to allow developers to run unit_tests without an X
    // server (e.g. via ssh). Note that both try bots and waterfall always have
    // an X server for running browser_tests.
    DVLOG(1) << "X server is not available. Skip the test.";
    return;
  }
  const bool initial_lock_state = xkey_->CapsLockIsEnabled();
  xkey_->SetCapsLockEnabled(true);
  EXPECT_TRUE(xkey_->CapsLockIsEnabled());
  xkey_->SetCapsLockEnabled(false);
  EXPECT_FALSE(xkey_->CapsLockIsEnabled());
  xkey_->SetCapsLockEnabled(true);
  EXPECT_TRUE(xkey_->CapsLockIsEnabled());
  xkey_->SetCapsLockEnabled(false);
  EXPECT_FALSE(xkey_->CapsLockIsEnabled());
  xkey_->SetCapsLockEnabled(initial_lock_state);
}

TEST_F(XKeyboardTest, TestSetNumLockEnabled) {
  if (!DisplayAvailable()) {
    DVLOG(1) << "X server is not available. Skip the test.";
    return;
  }
  const unsigned int num_lock_mask = xkey_->GetNumLockMask();
  ASSERT_NE(0U, num_lock_mask);

  const bool initial_lock_state = xkey_->NumLockIsEnabled();
  xkey_->SetNumLockEnabled(true);
  EXPECT_TRUE(xkey_->NumLockIsEnabled());
  xkey_->SetNumLockEnabled(false);
  EXPECT_FALSE(xkey_->NumLockIsEnabled());
  xkey_->SetNumLockEnabled(true);
  EXPECT_TRUE(xkey_->NumLockIsEnabled());
  xkey_->SetNumLockEnabled(false);
  EXPECT_FALSE(xkey_->NumLockIsEnabled());
  xkey_->SetNumLockEnabled(initial_lock_state);
}

TEST_F(XKeyboardTest, TestSetCapsLockAndNumLockAtTheSameTime) {
  if (!DisplayAvailable()) {
    DVLOG(1) << "X server is not available. Skip the test.";
    return;
  }
  const unsigned int num_lock_mask = xkey_->GetNumLockMask();
  ASSERT_NE(0U, num_lock_mask);

  const bool initial_caps_lock_state = xkey_->CapsLockIsEnabled();
  const bool initial_num_lock_state = xkey_->NumLockIsEnabled();

  // Flip both.
  xkey_->SetLockedModifiers(
      initial_caps_lock_state ? kDisableLock : kEnableLock,
      initial_num_lock_state ? kDisableLock : kEnableLock);
  EXPECT_EQ(!initial_caps_lock_state, xkey_->CapsLockIsEnabled());
  EXPECT_EQ(!initial_num_lock_state, xkey_->NumLockIsEnabled());

  // Flip Caps Lock.
  xkey_->SetLockedModifiers(
      initial_caps_lock_state ? kEnableLock : kDisableLock,
      kDontChange);
  // Use GetLockedModifiers() for verifying the result.
  bool c, n;
  xkey_->GetLockedModifiers(&c, &n);
  EXPECT_EQ(initial_caps_lock_state, c);
  EXPECT_EQ(!initial_num_lock_state, n);

  // Flip both.
  xkey_->SetLockedModifiers(
      initial_caps_lock_state ? kDisableLock : kEnableLock,
      initial_num_lock_state ? kEnableLock : kDisableLock);
  EXPECT_EQ(!initial_caps_lock_state, xkey_->CapsLockIsEnabled());
  EXPECT_EQ(initial_num_lock_state, xkey_->NumLockIsEnabled());

  // Flip Num Lock.
  xkey_->SetLockedModifiers(
      kDontChange,
      initial_num_lock_state ? kDisableLock : kEnableLock);
  xkey_->GetLockedModifiers(&c, &n);
  EXPECT_EQ(!initial_caps_lock_state, c);
  EXPECT_EQ(!initial_num_lock_state, n);

  // Flip both to restore the initial state.
  xkey_->SetLockedModifiers(
      initial_caps_lock_state ? kEnableLock : kDisableLock,
      initial_num_lock_state ? kEnableLock : kDisableLock);
  EXPECT_EQ(initial_caps_lock_state, xkey_->CapsLockIsEnabled());
  EXPECT_EQ(initial_num_lock_state, xkey_->NumLockIsEnabled());

  // No-op SetLockedModifiers call.
  xkey_->SetLockedModifiers(kDontChange, kDontChange);
  EXPECT_EQ(initial_caps_lock_state, xkey_->CapsLockIsEnabled());
  EXPECT_EQ(initial_num_lock_state, xkey_->NumLockIsEnabled());

  // No-op GetLockedModifiers call. Confirm it does not crash.
  xkey_->GetLockedModifiers(NULL, NULL);
}

TEST_F(XKeyboardTest, TestSetAutoRepeatEnabled) {
  if (!DisplayAvailable()) {
    DVLOG(1) << "X server is not available. Skip the test.";
    return;
  }
  const bool state = XKeyboard::GetAutoRepeatEnabledForTesting();
  XKeyboard::SetAutoRepeatEnabled(!state);
  EXPECT_EQ(!state, XKeyboard::GetAutoRepeatEnabledForTesting());
  // Restore the initial state.
  XKeyboard::SetAutoRepeatEnabled(state);
  EXPECT_EQ(state, XKeyboard::GetAutoRepeatEnabledForTesting());
}

TEST_F(XKeyboardTest, TestSetAutoRepeatRate) {
  if (!DisplayAvailable()) {
    DVLOG(1) << "X server is not available. Skip the test.";
    return;
  }
  AutoRepeatRate rate;
  EXPECT_TRUE(XKeyboard::GetAutoRepeatRateForTesting(&rate));

  AutoRepeatRate tmp(rate);
  ++tmp.initial_delay_in_ms;
  ++tmp.repeat_interval_in_ms;
  EXPECT_TRUE(XKeyboard::SetAutoRepeatRate(tmp));
  EXPECT_TRUE(XKeyboard::GetAutoRepeatRateForTesting(&tmp));
  EXPECT_EQ(rate.initial_delay_in_ms + 1, tmp.initial_delay_in_ms);
  EXPECT_EQ(rate.repeat_interval_in_ms + 1, tmp.repeat_interval_in_ms);

  // Restore the initial state.
  EXPECT_TRUE(XKeyboard::SetAutoRepeatRate(rate));
  EXPECT_TRUE(XKeyboard::GetAutoRepeatRateForTesting(&tmp));
  EXPECT_EQ(rate.initial_delay_in_ms, tmp.initial_delay_in_ms);
  EXPECT_EQ(rate.repeat_interval_in_ms, tmp.repeat_interval_in_ms);
}

}  // namespace input_method
}  // namespace chromeos