1 // Copyright 2015 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.
5 #include "remoting/test/app_remoting_latency_test_fixture.h"
7 #include "base/logging.h"
8 #include "base/run_loop.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "base/timer/timer.h"
11 #include "remoting/proto/event.pb.h"
12 #include "remoting/protocol/input_stub.h"
13 #include "remoting/protocol/usb_key_codes.h"
14 #include "remoting/test/app_remoting_connection_helper.h"
15 #include "remoting/test/app_remoting_test_driver_environment.h"
16 #include "remoting/test/test_chromoting_client.h"
17 #include "remoting/test/test_video_renderer.h"
22 AppRemotingLatencyTestFixture::AppRemotingLatencyTestFixture()
23 : timer_(new base::Timer(true, false)) {
24 // NOTE: Derived fixture must initialize application details in constructor.
27 AppRemotingLatencyTestFixture::~AppRemotingLatencyTestFixture() {
30 void AppRemotingLatencyTestFixture::SetUp() {
31 DCHECK(thread_checker_
.CalledOnValidThread());
33 scoped_ptr
<TestVideoRenderer
> test_video_renderer(new TestVideoRenderer());
34 test_video_renderer_
= test_video_renderer
->GetWeakPtr();
36 scoped_ptr
<TestChromotingClient
> test_chromoting_client(
37 new TestChromotingClient(test_video_renderer
.Pass()));
39 connection_helper_
.reset(
40 new AppRemotingConnectionHelper(GetApplicationDetails()));
41 connection_helper_
->Initialize(test_chromoting_client
.Pass());
43 if (!connection_helper_
->StartConnection()) {
44 LOG(ERROR
) << "Remote host connection could not be established.";
49 void AppRemotingLatencyTestFixture::TearDown() {
50 // Only reset application state when remote host connection is established.
51 if (connection_helper_
->ConnectionIsReadyForTest()) {
52 ResetApplicationState();
55 connection_helper_
.reset();
58 WaitForImagePatternMatchCallback
59 AppRemotingLatencyTestFixture::SetExpectedImagePattern(
60 const webrtc::DesktopRect
& expected_rect
,
61 uint32_t expected_color
) {
62 DCHECK(thread_checker_
.CalledOnValidThread());
64 scoped_ptr
<base::RunLoop
> run_loop(new base::RunLoop());
66 base::ThreadTaskRunnerHandle::Get()->PostTask(
67 FROM_HERE
, base::Bind(&TestVideoRenderer::ExpectAverageColorInRect
,
68 test_video_renderer_
, expected_rect
, expected_color
,
69 run_loop
->QuitClosure()));
71 return base::Bind(&AppRemotingLatencyTestFixture::WaitForImagePatternMatch
,
72 base::Unretained(this), base::Passed(&run_loop
));
75 bool AppRemotingLatencyTestFixture::WaitForImagePatternMatch(
76 scoped_ptr
<base::RunLoop
> run_loop
,
77 const base::TimeDelta
& max_wait_time
) {
78 DCHECK(thread_checker_
.CalledOnValidThread());
80 DCHECK(!timer_
->IsRunning());
82 timer_
->Start(FROM_HERE
, max_wait_time
, run_loop
->QuitClosure());
86 // Image pattern is matched if we stopped because of the reply not the timer.
87 bool image_pattern_is_matched
= (timer_
->IsRunning());
91 return image_pattern_is_matched
;
94 void AppRemotingLatencyTestFixture::PressKey(uint32_t usb_keycode
,
96 remoting::protocol::KeyEvent event
;
97 event
.set_usb_keycode(usb_keycode
);
98 event
.set_pressed(pressed
);
99 connection_helper_
->input_stub()->InjectKeyEvent(event
);
102 void AppRemotingLatencyTestFixture::PressAndReleaseKey(uint32_t usb_keycode
) {
103 PressKey(usb_keycode
, true);
104 PressKey(usb_keycode
, false);
107 void AppRemotingLatencyTestFixture::PressAndReleaseKeyCombination(
108 const std::vector
<uint32_t>& usb_keycodes
) {
109 for (std::vector
<uint32_t>::const_iterator iter
= usb_keycodes
.begin();
110 iter
!= usb_keycodes
.end(); ++iter
) {
111 PressKey(*iter
, true);
113 for (std::vector
<uint32_t>::const_reverse_iterator iter
=
114 usb_keycodes
.rbegin();
115 iter
!= usb_keycodes
.rend(); ++iter
) {
116 PressKey(*iter
, false);
120 void AppRemotingLatencyTestFixture::ResetApplicationState() {
121 DCHECK(!timer_
->IsRunning());
122 DCHECK(!run_loop_
|| !run_loop_
->running());
124 // Give the app some time to settle before reseting to initial state.
125 run_loop_
.reset(new base::RunLoop());
126 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
127 FROM_HERE
, run_loop_
->QuitClosure(), base::TimeDelta::FromSeconds(1));
130 // Press Alt + F4 and wait for amount of time for the input to be delivered
132 std::vector
<uint32_t> usb_keycodes
;
133 usb_keycodes
.push_back(kUsbLeftAlt
);
134 usb_keycodes
.push_back(kUsbF4
);
135 PressAndReleaseKeyCombination(usb_keycodes
);
137 run_loop_
.reset(new base::RunLoop());
138 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
139 FROM_HERE
, run_loop_
->QuitClosure(), base::TimeDelta::FromSeconds(2));
142 // Press 'N' to choose not save and wait for 1 second for the input to be
143 // delivered and processed.
144 PressAndReleaseKey(kUsbN
);
146 run_loop_
.reset(new base::RunLoop());
147 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
148 FROM_HERE
, run_loop_
->QuitClosure(), base::TimeDelta::FromSeconds(2));
154 } // namespace remoting