blob: 528b283b2ca5e75081f6696df156f6fbe9596440 [file]
// 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 {
super::{DoneSignaler, TestEvent, TestEventSender},
anyhow::{bail, Context, Error},
async_trait::async_trait,
fcrash::FileReportResults,
fidl_fuchsia_feedback as fcrash,
fidl_server::*,
tracing::*,
};
const REPORT_PROGRAM_NAME: &str = "triage_detect";
/// FakeCrashReporter can be injected to capture Detect's crash report requests.
#[derive(Clone)]
pub struct FakeCrashReporter {
event_sender: TestEventSender,
done_signaler: DoneSignaler,
}
fn evaluate_report(report: &fcrash::CrashReport) -> Result<String, Error> {
let fcrash::CrashReport { program_name, crash_signature, is_fatal, .. } = report;
if program_name != &Some(REPORT_PROGRAM_NAME.to_string()) {
bail!(
"Crash report program name should be {} but it was {:?}",
REPORT_PROGRAM_NAME,
program_name
);
}
if is_fatal != &Some(false) {
bail!("Crash report should not be fatal, but it was {:?}", is_fatal);
}
match crash_signature {
Some(signature) => return Ok(signature.to_string()),
None => bail!("Crash report crash signature was None"),
}
}
impl FakeCrashReporter {
pub fn new(event_sender: TestEventSender, done_signaler: DoneSignaler) -> Self {
Self { event_sender, done_signaler }
}
fn send_test_event(&self, event: Result<TestEvent, Error>) -> Result<(), Error> {
Ok(self.event_sender.unbounded_send(event)?)
}
}
#[async_trait]
impl AsyncRequestHandler<fcrash::CrashReporterMarker> for FakeCrashReporter {
async fn handle_request(&self, request: fcrash::CrashReporterRequest) -> Result<(), Error> {
match request {
fcrash::CrashReporterRequest::File { report, responder } => {
match evaluate_report(&report) {
Ok(signature) => {
info!("Received crash report: {}", signature);
self.send_test_event(Ok(TestEvent::CrashReport(signature)))?;
responder.send(Ok(())).context("failed to send response to client")?;
}
Err(problem) => {
error!("Problem in report: {}", problem);
self.send_test_event(Err(problem))?;
self.done_signaler.signal_done().await;
}
}
}
fcrash::CrashReporterRequest::FileReport { report, responder } => {
match evaluate_report(&report) {
Ok(signature) => {
info!("Received crash report: {}", signature);
self.send_test_event(Ok(TestEvent::CrashReport(signature)))?;
responder
.send(Ok(&FileReportResults::default()))
.context("failed to send response to client")?;
}
Err(problem) => {
error!("Problem in report: {}", problem);
self.send_test_event(Err(problem))?;
self.done_signaler.signal_done().await;
}
}
}
}
Ok(())
}
}