blob: 7fa2a326eaec9918246552e108b33b7b6104390d [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 crate::datatypes::{HttpsSample, Phase};
use crate::diagnostics::{Diagnostics, Event};
use fuchsia_sync::Mutex;
use httpdate_hyper::HttpsDateErrorType;
/// A fake `Diagnostics` implementation useful for verifying unittests.
pub struct FakeDiagnostics {
/// An ordered list of the events received since the last reset.
events: Mutex<Vec<OwnedEvent>>,
}
/// A copy of `Event` where all contents are owned.
#[derive(PartialEq, Debug)]
enum OwnedEvent {
NetworkCheckSuccessful,
Success(HttpsSample),
Failure(HttpsDateErrorType),
Phase(Phase),
}
impl<'a> From<Event<'a>> for OwnedEvent {
fn from(event: Event<'a>) -> Self {
match event {
Event::NetworkCheckSuccessful => Self::NetworkCheckSuccessful,
Event::Success(sample) => Self::Success(sample.clone()),
Event::Failure(error) => Self::Failure(error),
Event::Phase(phase) => Self::Phase(phase),
}
}
}
impl FakeDiagnostics {
/// Constructs a new `FakeDiagnostics`.
pub fn new() -> Self {
FakeDiagnostics { events: Mutex::new(Vec::new()) }
}
/// Assert that the recorded events equals the provided events.
pub fn assert_events<'a, I: IntoIterator<Item = Event<'a>>>(&self, events: I) {
let owned_events =
events.into_iter().map(|event| OwnedEvent::from(event)).collect::<Vec<_>>();
assert_eq!(owned_events, *self.events.lock());
}
/// Assert that the recorded events starts with the provided events.
pub fn assert_events_starts_with<'a, I: IntoIterator<Item = Event<'a>>>(&self, events: I) {
let expected_events =
events.into_iter().map(|event| OwnedEvent::from(event)).collect::<Vec<_>>();
let actual_events = self.events.lock();
assert!(actual_events.len() >= expected_events.len());
assert_eq!(expected_events.as_slice(), &actual_events[..expected_events.len()]);
}
/// Clears all recorded interactions.
pub fn reset(&self) {
self.events.lock().clear();
}
}
impl Diagnostics for FakeDiagnostics {
fn record<'a>(&self, event: Event<'a>) {
self.events.lock().push(event.into());
}
}
impl<T: AsRef<FakeDiagnostics> + Send + Sync> Diagnostics for T {
fn record<'a>(&self, event: Event<'a>) {
self.as_ref().record(event);
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::datatypes::Poll;
use fuchsia_zircon as zx;
use lazy_static::lazy_static;
lazy_static! {
static ref TEST_SAMPLE: HttpsSample = HttpsSample {
utc: zx::Time::from_nanos(111_111_111),
monotonic: zx::Time::from_nanos(222_222_222),
standard_deviation: zx::Duration::from_millis(235),
final_bound_size: zx::Duration::from_millis(100),
polls: vec![Poll { round_trip_time: zx::Duration::from_nanos(23) }],
};
static ref TEST_SUCCESS: Event<'static> = Event::Success(&*TEST_SAMPLE);
static ref TEST_SAMPLE_2: HttpsSample = {
let mut new = TEST_SAMPLE.clone();
new.polls = vec![];
new
};
static ref TEST_SUCCESS_2: Event<'static> = Event::Success(&*TEST_SAMPLE_2);
}
const TEST_FAILURE: Event<'static> = Event::Failure(HttpsDateErrorType::NetworkError);
const TEST_PHASE: Event<'static> = Event::Phase(Phase::Converge);
#[fuchsia::test]
fn log_and_reset_events() {
let diagnostics = FakeDiagnostics::new();
diagnostics.assert_events(vec![]);
diagnostics.record(*TEST_SUCCESS);
diagnostics.assert_events(vec![*TEST_SUCCESS]);
diagnostics.record(TEST_FAILURE);
diagnostics.record(TEST_PHASE);
diagnostics.assert_events(vec![*TEST_SUCCESS, TEST_FAILURE, TEST_PHASE]);
diagnostics.reset();
diagnostics.assert_events(vec![]);
}
#[test]
#[should_panic]
fn log_events_wrong_event_type() {
let diagnostics = FakeDiagnostics::new();
diagnostics.assert_events(vec![]);
diagnostics.record(*TEST_SUCCESS);
diagnostics.assert_events(vec![TEST_FAILURE]);
}
#[test]
#[should_panic]
fn log_events_wrong_sample() {
let diagnostics = FakeDiagnostics::new();
diagnostics.assert_events(vec![]);
diagnostics.record(*TEST_SUCCESS);
diagnostics.assert_events(vec![*TEST_SUCCESS_2]);
}
#[test]
#[should_panic]
fn log_events_wrong_event_count() {
let diagnostics = FakeDiagnostics::new();
diagnostics.assert_events(vec![]);
diagnostics.record(*TEST_SUCCESS);
diagnostics.assert_events(vec![*TEST_SUCCESS, *TEST_SUCCESS]);
}
}