Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1451)

Unified Diff: remoting/host/touch_injector_win_unittest.cc

Issue 991643002: Windows Host Touch Injection (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebased Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/host/touch_injector_win.cc ('k') | remoting/host/win/session_input_injector.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/touch_injector_win_unittest.cc
diff --git a/remoting/host/touch_injector_win_unittest.cc b/remoting/host/touch_injector_win_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..791b95fcca045670d65c26f497d956167df6f0a7
--- /dev/null
+++ b/remoting/host/touch_injector_win_unittest.cc
@@ -0,0 +1,514 @@
+// Copyright 2015 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 "remoting/host/touch_injector_win.h"
+
+#include <map>
+
+#include "base/stl_util.h"
+#include "remoting/proto/event.pb.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::AtLeast;
+using ::testing::InSequence;
+using ::testing::ExpectationSet;
+using ::testing::Return;
+
+namespace remoting {
+
+using protocol::TouchEvent;
+using protocol::TouchEventPoint;
+
+namespace {
+
+// Maps touch pointer ID to expected flags [start, move, end, cancel] listed
+// below.
+typedef std::map<uint32_t, uint32_t> IdFlagMap;
+
+const uint32_t kStartFlag =
+ POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_DOWN;
+
+const uint32_t kMoveFlag =
+ POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_UPDATE;
+
+const uint32_t kEndFlag = POINTER_FLAG_UP;
+
+const uint32_t kCancelFlag = POINTER_FLAG_UP | POINTER_FLAG_CANCELED;
+
+MATCHER_P(EqualsSinglePointerTouchInfo, expected, "") {
+ return arg->touchMask == expected.touchMask &&
+ arg->rcContact.left == expected.rcContact.left &&
+ arg->rcContact.top == expected.rcContact.top &&
+ arg->rcContact.right == expected.rcContact.right &&
+ arg->rcContact.bottom == expected.rcContact.bottom &&
+ arg->orientation == expected.orientation &&
+ arg->pressure == expected.pressure &&
+ arg->pointerInfo.pointerType == expected.pointerInfo.pointerType &&
+ arg->pointerInfo.pointerId == expected.pointerInfo.pointerId &&
+ arg->pointerInfo.ptPixelLocation.x ==
+ expected.pointerInfo.ptPixelLocation.x &&
+ arg->pointerInfo.ptPixelLocation.y ==
+ expected.pointerInfo.ptPixelLocation.y;
+}
+
+// Make sure that every touch point has the right flag (pointerFlags).
+MATCHER_P(EqualsPointerTouchInfoFlag, id_to_flag_map, "") {
+ for (size_t i = 0; i < id_to_flag_map.size(); ++i) {
+ const POINTER_TOUCH_INFO* touch_info = arg + i;
+ const uint32_t id = touch_info->pointerInfo.pointerId;
+ if (!ContainsKey(id_to_flag_map, id))
+ return false;
+
+ if (id_to_flag_map.find(id)->second != touch_info->pointerInfo.pointerFlags)
+ return false;
+ }
+ return true;
+}
+
+class TouchInjectorWinDelegateMock : public TouchInjectorWinDelegate {
+ public:
+ TouchInjectorWinDelegateMock()
+ : TouchInjectorWinDelegate(nullptr, nullptr, nullptr) {}
+ ~TouchInjectorWinDelegateMock() override {};
+
+ MOCK_METHOD2(InitializeTouchInjection, BOOL(UINT32 max_count, DWORD dw_mode));
+ MOCK_METHOD2(InjectTouchInput,
+ DWORD(UINT32 count, const POINTER_TOUCH_INFO* contacts));
+};
+
+} // namespace
+
+// A test to make sure that the touch event is converted correctly to
+// POINTER_TOUCH_INFO.
+TEST(TouchInjectorWinTest, CheckConversionWithPressure) {
+ scoped_ptr<TouchInjectorWinDelegateMock> delegate_mock(
+ new ::testing::StrictMock<TouchInjectorWinDelegateMock>());
+
+ TouchEvent event;
+ event.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point = event.add_touch_points();
+ point->set_id(1234u);
+ point->set_x(321.0f);
+ point->set_y(123.0f);
+ point->set_radius_x(10.0f);
+ point->set_radius_y(20.0f);
+ point->set_pressure(0.5f);
+ point->set_angle(45.0f);
+
+ POINTER_TOUCH_INFO expected_touch_info;
+ expected_touch_info.touchMask =
+ TOUCH_MASK_CONTACTAREA | TOUCH_MASK_ORIENTATION | TOUCH_MASK_PRESSURE;
+ expected_touch_info.rcContact.left = 311;
+ expected_touch_info.rcContact.top = 103;
+ expected_touch_info.rcContact.right = 331;
+ expected_touch_info.rcContact.bottom = 143;
+ expected_touch_info.orientation = 0;
+ expected_touch_info.pressure = 512;
+ expected_touch_info.orientation = 45;
+
+ expected_touch_info.pointerInfo.pointerType = PT_TOUCH;
+ expected_touch_info.pointerInfo.pointerId = 1234u;
+ expected_touch_info.pointerInfo.ptPixelLocation.x = 321;
+ expected_touch_info.pointerInfo.ptPixelLocation.y = 123;
+
+ InSequence s;
+ EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
+ .WillOnce(Return(1));
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsSinglePointerTouchInfo(expected_touch_info)))
+ .WillOnce(Return(1));
+
+ // Check pressure clamping as well.
+ expected_touch_info.pressure = 1024; // Max
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsSinglePointerTouchInfo(expected_touch_info)))
+ .WillOnce(Return(1));
+
+ expected_touch_info.pressure = 0; // Min
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsSinglePointerTouchInfo(expected_touch_info)))
+ .WillOnce(Return(1));
+
+ TouchInjectorWin injector;
+ injector.SetInjectorDelegateForTest(delegate_mock.Pass());
+ EXPECT_TRUE(injector.Init());
+ injector.InjectTouchEvent(event);
+
+ // Change to MOVE so that there still only one point.
+ event.set_event_type(TouchEvent::TOUCH_POINT_MOVE);
+ point->set_pressure(2.0f);
+ injector.InjectTouchEvent(event);
+
+ point->set_pressure(-3.0f);
+ injector.InjectTouchEvent(event);
+}
+
+// Some devices don't detect pressure. This test is a conversion check for
+// such devices.
+TEST(TouchInjectorWinTest, CheckConversionNoPressure) {
+ scoped_ptr<TouchInjectorWinDelegateMock> delegate_mock(
+ new ::testing::StrictMock<TouchInjectorWinDelegateMock>());
+
+ TouchEvent event;
+ event.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point = event.add_touch_points();
+ point->set_id(1234u);
+ point->set_x(321.0f);
+ point->set_y(123.0f);
+ point->set_radius_x(10.0f);
+ point->set_radius_y(20.0f);
+ point->set_angle(45.0f);
+
+ POINTER_TOUCH_INFO expected_touch_info;
+ expected_touch_info.touchMask =
+ TOUCH_MASK_CONTACTAREA | TOUCH_MASK_ORIENTATION;
+ expected_touch_info.rcContact.left = 311;
+ expected_touch_info.rcContact.top = 103;
+ expected_touch_info.rcContact.right = 331;
+ expected_touch_info.rcContact.bottom = 143;
+ expected_touch_info.orientation = 0;
+ expected_touch_info.pressure = 0;
+ expected_touch_info.orientation = 45;
+
+ expected_touch_info.pointerInfo.pointerType = PT_TOUCH;
+ expected_touch_info.pointerInfo.pointerId = 1234u;
+ expected_touch_info.pointerInfo.ptPixelLocation.x = 321;
+ expected_touch_info.pointerInfo.ptPixelLocation.y = 123;
+
+ InSequence s;
+ EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
+ .WillOnce(Return(1));
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsSinglePointerTouchInfo(expected_touch_info)))
+ .WillOnce(Return(1));
+
+ TouchInjectorWin injector;
+ injector.SetInjectorDelegateForTest(delegate_mock.Pass());
+ EXPECT_TRUE(injector.Init());
+ injector.InjectTouchEvent(event);
+}
+
+// If initialization fails, it should not call any touch injection functions.
+TEST(TouchInjectorWinTest, InitFailed) {
+ scoped_ptr<TouchInjectorWinDelegateMock> delegate_mock(
+ new ::testing::StrictMock<TouchInjectorWinDelegateMock>());
+
+ TouchEvent event;
+ event.set_event_type(TouchEvent::TOUCH_POINT_START);
+
+ InSequence s;
+ EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
+ .WillOnce(Return(0));
+ EXPECT_CALL(*delegate_mock, InjectTouchInput(_, _)).Times(0);
+
+ TouchInjectorWin injector;
+ injector.SetInjectorDelegateForTest(delegate_mock.Pass());
+ EXPECT_FALSE(injector.Init());
+ injector.InjectTouchEvent(event);
+}
+
+// Deinitialize and initialize should clean the state.
+TEST(TouchInjectorWinTest, Reinitialize) {
+ scoped_ptr<TouchInjectorWinDelegateMock> delegate_mock_before_deinitialize(
+ new ::testing::StrictMock<TouchInjectorWinDelegateMock>());
+ scoped_ptr<TouchInjectorWinDelegateMock> delegate_mock_after_deinitialize(
+ new ::testing::StrictMock<TouchInjectorWinDelegateMock>());
+
+ TouchEvent first_event;
+ first_event.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point0 = first_event.add_touch_points();
+ point0->set_id(0u);
+
+ TouchEvent second_event;
+ second_event.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point1 = second_event.add_touch_points();
+ point1->set_id(1u);
+
+ InSequence s;
+ EXPECT_CALL(*delegate_mock_before_deinitialize,
+ InitializeTouchInjection(_, _)).WillOnce(Return(1));
+
+ IdFlagMap id_to_flags;
+ id_to_flags[0u] = kStartFlag;
+ EXPECT_CALL(
+ *delegate_mock_before_deinitialize,
+ InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ EXPECT_CALL(*delegate_mock_after_deinitialize,
+ InitializeTouchInjection(_, _)).WillOnce(Return(1));
+
+ // After deinitializing and then initializing, previous touch points should be
+ // gone.
+ id_to_flags.clear();
+ id_to_flags[1u] = kStartFlag;
+ EXPECT_CALL(
+ *delegate_mock_after_deinitialize,
+ InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ TouchInjectorWin injector;
+ injector.SetInjectorDelegateForTest(delegate_mock_before_deinitialize.Pass());
+
+ EXPECT_TRUE(injector.Init());
+ injector.InjectTouchEvent(first_event);
+ injector.Deinitialize();
+
+ injector.SetInjectorDelegateForTest(delegate_mock_after_deinitialize.Pass());
+ EXPECT_TRUE(injector.Init());
+ injector.InjectTouchEvent(second_event);
+}
+
+// Make sure that the flag is set to kStartFlag.
+TEST(TouchInjectorWinTest, StartTouchPoint) {
+ scoped_ptr<TouchInjectorWinDelegateMock> delegate_mock(
+ new ::testing::StrictMock<TouchInjectorWinDelegateMock>());
+
+ TouchEvent event;
+ event.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point = event.add_touch_points();
+ point->set_id(0u);
+
+ InSequence s;
+ EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
+ .WillOnce(Return(1));
+
+ IdFlagMap id_to_flags;
+ id_to_flags[0u] = kStartFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ TouchInjectorWin injector;
+ injector.SetInjectorDelegateForTest(delegate_mock.Pass());
+ EXPECT_TRUE(injector.Init());
+ injector.InjectTouchEvent(event);
+}
+
+// Start a point and then move, make sure the flag is set to kMoveFlag.
+TEST(TouchInjectorWinTest, MoveTouchPoint) {
+ scoped_ptr<TouchInjectorWinDelegateMock> delegate_mock(
+ new ::testing::StrictMock<TouchInjectorWinDelegateMock>());
+
+ TouchEvent event;
+ event.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point = event.add_touch_points();
+ point->set_id(0u);
+
+
+ InSequence s;
+ EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
+ .WillOnce(Return(1));
+
+ IdFlagMap id_to_flags;
+ id_to_flags[0u] = kStartFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ id_to_flags[0u] = kMoveFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ TouchInjectorWin injector;
+ injector.SetInjectorDelegateForTest(delegate_mock.Pass());
+ EXPECT_TRUE(injector.Init());
+ injector.InjectTouchEvent(event);
+ event.set_event_type(TouchEvent::TOUCH_POINT_MOVE);
+ injector.InjectTouchEvent(event);
+}
+
+// Start a point and then move, make sure the flag is set to kEndFlag.
+TEST(TouchInjectorWinTest, EndTouchPoint) {
+ scoped_ptr<TouchInjectorWinDelegateMock> delegate_mock(
+ new ::testing::StrictMock<TouchInjectorWinDelegateMock>());
+
+ TouchEvent event;
+ event.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point = event.add_touch_points();
+ point->set_id(0u);
+
+ InSequence s;
+ EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
+ .WillOnce(Return(1));
+
+ IdFlagMap id_to_flags;
+ id_to_flags[0u] = kStartFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ id_to_flags[0u] = kEndFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ TouchInjectorWin injector;
+ injector.SetInjectorDelegateForTest(delegate_mock.Pass());
+ EXPECT_TRUE(injector.Init());
+ injector.InjectTouchEvent(event);
+ event.set_event_type(TouchEvent::TOUCH_POINT_END);
+ injector.InjectTouchEvent(event);
+}
+
+// Start a point and then move, make sure the flag is set to kCancelFlag.
+TEST(TouchInjectorWinTest, CancelTouchPoint) {
+ scoped_ptr<TouchInjectorWinDelegateMock> delegate_mock(
+ new ::testing::StrictMock<TouchInjectorWinDelegateMock>());
+
+ TouchEvent event;
+ event.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point = event.add_touch_points();
+ point->set_id(0u);
+
+ InSequence s;
+ EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
+ .WillOnce(Return(1));
+
+ IdFlagMap id_to_flags;
+ id_to_flags[0u] = kStartFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ id_to_flags[0u] = kCancelFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ TouchInjectorWin injector;
+ injector.SetInjectorDelegateForTest(delegate_mock.Pass());
+ EXPECT_TRUE(injector.Init());
+ injector.InjectTouchEvent(event);
+ event.set_event_type(TouchEvent::TOUCH_POINT_CANCEL);
+ injector.InjectTouchEvent(event);
+}
+
+// Note that points that haven't changed should be injected as MOVE.
+// This tests:
+// 1. Start first touch point.
+// 2. Start second touch point.
+// 3. Move both touch points.
+// 4. Start third touch point.
+// 5. End second touch point.
+// 6. Cancel remaining (first and third) touch points.
+TEST(TouchInjectorWinTest, MultiTouch) {
+ scoped_ptr<TouchInjectorWinDelegateMock> delegate_mock(
+ new ::testing::StrictMock<TouchInjectorWinDelegateMock>());
+
+ InSequence s;
+ EXPECT_CALL(*delegate_mock, InitializeTouchInjection(_, _))
+ .WillOnce(Return(1));
+
+ IdFlagMap id_to_flags;
+ id_to_flags[0u] = kStartFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(1, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ id_to_flags[0u] = kMoveFlag;
+ id_to_flags[1u] = kStartFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(2, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ id_to_flags[0u] = kMoveFlag;
+ id_to_flags[1u] = kMoveFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(2, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ id_to_flags[0u] = kMoveFlag;
+ id_to_flags[1u] = kMoveFlag;
+ id_to_flags[2u] = kStartFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(3, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ id_to_flags[0u] = kMoveFlag;
+ id_to_flags[1u] = kEndFlag;
+ id_to_flags[2u] = kMoveFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(3, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ id_to_flags.erase(1u);
+ id_to_flags[0u] = kCancelFlag;
+ id_to_flags[2u] = kCancelFlag;
+ EXPECT_CALL(
+ *delegate_mock,
+ InjectTouchInput(2, EqualsPointerTouchInfoFlag(id_to_flags)))
+ .WillOnce(Return(1));
+
+ TouchInjectorWin injector;
+ injector.SetInjectorDelegateForTest(delegate_mock.Pass());
+ EXPECT_TRUE(injector.Init());
+
+ // Start first touch point.
+ TouchEvent first_touch_start;
+ first_touch_start.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point0 = first_touch_start.add_touch_points();
+ point0->set_id(0u);
+ injector.InjectTouchEvent(first_touch_start);
+
+ // Add second touch point.
+ TouchEvent second_touch_start;
+ second_touch_start.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point1 = second_touch_start.add_touch_points();
+ point1->set_id(1u);
+ injector.InjectTouchEvent(second_touch_start);
+
+ // Move both touch points.
+ TouchEvent move_both;
+ move_both.set_event_type(TouchEvent::TOUCH_POINT_MOVE);
+ point0 = second_touch_start.add_touch_points();
+ point1 = second_touch_start.add_touch_points();
+ point0->set_id(0u);
+ point1->set_id(1u);
+ injector.InjectTouchEvent(move_both);
+
+ // Add another.
+ TouchEvent third_touch_start;
+ third_touch_start.set_event_type(TouchEvent::TOUCH_POINT_START);
+ TouchEventPoint* point2 = third_touch_start.add_touch_points();
+ point2->set_id(2u);
+ injector.InjectTouchEvent(third_touch_start);
+
+ // Release second touch point.
+ TouchEvent release_second;
+ release_second.set_event_type(TouchEvent::TOUCH_POINT_END);
+ point1 = release_second.add_touch_points();
+ point1->set_id(1u);
+ injector.InjectTouchEvent(release_second);
+
+ // Cancel the remaining two points.
+ TouchEvent cancel_rest;
+ cancel_rest.set_event_type(TouchEvent::TOUCH_POINT_CANCEL);
+ point0 = cancel_rest.add_touch_points();
+ point0->set_id(0u);
+ point2 = cancel_rest.add_touch_points();
+ point2->set_id(2u);
+ injector.InjectTouchEvent(cancel_rest);
+}
+
+} // namespace remoting
« no previous file with comments | « remoting/host/touch_injector_win.cc ('k') | remoting/host/win/session_input_injector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698