<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Temporal quantification.

#![stable(feature = "time", since = "1.3.0")]

use error::Error;
use fmt;
use ops::{Add, Sub};
use sys::time;

#[stable(feature = "time", since = "1.3.0")]
pub use self::duration::Duration;

mod duration;

/// A measurement of a monotonically increasing clock.
///
/// Instants are guaranteed always be greater than any previously measured
/// instant when created, and are often useful for tasks such as measuring
/// benchmarks or timing how long an operation takes.
///
/// Note, however, that instants are not guaranteed to be **steady**.  In other
/// words each tick of the underlying clock may not be the same length (e.g.
/// some seconds may be longer than others). An instant may jump forwards or
/// experience time dilation (slow down or speed up), but it will never go
/// backwards.
///
/// Instants are opaque types that can only be compared to one another. There is
/// no method to get "the number of seconds" from an instant but instead it only
/// allow learning the duration between two instants (or comparing two
/// instants).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct Instant(time::Instant);

/// A measurement of the system clock appropriate for timestamps such as those
/// on files on the filesystem.
///
/// Distinct from the `Instant` type, this time measurement **is not
/// monotonic**. This means that you can save a file to the file system, then
/// save another file to the file system, **and the second file has a
/// `SystemTime` measurement earlier than the second**. In other words, an
/// operation that happens after another operation in real time may have an
/// earlier `SystemTime`!
///
/// Consequently, comparing two `SystemTime` instances to learn about the
/// duration between them returns a `Result` instead of an infallible `Duration`
/// to indicate that this sort of time drift may happen and needs to be handled.
///
/// Although a `SystemTime` cannot be directly inspected, the `UNIX_EPOCH`
/// constant is provided in this module as an anchor in time to learn
/// information about a `SystemTime`. By calculating the duration from this
/// fixed point in time a `SystemTime` can be converted to a human-readable time
/// or perhaps some other string representation.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTime(time::SystemTime);

