Files
miner/tests/integration_tests.rs
T

208 lines
6.1 KiB
Rust

use primitive_types::U512;
use quantus_miner::*;
use resonance_miner_api::*;
use warp::test::request;
use warp::Filter; // Import shared API types
#[tokio::test]
async fn test_mine_endpoint() {
let state = MiningState::new();
let state_clone = state.clone();
let state_filter = warp::any().map(move || state_clone.clone());
let mine_route = warp::post()
.and(warp::path("mine"))
.and(warp::body::json())
.and(state_filter.clone())
.and_then(handle_mine_request);
// Test valid request
let valid_request = MiningRequest {
job_id: "test".to_string(),
mining_hash: "a".repeat(64),
distance_threshold: "1000".to_string(),
nonce_start: "0".repeat(128),
nonce_end: "1".repeat(128),
};
let resp = request()
.method("POST")
.path("/mine")
.json(&valid_request)
.reply(&mine_route)
.await;
assert_eq!(resp.status(), 200);
let body: MiningResponse = serde_json::from_slice(resp.body()).unwrap();
assert_eq!(body.status, ApiResponseStatus::Accepted);
assert_eq!(body.job_id, "test");
// Test duplicate job ID
let resp = request()
.method("POST")
.path("/mine")
.json(&valid_request)
.reply(&mine_route)
.await;
assert_eq!(resp.status(), 409);
let body: MiningResponse = serde_json::from_slice(resp.body()).unwrap();
assert_eq!(body.status, ApiResponseStatus::Error);
assert!(body.message.is_some());
assert!(body.message.unwrap().contains("Job already exists"));
// Test invalid request
let invalid_request = MiningRequest {
job_id: "".to_string(), // Empty job ID
mining_hash: "a".repeat(64),
distance_threshold: "1000".to_string(),
nonce_start: "0".repeat(128),
nonce_end: "1".repeat(128),
};
let resp = request()
.method("POST")
.path("/mine")
.json(&invalid_request)
.reply(&mine_route)
.await;
assert_eq!(resp.status(), 400);
}
#[tokio::test]
async fn test_result_endpoint() {
let state = MiningState::new();
let state_clone = state.clone();
let state_filter = warp::any().map(move || state_clone.clone());
// First create a job
let job = MiningJob::new([0; 32], U512::from(1000), U512::from(0), U512::from(1000));
state.add_job("test".to_string(), job).await.unwrap();
let result_route = warp::get()
.and(warp::path("result"))
.and(warp::path::param())
.and(state_filter.clone())
.and_then(handle_result_request);
// Test existing job
let resp = request()
.method("GET")
.path("/result/test")
.reply(&result_route)
.await;
assert_eq!(resp.status(), 200);
let body: MiningResult = serde_json::from_slice(resp.body()).unwrap();
assert_eq!(body.status, ApiResponseStatus::Running);
assert_eq!(body.job_id, "test");
// Test non-existent job
let resp = request()
.method("GET")
.path("/result/nonexistent")
.reply(&result_route)
.await;
assert_eq!(resp.status(), 404);
let body: MiningResult = serde_json::from_slice(resp.body()).unwrap();
assert_eq!(body.status, ApiResponseStatus::NotFound);
}
#[tokio::test]
async fn test_cancel_endpoint() {
let state = MiningState::new();
let state_clone = state.clone();
let state_filter = warp::any().map(move || state_clone.clone());
// First create a job
let job = MiningJob::new([0; 32], U512::from(1000), U512::from(0), U512::from(1000));
state.add_job("test".to_string(), job).await.unwrap();
let cancel_route = warp::post()
.and(warp::path("cancel"))
.and(warp::path::param())
.and(state_filter.clone())
.and_then(handle_cancel_request);
// Test cancel existing job
let resp = request()
.method("POST")
.path("/cancel/test")
.reply(&cancel_route)
.await;
assert_eq!(resp.status(), 200);
let body: MiningResponse = serde_json::from_slice(resp.body()).unwrap();
assert_eq!(body.status, ApiResponseStatus::Cancelled);
assert_eq!(body.job_id, "test");
// Test cancel non-existent job
let resp = request()
.method("POST")
.path("/cancel/nonexistent")
.reply(&cancel_route)
.await;
assert_eq!(resp.status(), 404);
let body: MiningResponse = serde_json::from_slice(resp.body()).unwrap();
assert_eq!(body.status, ApiResponseStatus::NotFound);
}
#[tokio::test]
async fn test_concurrent_access() {
let state = MiningState::new();
let state_clone = state.clone();
let state_filter = warp::any().map(move || state_clone.clone());
// Create multiple jobs concurrently
let mut handles = vec![];
for i in 0..10 {
let state = state.clone();
let handle = tokio::spawn(async move {
let job = MiningJob::new([0; 32], U512::from(1000), U512::from(0), U512::from(1000));
state.add_job(format!("test{}", i), job).await
});
handles.push(handle);
}
// Wait for all jobs to be created
for handle in handles {
assert!(handle.await.unwrap().is_ok());
}
// Verify all jobs exist
for i in 0..10 {
assert!(state.get_job(&format!("test{}", i)).await.is_some());
}
// Test concurrent result checks
let result_route = warp::get()
.and(warp::path("result"))
.and(warp::path::param())
.and(state_filter.clone())
.and_then(handle_result_request);
let mut result_handles = vec![];
for i in 0..10 {
let route = result_route.clone();
let handle = tokio::spawn(async move {
request()
.method("GET")
.path(&format!("/result/test{}", i))
.reply(&route)
.await
});
result_handles.push(handle);
}
// Verify all result checks succeed
for handle in result_handles {
let resp = handle.await.unwrap();
assert_eq!(resp.status(), 200);
let body: MiningResult = serde_json::from_slice(resp.body()).unwrap();
assert_eq!(body.status, ApiResponseStatus::Running);
}
}