Skip to content

Commit 506e45f

Browse files
committed
Add Unit tests for VssAccessor
1 parent 6d67dda commit 506e45f

File tree

4 files changed

+286
-2
lines changed

4 files changed

+286
-2
lines changed

vss-accessor/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ reqwest = { version = "0.11.13", features = ["rustls-tls"] }
1010

1111
[dev-dependencies]
1212
mockito = "0.31.1"
13-
tokio = { version = "1.22.0"}
13+
tokio = { version = "1.22.0", features = ["full"]}
1414

1515
[build-dependencies]
1616
prost-build = { version = "0.11.3" }

vss-accessor/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::vss::{
99
};
1010
use crate::vss_error::VssError;
1111

12-
mod vss_error;
12+
pub mod vss_error;
1313

1414
pub mod vss {
1515
include!(concat!(env!("OUT_DIR"), "/org.vss.rs"));

vss-accessor/src/vss_error.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,15 @@ impl From<reqwest::Error> for VssError {
7373
VssError::InternalError(err.to_string())
7474
}
7575
}
76+
77+
impl PartialEq for VssError {
78+
fn eq(&self, other: &Self) -> bool {
79+
match (self, other) {
80+
(VssError::InvalidRequestError(_e1), VssError::InvalidRequestError(_e2)) => true,
81+
(VssError::ConflictError(_e1), VssError::ConflictError(_e2)) => true,
82+
(VssError::InternalServerError(_e1), VssError::InternalServerError(_e2)) => true,
83+
(VssError::InternalError(_m1), VssError::InternalError(_m2)) => true,
84+
_ => false,
85+
}
86+
}
87+
}

