chromium/remoting/client/input/normalizing_input_filter_cros_unittest.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/client/input/normalizing_input_filter_cros.h"

#include <stdint.h>

#include "remoting/proto/event.pb.h"
#include "remoting/protocol/protocol_mock_objects.h"
#include "remoting/protocol/test_event_matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/keycodes/dom/dom_code.h"

using ::testing::InSequence;
InputStub;
KeyEvent;
MockInputStub;
MouseEvent;
EqualsKeyEvent;
EqualsKeyEventWithNumLock;
EqualsMouseButtonEvent;
EqualsMouseMoveEvent;

namespace remoting {

namespace {

KeyEvent MakeKeyEvent(ui::DomCode keycode, bool pressed) {}

void PressAndReleaseKey(InputStub* input_stub, ui::DomCode keycode) {}

static MouseEvent MakeMouseMoveEvent(int x, int y) {}

static MouseEvent MakeMouseButtonEvent(MouseEvent::MouseButton button,
                                       bool button_down) {}

}  // namespace

// Test OSKey press/release.
TEST() {
  MockInputStub stub;
  std::unique_ptr<protocol::InputFilter> processor(
      new NormalizingInputFilterCros(&stub));

  {
    InSequence s;

    EXPECT_CALL();
    EXPECT_CALL();

    EXPECT_CALL();
    EXPECT_CALL();
  }

  // Inject press & release events for left & right OSKeys.
  PressAndReleaseKey(processor.get(), ui::DomCode::META_LEFT);
  PressAndReleaseKey(processor.get(), ui::DomCode::META_RIGHT);
}

// Test OSKey key repeat switches it to "modifying" mode.
TEST() {
  MockInputStub stub;
  std::unique_ptr<protocol::InputFilter> processor(
      new NormalizingInputFilterCros(&stub));

  {
    InSequence s;

    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
  }

  // Inject a press and repeats for the left OSKey, but don't release it, and
  // verify that the repeats result in press events.
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, true));
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, true));
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, true));
}

// Test OSKey press followed by function key press and release results in
// just the function key events.
TEST() {
  MockInputStub stub;
  std::unique_ptr<protocol::InputFilter> processor(
      new NormalizingInputFilterCros(&stub));

  {
    InSequence s;

    EXPECT_CALL();
    EXPECT_CALL();
  }

  // Hold the left OSKey while pressing & releasing the function key.
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, true));
  PressAndReleaseKey(processor.get(), ui::DomCode::F1);
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, false));
}

// Test OSKey press followed by extended key press and release results in
// just the function key events.
TEST() {
  MockInputStub stub;
  std::unique_ptr<protocol::InputFilter> processor(
      new NormalizingInputFilterCros(&stub));

  {
    InSequence s;

    EXPECT_CALL();
    EXPECT_CALL();
  }

  // Hold the left OSKey while pressing & releasing the function key.
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, true));
  PressAndReleaseKey(processor.get(), ui::DomCode::INSERT);
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, false));
}

// Test OSKey press followed by non-function, non-extended key press and release
// results in normal-looking sequence. We use the Tab key arbitrarily for this
// test.
TEST() {
  MockInputStub stub;
  std::unique_ptr<protocol::InputFilter> processor(
      new NormalizingInputFilterCros(&stub));

  {
    InSequence s;

    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
  }

  // Hold the left OSKey while pressing & releasing the function key.
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, true));
  PressAndReleaseKey(processor.get(), ui::DomCode::TAB);
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, false));
}

// Test OSKey press followed by extended key press, then normal key press
// results in OSKey switching to modifying mode for the normal key.
TEST() {
  MockInputStub stub;
  std::unique_ptr<protocol::InputFilter> processor(
      new NormalizingInputFilterCros(&stub));

  {
    InSequence s;

    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
  }

  // Hold the left OSKey while pressing & releasing the function key.
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, true));
  PressAndReleaseKey(processor.get(), ui::DomCode::INSERT);
  PressAndReleaseKey(processor.get(), ui::DomCode::TAB);
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, false));
}

// Test OSKey press followed by mouse event puts the OSKey into modifying mode.
TEST() {
  MockInputStub stub;
  std::unique_ptr<protocol::InputFilter> processor(
      new NormalizingInputFilterCros(&stub));

  {
    InSequence s;

    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
  }

  // Hold the left OSKey while pressing & releasing the function key.
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, true));
  processor->InjectMouseEvent(MakeMouseMoveEvent(0, 0));
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::META_LEFT, false));
}

// Test left alt + right click is remapped to left alt + left click.
TEST() {
  MockInputStub stub;
  std::unique_ptr<protocol::InputFilter> processor(
      new NormalizingInputFilterCros(&stub));

  {
    InSequence s;

    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
  }

  // Hold the left alt key while left-clicking. ChromeOS will rewrite this as
  // Alt+RightClick
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::ALT_LEFT, true));
  processor->InjectMouseEvent(
      MakeMouseButtonEvent(MouseEvent::BUTTON_RIGHT, true));
  processor->InjectMouseEvent(
      MakeMouseButtonEvent(MouseEvent::BUTTON_RIGHT, false));
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::ALT_LEFT, false));
}

// Test that right alt + right click is unchanged.
TEST() {
  MockInputStub stub;
  std::unique_ptr<protocol::InputFilter> processor(
      new NormalizingInputFilterCros(&stub));

  {
    InSequence s;

    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
  }

  // Hold the right alt key while left-clicking. ChromeOS will rewrite this as
  // Alt+RightClick
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::ALT_RIGHT, true));
  processor->InjectMouseEvent(
      MakeMouseButtonEvent(MouseEvent::BUTTON_RIGHT, true));
  processor->InjectMouseEvent(
      MakeMouseButtonEvent(MouseEvent::BUTTON_RIGHT, false));
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::ALT_RIGHT, false));
}

// Test that the Alt-key remapping for Up and Down is not applied.
TEST() {
  MockInputStub stub;
  std::unique_ptr<protocol::InputFilter> processor(
      new NormalizingInputFilterCros(&stub));

  {
    InSequence s;

    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();

    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
    EXPECT_CALL();
  }

  // Hold the left Alt key while pressing & releasing the PgUp, PgDown and
  // Delete keys. This simulates the mapping that ChromeOS applies if the Up,
  // Down and Backspace keys are pressed, respectively, while the Alt key is
  // held.
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::ALT_LEFT, true));
  PressAndReleaseKey(processor.get(), ui::DomCode::PAGE_UP);
  PressAndReleaseKey(processor.get(), ui::DomCode::PAGE_DOWN);
  PressAndReleaseKey(processor.get(), ui::DomCode::DEL);
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::ALT_LEFT, false));

  // Repeat the test for the right Alt key.
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::ALT_RIGHT, true));
  PressAndReleaseKey(processor.get(), ui::DomCode::PAGE_UP);
  PressAndReleaseKey(processor.get(), ui::DomCode::PAGE_DOWN);
  PressAndReleaseKey(processor.get(), ui::DomCode::DEL);
  processor->InjectKeyEvent(MakeKeyEvent(ui::DomCode::ALT_RIGHT, false));
}

}  // namespace remoting