Testing TCPstream reading function

51 Views Asked by At

I'm creating a simple HTTP 1.1 sever that will be able to read and write to new connections. Everything seems to be building and running fine, as used a print statement to confirm a test connection is established. I was wondering if there was a way to test the stream.read() function, which takes a mut buffer: [u8;1024]. I want to test and see if the program is awaiting new connections via the terminal. I am currently using VSCode and the standard terminal.

I will provide the Server module, I have written.

use ::std::io::Read;
use std::net::TcpListener;

pub struct Server_Node {
    address: String,
}
impl Server_Node {
    pub fn new(address: String) -> Self {
        Server_Node { address }
    }

    pub fn run(self) {
        println!("Listening on {} !!!!凸(⊙▂⊙✖ )!!!!", self.address);
        let listener = TcpListener::bind(&self.address).unwrap();

        loop {
            match listener.accept() {
                Ok((mut _stream, _)) => {
                    let mut buffer = [0; 1024];
                    match _stream.read(&mut buffer) {
                        Ok(_) => {
                            println!("Recieved  a request: {}", String::from_utf8_lossy(&buffer));
                        }

                        Err((e)) => println!("FAILED TO READ FVROM CONNECTION: {}", e),
                    }
                }
                Err(e) => println!("ERROR: FAILED TO ESTABLISH CONNECTION :{} ", e),
            }
        }
    }
}
1

There are 1 best solutions below

0
Daniil Trotsenko On

listener.accept() returns a TcpStream which implements Read trait. Docs

If you haven't already studied trait and trait objects, I suggest to read about it in the Rust book. You can write a separate function that accepts a generic parameter with a specified trait bound.

match listener.accept() {
                Ok((mut _stream, _)) => {
                    let mut buffer = [0; 1024];
                    match _stream.read(&mut buffer) {
                        Ok(_) => {
                            println!("Recieved  a request: {}", String::from_utf8_lossy(&buffer));
                        }

                        Err((e)) => println!("FAILED TO READ FVROM CONNECTION: {}", e),
                    }
                }
                Err(e) => println!("ERROR: FAILED TO ESTABLISH CONNECTION :{} ", e),
            }

You can rewrite in something like this:

fn process_stream<R: Read>(mut stream: R) -> Result<(), String> {
    // process stream here
    ...
}

// Server_Node.run
match listener.accept() {
     Ok((stream, _)) => process_stream(stream), // extend your logic
     Err(err) => {...},
}

With such decomposition, you can cover your process_stream function with unit tests and test it separately, even without running the whole application.