Use fake connection in tests

CandyCorvid
Jul 13, 2023, 10:57 AM
7LBPQ2M6XAXS3PMAA7W54KLH4J4YE6KCLIEHX6QW4C2QDQBYZORAC

Dependencies

  • [2] J7MKV7UT Refactor UI trait, add fake ui
  • [3] WGRFJRTE Add tests, rename Status to Header, implement redirect and proper input handling
  • [4] ARXVO5XA Make connection generic on the network
  • [5] ONQEIR5B WIP mime-type handling
  • [6] JWLMAS7U Simplify tests with rstest
  • [7] FZIABKEV New tests, refactor to be more modular, improve prompt ui, add test run parameter
  • [8] DBKKKHC2 Initial commit
  • [9] 3SPNKI46 Improve parsing. Add modules that were missed
  • [10] AMTMTTJT Upgrade status parsing
  • [11] 3VVQWLOX Major refactor: modularisation

Change contents

  • replacement in src/network.rs at line 13
    [3.144][3.144:212]()
    fn connect(url: &Url) -> Result<Self::Connection, Self::Error>;
    [3.144]
    [3.212]
    fn connect(&mut self, url: &Url) -> Result<Self::Connection, Self::Error>;
  • replacement in src/network.rs at line 17
    [3.27][3.27:44]()
    verifier: V,
    [3.27]
    [3.44]
    _verifier: V,
  • replacement in src/network.rs at line 22
    [3.104][3.104:135]()
    Self { verifier: ver }
    [3.104]
    [3.135]
    Self { _verifier: ver }
  • replacement in src/network.rs at line 30
    [3.417][3.417:486]()
    fn connect(url: &Url) -> Result<Self::Connection, Self::Error> {
    [3.417]
    [3.486]
    fn connect(&mut self, url: &Url) -> Result<Self::Connection, Self::Error> {
  • edit in src/main.rs at line 39
    [3.2344][2.779:1847](),[3.1468][3.2456:2462](),[2.1847][3.2456:2462](),[3.2456][3.2456:2462](),[3.2678][3.319:321](),[3.319][3.319:321](),[3.3924][3.5052:5115]()
    /// User interface that records method calls and returns canned inputs
    #[cfg(test)]
    #[derive(Default)]
    struct FakeUi {
    inputs: Vec<String>,
    events: Vec<FUIEvent>,
    }
    #[cfg(test)]
    enum FUIEvent {
    //TODO figure out how to solve lifetime issues
    // and store Media in this variant
    // Or just convert it to a string? idk
    Show,
    Warn(String),
    Read(String),
    ReadSecret(String),
    }
    #[cfg(test)]
    impl FakeUi {
    pub fn new() -> Self {
    Default::default()
    }
    }
    #[cfg(test)]
    impl Ui for FakeUi {
    fn show(&mut self, _content: media::Media) {
    self.events.push(FUIEvent::Show)
    }
    fn warn<D: Display>(&mut self, warning: D) {
    self.events.push(FUIEvent::Warn(warning.to_string()))
    }
    fn read(&mut self, prompt: impl Display) -> Option<String> {
    self.events.push(FUIEvent::Read(prompt.to_string()));
    self.inputs.pop()
    }
    fn read_secret(&mut self, prompt: impl Display) -> Option<String> {
    self.events.push(FUIEvent::ReadSecret(prompt.to_string()));
    self.inputs.pop()
    }
    }
    // TODO make tests using a fake connection to a local buffer
  • edit in src/main.rs at line 57
    [3.6189]
    [3.1536]
    use std::{
    cell::RefCell,
    fmt::Display,
    io::{Read, Write},
    rc::Rc,
    };
  • replacement in src/main.rs at line 67
    [3.6483][2.1848:1870]()
    use crate::NopUi;
    [3.6483]
    [2.1870]
    use crate::{media, network::Network, NopUi, Ui};
  • replacement in src/main.rs at line 73
    [3.1716][2.1872:1971]()
    crate::core::run_url::<crate::network::TcpNetwork<crate::danger::Naive>>(&mut NopUi, url);
    [3.1716]
    [3.7125]
    let mut net = crate::network::TcpNetwork::new(crate::danger::Naive);
    crate::core::run_url(&mut net, &mut NopUi, url);
  • replacement in src/main.rs at line 79
    [3.7103][3.7103:7147]()
    let body: &[u8] = b"some text\r\n";
    [3.7103]
    [3.7147]
    let url: Url = "gemini://gemini.circumlunar.space".parse().unwrap();
    let response = "20 \r\nsome text\r\n";
    let body = "some text\r\n";
    let mut fui = FakeUi::new();
    let mut net = FakeNet::new(FakeConn::new(response.into()));
    crate::core::run_url(&mut net, &mut fui, url.clone());
    let net_sink = Rc::try_unwrap(net.conn.0).unwrap().into_inner().sink;
    let net_sink = String::from_utf8(net_sink).unwrap();
    assert_eq!(net_sink, format!("{}\r\n", url));
    let ui_sink = fui.sink;
    assert_eq!(ui_sink.as_ref(), [FUIEvent::Show]);
    }
    /// User interface that records method calls and returns canned inputs
    #[derive(Default)]
    struct FakeUi {
    source: Vec<String>,
    sink: Vec<FUIEvent>,
    }
    #[derive(Debug, PartialEq, PartialOrd, Ord, Eq)]
    enum FUIEvent {
    //TODO figure out how to solve lifetime issues
    // and store Media in this variant
    // Or just convert it to a string? idk
    Show,
    Warn(String),
    Read(String),
    ReadSecret(String),
    }
    impl FakeUi {
    pub fn new() -> Self {
    Default::default()
    }
    }
    impl Ui for FakeUi {
    fn show(&mut self, content: media::Media) {
    self.sink.push(FUIEvent::Show)
    }
    fn warn<D: Display>(&mut self, warning: D) {
    self.sink.push(FUIEvent::Warn(warning.to_string()))
    }
    fn read(&mut self, prompt: impl Display) -> Option<String> {
    self.sink.push(FUIEvent::Read(prompt.to_string()));
    self.source.pop()
    }
    fn read_secret(&mut self, prompt: impl Display) -> Option<String> {
    self.sink.push(FUIEvent::ReadSecret(prompt.to_string()));
    self.source.pop()
    }
    }
    #[derive(Debug)]
    struct FakeNet {
    conn: SharedFakeConn,
    }
    impl FakeNet {
    fn new(conn: FakeConn) -> Self {
    Self {
    conn: SharedFakeConn(Rc::new(RefCell::new(conn))),
    }
    }
    }
    #[derive(Clone, Debug)]
    struct SharedFakeConn(Rc<RefCell<FakeConn>>);
    #[derive(Debug)]
    struct FakeConn {
    sink: Vec<u8>,
    source: Vec<u8>,
    }
    impl FakeConn {
    fn new(source: String) -> Self {
    Self {
    sink: Vec::new(),
    source: source.into_bytes(),
    }
    }
    }
    impl Read for SharedFakeConn {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
    self.0.borrow_mut().read(buf)
    }
    }
    impl Write for SharedFakeConn {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
    self.0.borrow_mut().write(buf)
    }
    fn flush(&mut self) -> std::io::Result<()> {
    self.0.borrow_mut().flush()
    }
    }
    impl Read for FakeConn {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
    (&*self.source).read(buf)
    }
    }
    impl Write for FakeConn {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
    self.sink.write(buf)
    }
    fn flush(&mut self) -> std::io::Result<()> {
    self.sink.flush()
    }
    }
    impl Network for FakeNet {
    type Error = &'static str;
    type Connection = SharedFakeConn;
    fn connect(&mut self, _: &Url) -> Result<Self::Connection, Self::Error> {
    Ok(self.conn.clone())
    }
  • edit in src/main.rs at line 199
    [3.7153]
    [3.7131]
    // TODO make tests using a fake connection to a local buffer
  • replacement in src/core.rs at line 8
    [3.2080][3.2080:2135]()
    pub fn run<N: Network>(ui: &mut impl Ui, mut url: Url)
    [3.2080]
    [3.2135]
    pub fn run<N: Network>(net: &mut N, ui: &mut impl Ui, mut url: Url)
  • replacement in src/core.rs at line 12
    [3.2187][3.2187:2241]()
    while let Some(new_url) = run_url::<N>(ui, url) {
    [3.2187]
    [3.2241]
    while let Some(new_url) = run_url(net, ui, url) {
  • replacement in src/core.rs at line 17
    [3.2273][3.2273:2350]()
    pub(crate) fn run_url<N: Network>(ui: &mut impl Ui, url: Url) -> Option<Url>
    [3.2273]
    [3.2350]
    pub(crate) fn run_url<N: Network>(net: &mut N, ui: &mut impl Ui, url: Url) -> Option<Url>
  • replacement in src/core.rs at line 22
    [3.2448][3.2448:2515]()
    let mut stream = N::connect(&url).expect("Failed to connect");
    [3.2448]
    [3.2515]
    let mut stream = net.connect(&url).expect("Failed to connect");
  • replacement in src/core.rs at line 122
    [3.5510][3.5510:5529]()
    .unwrap();
    [3.5510]
    [3.5529]
    .expect("failed to read input from ui");
  • replacement in src/cli.rs at line 39
    [3.9479][3.9479:9540]()
    run::<TcpNetwork<danger::Naive>>(&mut cli, url);
    [3.9479]
    [3.9540]
    let mut net = TcpNetwork::new(danger::Naive);
    run(&mut net, &mut cli, url);
  • edit in Cargo.toml at line 19
    [3.42262]
    [3.42262]
    thiserror = "1.0.43"
  • replacement in Cargo.lock at line 141
    [3.45404][3.45404:45419]()
    "syn 2.0.13",
    [3.45404]
    [3.45419]
    "syn 2.0.23",
  • replacement in Cargo.lock at line 251
    [3.1702][3.1702:1717]()
    "syn 2.0.13",
    [3.1702]
    [3.1717]
    "syn 2.0.23",
  • edit in Cargo.lock at line 304
    [3.46877]
    [3.46877]
    "thiserror",
  • replacement in Cargo.lock at line 430
    [3.11664][3.11664:11679]()
    "syn 2.0.13",
    [3.11664]
    [3.11679]
    "syn 2.0.23",
  • replacement in Cargo.lock at line 469
    [3.49497][3.49497:49516]()
    version = "1.0.56"
    [3.49497]
    [3.49516]
    version = "1.0.63"
  • replacement in Cargo.lock at line 471
    [3.49581][3.49581:49659]()
    checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
    [3.49581]
    [3.49659]
    checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
  • replacement in Cargo.lock at line 478
    [3.49724][3.49724:49743]()
    version = "1.0.26"
    [3.49724]
    [3.49743]
    version = "1.0.29"
  • replacement in Cargo.lock at line 480
    [3.49808][3.49808:49886]()
    checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
    [3.49808]
    [3.49886]
    checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105"
  • replacement in Cargo.lock at line 654
    [3.52269][3.52269:52288]()
    version = "2.0.13"
    [3.52269]
    [3.52288]
    version = "2.0.23"
  • replacement in Cargo.lock at line 656
    [3.52353][3.52353:52431]()
    checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec"
    [3.52353]
    [3.52431]
    checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737"
  • edit in Cargo.lock at line 664
    [3.52507]
    [3.52507]
    name = "thiserror"
    version = "1.0.43"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42"
    dependencies = [
    "thiserror-impl",
    ]
    [[package]]
    name = "thiserror-impl"
    version = "1.0.43"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
    dependencies = [
    "proc-macro2",
    "quote",
    "syn 2.0.23",
    ]
    [[package]]