• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lpenz / ogle / 15799464343

21 Jun 2025 08:41PM UTC coverage: 59.94% (-0.6%) from 60.538%
15799464343

push

github

lpenz
Move process wrapping code to process_wrapper.rs

104 of 107 new or added lines in 2 files covered. (97.2%)

4 existing lines in 1 file now uncovered.

401 of 669 relevant lines covered (59.94%)

1.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.27
/src/sys_input.rs
1
// Copyright (C) 2025 Leandro Lisboa Penz <lpenz@lpenz.org>
2
// This file is subject to the terms and conditions defined in
3
// file 'LICENSE', which is part of this source code package.
4

5
//! Module that wraps system functions used as inputs
6
//!
7
//! Wrapping this makes it very easy to test the whole program.
8

9
use color_eyre::Result;
10
use std::cell::RefCell;
11
use std::collections::VecDeque;
12
use tokio::process::Command;
13
use tokio_process_stream as tps;
14

15
use crate::process_wrapper::Cmd;
16
use crate::process_wrapper::Item;
17
use crate::process_wrapper::ProcessStream;
18
use crate::term_wrapper;
19
use crate::time_wrapper::Duration;
20
use crate::time_wrapper::Instant;
21

22
//////////////////////////////////////////////////////////////////////////////
23

24
/// Wrap the system functions we use as inputs.
25
///
26
/// This wrapper makes testing easy.
27
pub trait SysInputApi: std::fmt::Debug + Clone + Default {
28
    fn now(&self) -> Instant;
29
    #[allow(dead_code)]
30
    fn get_width(&self) -> Option<u16>;
31
    fn run_command(&mut self, command: Cmd) -> Result<ProcessStream, std::io::Error>;
32
}
33

34
/// [`SysInputApi`] implementation of the real environment.
35
#[derive(Debug, Clone, Default)]
36
pub struct SysInputReal {}
37

38
impl SysInputApi for SysInputReal {
39
    fn now(&self) -> Instant {
4✔
40
        Instant::from(chrono::offset::Utc::now())
4✔
41
    }
4✔
42
    fn get_width(&self) -> Option<u16> {
×
43
        term_wrapper::get_width()
×
44
    }
×
UNCOV
45
    fn run_command(&mut self, cmd: Cmd) -> Result<ProcessStream, std::io::Error> {
×
UNCOV
46
        let process_stream = tps::ProcessLineStream::try_from(Command::from(&cmd))?;
×
UNCOV
47
        Ok(ProcessStream::from(process_stream))
×
UNCOV
48
    }
×
49
}
50

51
/// [`SysInputApi`] implementation of a virtual environment, to be used in tests.
52
#[derive(Debug, Clone, Default)]
53
pub struct SysInputVirtual {
54
    now: RefCell<Instant>,
55
    items: VecDeque<Item>,
56
}
57

58
impl SysInputApi for SysInputVirtual {
59
    fn now(&self) -> Instant {
10✔
60
        let mut now_ref = self.now.borrow_mut();
10✔
61
        let now = *now_ref;
10✔
62
        *now_ref = &now + &Duration::seconds(1);
10✔
63
        now
10✔
64
    }
10✔
65
    fn get_width(&self) -> Option<u16> {
1✔
66
        Some(80)
1✔
67
    }
1✔
68
    fn run_command(&mut self, _cmd: Cmd) -> Result<ProcessStream, std::io::Error> {
3✔
69
        let items = std::mem::take(&mut self.items);
3✔
70
        Ok(ProcessStream::from(items))
3✔
71
    }
3✔
72
}
73

74
#[cfg(test)]
75
impl SysInputVirtual {
76
    pub fn set_items(&mut self, items: Vec<Item>) {
3✔
77
        self.items = items.into_iter().collect();
3✔
78
    }
3✔
79
}
80

81
#[cfg(test)]
82
pub mod test {
83
    use color_eyre::Result;
84
    use std::process::ExitStatus;
85
    use tokio_stream::StreamExt;
86

87
    use crate::sys_input::SysInputReal;
88
    use crate::sys_input::SysInputVirtual;
89

90
    use super::*;
91

92
    #[test]
93
    fn test_now() {
1✔
94
        let sys = SysInputReal::default();
1✔
95
        let now = sys.now();
1✔
96
        let now2 = sys.now();
1✔
97
        assert!(&now2 >= &now);
1✔
98
    }
1✔
99

100
    // A simple test for SysInputVirtual as we cover it better in
101
    // downstream tests
102

103
    #[tokio::test]
104
    async fn test_sysinputvirtual() -> Result<()> {
1✔
105
        let list = vec![
1✔
106
            Item::Stdout("stdout".into()),
1✔
107
            Item::Stderr("stderr".into()),
1✔
108
            Item::Done(Ok(ExitStatus::default())),
1✔
109
        ];
1✔
110
        let mut sys = SysInputVirtual::default();
1✔
111
        sys.set_items(list.clone());
1✔
112
        let cmd = Cmd::default();
1✔
113
        assert_eq!(format!("{}", cmd), "");
1✔
114
        let streamer = sys.run_command(cmd)?;
1✔
115
        assert_eq!(format!("{:?}", streamer), "ProcessStream::Virtual");
1✔
116
        let streamed = streamer.collect::<Vec<_>>().await;
1✔
117
        assert_eq!(streamed, list);
1✔
118
        assert_eq!(sys.now(), Instant::default());
1✔
119
        assert_eq!(sys.now(), &Instant::default() + &Duration::seconds(1));
1✔
120
        assert_eq!(sys.get_width(), Some(80));
1✔
121
        Ok(())
1✔
122
    }
1✔
123
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc