Skip to content

Commit 28d7e6f

Browse files
authored
Merge pull request #12 from ionut-arm/test
Add testing framework and unit tests
2 parents 3db5dcb + 77db6ca commit 28d7e6f

File tree

10 files changed

+522
-12
lines changed

10 files changed

+522
-12
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ num = "0.2.1"
1717
rand = "0.7.3"
1818
log = "0.4.8"
1919
derivative = "2.0.2"
20+
21+
[dev-dependencies]
22+
mockstream = "0.0.3"
23+
uuid = "0.7.4"

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ This project uses the following third party crates:
1616
* rand (Apache-2.0)
1717
* log (Apache-2.0)
1818
* derivative (MIT and Apache-2.0)
19+
* mockstream (MIT)
20+
* uuid (MIT and Apache-2.0)
1921

2022
## Contributing
2123

src/core/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,20 @@ impl CoreClient {
8282
}
8383

8484
/// ping
85-
pub fn ping(&self) -> Result<()> {
86-
let _ = self.op_handler.process_operation(
85+
pub fn ping(&self) -> Result<(u8, u8)> {
86+
let res = self.op_handler.process_operation(
8787
NativeOperation::Ping(Ping {}),
8888
ProviderID::Core,
8989
&AuthenticationData::None,
9090
)?;
9191

92-
Ok(())
92+
if let NativeResult::Ping(res) = res {
93+
Ok((res.wire_protocol_version_maj, res.wire_protocol_version_min))
94+
} else {
95+
// Should really not be reached given the checks we do, but it's not impossible if some
96+
// changes happen in the interface
97+
Err(Error::Client(ClientErrorKind::InvalidServiceResponseType))
98+
}
9399
}
94100

95101
/// generate key

src/core/operation_handler.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub struct OperationHandler {
2222
pub wire_protocol_version_min: u8,
2323
pub content_type: BodyType,
2424
pub accept_type: BodyType,
25+
#[cfg_attr(test, derivative(Debug = "ignore"))]
2526
pub request_handler: RequestHandler,
2627
}
2728

src/core/request_handler.rs

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,51 @@
22
// SPDX-License-Identifier: Apache-2.0
33
#![allow(dead_code)]
44

5-
use crate::error::{ClientErrorKind, Error, Result};
5+
use crate::error::{ClientErrorKind, Result};
6+
#[cfg(test)]
7+
use mockstream::SyncMockStream;
68
use parsec_interface::requests::{Request, Response};
9+
use std::io::{Read, Write};
10+
#[cfg(not(test))]
711
use std::os::unix::net::UnixStream;
812
use std::path::PathBuf;
913
use std::time::Duration;
1014

11-
const DEFAULT_MAX_BODY_SIZE: usize = 1 << 31;
15+
const DEFAULT_MAX_BODY_SIZE: usize = usize::max_value();
1216
const DEFAULT_SOCKET_PATH: &str = "/tmp/security-daemon-socket";
1317

1418
/// Low level client structure to send a `Request` and get a `Response`.
15-
#[derive(Clone, Debug)]
19+
#[derive(Clone)]
20+
#[cfg_attr(not(test), derive(Debug))]
1621
pub struct RequestHandler {
1722
pub max_body_size: usize,
1823
pub timeout: Option<Duration>,
1924
pub socket_path: PathBuf,
25+
#[cfg(test)]
26+
pub mock_stream: SyncMockStream,
2027
}
2128

2229
impl RequestHandler {
2330
/// Send a request and get a response.
2431
pub fn process_request(&self, request: Request) -> Result<Response> {
2532
// Try to connect once, wait for a timeout until trying again.
26-
let mut stream = UnixStream::connect(&self.socket_path).map_err(ClientErrorKind::Ipc)?;
33+
let mut stream = self.connect_to_socket()?;
34+
35+
request
36+
.write_to_stream(&mut stream)
37+
.map_err(ClientErrorKind::Interface)?;
38+
Ok(Response::read_from_stream(&mut stream, self.max_body_size)
39+
.map_err(ClientErrorKind::Interface)?)
40+
}
41+
42+
#[cfg(test)]
43+
fn connect_to_socket(&self) -> Result<impl Read + Write> {
44+
Ok(self.mock_stream.clone())
45+
}
46+
47+
#[cfg(not(test))]
48+
fn connect_to_socket(&self) -> Result<impl Read + Write> {
49+
let stream = UnixStream::connect(&self.socket_path).map_err(ClientErrorKind::Ipc)?;
2750

2851
stream
2952
.set_read_timeout(self.timeout)
@@ -32,10 +55,7 @@ impl RequestHandler {
3255
.set_write_timeout(self.timeout)
3356
.map_err(ClientErrorKind::Ipc)?;
3457

35-
request
36-
.write_to_stream(&mut stream)
37-
.map_err(ClientErrorKind::Interface)?;
38-
Ok(Response::read_from_stream(&mut stream, self.max_body_size).map_err(Error::Service)?)
58+
Ok(stream)
3959
}
4060
}
4161

@@ -45,6 +65,8 @@ impl Default for RequestHandler {
4565
max_body_size: DEFAULT_MAX_BODY_SIZE,
4666
timeout: None,
4767
socket_path: DEFAULT_SOCKET_PATH.into(),
68+
#[cfg(test)]
69+
mock_stream: SyncMockStream::new(),
4870
}
4971
}
5072
}
@@ -66,4 +88,22 @@ impl crate::CoreClient {
6688
pub fn set_socket_path(&mut self, socket_path: PathBuf) {
6789
self.op_handler.request_handler.socket_path = socket_path;
6890
}
91+
92+
/// Test helper used to set the data to be returned from the mock stream
93+
#[cfg(test)]
94+
pub fn set_mock_read(&mut self, data: &[u8]) {
95+
self.op_handler
96+
.request_handler
97+
.mock_stream
98+
.push_bytes_to_read(data);
99+
}
100+
101+
/// Test helper used to verify the data written to the mock stream
102+
#[cfg(test)]
103+
pub fn get_mock_write(&mut self) -> Vec<u8> {
104+
self.op_handler
105+
.request_handler
106+
.mock_stream
107+
.pop_bytes_written()
108+
}
69109
}

src/error.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use parsec_interface::requests::ResponseStatus;
55

66
/// Enum used to denote errors returned to the library user
7-
#[derive(Debug)]
7+
#[derive(Debug, PartialEq)]
88
pub enum Error {
99
/// Errors originating in the service
1010
Service(ResponseStatus),
@@ -29,5 +29,33 @@ impl From<ClientErrorKind> for Error {
2929
}
3030
}
3131

32+
impl PartialEq for ClientErrorKind {
33+
fn eq(&self, other: &Self) -> bool {
34+
match self {
35+
ClientErrorKind::Interface(status) => {
36+
if let ClientErrorKind::Interface(other_status) = other {
37+
other_status == status
38+
} else {
39+
false
40+
}
41+
}
42+
ClientErrorKind::Ipc(error) => {
43+
if let ClientErrorKind::Ipc(other_error) = other {
44+
other_error.kind() == error.kind()
45+
} else {
46+
false
47+
}
48+
}
49+
ClientErrorKind::InvalidServiceResponseType => {
50+
if let ClientErrorKind::InvalidServiceResponseType = other {
51+
true
52+
} else {
53+
false
54+
}
55+
}
56+
}
57+
}
58+
}
59+
3260
/// Result type used for the internals and interface of the Parsec client
3361
pub type Result<T> = ::std::result::Result<T, Error>;

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
pub mod auth;
3535
mod core;
3636
pub mod error;
37+
mod tests;
3738

3839
pub use crate::core::CoreClient;

0 commit comments

Comments
 (0)