blob: bd36ab3065680f05df92915a275223d8bfe54763 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
anyhow::Error,
fuchsia_async as fasync, fuchsia_syslog as syslog,
input_synthesis::{legacy_backend::InputDeviceRegistry, synthesizer::tap_event},
log::{error, info, set_logger, set_max_level, LevelFilter},
matches::assert_matches,
scenic_stress_tests_lib::utils::init_scenic,
std::time::Duration,
structopt::StructOpt,
};
#[derive(Clone, StructOpt, Debug)]
#[structopt(
name = "scenic stress test (scenic_stressor) tool",
about = "Creates an instance of scenic and performs stressful operations on it"
)]
struct Opt {
/// Number of operations to complete before exiting.
#[structopt(short = "ops", long = "num_operations", default_value = "50")]
num_operations: u64,
/// Filter logging by level (off, error, warn, info, debug, trace)
#[structopt(short = "l", long = "log_filter", default_value = "info")]
log_filter: LevelFilter,
/// Use stdout for stressor output
#[structopt(long = "stdout")]
stdout: bool,
}
// A simple logger that prints to stdout
struct SimpleStdoutLogger;
impl log::Log for SimpleStdoutLogger {
fn enabled(&self, _metadata: &log::Metadata<'_>) -> bool {
true
}
fn log(&self, record: &log::Record<'_>) {
if self.enabled(record.metadata()) {
match record.level() {
log::Level::Info => {
println!("{}", record.args());
}
log::Level::Error => {
eprintln!("{}: {}", record.level(), record.args());
}
_ => {
println!("{}: {}", record.level(), record.args());
}
}
}
}
fn flush(&self) {}
}
#[fasync::run_singlethreaded]
async fn main() -> Result<(), Error> {
// Get arguments from command line
let opt = Opt::from_args();
if opt.stdout {
// Initialize SimpleStdoutLogger
set_logger(&SimpleStdoutLogger).expect("Failed to set SimpleLogger as global logger");
} else {
// Use syslog
syslog::init().unwrap();
}
set_max_level(opt.log_filter);
info!("------------------ scenic_stressor is starting -------------------");
info!("ARGUMENTS = {:#?}", opt);
info!("------------------------------------------------------------------");
// Setup a panic handler that prints out details of this invocation
let opt_clone = opt.clone();
let default_panic_hook = std::panic::take_hook();
std::panic::set_hook(Box::new(move |panic_info| {
error!("");
error!("------------------ scenic_stressor has crashed -------------------");
error!("ARGUMENTS = {:#?}", opt_clone);
error!("------------------------------------------------------------------");
error!("");
default_panic_hook(panic_info);
}));
// Setup the component tree and inject Scenic's dependencies.
// Wait for at least 1 display update before sending touch events to the screen.
let (test, display_state) = init_scenic(1).await;
info!("Starting tap event send");
let svc_dir_path = test.get_hub_v2_path().join("children/root_presenter/exec/out/svc");
let svc_dir_path = svc_dir_path.to_str().unwrap().to_string();
// Tap once every 100ms at the center of the touchscreen [num_operations] times
let num_tap_events = opt.num_operations;
tap_event(
320,
240,
640,
480,
num_tap_events as usize,
Duration::from_millis(100 * num_tap_events),
&mut InputDeviceRegistry::new_with_path(svc_dir_path),
)
.await
.unwrap();
info!("Sent all tap events");
// The display should have updated more than 3 times.
assert_matches!(display_state.get_num_updates(), x if x > 3);
info!("Exiting");
Ok(())
}