/// An error returned from the `duration_from_earlier` method on `SystemTime`,
/// used to learn about why how far in the opposite direction a timestamp lies.
#[derive(Clone, Debug)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTimeError(Duration);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Instant {
    /// Returns an instant corresponding to "now".
    pub fn now() -> Instant {
        Instant(time::Instant::now())
    }

    /// Returns the amount of time elapsed from another instant to this one.
    ///
    /// # Panics
    ///
    /// This function will panic if `earlier` is later than `self`, which should
    /// only be possible if `earlier` was created after `self`. Because
    /// `Instant` is monotonic, the only time that this should happen should be
    /// a bug.
    pub fn duration_from_earlier(&self, earlier: Instant) -> Duration {
        self.0.sub_instant(&earlier.0)
    }

    /// Returns the amount of time elapsed since this instant was created.
    ///
    /// # Panics
    ///
    /// This function may panic if the current time is earlier than this instant
    /// which can happen if an `Instant` is produced synthetically.
    pub fn elapsed(&self) -> Duration {
        Instant::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for Instant {
    type Output = Instant;

    fn add(self, other: Duration) -> Instant {
        Instant(self.0.add_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for Instant {
    type Output = Instant;

    fn sub(self, other: Duration) -> Instant {
        Instant(self.0.sub_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for Instant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTime {
    /// Returns the system time corresponding to "now".
    pub fn now() -> SystemTime {
        SystemTime(time::SystemTime::now())
    }

    /// Returns the amount of time elapsed from an earlier point in time.
    ///
    /// This function may fail because measurements taken earlier are not
    /// guaranteed to always be before later measurements (due to anomalies such
    /// as the system clock being adjusted either forwards or backwards).
    ///
    /// If successful, `Ok(duration)` is returned where the duration represents
    /// the amount of time elapsed from the specified measurement to this one.
    ///
    /// Returns an `Err` if `earlier` is later than `self`, and the error
    /// contains how far from `self` the time is.
    pub fn duration_from_earlier(&self, earlier: SystemTime)
                                 -> Result<Duration, SystemTimeError> {
        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
    }

    /// Returns the amount of time elapsed since this system time was created.
    ///
    /// This function may fail as the underlying system clock is susceptible to
    /// drift and updates (e.g. the system clock could go backwards), so this
    /// function may not always succeed. If successful, `Ok(duration)` is
    /// returned where the duration represents the amount of time elapsed from
    /// this time measurement to the current time.
    ///
    /// Returns an `Err` if `self` is later than the current system time, and
    /// the error contains how far from the current system time `self` is.
    pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
        SystemTime::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for SystemTime {
    type Output = SystemTime;

    fn add(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.add_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for SystemTime {
    type Output = SystemTime;

    fn sub(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.sub_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for SystemTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// An anchor in time which can be used to create new `SystemTime` instances or
/// learn about where in time a `SystemTime` lies.
///
/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
/// respect to the system clock. Using `duration_from_earlier` on an existing
/// `SystemTime` instance can tell how far away from this point in time a
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
/// `SystemTime` instance to represent another fixed point in time.
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTimeError {
    /// Returns the positive duration which represents how far forward the
    /// second system time was from the first.
    ///
    /// A `SystemTimeError` is returned from the `duration_from_earlier`
    /// operation whenever the second duration, `earlier`, actually represents a
    /// point later in time than the `self` of the method call. This function
    /// will extract and return the amount of time later `earlier` actually is.
    pub fn duration(&self) -> Duration {
        self.0
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Error for SystemTimeError {
    fn description(&self) -> &str { "other time was not earlier than self" }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Display for SystemTimeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "second time provided was later than self")
    }
}

#[cfg(test)]
mod tests {
    use super::{Instant, SystemTime, Duration, UNIX_EPOCH};

    macro_rules! assert_almost_eq {
        ($a:expr, $b:expr) => ({
            let (a, b) = ($a, $b);
            if a != b {
                let (a, b) = if a > b {(a, b)} else {(b, a)};
                assert!(a - Duration::new(0, 1) <= b);
            }
        })
    }

    #[test]
    fn instant_monotonic() {
        let a = Instant::now();
        let b = Instant::now();
        assert!(b >= a);
    }

    #[test]
    fn instant_elapsed() {
        let a = Instant::now();
        a.elapsed();
    }

    #[test]
    fn instant_math() {
        let a = Instant::now();
        let b = Instant::now();
        let dur = b.duration_from_earlier(a);
        assert_almost_eq!(b - dur, a);
        assert_almost_eq!(a + dur, b);

        let second = Duration::new(1, 0);
        assert_almost_eq!(a - second + second, a);
    }

    #[test]
    #[should_panic]
    fn instant_duration_panic() {
        let a = Instant::now();
        (a - Duration::new(1, 0)).duration_from_earlier(a);
    }

    #[test]
    fn system_time_math() {
        let a = SystemTime::now();
        let b = SystemTime::now();
        match b.duration_from_earlier(a) {
            Ok(dur) if dur == Duration::new(0, 0) => {
                assert_almost_eq!(a, b);
            }
            Ok(dur) => {
                assert!(b > a);
                assert_almost_eq!(b - dur, a);
                assert_almost_eq!(a + dur, b);
            }
            Err(dur) => {
                let dur = dur.duration();
                assert!(a > b);
                assert_almost_eq!(b + dur, a);
                assert_almost_eq!(b - dur, a);
            }
        }

        let second = Duration::new(1, 0);
        assert_almost_eq!(a.duration_from_earlier(a - second).unwrap(), second);
        assert_almost_eq!(a.duration_from_earlier(a + second).unwrap_err()
                           .duration(), second);

        assert_almost_eq!(a - second + second, a);

        let eighty_years = second * 60 * 60 * 24 * 365 * 80;
        assert_almost_eq!(a - eighty_years + eighty_years, a);
        assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
    }

    #[test]
    fn system_time_elapsed() {
        let a = SystemTime::now();
        drop(a.elapsed());
    }

    #[test]
    fn since_epoch() {
        let ts = SystemTime::now();
        let a = ts.duration_from_earlier(UNIX_EPOCH).unwrap();
        let b = ts.duration_from_earlier(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
        assert!(b > a);
        assert_eq!(b - a, Duration::new(1, 0));

        // let's assume that we're all running computers later than 2000
        let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30;
        assert!(a > thirty_years);

        // let's assume that we're all running computers earlier than 2090.
        // Should give us ~70 years to fix this!
        let hundred_twenty_years = thirty_years * 4;
        assert!(a < hundred_twenty_years);
    }
}
<commit_msg>doc: fix grammar<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Temporal quantification.

#![stable(feature = "time", since = "1.3.0")]

use error::Error;
use fmt;
use ops::{Add, Sub};
use sys::time;

#[stable(feature = "time", since = "1.3.0")]
pub use self::duration::Duration;

mod duration;

/// A measurement of a monotonically increasing clock.
///
/// Instants are always guaranteed to be greater than any previously measured
/// instant when created, and are often useful for tasks such as measuring
/// benchmarks or timing how long an operation takes.
///
/// Note, however, that instants are not guaranteed to be **steady**.  In other
/// words each tick of the underlying clock may not be the same length (e.g.
/// some seconds may be longer than others). An instant may jump forwards or
/// experience time dilation (slow down or speed up), but it will never go
/// backwards.
///
/// Instants are opaque types that can only be compared to one another. There is
/// no method to get "the number of seconds" from an instant but instead it only
/// allow learning the duration between two instants (or comparing two
/// instants).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct Instant(time::Instant);

/// A measurement of the system clock appropriate for timestamps such as those
/// on files on the filesystem.
///
/// Distinct from the `Instant` type, this time measurement **is not
/// monotonic**. This means that you can save a file to the file system, then
/// save another file to the file system, **and the second file has a
/// `SystemTime` measurement earlier than the second**. In other words, an
/// operation that happens after another operation in real time may have an
/// earlier `SystemTime`!
///
/// Consequently, comparing two `SystemTime` instances to learn about the
/// duration between them returns a `Result` instead of an infallible `Duration`
/// to indicate that this sort of time drift may happen and needs to be handled.
///
/// Although a `SystemTime` cannot be directly inspected, the `UNIX_EPOCH`
/// constant is provided in this module as an anchor in time to learn
/// information about a `SystemTime`. By calculating the duration from this
/// fixed point in time a `SystemTime` can be converted to a human-readable time
/// or perhaps some other string representation.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTime(time::SystemTime);

/// An error returned from the `duration_from_earlier` method on `SystemTime`,
/// used to learn about why how far in the opposite direction a timestamp lies.
#[derive(Clone, Debug)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTimeError(Duration);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Instant {
    /// Returns an instant corresponding to "now".
    pub fn now() -> Instant {
        Instant(time::Instant::now())
    }

    /// Returns the amount of time elapsed from another instant to this one.
    ///
    /// # Panics
    ///
    /// This function will panic if `earlier` is later than `self`, which should
    /// only be possible if `earlier` was created after `self`. Because
    /// `Instant` is monotonic, the only time that this should happen should be
    /// a bug.
    pub fn duration_from_earlier(&self, earlier: Instant) -> Duration {
        self.0.sub_instant(&earlier.0)
    }

    /// Returns the amount of time elapsed since this instant was created.
    ///
    /// # Panics
    ///
    /// This function may panic if the current time is earlier than this instant
    /// which can happen if an `Instant` is produced synthetically.
    pub fn elapsed(&self) -> Duration {
        Instant::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for Instant {
    type Output = Instant;

    fn add(self, other: Duration) -> Instant {
        Instant(self.0.add_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for Instant {
    type Output = Instant;

    fn sub(self, other: Duration) -> Instant {
        Instant(self.0.sub_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for Instant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTime {
    /// Returns the system time corresponding to "now".
    pub fn now() -> SystemTime {
        SystemTime(time::SystemTime::now())
    }

    /// Returns the amount of time elapsed from an earlier point in time.
    ///
    /// This function may fail because measurements taken earlier are not
    /// guaranteed to always be before later measurements (due to anomalies such
    /// as the system clock being adjusted either forwards or backwards).
    ///
    /// If successful, `Ok(duration)` is returned where the duration represents
    /// the amount of time elapsed from the specified measurement to this one.
    ///
    /// Returns an `Err` if `earlier` is later than `self`, and the error
    /// contains how far from `self` the time is.
    pub fn duration_from_earlier(&self, earlier: SystemTime)
                                 -> Result<Duration, SystemTimeError> {
        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
    }

    /// Returns the amount of time elapsed since this system time was created.
    ///
    /// This function may fail as the underlying system clock is susceptible to
    /// drift and updates (e.g. the system clock could go backwards), so this
    /// function may not always succeed. If successful, `Ok(duration)` is
    /// returned where the duration represents the amount of time elapsed from
    /// this time measurement to the current time.
    ///
    /// Returns an `Err` if `self` is later than the current system time, and
    /// the error contains how far from the current system time `self` is.
    pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
        SystemTime::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for SystemTime {
    type Output = SystemTime;

    fn add(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.add_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for SystemTime {
    type Output = SystemTime;

    fn sub(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.sub_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for SystemTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// An anchor in time which can be used to create new `SystemTime` instances or
/// learn about where in time a `SystemTime` lies.
///
/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
/// respect to the system clock. Using `duration_from_earlier` on an existing
/// `SystemTime` instance can tell how far away from this point in time a
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
/// `SystemTime` instance to represent another fixed point in time.
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTimeError {
    /// Returns the positive duration which represents how far forward the
    /// second system time was from the first.
    ///
    /// A `SystemTimeError` is returned from the `duration_from_earlier`
    /// operation whenever the second duration, `earlier`, actually represents a
    /// point later in time than the `self` of the method call. This function
    /// will extract and return the amount of time later `earlier` actually is.
    pub fn duration(&self) -> Duration {
        self.0
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Error for SystemTimeError {
    fn description(&self) -> &str { "other time was not earlier than self" }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Display for SystemTimeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "second time provided was later than self")
    }
}

#[cfg(test)]
mod tests {
    use super::{Instant, SystemTime, Duration, UNIX_EPOCH};

    macro_rules! assert_almost_eq {
        ($a:expr, $b:expr) => ({
            let (a, b) = ($a, $b);
            if a != b {
                let (a, b) = if a > b {(a, b)} else {(b, a)};
                assert!(a - Duration::new(0, 1) <= b);
            }
        })
    }

    #[test]
    fn instant_monotonic() {
        let a = Instant::now();
        let b = Instant::now();
        assert!(b >= a);
    }

    #[test]
    fn instant_elapsed() {
        let a = Instant::now();
        a.elapsed();
    }

    #[test]
    fn instant_math() {
        let a = Instant::now();
        let b = Instant::now();
        let dur = b.duration_from_earlier(a);
        assert_almost_eq!(b - dur, a);
        assert_almost_eq!(a + dur, b);

        let second = Duration::new(1, 0);
        assert_almost_eq!(a - second + second, a);
    }

    #[test]
    #[should_panic]
    fn instant_duration_panic() {
        let a = Instant::now();
        (a - Duration::new(1, 0)).duration_from_earlier(a);
    }

    #[test]
    fn system_time_math() {
        let a = SystemTime::now();
        let b = SystemTime::now();
        match b.duration_from_earlier(a) {
            Ok(dur) if dur == Duration::new(0, 0) => {
                assert_almost_eq!(a, b);
            }
            Ok(dur) => {
                assert!(b > a);
                assert_almost_eq!(b - dur, a);
                assert_almost_eq!(a + dur, b);
            }
            Err(dur) => {
                let dur = dur.duration();
                assert!(a > b);
                assert_almost_eq!(b + dur, a);
                assert_almost_eq!(b - dur, a);
            }
        }

        let second = Duration::new(1, 0);
        assert_almost_eq!(a.duration_from_earlier(a - second).unwrap(), second);
        assert_almost_eq!(a.duration_from_earlier(a + second).unwrap_err()
                           .duration(), second);

        assert_almost_eq!(a - second + second, a);

        let eighty_years = second * 60 * 60 * 24 * 365 * 80;
        assert_almost_eq!(a - eighty_years + eighty_years, a);
        assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
    }

    #[test]
    fn system_time_elapsed() {
        let a = SystemTime::now();
        drop(a.elapsed());
    }

    #[test]
    fn since_epoch() {
        let ts = SystemTime::now();
        let a = ts.duration_from_earlier(UNIX_EPOCH).unwrap();
        let b = ts.duration_from_earlier(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
        assert!(b > a);
        assert_eq!(b - a, Duration::new(1, 0));

        // let's assume that we're all running computers later than 2000
        let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30;
        assert!(a > thirty_years);

        // let's assume that we're all running computers earlier than 2090.
        // Should give us ~70 years to fix this!
        let hundred_twenty_years = thirty_years * 4;
        assert!(a < hundred_twenty_years);
    }
}
<|endoftext|>


<commit_before>//! Utilities to make testing [`Future`s](futures_core::future::Future) easier

#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
// It cannot be included in the published code because this lints have false positives in the minimum required version.
#![cfg_attr(test, warn(single_use_lifetimes))]
#![warn(clippy::all)]
#![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))]

#[cfg(not(feature = "std"))]
compile_error!(
    "`futures-test` must have the `std` feature activated, this is a default-active feature"
);

// Not public API.
#[doc(hidden)]
#[cfg(feature = "std")]
pub mod __private {
    pub use futures_core::{future, stream, task};
    pub use futures_executor::block_on;
    pub use std::{
        option::Option::{None, Some},
        pin::Pin,
        result::Result::{Err, Ok},
    };

    pub mod assert {
        pub use crate::assert::*;
    }
}

#[macro_use]
#[cfg(feature = "std")]
mod assert;

#[cfg(feature = "std")]
pub mod task;

#[cfg(feature = "std")]
pub mod future;

#[cfg(feature = "std")]
pub mod stream;

#[cfg(feature = "std")]
pub mod sink;

#[cfg(feature = "std")]
pub mod io;

mod assert_unmoved;
mod interleave_pending;
mod track_closed;

/// Enables an `async` test function. The generated future will be run to completion with
/// [`futures_executor::block_on`](futures_executor::block_on).
///
/// ```no_run
/// #[futures_test::test]
/// async fn my_test() {
///     let fut = async { true };
///     assert!(fut.await);
/// }
/// ```
#[cfg(feature = "std")]
pub use futures_macro::test_internal as test;
<commit_msg>don't skip async-test macro doc tests<commit_after>//! Utilities to make testing [`Future`s](futures_core::future::Future) easier

#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
// It cannot be included in the published code because this lints have false positives in the minimum required version.
#![cfg_attr(test, warn(single_use_lifetimes))]
#![warn(clippy::all)]
#![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))]

#[cfg(not(feature = "std"))]
compile_error!(
    "`futures-test` must have the `std` feature activated, this is a default-active feature"
);

// Not public API.
#[doc(hidden)]
#[cfg(feature = "std")]
pub mod __private {
    pub use futures_core::{future, stream, task};
    pub use futures_executor::block_on;
    pub use std::{
        option::Option::{None, Some},
        pin::Pin,
        result::Result::{Err, Ok},
    };

    pub mod assert {
        pub use crate::assert::*;
    }
}

#[macro_use]
#[cfg(feature = "std")]
mod assert;

#[cfg(feature = "std")]
pub mod task;

#[cfg(feature = "std")]
pub mod future;

#[cfg(feature = "std")]
pub mod stream;

#[cfg(feature = "std")]
pub mod sink;

#[cfg(feature = "std")]
pub mod io;

mod assert_unmoved;
mod interleave_pending;
mod track_closed;

/// Enables an `async` test function. The generated future will be run to completion with
/// [`futures_executor::block_on`](futures_executor::block_on).
///
/// ```
/// #[futures_test::test]
/// async fn my_test() {
///     let fut = async { true };
///     assert!(fut.await);
/// }
/// ```
#[cfg(feature = "std")]
pub use futures_macro::test_internal as test;
<|endoftext|>


<commit_before>use std::mem;
use slsr_core::geom::{Geom, Move};
use slsr_core::puzzle::Puzzle;

use ::SolverResult;
use ::model::side_map::SideMap;
use ::model::theorem::{Pattern, Theorem, TheoremMatcher};

#[derive(Clone, Debug)]
pub struct TheoremPool {
    data: Vec<TheoremMatcher>
}

impl TheoremPool {
    pub fn new<'a, T>(theo_defs: T,
                      puzzle: &Puzzle,
                      sum_of_hint: u32,
                      side_map: &mut SideMap)
                      -> SolverResult<TheoremPool>
        where T: IntoIterator<Item=Theorem>
    {
        let it = theo_defs
            .into_iter()
            .flat_map(|theo| theo.all_rotations());

        let mut hint_theorem = [vec![], vec![], vec![], vec![], vec![]];
        let mut nonhint_theorem = vec![];

        for theo in it {
            match theo.head() {
                Pattern::Hint(h) => hint_theorem[h.hint() as usize].push(theo),
                _ => nonhint_theorem.push(theo)
            }
        }

        let mut data = vec![];

        for p in puzzle.points() {
            if let Some(x) = puzzle.hint(p) {
                for theo in &hint_theorem[x as usize] {
                    let o = match theo.head() {
                        Pattern::Hint(hint) => hint.point(),
                        _ => panic!()
                    };
                    let matcher = theo.clone().shift(p - o);
                    try!(matcher.matches(puzzle, sum_of_hint, side_map))
                        .update(side_map, &mut data);
                }
            }
        }

        for theo in nonhint_theorem {
            let sz = theo.size();
            for r in (1 - sz.0)..(puzzle.row() + sz.0 - 1) {
                for c in (1 - sz.1)..(puzzle.column() + sz.1 - 1) {
                    let matcher = theo.clone().shift(Move(r, c));
                    try!(matcher.matches(puzzle, sum_of_hint, side_map))
                        .update(side_map, &mut data);
                }
            }
        }

        let mut pool = TheoremPool { data: data };
        let mut rev = side_map.revision();
        loop {
            try!(pool.apply_all(side_map));
            if side_map.revision() == rev {
                break
            }
            rev = side_map.revision();
        }

        pool.merge_dup();

        Ok(pool)
    }

    pub fn apply_all(&mut self, side_map: &mut SideMap) -> SolverResult<()> {
        let cap = self.data.len();

        for matcher in mem::replace(&mut self.data, Vec::with_capacity(cap)) {
            try!(matcher.matches(side_map))
                .update(side_map, &mut self.data);
        }

        Ok(())
    }

    fn merge_dup(&mut self) {
        self.data.sort();
        // Merge elements that have same matchers.
        unsafe {
            let len = self.data.len();
            let p = self.data.as_mut_ptr();

            let mut w = 1;
            for r in 1..len {
                let read = p.offset(r as isize);
                let cmp = p.offset((w - 1) as isize);

                match (*cmp).merge(&*read) {
                    Ok(()) => {}
                    Err(()) => {
                        let write = cmp.offset(1);
                        mem::swap(&mut *write, &mut *read);
                        w += 1;
                    }
                }
            }

            self.data.truncate(w);
        }
    }
}
<commit_msg>solver: small refactoring<commit_after>use std::mem;
use slsr_core::geom::{Geom, Move};
use slsr_core::puzzle::Puzzle;

use ::SolverResult;
use ::model::side_map::SideMap;
use ::model::theorem::{Pattern, Theorem, TheoremMatcher};

#[derive(Clone, Debug)]
pub struct TheoremPool {
    matchers: Vec<TheoremMatcher>
}

impl TheoremPool {
    pub fn new<'a, T>(theo_defs: T,
                      puzzle: &Puzzle,
                      sum_of_hint: u32,
                      side_map: &mut SideMap)
                      -> SolverResult<TheoremPool>
        where T: IntoIterator<Item=Theorem>
    {
        let mut matchers = try!(create_matcher_list(theo_defs,
                                                    puzzle,
                                                    sum_of_hint,
                                                    side_map));

        loop {
            let rev = side_map.revision();

            try!(apply_all_theorem(&mut matchers, side_map));
            if side_map.revision() != rev {
                continue
            }

            break
        }

        merge_duplicate_matchers(&mut matchers);

        Ok(TheoremPool { matchers: matchers })
    }

    pub fn apply_all(&mut self, side_map: &mut SideMap) -> SolverResult<()> {
        apply_all_theorem(&mut self.matchers, side_map)
    }
}

fn create_matcher_list<'a, T>(theo_defs: T,
                              puzzle: &Puzzle,
                              sum_of_hint: u32,
                              side_map: &mut SideMap)
                              -> SolverResult<Vec<TheoremMatcher>>
    where T: IntoIterator<Item=Theorem>
{
    let it = theo_defs
        .into_iter()
        .flat_map(|theo| theo.all_rotations());

    let mut hint_theorem = [vec![], vec![], vec![], vec![], vec![]];
    let mut nonhint_theorem = vec![];

    for theo in it {
        match theo.head() {
            Pattern::Hint(h) => hint_theorem[h.hint() as usize].push(theo),
            _ => nonhint_theorem.push(theo)
        }
    }

    let mut data = vec![];

    for p in puzzle.points() {
        if let Some(x) = puzzle.hint(p) {
            for theo in &hint_theorem[x as usize] {
                let o = match theo.head() {
                    Pattern::Hint(hint) => hint.point(),
                    _ => panic!()
                };
                let matcher = theo.clone().shift(p - o);
                try!(matcher.matches(puzzle, sum_of_hint, side_map))
                    .update(side_map, &mut data);
            }
        }
    }

    for theo in nonhint_theorem {
        let sz = theo.size();
        for r in (1 - sz.0)..(puzzle.row() + sz.0 - 1) {
            for c in (1 - sz.1)..(puzzle.column() + sz.1 - 1) {
                let matcher = theo.clone().shift(Move(r, c));
                try!(matcher.matches(puzzle, sum_of_hint, side_map))
                    .update(side_map, &mut data);
            }
        }
    }

    Ok(data)
}

fn apply_all_theorem(matchers: &mut Vec<TheoremMatcher>,
                     side_map: &mut SideMap)
                     -> SolverResult<()>
{
    let cap = matchers.len();

    for m in mem::replace(matchers, Vec::with_capacity(cap)) {
        try!(m.matches(side_map)).update(side_map, matchers);
    }

    Ok(())
}

fn merge_duplicate_matchers(matchers: &mut Vec<TheoremMatcher>) {
    matchers.sort();

    // Merge elements that have same matchers.
    unsafe {
        let len = matchers.len();
        let p = matchers.as_mut_ptr();

        let mut w = 1;
        for r in 1..len {
            let read = p.offset(r as isize);
            let cmp = p.offset((w - 1) as isize);

            match (*cmp).merge(&*read) {
                Ok(()) => {}
                Err(()) => {
                    let write = cmp.offset(1);
                    mem::swap(&mut *write, &mut *read);
                    w += 1;
                }
            }
        }

        matchers.truncate(w);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

#[allow(non_snake_case)]
#[derive(RustcDecodable, RustcEncodable)]
pub struct AccountSettingBody {
    pub country: Option<String>,
    pub firstName: Option<String>,
    pub language: Option<String>,
    pub ssoProvider: Option<String>,
    pub timezone: Option<String>,
    pub position: Option<String>,
    pub authenticationModes: Vec<String>,
    pub companyName: Option<String>,
    pub login: Option<String>,
    pub email: Option<String>,
    pub created: Option<String>,
    pub updated: Option<String>,
    pub lastName: Option<String>,
    pub phoneNumber: Option<String>,
    pub links: Option<HashMap<String, String>>,
}

#[allow(non_snake_case)]
#[derive(RustcDecodable, RustcEncodable)]
pub struct AccountSetting {
    pub accountSetting: AccountSettingBody,
}
<commit_msg>Optional authenticationModes<commit_after>use std::collections::HashMap;

#[allow(non_snake_case)]
#[derive(RustcDecodable, RustcEncodable)]
pub struct AccountSettingBody {
    pub country: Option<String>,
    pub firstName: Option<String>,
    pub language: Option<String>,
    pub ssoProvider: Option<String>,
    pub timezone: Option<String>,
    pub position: Option<String>,
    pub authenticationModes: Option<Vec<String>>,
    pub companyName: Option<String>,
    pub login: Option<String>,
    pub email: Option<String>,
    pub created: Option<String>,
    pub updated: Option<String>,
    pub lastName: Option<String>,
    pub phoneNumber: Option<String>,
    pub links: Option<HashMap<String, String>>,
}

#[allow(non_snake_case)]
#[derive(RustcDecodable, RustcEncodable)]
pub struct AccountSetting {
    pub accountSetting: AccountSettingBody,
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;

use runtime::{Class, Method, Object, Sel, self};
use {encode, Encode, EncodePtr};

/*
 The Sized bound on Message is unfortunate; ideally, objc objects would not be
 treated as Sized. However, rust won't allow casting a dynamically-sized type
 pointer to an Object pointer, because dynamically-sized types can have fat
 pointers (two words) instead of real pointers.
 */
/// Types that may be sent Objective-C messages.
/// For example: objects, classes, and blocks.
pub unsafe trait Message: Sized + EncodePtr { }

unsafe impl Message for Object { }

unsafe impl Message for Class { }

/// A trait for converting to a pointer to a type that may be sent Objective-C
/// messages.
pub trait ToMessage : Encode {
    type Target: Message;

    fn as_ptr(&self) -> *mut Self::Target;

    fn is_nil(&self) -> bool {
        self.as_ptr().is_null()
    }
}

impl<T> ToMessage for *const T where T: Message {
    type Target = T;

    fn as_ptr(&self) -> *mut T {
        *self as *mut T
    }
}

impl<T> ToMessage for *mut T where T: Message {
    type Target = T;

    fn as_ptr(&self) -> *mut T {
        *self
    }
}

impl<'a, T> ToMessage for &'a T where T: Message {
    type Target = T;

    fn as_ptr(&self) -> *mut T {
        *self as *const T as *mut T
    }
}

impl<'a, T> ToMessage for &'a mut T where T: Message {
    type Target = T;

    fn as_ptr(&self) -> *mut T {
        *self
    }
}

impl<'a, T> ToMessage for Option<&'a T> where T: Message {
    type Target = T;

    fn as_ptr(&self) -> *mut T {
        match *self {
            None => ptr::null_mut(),
            Some(ref obj) => obj.as_ptr(),
        }
    }
}

impl<'a, T> ToMessage for Option<&'a mut T> where T: Message {
    type Target = T;

    fn as_ptr(&self) -> *mut T {
        match *self {
            None => ptr::null_mut(),
            Some(ref obj) => obj.as_ptr(),
        }
    }
}

fn msg_send_fn<R>() -> unsafe extern fn(*mut Object, Sel, ...) -> R {
    unsafe {
        mem::transmute(runtime::objc_msgSend)
    }
}

pub trait MessageArguments {
    unsafe fn send<T, R>(self, obj: &T, sel: Sel) -> R where T: ToMessage;
}

macro_rules! message_args_impl {
    ($($a:ident : $t:ident),*) => (
        impl<$($t),*> MessageArguments for ($($t,)*) {
            unsafe fn send<T, R>(self, obj: &T, sel: Sel) -> R where T: ToMessage {
                let msg_send_fn = msg_send_fn::<R>();
                let msg_send_fn: unsafe extern fn(*mut Object, Sel $(, $t)*) -> R =
                    mem::transmute(msg_send_fn);
                let obj_ptr = obj.as_ptr() as *mut Object;
                let ($($a,)*) = self;
                msg_send_fn(obj_ptr, sel $(, $a)*)
            }
        }
    );
}

message_args_impl!();
message_args_impl!(a: A);
message_args_impl!(a: A, b: B);
message_args_impl!(a: A, b: B, c: C);
message_args_impl!(a: A, b: B, c: C, d: D);
message_args_impl!(a: A, b: B, c: C, d: D, e: E);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);

#[allow(dead_code)]
fn verify_message_arguments(types: &[&str], method: &Method) -> Result<(), String> {
    let count = 2 + types.len();
    let expected_count = method.arguments_count();
    if count != expected_count {
        return Err(format!("Method {:?} accepts {} arguments, but {} were given",
            method.name(), expected_count, count));
    }

    let expected_types = (2..expected_count).map(|i| method.argument_type(i));
    for (&arg, expected) in types.iter().zip(expected_types) {
        let expected = match expected {
            Some(s) => s,
            None => return Err(format!("Method {:?} doesn't expect argument with type code {}",
                method.name(), arg)),
        };
        if arg != &*expected {
            return Err(format!("Method {:?} expected argument with type code {} but was given {}",
                method.name(), &*expected, arg));
        }
    }

    Ok(())
}

fn verify_message_signature<T, A, R>(obj: Option<&T>, sel: Sel, _args: &A) ->
        Result<(), String> where T: Message, A: MessageArguments, R: Encode {
    let obj = match obj {
        Some(obj) => obj,
        None => return Err(format!("Messaging {:?} to nil", sel)),
    };
    let cls = unsafe {
        let obj = &*(obj as *const _ as *const Object);
        obj.class()
    };
    let method = match cls.instance_method(sel) {
        Some(method) => method,
        None => return Err(format!("Method {:?} not found on class {:?}",
            sel, cls)),
    };

    let ret = encode::<R>();
    let expected_ret = method.return_type();
    // Allow encoding "oneway void" (Vv) as "void" (v)
    if &*expected_ret != ret && !(&*expected_ret == "Vv" && ret == "v") {
        return Err(format!("Return type code {} does not match expected {} for method {:?} on class {:?}",
            ret, &*expected_ret, sel, cls));
    }

    // I don't think either of these can happen, but just to be safe...
    let accepts_self_arg = match method.argument_type(0) {
        Some(s) => &*s == "@",
        None => false,
    };
    if !accepts_self_arg {
        return Err(format!("Method {:?} of class {:?} doesn't accept an argument for self",
            sel, cls));
    }
    let accepts_cmd_arg = match method.argument_type(1) {
        Some(s) => &*s == ":",
        None => false,
    };
    if !accepts_cmd_arg {
        return Err(format!("Method {:?} of class {:?} doesn't accept an argument for the selector",
            sel, cls));
    }

    Ok(())
}

pub unsafe fn send_message<T, A, R>(obj: &T, sel: Sel, args: A) -> R
        where T: ToMessage, A: MessageArguments {
    args.send(obj, sel)
}

pub unsafe fn send_message_verified<T, A, R>(obj: &T, sel: Sel, args: A) ->
        Result<R, String> where T: ToMessage, A: MessageArguments, R: Encode {
    let obj_ref = obj.as_ptr().as_ref();
    verify_message_signature::<_, _, R>(obj_ref, sel, &args).and_then(
        move |()| Ok(args.send(obj, sel)))
}
<commit_msg>Removed ToMessage for Option.<commit_after>use std::mem;

use runtime::{Class, Method, Object, Sel, self};
use {encode, Encode, EncodePtr};

/*
 The Sized bound on Message is unfortunate; ideally, objc objects would not be
 treated as Sized. However, rust won't allow casting a dynamically-sized type
 pointer to an Object pointer, because dynamically-sized types can have fat
 pointers (two words) instead of real pointers.
 */
/// Types that may be sent Objective-C messages.
/// For example: objects, classes, and blocks.
pub unsafe trait Message: Sized + EncodePtr { }

unsafe impl Message for Object { }

unsafe impl Message for Class { }

/// A trait for converting to a pointer to a type that may be sent Objective-C
/// messages.
pub trait ToMessage : Encode {
    type Target: Message;

    fn as_ptr(&self) -> *mut Self::Target;

    fn is_nil(&self) -> bool {
        self.as_ptr().is_null()
    }
}

impl<T> ToMessage for *const T where T: Message {
    type Target = T;

    fn as_ptr(&self) -> *mut T {
        *self as *mut T
    }
}

impl<T> ToMessage for *mut T where T: Message {
    type Target = T;

    fn as_ptr(&self) -> *mut T {
        *self
    }
}

impl<'a, T> ToMessage for &'a T where T: Message {
    type Target = T;

    fn as_ptr(&self) -> *mut T {
        *self as *const T as *mut T
    }
}

impl<'a, T> ToMessage for &'a mut T where T: Message {
    type Target = T;

    fn as_ptr(&self) -> *mut T {
        *self
    }
}

fn msg_send_fn<R>() -> unsafe extern fn(*mut Object, Sel, ...) -> R {
    unsafe {
        mem::transmute(runtime::objc_msgSend)
    }
}

pub trait MessageArguments {
    unsafe fn send<T, R>(self, obj: &T, sel: Sel) -> R where T: ToMessage;
}

macro_rules! message_args_impl {
    ($($a:ident : $t:ident),*) => (
        impl<$($t),*> MessageArguments for ($($t,)*) {
            unsafe fn send<T, R>(self, obj: &T, sel: Sel) -> R where T: ToMessage {
                let msg_send_fn = msg_send_fn::<R>();
                let msg_send_fn: unsafe extern fn(*mut Object, Sel $(, $t)*) -> R =
                    mem::transmute(msg_send_fn);
                let obj_ptr = obj.as_ptr() as *mut Object;
                let ($($a,)*) = self;
                msg_send_fn(obj_ptr, sel $(, $a)*)
            }
        }
    );
}

message_args_impl!();
message_args_impl!(a: A);
message_args_impl!(a: A, b: B);
message_args_impl!(a: A, b: B, c: C);
message_args_impl!(a: A, b: B, c: C, d: D);
message_args_impl!(a: A, b: B, c: C, d: D, e: E);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
message_args_impl!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);

#[allow(dead_code)]
fn verify_message_arguments(types: &[&str], method: &Method) -> Result<(), String> {
    let count = 2 + types.len();
    let expected_count = method.arguments_count();
    if count != expected_count {
        return Err(format!("Method {:?} accepts {} arguments, but {} were given",
            method.name(), expected_count, count));
    }

    let expected_types = (2..expected_count).map(|i| method.argument_type(i));
    for (&arg, expected) in types.iter().zip(expected_types) {
        let expected = match expected {
            Some(s) => s,
            None => return Err(format!("Method {:?} doesn't expect argument with type code {}",
                method.name(), arg)),
        };
        if arg != &*expected {
            return Err(format!("Method {:?} expected argument with type code {} but was given {}",
                method.name(), &*expected, arg));
        }
    }

    Ok(())
}

fn verify_message_signature<T, A, R>(obj: Option<&T>, sel: Sel, _args: &A) ->
        Result<(), String> where T: Message, A: MessageArguments, R: Encode {
    let obj = match obj {
        Some(obj) => obj,
        None => return Err(format!("Messaging {:?} to nil", sel)),
    };
    let cls = unsafe {
        let obj = &*(obj as *const _ as *const Object);
        obj.class()
    };
    let method = match cls.instance_method(sel) {
        Some(method) => method,
        None => return Err(format!("Method {:?} not found on class {:?}",
            sel, cls)),
    };

    let ret = encode::<R>();
    let expected_ret = method.return_type();
    // Allow encoding "oneway void" (Vv) as "void" (v)
    if &*expected_ret != ret && !(&*expected_ret == "Vv" && ret == "v") {
        return Err(format!("Return type code {} does not match expected {} for method {:?} on class {:?}",
            ret, &*expected_ret, sel, cls));
    }

    // I don't think either of these can happen, but just to be safe...
    let accepts_self_arg = match method.argument_type(0) {
        Some(s) => &*s == "@",
        None => false,
    };
    if !accepts_self_arg {
        return Err(format!("Method {:?} of class {:?} doesn't accept an argument for self",
            sel, cls));
    }
    let accepts_cmd_arg = match method.argument_type(1) {
        Some(s) => &*s == ":",
        None => false,
    };
    if !accepts_cmd_arg {
        return Err(format!("Method {:?} of class {:?} doesn't accept an argument for the selector",
            sel, cls));
    }

    Ok(())
}

pub unsafe fn send_message<T, A, R>(obj: &T, sel: Sel, args: A) -> R
        where T: ToMessage, A: MessageArguments {
    args.send(obj, sel)
}

pub unsafe fn send_message_verified<T, A, R>(obj: &T, sel: Sel, args: A) ->
        Result<R, String> where T: ToMessage, A: MessageArguments, R: Encode {
    let obj_ref = obj.as_ptr().as_ref();
    verify_message_signature::<_, _, R>(obj_ref, sel, &args).and_then(
        move |()| Ok(args.send(obj, sel)))
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use super::*;
use crate::{
    error::NetworkErrorKind,
    peer_manager::{
        self, conn_notifs_channel, ConnectionRequestSender, PeerManagerNotification,
        PeerManagerRequest,
    },
    protocols::direct_send::Message,
    ProtocolId,
};
use anyhow::anyhow;
use channel::{libra_channel, message_queues::QueueStyle};
use futures::channel::oneshot;
use libra_config::config::RoleType;
use libra_network_address::NetworkAddress;
use std::{num::NonZeroUsize, str::FromStr};
use tokio::runtime::Runtime;

fn gen_peer_info() -> PeerInfo {
    PeerInfo {
        addrs: vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9090").unwrap()],
        epoch: 1,
    }
}

fn get_raw_message(msg: DiscoveryMsg) -> Message {
    Message {
        protocol: ProtocolId::DiscoveryDirectSend,
        mdata: lcs::to_bytes(&msg).unwrap().into(),
    }
}

fn parse_raw_message(msg: Message) -> Result<DiscoveryMsg, NetworkError> {
    assert_eq!(msg.protocol, ProtocolId::DiscoveryDirectSend);
    let msg: DiscoveryMsg = lcs::from_bytes(&msg.mdata)
        .map_err(|err| anyhow!(err).context(NetworkErrorKind::ParsingError))?;
    Ok(msg)
}

fn setup_discovery(
    rt: &mut Runtime,
    peer_id: PeerId,
    addrs: Vec<NetworkAddress>,
) -> (
    libra_channel::Receiver<(PeerId, ProtocolId), PeerManagerRequest>,
    channel::Receiver<ConnectivityRequest>,
    libra_channel::Sender<(PeerId, ProtocolId), PeerManagerNotification>,
    conn_notifs_channel::Sender,
    channel::Sender<()>,
) {
    let (peer_mgr_reqs_tx, peer_mgr_reqs_rx) =
        libra_channel::new(QueueStyle::FIFO, NonZeroUsize::new(1).unwrap(), None);
    let (connection_reqs_tx, _) =
        libra_channel::new(QueueStyle::FIFO, NonZeroUsize::new(1).unwrap(), None);
    let (conn_mgr_reqs_tx, conn_mgr_reqs_rx) = channel::new_test(1);
    let (network_notifs_tx, network_notifs_rx) =
        libra_channel::new(QueueStyle::FIFO, NonZeroUsize::new(1).unwrap(), None);
    let (connection_notifs_tx, connection_notifs_rx) = conn_notifs_channel::new();
    let (ticker_tx, ticker_rx) = channel::new_test(0);
    let role = RoleType::Validator;
    let discovery = {
        Discovery::new(
            peer_id,
            role,
            addrs,
            ticker_rx,
            DiscoveryNetworkSender::new(
                PeerManagerRequestSender::new(peer_mgr_reqs_tx),
                ConnectionRequestSender::new(connection_reqs_tx),
            ),
            DiscoveryNetworkEvents::new(network_notifs_rx, connection_notifs_rx),
            conn_mgr_reqs_tx,
        )
    };
    rt.spawn(discovery.start());
    (
        peer_mgr_reqs_rx,
        conn_mgr_reqs_rx,
        network_notifs_tx,
        connection_notifs_tx,
        ticker_tx,
    )
}

async fn expect_address_update(
    conn_mgr_reqs_rx: &mut channel::Receiver<ConnectivityRequest>,
    expected_address_map: HashMap<PeerId, Vec<NetworkAddress>>,
) {
    match conn_mgr_reqs_rx.next().await.unwrap() {
        ConnectivityRequest::UpdateAddresses(src, address_map) => {
            assert_eq!(DiscoverySource::Gossip, src);
            assert_eq!(expected_address_map, address_map);
        }
        req => {
            panic!("Unexpected request to connectivity manager: {:?}", req);
        }
    }
}

#[test]
// Test behavior on receipt of an inbound DiscoveryMsg.
fn inbound() {
    ::libra_logger::Logger::new().environment_only(true).init();
    let mut rt = Runtime::new().unwrap();

    // Setup self.
    let self_peer_id = PeerId::random();
    let self_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9090").unwrap()];

    // Setup other peer.
    let other_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/8080").unwrap()];
    let other_peer_id = PeerId::random();

    // Setup new peer to be added later.
    let new_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/7070").unwrap()];
    let new_peer_id = PeerId::random();

    // Setup discovery.
    let (_, mut conn_mgr_reqs_rx, mut network_notifs_tx, _, _) =
        setup_discovery(&mut rt, self_peer_id, self_addrs.clone());

    // Fake connectivity manager and dialer.
    let f_network = async move {
        // Send a message from other peer containing their discovery note.
        let other_note = Note::new(
            other_peer_id,
            other_addrs.clone(),
            b"example.com",
            get_unix_epoch(),
        );
        let msg = DiscoveryMsg {
            notes: vec![other_note],
        };
        let msg_key = (other_peer_id, ProtocolId::DiscoveryDirectSend);
        let (delivered_tx, delivered_rx) = oneshot::channel();
        network_notifs_tx
            .push_with_feedback(
                msg_key.clone(),
                PeerManagerNotification::RecvMessage(other_peer_id, get_raw_message(msg)),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Connectivity manager receives address of other peer.
        expect_address_update(
            &mut conn_mgr_reqs_rx,
            [
                (other_peer_id, other_addrs),
                (self_peer_id, self_addrs.clone()),
            ]
            .iter()
            .cloned()
            .collect(),
        )
        .await;

        // Send a message from other peer containing their updated discovery note
        // and another peer's new note.
        let new_note = Note::new(
            new_peer_id,
            new_addrs.clone(),
            b"example.com",
            get_unix_epoch(),
        );

        // Update other peer's note.
        let other_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/1234").unwrap()];
        let other_note = Note::new(
            other_peer_id,
            other_addrs.clone(),
            b"example.com",
            get_unix_epoch(),
        );

        let msg = DiscoveryMsg {
            notes: vec![new_note, other_note],
        };
        let (delivered_tx, delivered_rx) = oneshot::channel();
        network_notifs_tx
            .push_with_feedback(
                msg_key,
                PeerManagerNotification::RecvMessage(other_peer_id, get_raw_message(msg)),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Connectivity manager receives new addresses.
        expect_address_update(
            &mut conn_mgr_reqs_rx,
            [
                (new_peer_id, new_addrs),
                (other_peer_id, other_addrs),
                (self_peer_id, self_addrs),
            ]
            .iter()
            .cloned()
            .collect(),
        )
        .await;
    };
    rt.block_on(f_network);
}

#[test]
// Test that discovery actor sends a DiscoveryMsg to a neighbor on receiving a clock tick.
fn outbound() {
    ::libra_logger::Logger::new().environment_only(true).init();
    let mut rt = Runtime::new().unwrap();

    // Setup self peer.
    let peer_id = PeerId::random();
    let addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9090").unwrap()];

    // Setup other peer.
    let other_peer_id = PeerId::random();
    let other_peer_info = gen_peer_info();

    // Setup discovery.
    let (
        mut network_reqs_rx,
        _conn_mgr_req_rx,
        _network_notifs_tx,
        mut connection_notifs_tx,
        mut ticker_tx,
    ) = setup_discovery(&mut rt, peer_id, addrs.clone());

    // Fake connectivity manager and dialer.
    let f_network = async move {
        let (delivered_tx, delivered_rx) = oneshot::channel();
        // Notify discovery actor of connection to other peer.
        connection_notifs_tx
            .push_with_feedback(
                other_peer_id,
                peer_manager::ConnectionNotification::NewPeer(
                    other_peer_id,
                    other_peer_info.addrs[0].clone(),
                ),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Trigger outbound msg.
        ticker_tx.send(()).await.unwrap();

        // Check request sent as message over network.
        match network_reqs_rx.select_next_some().await {
            PeerManagerRequest::SendMessage(peer, raw_msg) => {
                assert_eq!(peer, other_peer_id);
                let msg = parse_raw_message(raw_msg).unwrap();
                // Receive DiscoveryMsg from actor. The message should contain only a note for the
                // sending peer since it doesn't yet have the note for the other peer.
                assert_eq!(1, msg.notes.len());
                assert_eq!(peer_id, msg.notes[0].peer_id);
                assert_eq!(&addrs, msg.notes[0].addrs());
            }
            req => {
                panic!("Unexpected request to peer manager: {:?}", req);
            }
        }
    };

    rt.block_on(f_network);
}

#[test]
fn old_note_higher_epoch() {
    ::libra_logger::Logger::new().environment_only(true).init();
    let mut rt = Runtime::new().unwrap();

    // Setup self peer.
    let peer_id = PeerId::random();
    let addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9090").unwrap()];

    // Setup other peer.
    let other_peer_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/8080").unwrap()];
    let other_peer_id = PeerId::random();

    // Setup discovery.
    let (mut network_reqs_rx, _, mut network_notifs_tx, mut connection_notifs_tx, mut ticker_tx) =
        setup_discovery(&mut rt, peer_id, addrs);

    // Fake connectivity manager and dialer.
    let f_network = async move {
        // Notify discovery actor of connection to other peer.
        let (delivered_tx, delivered_rx) = oneshot::channel();
        connection_notifs_tx
            .push_with_feedback(
                other_peer_id,
                peer_manager::ConnectionNotification::NewPeer(
                    other_peer_id,
                    other_peer_addrs[0].clone(),
                ),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Send DiscoveryMsg consisting of the this node's older note which has higher epoch than
        // current note.
        let old_self_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9091").unwrap()];
        let old_epoch = get_unix_epoch() + 100;
        let old_note = Note::new(peer_id, old_self_addrs.clone(), b"example.com", old_epoch);
        let msg = DiscoveryMsg {
            notes: vec![old_note],
        };
        let msg_key = (other_peer_id, ProtocolId::DiscoveryDirectSend);
        let (delivered_tx, delivered_rx) = oneshot::channel();
        network_notifs_tx
            .push_with_feedback(
                msg_key,
                PeerManagerNotification::RecvMessage(other_peer_id, get_raw_message(msg)),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Trigger outbound msg.
        ticker_tx.send(()).await.unwrap();

        // Check request sent as message over network.
        match network_reqs_rx.select_next_some().await {
            PeerManagerRequest::SendMessage(peer, raw_msg) => {
                assert_eq!(peer, other_peer_id);
                let msg = parse_raw_message(raw_msg).unwrap();
                // Receive DiscoveryMsg from actor. The message should contain only a note for the
                // sending peer since it doesn't yet have the note for the other peer.
                assert_eq!(1, msg.notes.len());
                assert_eq!(peer_id, msg.notes[0].peer_id);
                assert!(msg.notes[0].epoch() > old_epoch);
            }
            req => {
                panic!("Unexpected request to peer manager: {:?}", req);
            }
        }
    };
    rt.block_on(f_network);
}

#[test]
fn old_note_max_epoch() {
    ::libra_logger::Logger::new().environment_only(true).init();
    let mut rt = Runtime::new().unwrap();

    // Setup self.
    let peer_id = PeerId::random();
    let addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9090").unwrap()];

    // Setup other.
    let other_peer_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/8080").unwrap()];
    let other_peer_id = PeerId::random();

    // Setup discovery.
    let (mut network_reqs_rx, _, mut network_notifs_tx, mut connection_notifs_tx, mut ticker_tx) =
        setup_discovery(&mut rt, peer_id, addrs);

    // Fake connectivity manager and dialer.
    let f_network = async move {
        // Notify discovery actor of connection to other peer.
        let (delivered_tx, delivered_rx) = oneshot::channel();
        connection_notifs_tx
            .push_with_feedback(
                other_peer_id,
                peer_manager::ConnectionNotification::NewPeer(
                    other_peer_id,
                    other_peer_addrs[0].clone(),
                ),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Send DiscoveryMsg consisting of the this node's older note which has u64::MAX epoch.
        let old_self_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9091").unwrap()];
        let old_epoch = std::u64::MAX;
        let old_note = Note::new(peer_id, old_self_addrs.clone(), b"example.com", old_epoch);
        let msg = DiscoveryMsg {
            notes: vec![old_note],
        };
        let msg_key = (other_peer_id, ProtocolId::DiscoveryDirectSend);
        let (delivered_tx, delivered_rx) = oneshot::channel();
        network_notifs_tx
            .push_with_feedback(
                msg_key,
                PeerManagerNotification::RecvMessage(other_peer_id, get_raw_message(msg)),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Trigger outbound msg.
        ticker_tx.send(()).await.unwrap();

        // Check request sent as message over network.
        match network_reqs_rx.select_next_some().await {
            PeerManagerRequest::SendMessage(peer, raw_msg) => {
                assert_eq!(peer, other_peer_id);
                let msg = parse_raw_message(raw_msg).unwrap();
                // Receive DiscoveryMsg from actor. The message should contain only a note for the
                // sending peer since it doesn't yet have the note for the other peer.
                assert_eq!(1, msg.notes.len());
                assert_eq!(peer_id, msg.notes[0].peer_id);
                assert!(msg.notes[0].epoch() < old_epoch);
            }
            req => {
                panic!("Unexpected request to peer manager: {:?}", req);
            }
        }
    };
    rt.block_on(f_network);
}
<commit_msg>[network] fix flaky gossip discovery test<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use super::*;
use crate::{
    error::NetworkErrorKind,
    peer_manager::{
        self, conn_notifs_channel, ConnectionRequestSender, PeerManagerNotification,
        PeerManagerRequest,
    },
    protocols::direct_send::Message,
    ProtocolId,
};
use anyhow::anyhow;
use channel::{libra_channel, message_queues::QueueStyle};
use futures::channel::oneshot;
use libra_config::config::RoleType;
use libra_network_address::NetworkAddress;
use std::{num::NonZeroUsize, str::FromStr};
use tokio::runtime::Runtime;

fn get_raw_message(msg: DiscoveryMsg) -> Message {
    Message {
        protocol: ProtocolId::DiscoveryDirectSend,
        mdata: lcs::to_bytes(&msg).unwrap().into(),
    }
}

fn parse_raw_message(msg: Message) -> Result<DiscoveryMsg, NetworkError> {
    assert_eq!(msg.protocol, ProtocolId::DiscoveryDirectSend);
    let msg: DiscoveryMsg = lcs::from_bytes(&msg.mdata)
        .map_err(|err| anyhow!(err).context(NetworkErrorKind::ParsingError))?;
    Ok(msg)
}

fn setup_discovery(
    rt: &mut Runtime,
    peer_id: PeerId,
    addrs: Vec<NetworkAddress>,
) -> (
    libra_channel::Receiver<(PeerId, ProtocolId), PeerManagerRequest>,
    channel::Receiver<ConnectivityRequest>,
    libra_channel::Sender<(PeerId, ProtocolId), PeerManagerNotification>,
    conn_notifs_channel::Sender,
    channel::Sender<()>,
) {
    let (peer_mgr_reqs_tx, peer_mgr_reqs_rx) =
        libra_channel::new(QueueStyle::FIFO, NonZeroUsize::new(1).unwrap(), None);
    let (connection_reqs_tx, _) =
        libra_channel::new(QueueStyle::FIFO, NonZeroUsize::new(1).unwrap(), None);
    let (conn_mgr_reqs_tx, conn_mgr_reqs_rx) = channel::new_test(1);
    let (network_notifs_tx, network_notifs_rx) =
        libra_channel::new(QueueStyle::FIFO, NonZeroUsize::new(1).unwrap(), None);
    let (connection_notifs_tx, connection_notifs_rx) = conn_notifs_channel::new();
    let (ticker_tx, ticker_rx) = channel::new_test(0);
    let role = RoleType::Validator;
    let discovery = {
        Discovery::new(
            peer_id,
            role,
            addrs,
            ticker_rx,
            DiscoveryNetworkSender::new(
                PeerManagerRequestSender::new(peer_mgr_reqs_tx),
                ConnectionRequestSender::new(connection_reqs_tx),
            ),
            DiscoveryNetworkEvents::new(network_notifs_rx, connection_notifs_rx),
            conn_mgr_reqs_tx,
        )
    };
    rt.spawn(discovery.start());
    (
        peer_mgr_reqs_rx,
        conn_mgr_reqs_rx,
        network_notifs_tx,
        connection_notifs_tx,
        ticker_tx,
    )
}

async fn expect_address_update(
    conn_mgr_reqs_rx: &mut channel::Receiver<ConnectivityRequest>,
    expected_address_map: HashMap<PeerId, Vec<NetworkAddress>>,
) {
    match conn_mgr_reqs_rx.next().await.unwrap() {
        ConnectivityRequest::UpdateAddresses(src, address_map) => {
            assert_eq!(DiscoverySource::Gossip, src);
            assert_eq!(expected_address_map, address_map);
        }
        req => {
            panic!("Unexpected request to connectivity manager: {:?}", req);
        }
    }
}

#[test]
// Test behavior on receipt of an inbound DiscoveryMsg.
fn inbound() {
    ::libra_logger::Logger::new().environment_only(true).init();
    let mut rt = Runtime::new().unwrap();

    // Setup self.
    let self_peer_id = PeerId::random();
    let self_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9090").unwrap()];

    // Setup other peer.
    let other_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/8080").unwrap()];
    let other_peer_id = PeerId::random();

    // Setup new peer to be added later.
    let new_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/7070").unwrap()];
    let new_peer_id = PeerId::random();

    // Setup discovery.
    let (_, mut conn_mgr_reqs_rx, mut network_notifs_tx, _, _) =
        setup_discovery(&mut rt, self_peer_id, self_addrs.clone());

    // Fake connectivity manager and dialer.
    let f_network = async move {
        // Send a message from other peer containing their discovery note.
        let other_note = Note::new(
            other_peer_id,
            other_addrs.clone(),
            b"example.com",
            100, /* epoch */
        );
        let msg = DiscoveryMsg {
            notes: vec![other_note],
        };
        let msg_key = (other_peer_id, ProtocolId::DiscoveryDirectSend);
        let (delivered_tx, delivered_rx) = oneshot::channel();
        network_notifs_tx
            .push_with_feedback(
                msg_key.clone(),
                PeerManagerNotification::RecvMessage(other_peer_id, get_raw_message(msg)),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Connectivity manager receives address of other peer.
        expect_address_update(
            &mut conn_mgr_reqs_rx,
            [
                (other_peer_id, other_addrs),
                (self_peer_id, self_addrs.clone()),
            ]
            .iter()
            .cloned()
            .collect(),
        )
        .await;

        // Send a message from other peer containing their updated discovery note
        // and another peer's new note.
        let new_note = Note::new(
            new_peer_id,
            new_addrs.clone(),
            b"example.com",
            200, /* epoch */
        );

        // Update other peer's note.
        let other_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/1234").unwrap()];
        let other_note = Note::new(
            other_peer_id,
            other_addrs.clone(),
            b"example.com",
            300, /* epoch */
        );

        let msg = DiscoveryMsg {
            notes: vec![new_note, other_note],
        };
        let (delivered_tx, delivered_rx) = oneshot::channel();
        network_notifs_tx
            .push_with_feedback(
                msg_key,
                PeerManagerNotification::RecvMessage(other_peer_id, get_raw_message(msg)),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Connectivity manager receives new addresses.
        expect_address_update(
            &mut conn_mgr_reqs_rx,
            [
                (new_peer_id, new_addrs),
                (other_peer_id, other_addrs),
                (self_peer_id, self_addrs),
            ]
            .iter()
            .cloned()
            .collect(),
        )
        .await;
    };
    rt.block_on(f_network);
}

#[test]
// Test that discovery actor sends a DiscoveryMsg to a neighbor on receiving a clock tick.
fn outbound() {
    ::libra_logger::Logger::new().environment_only(true).init();
    let mut rt = Runtime::new().unwrap();

    // Setup self peer.
    let peer_id = PeerId::random();
    let addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9090").unwrap()];

    // Setup other peer.
    let other_peer_id = PeerId::random();
    let other_peer_addr = NetworkAddress::from_str("/ip4/127.0.0.1/tcp/8080").unwrap();

    // Setup discovery.
    let (
        mut network_reqs_rx,
        _conn_mgr_req_rx,
        _network_notifs_tx,
        mut connection_notifs_tx,
        mut ticker_tx,
    ) = setup_discovery(&mut rt, peer_id, addrs.clone());

    // Fake connectivity manager and dialer.
    let f_network = async move {
        let (delivered_tx, delivered_rx) = oneshot::channel();
        // Notify discovery actor of connection to other peer.
        connection_notifs_tx
            .push_with_feedback(
                other_peer_id,
                peer_manager::ConnectionNotification::NewPeer(other_peer_id, other_peer_addr),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Trigger outbound msg.
        ticker_tx.send(()).await.unwrap();

        // Check request sent as message over network.
        match network_reqs_rx.select_next_some().await {
            PeerManagerRequest::SendMessage(peer, raw_msg) => {
                assert_eq!(peer, other_peer_id);
                let msg = parse_raw_message(raw_msg).unwrap();
                // Receive DiscoveryMsg from actor. The message should contain only a note for the
                // sending peer since it doesn't yet have the note for the other peer.
                assert_eq!(1, msg.notes.len());
                assert_eq!(peer_id, msg.notes[0].peer_id);
                assert_eq!(&addrs, msg.notes[0].addrs());
            }
            req => {
                panic!("Unexpected request to peer manager: {:?}", req);
            }
        }
    };

    rt.block_on(f_network);
}

#[test]
fn old_note_higher_epoch() {
    ::libra_logger::Logger::new().environment_only(true).init();
    let mut rt = Runtime::new().unwrap();

    // Setup self peer.
    let peer_id = PeerId::random();
    let addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9090").unwrap()];

    // Setup other peer.
    let other_peer_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/8080").unwrap()];
    let other_peer_id = PeerId::random();

    // Setup discovery.
    let (mut network_reqs_rx, _, mut network_notifs_tx, mut connection_notifs_tx, mut ticker_tx) =
        setup_discovery(&mut rt, peer_id, addrs);

    // Fake connectivity manager and dialer.
    let f_network = async move {
        // Notify discovery actor of connection to other peer.
        let (delivered_tx, delivered_rx) = oneshot::channel();
        connection_notifs_tx
            .push_with_feedback(
                other_peer_id,
                peer_manager::ConnectionNotification::NewPeer(
                    other_peer_id,
                    other_peer_addrs[0].clone(),
                ),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Send DiscoveryMsg consisting of the this node's older note which has higher epoch than
        // current note.
        let old_self_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9091").unwrap()];
        let old_epoch = get_unix_epoch() + 1_000_000;
        let old_note = Note::new(peer_id, old_self_addrs.clone(), b"example.com", old_epoch);
        let msg = DiscoveryMsg {
            notes: vec![old_note],
        };
        let msg_key = (other_peer_id, ProtocolId::DiscoveryDirectSend);
        let (delivered_tx, delivered_rx) = oneshot::channel();
        network_notifs_tx
            .push_with_feedback(
                msg_key,
                PeerManagerNotification::RecvMessage(other_peer_id, get_raw_message(msg)),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Trigger outbound msg.
        ticker_tx.send(()).await.unwrap();

        // Check request sent as message over network.
        match network_reqs_rx.select_next_some().await {
            PeerManagerRequest::SendMessage(peer, raw_msg) => {
                assert_eq!(peer, other_peer_id);
                let msg = parse_raw_message(raw_msg).unwrap();
                // Receive DiscoveryMsg from actor. The message should contain only a note for the
                // sending peer since it doesn't yet have the note for the other peer.
                assert_eq!(1, msg.notes.len());
                assert_eq!(peer_id, msg.notes[0].peer_id);
                assert!(msg.notes[0].epoch() > old_epoch);
            }
            req => {
                panic!("Unexpected request to peer manager: {:?}", req);
            }
        }
    };
    rt.block_on(f_network);
}

#[test]
fn old_note_max_epoch() {
    ::libra_logger::Logger::new().environment_only(true).init();
    let mut rt = Runtime::new().unwrap();

    // Setup self.
    let peer_id = PeerId::random();
    let addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9090").unwrap()];

    // Setup other.
    let other_peer_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/8080").unwrap()];
    let other_peer_id = PeerId::random();

    // Setup discovery.
    let (mut network_reqs_rx, _, mut network_notifs_tx, mut connection_notifs_tx, mut ticker_tx) =
        setup_discovery(&mut rt, peer_id, addrs);

    // Fake connectivity manager and dialer.
    let f_network = async move {
        // Notify discovery actor of connection to other peer.
        let (delivered_tx, delivered_rx) = oneshot::channel();
        connection_notifs_tx
            .push_with_feedback(
                other_peer_id,
                peer_manager::ConnectionNotification::NewPeer(
                    other_peer_id,
                    other_peer_addrs[0].clone(),
                ),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Send DiscoveryMsg consisting of the this node's older note which has u64::MAX epoch.
        let old_self_addrs = vec![NetworkAddress::from_str("/ip4/127.0.0.1/tcp/9091").unwrap()];
        let old_epoch = std::u64::MAX;
        let old_note = Note::new(peer_id, old_self_addrs.clone(), b"example.com", old_epoch);
        let msg = DiscoveryMsg {
            notes: vec![old_note],
        };
        let msg_key = (other_peer_id, ProtocolId::DiscoveryDirectSend);
        let (delivered_tx, delivered_rx) = oneshot::channel();
        network_notifs_tx
            .push_with_feedback(
                msg_key,
                PeerManagerNotification::RecvMessage(other_peer_id, get_raw_message(msg)),
                Some(delivered_tx),
            )
            .unwrap();
        delivered_rx.await.unwrap();

        // Trigger outbound msg.
        ticker_tx.send(()).await.unwrap();

        // Check request sent as message over network.
        match network_reqs_rx.select_next_some().await {
            PeerManagerRequest::SendMessage(peer, raw_msg) => {
                assert_eq!(peer, other_peer_id);
                let msg = parse_raw_message(raw_msg).unwrap();
                // Receive DiscoveryMsg from actor. The message should contain only a note for the
                // sending peer since it doesn't yet have the note for the other peer.
                assert_eq!(1, msg.notes.len());
                assert_eq!(peer_id, msg.notes[0].peer_id);
                assert!(msg.notes[0].epoch() < old_epoch);
            }
            req => {
                panic!("Unexpected request to peer manager: {:?}", req);
            }
        }
    };
    rt.block_on(f_network);
}
<|endoftext|>


<commit_before>extern crate lancelot;
extern crate log;
extern crate chrono;
#[macro_use] extern crate clap;

use fern;
use log::{error, info, debug};
use failure::{Error};
use better_panic;

use lancelot::workspace::Workspace;

fn handle_functions(ws: &Workspace) -> Result<(), Error> {
    let mut functions = ws.get_functions().collect::<Vec<_>>();
    functions.sort();

    info!("found {} functions", functions.len());
    for rva in functions.iter() {
        if let Ok(basic_blocks) = ws.get_basic_blocks(**rva) {
            println!("{} with {} basic blocks", ws.va(**rva).unwrap(), basic_blocks.len());
        } else {
            println!("{}", rva);
        }
    }

    Ok(())
}

fn handle_layout(ws: &Workspace) -> Result<(), Error> {
    Ok(())
}

fn main() {
    better_panic::install();

    let matches = clap_app!(lancelot =>
        (author: "Willi Ballenthin <willi.ballenthin@gmail.com>")
        (about: "Binary analysis framework")
        (@arg verbose: -v --verbose +multiple "log verbose messages")
        (@subcommand functions =>
            (about: "find functions")
            (@arg input: +required "path to file to analyze"))
        (@subcommand layout =>
            (about: "show file sections")
            (@arg input: +required "path to file to analyze"))
        (@subcommand smoketest =>
            (about: "analyze file and exit on analysis failure")
            (@arg input: +required "path to file to analyze"))
    ).get_matches();

    let log_level = match matches.occurrences_of("verbose") {
        0 => log::LevelFilter::Info,
        1 => log::LevelFilter::Debug,
        2 => log::LevelFilter::Trace,
        _ => log::LevelFilter::Trace,
    };

    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{} [{:5}] {} {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                record.level(),
                if log_level == log::LevelFilter::Trace {record.target()} else {""},
                message
            ))
        })
        .level(log_level)
        .chain(std::io::stderr())
        .filter(|metadata| {
            !metadata.target().starts_with("goblin::pe")
        })
        .apply()
        .expect("failed to configure logging");

    if let Some(matches) = matches.subcommand_matches("functions") {
        debug!("mode: find functions");

        let filename = matches.value_of("input").unwrap();
        debug!("input: {}", filename);

        let ws = Workspace::from_file(filename)
            .unwrap_or_else(|e| panic!("failed to load workspace: {}", e));

        let ws = ws.load()
            .unwrap_or_else(|e| panic!("failed to load workspace: {}", e));

        if let Err(e) = handle_functions(&ws) {
            error!("error: {}", e)
        }
    } else if let Some(matches) = matches.subcommand_matches("layout") {
        debug!("mode: layout");

        let filename = matches.value_of("input").unwrap();
        debug!("input: {}", filename);

        let ws = Workspace::from_file(filename)
            .unwrap_or_else(|e| panic!("failed to load workspace: {}", e))
            .disable_analysis()
            .load()
            .unwrap_or_else(|e| panic!("failed to load workspace: {}", e));

        if let Err(e) = handle_functions(&ws) {
            error!("error: {}", e)
        }
    } else if let Some(matches) = matches.subcommand_matches("smoketest") {
        debug!("mode: smoketest");

        let filename = matches.value_of("input").unwrap();
        debug!("input: {}", filename);

        match Workspace::from_file(filename)
            .unwrap_or_else(|e| panic!("failed to load workspace: {}", e))
            .enable_strict_mode()
            .load() {
            Err(e) => {
                println!("error");
                eprintln!("{:?}", e);
            },
            Ok(_) => println!("ok"),
        }
    };

    return;
}
<commit_msg>bin: add --quiet flag<commit_after>extern crate lancelot;
extern crate log;
extern crate chrono;
#[macro_use] extern crate clap;

use fern;
use log::{error, info, debug};
use failure::{Error};
use better_panic;

use lancelot::workspace::Workspace;

fn handle_functions(ws: &Workspace) -> Result<(), Error> {
    let mut functions = ws.get_functions().collect::<Vec<_>>();
    functions.sort();

    info!("found {} functions", functions.len());
    for rva in functions.iter() {
        if let Ok(basic_blocks) = ws.get_basic_blocks(**rva) {
            println!("{} with {} basic blocks", ws.va(**rva).unwrap(), basic_blocks.len());
        } else {
            println!("{}", rva);
        }
    }

    Ok(())
}

fn handle_layout(ws: &Workspace) -> Result<(), Error> {
    Ok(())
}

fn main() {
    better_panic::install();

    let matches = clap_app!(lancelot =>
        (author: "Willi Ballenthin <willi.ballenthin@gmail.com>")
        (about: "Binary analysis framework")
        (@arg verbose: -v --verbose +multiple "log verbose messages")
        (@arg quiet: -q --quiet "disable informational messages")
        (@subcommand functions =>
            (about: "find functions")
            (@arg input: +required "path to file to analyze"))
        (@subcommand layout =>
            (about: "show file sections")
            (@arg input: +required "path to file to analyze"))
        (@subcommand smoketest =>
            (about: "analyze file and exit on analysis failure")
            (@arg input: +required "path to file to analyze"))
    ).get_matches();

    // --quiet overrides --verbose
    let log_level = if matches.is_present("quiet") {
        log::LevelFilter::Error
    } else {
        match matches.occurrences_of("verbose") {
            0 => log::LevelFilter::Info,
            1 => log::LevelFilter::Debug,
            2 => log::LevelFilter::Trace,
            _ => log::LevelFilter::Trace,
        }
    };

    fern::Dispatch::new()
        .format(move |out, message, record| {
            out.finish(format_args!(
                "{} [{:5}] {} {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
                record.level(),
                if log_level == log::LevelFilter::Trace {record.target()} else {""},
                message
            ))
        })
        .level(log_level)
        .chain(std::io::stderr())
        .filter(|metadata| {
            !metadata.target().starts_with("goblin::pe")
        })
        .apply()
        .expect("failed to configure logging");

    if let Some(matches) = matches.subcommand_matches("functions") {
        debug!("mode: find functions");

        let filename = matches.value_of("input").unwrap();
        debug!("input: {}", filename);

        let ws = Workspace::from_file(filename)
            .unwrap_or_else(|e| panic!("failed to load workspace: {}", e));

        let ws = ws.load()
            .unwrap_or_else(|e| panic!("failed to load workspace: {}", e));

        if let Err(e) = handle_functions(&ws) {
            error!("error: {}", e)
        }
    } else if let Some(matches) = matches.subcommand_matches("layout") {
        debug!("mode: layout");

        let filename = matches.value_of("input").unwrap();
        debug!("input: {}", filename);

        let ws = Workspace::from_file(filename)
            .unwrap_or_else(|e| panic!("failed to load workspace: {}", e))
            .disable_analysis()
            .load()
            .unwrap_or_else(|e| panic!("failed to load workspace: {}", e));

        if let Err(e) = handle_functions(&ws) {
            error!("error: {}", e)
        }
    } else if let Some(matches) = matches.subcommand_matches("smoketest") {
        debug!("mode: smoketest");

        let filename = matches.value_of("input").unwrap();
        debug!("input: {}", filename);

        match Workspace::from_file(filename)
            .unwrap_or_else(|e| panic!("failed to load workspace: {}", e))
            .enable_strict_mode()
            .load() {
            Err(e) => {
                println!("error");
                eprintln!("{:?}", e);
            },
            Ok(_) => println!("ok"),
        }
    };

    return;
}
<|endoftext|>


<commit_before>use std::{fmt, iter::FromIterator, sync::Arc};

use hir::{ExpandResult, MacroFile};
use ide_db::base_db::{
    salsa::debug::{DebugQueryTable, TableEntry},
    CrateId, FileId, FileTextQuery, SourceDatabase, SourceRootId,
};
use ide_db::{
    symbol_index::{LibrarySymbolsQuery, SymbolIndex},
    RootDatabase,
};
use itertools::Itertools;
use profile::{memory_usage, Bytes};
use rustc_hash::FxHashMap;
use stdx::format_to;
use syntax::{ast, Parse, SyntaxNode};

fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
    ide_db::base_db::ParseQuery.in_db(db).entries::<SyntaxTreeStats>()
}
fn macro_syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
    hir::db::ParseMacroExpansionQuery.in_db(db).entries::<SyntaxTreeStats>()
}

// Feature: Status
//
// Shows internal statistic about memory usage of rust-analyzer.
//
// |===
// | Editor  | Action Name
//
// | VS Code | **Rust Analyzer: Status**
// |===
// image::https://user-images.githubusercontent.com/48062697/113065584-05f34500-91b1-11eb-98cc-5c196f76be7f.gif[]
pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
    let mut buf = String::new();
    let count = profile::countme::get_all();
    format_to!(buf, "{}\n", FileTextQuery.in_db(db).entries::<FilesStats>());
    format_to!(buf, "{}\n", LibrarySymbolsQuery.in_db(db).entries::<LibrarySymbolsStats>());
    format_to!(buf, "{}\n", syntax_tree_stats(db));
    format_to!(buf, "{} (Macros)\n", macro_syntax_tree_stats(db));
    format_to!(buf, "{} in total\n", memory_usage());
    format_to!(
        buf,
        "\nCounts:\n{}",
        if count.to_string().contains("all counts are zero") {
            String::from("All counts are zero\n")
        } else {
            count.to_string()
        }
    );

    if let Some(file_id) = file_id {
        format_to!(buf, "\nFile info:\n");
        let krate = crate::parent_module::crate_for(db, file_id).pop();
        match krate {
            Some(krate) => {
                let crate_graph = db.crate_graph();
                let display_crate = |krate: CrateId| match &crate_graph[krate].display_name {
                    Some(it) => format!("{}({:?})", it, krate),
                    None => format!("{:?}", krate),
                };
                format_to!(buf, "Crate: {}\n", display_crate(krate));
                let deps = crate_graph[krate]
                    .dependencies
                    .iter()
                    .map(|dep| format!("{}={:?}", dep.name, dep.crate_id))
                    .format(", ");
                format_to!(buf, "Dependencies: {}\n", deps);
            }
            None => format_to!(buf, "Does not belong to any crate"),
        }
    }

    buf.trim().to_string()
}

#[derive(Default)]
struct FilesStats {
    total: usize,
    size: Bytes,
}

impl fmt::Display for FilesStats {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{} of files", self.size)
    }
}

impl FromIterator<TableEntry<FileId, Arc<String>>> for FilesStats {
    fn from_iter<T>(iter: T) -> FilesStats
    where
        T: IntoIterator<Item = TableEntry<FileId, Arc<String>>>,
    {
        let mut res = FilesStats::default();
        for entry in iter {
            res.total += 1;
            res.size += entry.value.unwrap().len();
        }
        res
    }
}

#[derive(Default)]
pub(crate) struct SyntaxTreeStats {
    total: usize,
    pub(crate) retained: usize,
}

impl fmt::Display for SyntaxTreeStats {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{} trees, {} preserved", self.total, self.retained)
    }
}

impl FromIterator<TableEntry<FileId, Parse<ast::SourceFile>>> for SyntaxTreeStats {
    fn from_iter<T>(iter: T) -> SyntaxTreeStats
    where
        T: IntoIterator<Item = TableEntry<FileId, Parse<ast::SourceFile>>>,
    {
        let mut res = SyntaxTreeStats::default();
        for entry in iter {
            res.total += 1;
            res.retained += entry.value.is_some() as usize;
        }
        res
    }
}

impl<M> FromIterator<TableEntry<MacroFile, ExpandResult<Option<(Parse<SyntaxNode>, M)>>>>
    for SyntaxTreeStats
{
    fn from_iter<T>(iter: T) -> SyntaxTreeStats
    where
        T: IntoIterator<Item = TableEntry<MacroFile, ExpandResult<Option<(Parse<SyntaxNode>, M)>>>>,
    {
        let mut res = SyntaxTreeStats::default();
        for entry in iter {
            res.total += 1;
            res.retained += entry.value.is_some() as usize;
        }
        res
    }
}

#[derive(Default)]
struct LibrarySymbolsStats {
    total: usize,
    size: Bytes,
}

impl fmt::Display for LibrarySymbolsStats {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{} of index symbols ({})", self.size, self.total)
    }
}

impl FromIterator<TableEntry<(), Arc<FxHashMap<SourceRootId, SymbolIndex>>>>
    for LibrarySymbolsStats
{
    fn from_iter<T>(iter: T) -> LibrarySymbolsStats
    where
        T: IntoIterator<Item = TableEntry<(), Arc<FxHashMap<SourceRootId, SymbolIndex>>>>,
    {
        let mut res = LibrarySymbolsStats::default();
        for entry in iter {
            let value = entry.value.unwrap();
            for symbols in value.values() {
                res.total += symbols.len();
                res.size += symbols.memory_size();
            }
        }
        res
    }
}
<commit_msg>check if counts should be a thing<commit_after>use std::{fmt, iter::FromIterator, sync::Arc};

use hir::{ExpandResult, MacroFile};
use ide_db::base_db::{
    salsa::debug::{DebugQueryTable, TableEntry},
    CrateId, FileId, FileTextQuery, SourceDatabase, SourceRootId,
};
use ide_db::{
    symbol_index::{LibrarySymbolsQuery, SymbolIndex},
    RootDatabase,
};
use itertools::Itertools;
use profile::{memory_usage, Bytes};
use rustc_hash::FxHashMap;
use std::env;
use stdx::format_to;
use syntax::{ast, Parse, SyntaxNode};

fn syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
    ide_db::base_db::ParseQuery.in_db(db).entries::<SyntaxTreeStats>()
}
fn macro_syntax_tree_stats(db: &RootDatabase) -> SyntaxTreeStats {
    hir::db::ParseMacroExpansionQuery.in_db(db).entries::<SyntaxTreeStats>()
}

// Feature: Status
//
// Shows internal statistic about memory usage of rust-analyzer.
//
// |===
// | Editor  | Action Name
//
// | VS Code | **Rust Analyzer: Status**
// |===
// image::https://user-images.githubusercontent.com/48062697/113065584-05f34500-91b1-11eb-98cc-5c196f76be7f.gif[]
pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
    let mut buf = String::new();
    let count = profile::countme::get_all();
    format_to!(buf, "{}\n", FileTextQuery.in_db(db).entries::<FilesStats>());
    format_to!(buf, "{}\n", LibrarySymbolsQuery.in_db(db).entries::<LibrarySymbolsStats>());
    format_to!(buf, "{}\n", syntax_tree_stats(db));
    format_to!(buf, "{} (Macros)\n", macro_syntax_tree_stats(db));
    format_to!(buf, "{} in total\n", memory_usage());
    if env::var("RA_COUNT").is_ok() {
        format_to!(
            buf,
            "\nCounts:\n{}",
            if count.to_string().contains("all counts are zero") {
                String::from("All counts are zero\n")
            } else {
                count.to_string()
            }
        );
    }

    if let Some(file_id) = file_id {
        format_to!(buf, "\nFile info:\n");
        let krate = crate::parent_module::crate_for(db, file_id).pop();
        match krate {
            Some(krate) => {
                let crate_graph = db.crate_graph();
                let display_crate = |krate: CrateId| match &crate_graph[krate].display_name {
                    Some(it) => format!("{}({:?})", it, krate),
                    None => format!("{:?}", krate),
                };
                format_to!(buf, "Crate: {}\n", display_crate(krate));
                let deps = crate_graph[krate]
                    .dependencies
                    .iter()
                    .map(|dep| format!("{}={:?}", dep.name, dep.crate_id))
                    .format(", ");
                format_to!(buf, "Dependencies: {}\n", deps);
            }
            None => format_to!(buf, "Does not belong to any crate"),
        }
    }

    buf.trim().to_string()
}

#[derive(Default)]
struct FilesStats {
    total: usize,
    size: Bytes,
}

impl fmt::Display for FilesStats {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{} of files", self.size)
    }
}

impl FromIterator<TableEntry<FileId, Arc<String>>> for FilesStats {
    fn from_iter<T>(iter: T) -> FilesStats
    where
        T: IntoIterator<Item = TableEntry<FileId, Arc<String>>>,
    {
        let mut res = FilesStats::default();
        for entry in iter {
            res.total += 1;
            res.size += entry.value.unwrap().len();
        }
        res
    }
}

#[derive(Default)]
pub(crate) struct SyntaxTreeStats {
    total: usize,
    pub(crate) retained: usize,
}

impl fmt::Display for SyntaxTreeStats {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{} trees, {} preserved", self.total, self.retained)
    }
}

impl FromIterator<TableEntry<FileId, Parse<ast::SourceFile>>> for SyntaxTreeStats {
    fn from_iter<T>(iter: T) -> SyntaxTreeStats
    where
        T: IntoIterator<Item = TableEntry<FileId, Parse<ast::SourceFile>>>,
    {
        let mut res = SyntaxTreeStats::default();
        for entry in iter {
            res.total += 1;
            res.retained += entry.value.is_some() as usize;
        }
        res
    }
}

impl<M> FromIterator<TableEntry<MacroFile, ExpandResult<Option<(Parse<SyntaxNode>, M)>>>>
    for SyntaxTreeStats
{
    fn from_iter<T>(iter: T) -> SyntaxTreeStats
    where
        T: IntoIterator<Item = TableEntry<MacroFile, ExpandResult<Option<(Parse<SyntaxNode>, M)>>>>,
    {
        let mut res = SyntaxTreeStats::default();
        for entry in iter {
            res.total += 1;
            res.retained += entry.value.is_some() as usize;
        }
        res
    }
}

#[derive(Default)]
struct LibrarySymbolsStats {
    total: usize,
    size: Bytes,
}

impl fmt::Display for LibrarySymbolsStats {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{} of index symbols ({})", self.size, self.total)
    }
}

impl FromIterator<TableEntry<(), Arc<FxHashMap<SourceRootId, SymbolIndex>>>>
    for LibrarySymbolsStats
{
    fn from_iter<T>(iter: T) -> LibrarySymbolsStats
    where
        T: IntoIterator<Item = TableEntry<(), Arc<FxHashMap<SourceRootId, SymbolIndex>>>>,
    {
        let mut res = LibrarySymbolsStats::default();
        for entry in iter {
            let value = entry.value.unwrap();
            for symbols in value.values() {
                res.total += symbols.len();
                res.size += symbols.memory_size();
            }
        }
        res
    }
}
<|endoftext|>