Skip to content

Commit f4e55f8

Browse files
committed
Add Unit tests for VssAccessor
1 parent 0031a6b commit f4e55f8

File tree

1 file changed

+311
-0
lines changed

1 file changed

+311
-0
lines changed

tests/tests.rs

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

0 commit comments

Comments
 (0)