async_test/
lib.rs

1//! Async testing utilities
2//!
3//! # Examples
4//!
5//! ```
6//! // tbi
7//! ```
8
9#![forbid(unsafe_code, future_incompatible, rust_2018_idioms)]
10#![deny(missing_debug_implementations, nonstandard_style)]
11#![warn(missing_docs, missing_doc_code_examples, unreachable_pub)]
12
13use async_std::fs::File;
14use async_std::io::prelude::*;
15use async_std::io::{self, SeekFrom};
16use async_std::sync::Arc;
17use async_std::task::{Context, Poll};
18use std::pin::Pin;
19use std::sync::Mutex;
20
21/// An async testcase that can be written to and read from.
22#[derive(Clone, Debug)]
23pub struct TestCase {
24    reader: Arc<Mutex<File>>,
25    writer: Arc<Mutex<File>>,
26}
27
28impl TestCase {
29    /// Create a new instance.
30    pub async fn new(reader: &str, writer: &str) -> TestCase {
31        use std::io::Write;
32
33        let mut temp = tempfile::tempfile().expect("Failed writer create tempfile");
34        temp.write(reader.as_bytes())
35            .expect("Could not write writer dest file");
36        let mut file: File = temp.into();
37        file.seek(SeekFrom::Start(0)).await.unwrap();
38        let reader = Arc::new(Mutex::new(file.into()));
39
40        let mut temp = tempfile::tempfile().expect("Failed writer create tempfile");
41        temp.write(writer.as_bytes())
42            .expect("Could not write writer dest file");
43        let mut file: File = temp.into();
44        file.seek(SeekFrom::Start(0)).await.unwrap();
45        let writer = Arc::new(Mutex::new(file.into()));
46
47        TestCase { reader, writer }
48    }
49
50    /// Get the value of the "writer" string.
51    pub async fn writer(&self) -> String {
52        let mut writer = String::new();
53        let mut file = self.writer.lock().unwrap();
54        file.seek(SeekFrom::Start(0)).await.unwrap();
55        file.read_to_string(&mut writer).await.unwrap();
56        writer
57    }
58
59    /// Assert the reader.
60    pub async fn assert_reader(&self, rhs: &str) {
61        let lhs = self.reader().await;
62        pretty_assertions::assert_eq!(lhs, rhs);
63    }
64
65    /// Assert the reader but pass it through a closure first..
66    pub async fn assert_reader_with(&self, rhs: &str, f: impl Fn(&mut String, &mut String)) {
67        let mut lhs = self.reader().await;
68        let mut rhs = String::from(rhs);
69        f(&mut lhs, &mut rhs);
70        pretty_assertions::assert_eq!(lhs, rhs);
71    }
72
73    /// Assert the writer.
74    pub async fn assert_writer(&self, rhs: &str) {
75        let lhs = self.writer().await;
76        pretty_assertions::assert_eq!(lhs, rhs);
77    }
78
79    /// Assert the reader but pass it through a closure first..
80    pub async fn assert_writer_with(&self, rhs: &str, f: impl Fn(&mut String, &mut String)) {
81        let mut lhs = self.writer().await;
82        let mut rhs = String::from(rhs);
83        f(&mut lhs, &mut rhs);
84        pretty_assertions::assert_eq!(lhs, rhs);
85    }
86
87    /// Get the value of the "reader" string.
88    pub async fn reader(&self) -> String {
89        let mut reader = String::new();
90        let mut file = self.reader.lock().unwrap();
91        file.seek(SeekFrom::Start(0)).await.unwrap();
92        file.read_to_string(&mut reader).await.unwrap();
93        reader
94    }
95}
96
97impl Read for TestCase {
98    fn poll_read(
99        self: Pin<&mut Self>,
100        cx: &mut Context<'_>,
101        buf: &mut [u8],
102    ) -> Poll<io::Result<usize>> {
103        Pin::new(&mut &*self.reader.lock().unwrap()).poll_read(cx, buf)
104    }
105}
106
107impl Write for TestCase {
108    fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
109        Pin::new(&mut &*self.writer.lock().unwrap()).poll_write(cx, buf)
110    }
111
112    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
113        Pin::new(&mut &*self.writer.lock().unwrap()).poll_flush(cx)
114    }
115
116    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
117        Pin::new(&mut &*self.writer.lock().unwrap()).poll_close(cx)
118    }
119}