blob: 2cd229b96fd498473b23f0a93bec884958d82cbf [file] [log] [blame]
// 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/test/app_remoting_latency_test_fixture.h"
#include <utility>
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "remoting/proto/event.pb.h"
#include "remoting/protocol/input_stub.h"
#include "remoting/test/app_remoting_connection_helper.h"
#include "remoting/test/app_remoting_test_driver_environment.h"
#include "remoting/test/rgb_value.h"
#include "remoting/test/test_chromoting_client.h"
#include "remoting/test/test_video_renderer.h"
namespace remoting {
namespace test {
AppRemotingLatencyTestFixture::AppRemotingLatencyTestFixture() {
// NOTE: Derived fixture must initialize application details in constructor.
}
AppRemotingLatencyTestFixture::~AppRemotingLatencyTestFixture() = default;
void AppRemotingLatencyTestFixture::SetUp() {
std::unique_ptr<TestVideoRenderer> test_video_renderer(
new TestVideoRenderer());
test_video_renderer_ = test_video_renderer->GetWeakPtr();
std::unique_ptr<TestChromotingClient> test_chromoting_client(
new TestChromotingClient(std::move(test_video_renderer)));
test_chromoting_client->AddRemoteConnectionObserver(this);
connection_helper_.reset(
new AppRemotingConnectionHelper(GetApplicationDetails()));
connection_helper_->Initialize(std::move(test_chromoting_client));
if (!connection_helper_->StartConnection()) {
LOG(ERROR) << "Remote host connection could not be established.";
FAIL();
}
if (!PrepareApplicationForTesting()) {
LOG(ERROR) << "Unable to prepare application for testing.";
FAIL();
}
}
void AppRemotingLatencyTestFixture::TearDown() {
// Only reset application state when remote host connection is established.
if (connection_helper_->ConnectionIsReadyForTest()) {
ResetApplicationState();
}
connection_helper_->test_chromoting_client()->RemoveRemoteConnectionObserver(
this);
connection_helper_.reset();
}
WaitForImagePatternMatchCallback
AppRemotingLatencyTestFixture::SetExpectedImagePattern(
const webrtc::DesktopRect& expected_rect,
const RGBValue& expected_color) {
std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop());
test_video_renderer_->ExpectAverageColorInRect(expected_rect, expected_color,
run_loop->QuitClosure());
return base::Bind(&AppRemotingLatencyTestFixture::WaitForImagePatternMatch,
base::Unretained(this), base::Passed(&run_loop));
}
void AppRemotingLatencyTestFixture::SaveFrameDataToDisk(
bool save_frame_data_to_disk) {
test_video_renderer_->SaveFrameDataToDisk(save_frame_data_to_disk);
}
bool AppRemotingLatencyTestFixture::WaitForImagePatternMatch(
std::unique_ptr<base::RunLoop> run_loop,
const base::TimeDelta& max_wait_time) {
DCHECK(run_loop);
DCHECK(!timer_.IsRunning());
timer_.Start(FROM_HERE, max_wait_time, run_loop->QuitClosure());
run_loop->Run();
// Image pattern is matched if we stopped because of the reply not the timer.
bool image_pattern_is_matched = (timer_.IsRunning());
timer_.Stop();
run_loop.reset();
return image_pattern_is_matched;
}
void AppRemotingLatencyTestFixture::HostMessageReceived(
const protocol::ExtensionMessage& message) {
if (!host_message_received_callback_.is_null()) {
host_message_received_callback_.Run(message);
}
}
void AppRemotingLatencyTestFixture::PressKey(ui::DomCode dom_code,
bool pressed) {
remoting::protocol::KeyEvent event;
event.set_usb_keycode(static_cast<unsigned int>(dom_code));
event.set_pressed(pressed);
connection_helper_->input_stub()->InjectKeyEvent(event);
}
void AppRemotingLatencyTestFixture::PressAndReleaseKey(ui::DomCode dom_code) {
PressKey(dom_code, true);
PressKey(dom_code, false);
}
void AppRemotingLatencyTestFixture::PressAndReleaseKeyCombination(
const std::vector<ui::DomCode>& dom_codes) {
for (auto iter = dom_codes.begin(); iter != dom_codes.end(); ++iter) {
PressKey(*iter, true);
}
for (auto iter = dom_codes.rbegin(); iter != dom_codes.rend(); ++iter) {
PressKey(*iter, false);
}
}
void AppRemotingLatencyTestFixture::SetHostMessageReceivedCallback(
const HostMessageReceivedCallback& host_message_received_callback) {
host_message_received_callback_ = host_message_received_callback;
}
void AppRemotingLatencyTestFixture::ResetHostMessageReceivedCallback() {
host_message_received_callback_.Reset();
}
void AppRemotingLatencyTestFixture::ResetApplicationState() {
DCHECK(!timer_.IsRunning());
DCHECK(!run_loop_ || !run_loop_->running());
// Give the app some time to settle before reseting to initial state.
run_loop_.reset(new base::RunLoop());
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop_->QuitClosure(), base::TimeDelta::FromSeconds(1));
run_loop_->Run();
// Press Alt + F4 and wait for amount of time for the input to be delivered
// and processed.
std::vector<ui::DomCode> dom_codes;
dom_codes.push_back(ui::DomCode::ALT_LEFT);
dom_codes.push_back(ui::DomCode::F4);
PressAndReleaseKeyCombination(dom_codes);
run_loop_.reset(new base::RunLoop());
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop_->QuitClosure(), base::TimeDelta::FromSeconds(2));
run_loop_->Run();
// Press 'N' to choose not save and wait for 1 second for the input to be
// delivered and processed.
PressAndReleaseKey(ui::DomCode::US_N);
run_loop_.reset(new base::RunLoop());
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop_->QuitClosure(), base::TimeDelta::FromSeconds(2));
run_loop_->Run();
run_loop_.reset();
}
} // namespace test
} // namespace remoting