vss-accessor/tests/tests.rs

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
#[cfg(test)]
2+
mod tests {
3+
use mockito::{self, Matcher};
4+
use prost::Message;
5+
use vss_accessor::vss::{
6+
ErrorCode, ErrorResponse, GetObjectRequest, GetObjectResponse, KeyValue, ListKeyVersionsRequest,
7+
ListKeyVersionsResponse, PutObjectRequest, PutObjectResponse,
8+
};
9+
use vss_accessor::vss_error::VssError;
10+
use vss_accessor::VssAccessor;
11+
12+
#[tokio::test]
13+
async fn test_get() {
14+
// Spin-up mock server with mock response for given request.
15+
let base_url = mockito::server_url().to_string();
16+
let mock_get_endpoint = "/getObject";
17+
18+
// Set up the mock request/response.
19+
let mock_request = GetObjectRequest { store_id: "store".to_string(), key: "k1".to_string() };
20+
let mut mock_response = GetObjectResponse::default();
21+
mock_response.value = Some(KeyValue { key: "k1".to_string(), version: 2, value: b"k1v2".to_vec() });
22+
23+
// Register the mock endpoint with the mockito server.
24+
let mock_server = mockito::mock("POST", mock_get_endpoint)
25+
.match_body(mock_request.encode_to_vec())
26+
.with_status(200)
27+
.with_body(mock_response.encode_to_vec())
28+
.create();
29+
30+
// Create a new VssAccessor with the mock server URL.
31+
let vss_acc = VssAccessor::new(&base_url).unwrap();
32+
let actual_result = vss_acc.get("store", "k1").await.unwrap();
33+
34+
let expected_result = &mock_response;
35+
assert_eq!(&actual_result, expected_result);
36+
37+
// Verify server endpoint was called exactly once.
38+
mock_server.expect(1).assert();
39+
}
40+
41+
#[tokio::test]
42+
async fn test_put() {
43+
// Spin-up mock server with mock response for given request.
44+
let base_url = mockito::server_url().to_string();
45+
let mock_put_endpoint = "/putObjects";
46+
47+
// Set up the mock request/response.
48+
let mock_request = PutObjectRequest {
49+
store_id: "store".to_string(),
50+
global_version: Some(4),
51+
transaction_items: vec![KeyValue { key: "k1".to_string(), version: 2, value: b"k1v3".to_vec() }],
52+
};
53+
let mock_response = PutObjectResponse::default();
54+
55+
// Register the mock endpoint with the mockito server.
56+
let mock_server = mockito::mock("POST", mock_put_endpoint)
57+
.match_body(mock_request.encode_to_vec())
58+
.with_status(200)
59+
.with_body(mock_response.encode_to_vec())
60+
.create();
61+
62+
// Create a new VssAccessor with the mock server URL.
63+
let vss_acc = VssAccessor::new(&base_url).unwrap();
64+
let actual_result = vss_acc.put("store", Some(4), "k1", 2, b"k1v3").await.unwrap();
65+
66+
let expected_result = &mock_response;
67+
assert_eq!(&actual_result, expected_result);
68+
69+
// Verify server endpoint was called exactly once.
70+
mock_server.expect(1).assert();
71+
}
72+
73+
#[tokio::test]
74+
async fn test_put_tx() {
75+
// Spin-up mock server with mock response for given request.
76+
let base_url = mockito::server_url().to_string();
77+
let mock_put_endpoint = "/putObjects";
78+
79+
// Set up the mock request/response.
80+
let mock_request = PutObjectRequest {
81+
store_id: "store".to_string(),
82+
global_version: Some(5),
83+
transaction_items: vec![
84+
KeyValue { key: "k1".to_string(), version: 3, value: b"k1v4".to_vec() },
85+
KeyValue { key: "k2".to_string(), version: 1, value: b"k2v2".to_vec() },
86+
],
87+
};
88+
let mock_response = PutObjectResponse {};
89+
90+
// Register the mock endpoint with the mockito server.
91+
let mock_server = mockito::mock("POST", mock_put_endpoint)
92+
.match_body(mock_request.encode_to_vec())
93+
.with_status(200)
94+
.with_body(mock_response.encode_to_vec())
95+
.create();
96+
97+
// Create a new VssAccessor with the mock server URL.
98+
let vss_acc = VssAccessor::new(&base_url).unwrap();
99+
100+
let actual_result = vss_acc
101+
.put_tx(
102+
"store",
103+
Some(5),
104+
vec![
105+
KeyValue { key: "k1".to_string(), version: 3, value: b"k1v4".to_vec() },
106+
KeyValue { key: "k2".to_string(), version: 1, value: b"k2v2".to_vec() },
107+
],
108+
)
109+
.await
110+
.unwrap();
111+
112+
let expected_result = &mock_response;
113+
assert_eq!(&actual_result, expected_result);
114+
115+
// Verify server endpoint was called exactly once.
116+
mock_server.expect(1).assert();
117+
}
118+
119+
#[tokio::test]
120+
async fn test_list_key_versions() {
121+
// Spin-up mock server with mock response for given request.
122+
let base_url = mockito::server_url().to_string();
123+
let mock_list_endpoint = "/listKeyVersions";
124+
125+
// Set up the mock request/response.
126+
let mock_request = ListKeyVersionsRequest {
127+
store_id: "store".to_string(),
128+
page_size: Some(5),
129+
page_token: None,
130+
key_prefix: Some("k".into()),
131+
};
132+
let key_versions = vec![
133+
KeyValue { key: "k1".to_string(), version: 3, value: b"".to_vec() },
134+
KeyValue { key: "k2".to_string(), version: 1, value: b"".to_vec() },
135+
];
136+
137+
let mock_response =
138+
ListKeyVersionsResponse { key_versions, global_version: Some(4), next_page_token: Some("k2".into()) };
139+
140+
// Register the mock endpoint with the mockito server.
141+
let mock_server = mockito::mock("POST", mock_list_endpoint)
142+
.match_body(mock_request.encode_to_vec())
143+
.with_status(200)
144+
.with_body(mock_response.encode_to_vec())
145+
.create();
146+
147+
// Create a new VssAccessor with the mock server URL.
148+
let vss_acc = VssAccessor::new(&base_url).unwrap();
149+
150+
let actual_result = vss_acc.list_key_versions("store", "k", Some(5), None).await.unwrap();
151+
152+
let expected_result = &mock_response;
153+
assert_eq!(&actual_result, expected_result);
154+
155+
// Verify server endpoint was called exactly once.
156+
mock_server.expect(1).assert();
157+
}
158+
159+
#[tokio::test]
160+
async fn test_invalid_request_err_handling() {
161+
let base_url = mockito::server_url();
162+
let vss_accessor = VssAccessor::new(&base_url).unwrap();
163+
164+
// Invalid Request Error
165+
let error_response = ErrorResponse {
166+
error_code: ErrorCode::InvalidRequestException.into(),
167+
message: "InvalidRequestException".to_string(),
168+
};
169+
let mock_server =
170+
mockito::mock("POST", Matcher::Any).with_status(400).with_body(&error_response.encode_to_vec()).create();
171+
172+
let get_result = vss_accessor.get("store", "key1").await;
173+
assert_eq!(get_result.unwrap_err(), VssError::InvalidRequestError(ErrorResponse::default()));
174+
175+
let put_result = vss_accessor.put("store", Some(4), "k1", 2, b"k1v3").await;
176+
assert_eq!(put_result.unwrap_err(), VssError::InvalidRequestError(ErrorResponse::default()));
177+
178+
let list_result = vss_accessor.list_key_versions("store", "k", Some(5), None).await;
179+
assert_eq!(list_result.unwrap_err(), VssError::InvalidRequestError(ErrorResponse::default()));
180+
181+
// Verify 3 requests hit the server
182+
mock_server.expect(3).assert();
183+
}
184+
185+
#[tokio::test]
186+
async fn test_conflict_err_handling() {
187+
let base_url = mockito::server_url();
188+
let vss_accessor = VssAccessor::new(&base_url).unwrap();
189+
190+
// Conflict Error
191+
let error_response =
192+
ErrorResponse { error_code: ErrorCode::ConflictException.into(), message: "ConflictException".to_string() };
193+
let mock_server =
194+
mockito::mock("POST", Matcher::Any).with_status(409).with_body(&error_response.encode_to_vec()).create();
195+
196+
let put_result = vss_accessor.put("store", Some(4), "k1", 2, b"k1v3").await;
197+
assert_eq!(put_result.unwrap_err(), VssError::ConflictError(ErrorResponse::default()));
198+
199+
// Verify 1 requests hit the server
200+
mock_server.expect(1).assert();
201+
}
202+
203+
#[tokio::test]
204+
async fn test_internal_server_err_handling() {
205+
let base_url = mockito::server_url();
206+
let vss_accessor = VssAccessor::new(&base_url).unwrap();
207+
208+
// Internal Server Error
209+
let error_response = ErrorResponse {
210+
error_code: ErrorCode::InternalServerException.into(),
211+
message: "InternalServerException".to_string(),
212+
};
213+
let mock_server =
214+
mockito::mock("POST", Matcher::Any).with_status(500).with_body(&error_response.encode_to_vec()).create();
215+
216+
let get_result = vss_accessor.get("store", "key1").await;
217+
assert_eq!(get_result.unwrap_err(), VssError::InternalServerError(ErrorResponse::default()));
218+
219+
let put_result = vss_accessor.put("store", Some(4), "k1", 2, b"k1v3").await;
220+
assert_eq!(put_result.unwrap_err(), VssError::InternalServerError(ErrorResponse::default()));
221+
222+
let list_result = vss_accessor.list_key_versions("store", "k", Some(5), None).await;
223+
assert_eq!(list_result.unwrap_err(), VssError::InternalServerError(ErrorResponse::default()));
224+
225+
// Verify 3 requests hit the server
226+
mock_server.expect(3).assert();
227+
}
228+
229+
#[tokio::test]
230+
async fn test_internal_err_handling() {
231+
let base_url = mockito::server_url();
232+
let vss_accessor = VssAccessor::new(&base_url).unwrap();
233+
234+
let error_response = ErrorResponse { error_code: 999, message: "UnknownException".to_string() };
235+
let mut mock_server =
236+
mockito::mock("POST", Matcher::Any).with_status(999).with_body(&error_response.encode_to_vec()).create();
237+
238+
let get_result = vss_accessor.get("store", "key1").await;
239+
assert_eq!(get_result.unwrap_err(), VssError::InternalError("InternalError".into()));
240+
241+
let put_result = vss_accessor.put("store", Some(4), "k1", 2, b"k1v3").await;
242+
assert_eq!(put_result.unwrap_err(), VssError::InternalError("InternalError".into()));
243+
244+
let list_result = vss_accessor.list_key_versions("store", "k", Some(5), None).await;
245+
assert_eq!(list_result.unwrap_err(), VssError::InternalError("InternalError".into()));
246+
247+
let malformed_error_response = b"malformed";
248+
mock_server =
249+
mockito::mock("POST", Matcher::Any).with_status(409).with_body(&malformed_error_response).create();
250+
251+
let get_malformed_err_response = vss_accessor.get("store", "key1").await;
252+
assert_eq!(get_malformed_err_response.unwrap_err(), VssError::InternalError("InternalError".into()));
253+
254+
let put_malformed_err_response = vss_accessor.put("store", Some(4), "k1", 2, b"k1v3").await;
255+
assert_eq!(put_malformed_err_response.unwrap_err(), VssError::InternalError("InternalError".into()));
256+
257+
let list_malformed_err_response = vss_accessor.list_key_versions("store", "k", Some(5), None).await;
258+
assert_eq!(list_malformed_err_response.unwrap_err(), VssError::InternalError("InternalError".into()));
259+
260+
// Requests to endpoints are no longer mocked and will result in network error.
261+
drop(mock_server);
262+
263+
let get_network_err = vss_accessor.get("store", "key1").await;
264+
assert_eq!(get_network_err.unwrap_err(), VssError::InternalError("InternalError".into()));
265+
266+
let put_network_err = vss_accessor.put("store", Some(4), "k1", 2, b"k1v3").await;
267+
assert_eq!(put_network_err.unwrap_err(), VssError::InternalError("InternalError".into()));
268+
269+
let list_network_err = vss_accessor.list_key_versions("store", "k", Some(5), None).await;
270+
assert_eq!(list_network_err.unwrap_err(), VssError::InternalError("InternalError".into()));
271+
}
272+
}

0 commit comments

Comments
 (0)