| // 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(()) |
| } |