Skip to content

Commit 8182a63

Browse files
apollo_storage: add tests for storage reader server
1 parent 9bc9f47 commit 8182a63

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/apollo_storage/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ tempfile = { workspace = true }
6363
test-case.workspace = true
6464
test-log.workspace = true
6565
tokio = { workspace = true, features = ["full", "sync"] }
66+
tower.workspace = true
6667

6768
[lints]
6869
workspace = true

crates/apollo_storage/src/storage_reader_server.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ use tracing::{error, info};
1414

1515
use crate::{StorageError, StorageReader};
1616

17+
#[cfg(test)]
18+
#[path = "storage_reader_server_test.rs"]
19+
mod storage_reader_server_test;
20+
1721
// TODO(Nadin): Remove #[allow(dead_code)] once the fields are used in the implementation.
1822
#[allow(dead_code)]
1923
/// Configuration for the storage reader server.
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
use std::net::SocketAddr;
2+
3+
use async_trait::async_trait;
4+
use axum::body::{Body, Bytes, HttpBody};
5+
use axum::http::{Request, StatusCode};
6+
use axum::response::Response;
7+
use pretty_assertions::assert_eq;
8+
use serde::{Deserialize, Serialize};
9+
use starknet_api::block::{BlockHeader, BlockNumber};
10+
use tower::ServiceExt;
11+
12+
use crate::header::{HeaderStorageReader, HeaderStorageWriter};
13+
use crate::storage_reader_server::{ServerConfig, StorageReaderServer, StorageReaderServerHandler};
14+
use crate::test_utils::get_test_storage;
15+
use crate::{StorageError, StorageReader};
16+
17+
const TEST_SERVER_IP: [u8; 4] = [127, 0, 0, 1];
18+
19+
// Test request and response types
20+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
21+
struct TestRequest {
22+
block_number: u64,
23+
}
24+
25+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
26+
struct TestResponse {
27+
block_number: u64,
28+
found: bool,
29+
}
30+
31+
// Mock handler that queries for block headers
32+
#[derive(Clone)]
33+
struct TestHandler;
34+
35+
#[async_trait]
36+
impl StorageReaderServerHandler<TestRequest, TestResponse> for TestHandler {
37+
async fn handle_request(
38+
storage_reader: &StorageReader,
39+
request: TestRequest,
40+
) -> Result<TestResponse, StorageError> {
41+
let block_number = BlockNumber(request.block_number);
42+
let txn = storage_reader.begin_ro_txn()?;
43+
let header = txn.get_block_header(block_number)?;
44+
Ok(TestResponse { block_number: request.block_number, found: header.is_some() })
45+
}
46+
}
47+
48+
#[tokio::test]
49+
async fn test_endpoint_successful_query() {
50+
let ((reader, mut writer), _temp_dir) = get_test_storage();
51+
52+
// Add a test header at block 0
53+
writer
54+
.begin_rw_txn()
55+
.unwrap()
56+
.append_header(BlockNumber(0), &BlockHeader::default())
57+
.unwrap()
58+
.commit()
59+
.unwrap();
60+
61+
let socket = SocketAddr::from((TEST_SERVER_IP, 8081));
62+
let config = ServerConfig::new(socket, true);
63+
64+
let server =
65+
StorageReaderServer::<TestHandler, TestRequest, TestResponse>::new(reader.clone(), config);
66+
let app = server.app();
67+
68+
// Test query for existing block
69+
let request = TestRequest { block_number: 0 };
70+
let response = app
71+
.clone()
72+
.oneshot(
73+
Request::builder()
74+
.method("POST")
75+
.uri("/storage/query")
76+
.header("content-type", "application/json")
77+
.body(Body::from(serde_json::to_string(&request).unwrap()))
78+
.unwrap(),
79+
)
80+
.await
81+
.unwrap();
82+
83+
assert_eq!(response.status(), StatusCode::OK);
84+
85+
let body = to_bytes(response).await;
86+
let test_response: TestResponse = serde_json::from_slice(&body).unwrap();
87+
88+
assert_eq!(test_response.block_number, 0);
89+
assert!(test_response.found);
90+
}
91+
92+
#[tokio::test]
93+
async fn test_endpoint_query_nonexistent_block() {
94+
let ((reader, _writer), _temp_dir) = get_test_storage();
95+
96+
let socket = SocketAddr::from((TEST_SERVER_IP, 8082));
97+
let config = ServerConfig::new(socket, true);
98+
99+
let server =
100+
StorageReaderServer::<TestHandler, TestRequest, TestResponse>::new(reader.clone(), config);
101+
let app = server.app();
102+
103+
// Test query for non-existent block
104+
let request = TestRequest { block_number: 999 };
105+
let response = app
106+
.oneshot(
107+
Request::builder()
108+
.method("POST")
109+
.uri("/storage/query")
110+
.header("content-type", "application/json")
111+
.body(Body::from(serde_json::to_string(&request).unwrap()))
112+
.unwrap(),
113+
)
114+
.await
115+
.unwrap();
116+
117+
assert_eq!(response.status(), StatusCode::OK);
118+
119+
let body = to_bytes(response).await;
120+
let test_response: TestResponse = serde_json::from_slice(&body).unwrap();
121+
122+
assert_eq!(test_response.block_number, 999);
123+
assert!(!test_response.found);
124+
}
125+
126+
// Helper function to convert response body to bytes
127+
async fn to_bytes(res: Response) -> Bytes {
128+
res.into_body().collect().await.unwrap().to_bytes()
129+
}

0 commit comments

Comments
 (0)