      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145

    //! Common types used by `libtest`.

    use std::fmt;
    use std::borrow::Cow;

    use super::options;
    use super::bench::Bencher;

    pub use NamePadding::*;
    pub use TestName::*;
    pub use TestFn::*;

    /// Type of the test according to the [rust book](https://doc.rust-lang.org/cargo/guide/tests.html)
    /// conventions.
    #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
    pub enum TestType {
        /// Unit-tests are expected to be in the `src` folder of the crate.
        UnitTest,
        /// Integration-style tests are expected to be in the `tests` folder of the crate.
        IntegrationTest,
        /// Doctests are created by the `librustdoc` manually, so it's a different type of test.
        DocTest,
        /// Tests for the sources that don't follow the project layout convention
        /// (e.g. tests in raw `main.rs` compiled by calling `rustc --test` directly).
        Unknown,
    }

    #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
    pub enum NamePadding {
        PadNone,
        PadOnRight,
    }

    // The name of a test. By convention this follows the rules for rust
    // paths; i.e., it should be a series of identifiers separated by double
    // colons. This way if some test runner wants to arrange the tests
    // hierarchically it may.
    #[derive(Clone, PartialEq, Eq, Hash, Debug)]
    pub enum TestName {
        StaticTestName(&'static str),
        DynTestName(String),
        AlignedTestName(Cow<'static, str>, NamePadding),
    }

    impl TestName {
        pub fn as_slice(&self) -> &str {
            match *self {
                StaticTestName(s) => s,
                DynTestName(ref s) => s,
                AlignedTestName(ref s, _) => &*s,
            }
        }

        pub fn padding(&self) -> NamePadding {
            match self {
                &AlignedTestName(_, p) => p,
                _ => PadNone,
            }
        }

        pub fn with_padding(&self, padding: NamePadding) -> TestName {
            let name = match self {
                &TestName::StaticTestName(name) => Cow::Borrowed(name),
                &TestName::DynTestName(ref name) => Cow::Owned(name.clone()),
                &TestName::AlignedTestName(ref name, _) => name.clone(),
            };

            TestName::AlignedTestName(name, padding)
        }
    }
    impl fmt::Display for TestName {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            fmt::Display::fmt(self.as_slice(), f)
        }
    }

    /// Represents a benchmark function.
    pub trait TDynBenchFn: Send {
        fn run(&self, harness: &mut Bencher);
    }

    // A function that runs a test. If the function returns successfully,
    // the test succeeds; if the function panics then the test fails. We
    // may need to come up with a more clever definition of test in order
    // to support isolation of tests into threads.
    pub enum TestFn {
        StaticTestFn(fn()),
        StaticBenchFn(fn(&mut Bencher)),
        DynTestFn(Box<dyn FnOnce() + Send>),
        DynBenchFn(Box<dyn TDynBenchFn + 'static>),
    }

    impl TestFn {
        pub fn padding(&self) -> NamePadding {
            match *self {
                StaticTestFn(..) => PadNone,
                StaticBenchFn(..) => PadOnRight,
                DynTestFn(..) => PadNone,
                DynBenchFn(..) => PadOnRight,
            }
        }
    }

    impl fmt::Debug for TestFn {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            f.write_str(match *self {
                StaticTestFn(..) => "StaticTestFn(..)",
                StaticBenchFn(..) => "StaticBenchFn(..)",
                DynTestFn(..) => "DynTestFn(..)",
                DynBenchFn(..) => "DynBenchFn(..)",
            })
        }
    }

    // The definition of a single test. A test runner will run a list of
    // these.
    #[derive(Clone, Debug, PartialEq, Eq, Hash)]
    pub struct TestDesc {
        pub name: TestName,
        pub ignore: bool,
        pub should_panic: options::ShouldPanic,
        pub allow_fail: bool,
        pub test_type: TestType,
    }

    impl TestDesc {
        pub fn padded_name(&self, column_count: usize, align: NamePadding) -> String {
            let mut name = String::from(self.name.as_slice());
            let fill = column_count.saturating_sub(name.len());
            let pad = " ".repeat(fill);
            match align {
                PadNone => name,
                PadOnRight => {
                    name.push_str(&pad);
                    name
                }
            }
        }
    }

    #[derive(Debug)]
    pub struct TestDescAndFn {
        pub desc: TestDesc,
        pub testfn: TestFn,
    }