410 lines
12 KiB
Rust
410 lines
12 KiB
Rust
use hero_openrpc_server::{OpenRpcServer, OpenRpcServerConfig, OpenRpcApiServer, Transport, types::*};
|
|
use hero_supervisor::{Supervisor, SupervisorBuilder};
|
|
use hero_job::{JobBuilder, JobStatus, ScriptType};
|
|
use jsonrpsee_types::error::ErrorCode;
|
|
use std::sync::Arc;
|
|
use tokio::sync::RwLock;
|
|
use std::time::Duration;
|
|
|
|
/// Helper function to create a test supervisor
|
|
async fn create_test_supervisor() -> Arc<RwLock<Supervisor>> {
|
|
let supervisor = SupervisorBuilder::new()
|
|
.redis_url("redis://localhost:6379")
|
|
.build()
|
|
.await
|
|
.expect("Failed to create test supervisor");
|
|
|
|
Arc::new(RwLock::new(supervisor))
|
|
}
|
|
|
|
/// Helper function to create a test OpenRPC server
|
|
async fn create_test_server() -> OpenRpcServer {
|
|
use std::net::SocketAddr;
|
|
use std::path::PathBuf;
|
|
|
|
let config = OpenRpcServerConfig {
|
|
transport: Transport::WebSocket("127.0.0.1:0".parse::<SocketAddr>().unwrap()),
|
|
supervisor_config_path: None,
|
|
db_path: PathBuf::from("/tmp/test_openrpc.db"),
|
|
};
|
|
OpenRpcServer::new(config).await.expect("Failed to create OpenRPC server")
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_fetch_nonce() {
|
|
let server = create_test_server().await;
|
|
let public_key = "test_public_key".to_string();
|
|
|
|
let result = server.fetch_nonce(public_key).await;
|
|
assert!(result.is_ok());
|
|
|
|
let nonce = result.unwrap();
|
|
assert!(!nonce.is_empty());
|
|
assert_eq!(nonce.len(), 64); // Should be a 32-byte hex string
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_create_job_success() {
|
|
let server = create_test_server().await;
|
|
|
|
let job_params = JobParams {
|
|
script: "print('Hello, World!');".to_string(),
|
|
script_type: ScriptType::OSIS,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(60),
|
|
prerequisites: None,
|
|
};
|
|
|
|
let result = server.create_job(job_params).await;
|
|
assert!(result.is_ok());
|
|
|
|
let job_id = result.unwrap();
|
|
assert!(!job_id.is_empty());
|
|
// Job ID should be a valid UUID format
|
|
assert!(uuid::Uuid::parse_str(&job_id).is_ok());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_create_job_with_prerequisites() {
|
|
let server = create_test_server().await;
|
|
|
|
let job_params = JobParams {
|
|
script: "print('Job with prerequisites');".to_string(),
|
|
script_type: ScriptType::SAL,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(120),
|
|
prerequisites: Some(vec!["prereq_job_1".to_string(), "prereq_job_2".to_string()]),
|
|
};
|
|
|
|
let result = server.create_job(job_params).await;
|
|
assert!(result.is_ok());
|
|
|
|
let job_id = result.unwrap();
|
|
assert!(!job_id.is_empty());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_create_job_invalid_params() {
|
|
let server = create_test_server().await;
|
|
|
|
// Test with empty caller_id (should fail JobBuilder validation)
|
|
let job_params = JobParams {
|
|
script: "print('Test');".to_string(),
|
|
script_type: ScriptType::OSIS,
|
|
caller_id: "".to_string(), // Empty caller_id should fail
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(60),
|
|
prerequisites: None,
|
|
};
|
|
|
|
let result = server.create_job(job_params).await;
|
|
assert!(result.is_err());
|
|
assert_eq!(result.unwrap_err(), ErrorCode::InvalidParams);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_start_job() {
|
|
let server = create_test_server().await;
|
|
|
|
// First create a job
|
|
let job_params = JobParams {
|
|
script: "print('Test job');".to_string(),
|
|
script_type: ScriptType::OSIS,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(60),
|
|
prerequisites: None,
|
|
};
|
|
|
|
let job_id = server.create_job(job_params).await.unwrap();
|
|
|
|
// Then start the job
|
|
let result = server.start_job(job_id).await;
|
|
assert!(result.is_ok());
|
|
|
|
let start_result = result.unwrap();
|
|
assert!(start_result.success);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_job_status() {
|
|
let server = create_test_server().await;
|
|
|
|
// First create a job
|
|
let job_params = JobParams {
|
|
script: "print('Status test');".to_string(),
|
|
script_type: ScriptType::OSIS,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(60),
|
|
prerequisites: None,
|
|
};
|
|
|
|
let job_id = server.create_job(job_params).await.unwrap();
|
|
|
|
// Get job status
|
|
let result = server.get_job_status(job_id).await;
|
|
assert!(result.is_ok());
|
|
|
|
let status = result.unwrap();
|
|
// Status should be one of the valid JobStatus variants
|
|
match status {
|
|
JobStatus::Dispatched | JobStatus::WaitingForPrerequisites |
|
|
JobStatus::Started | JobStatus::Error | JobStatus::Finished => {
|
|
// Valid status
|
|
}
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_job_output() {
|
|
let server = create_test_server().await;
|
|
|
|
// First create a job
|
|
let job_params = JobParams {
|
|
script: "print('Output test');".to_string(),
|
|
script_type: ScriptType::OSIS,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(60),
|
|
prerequisites: None,
|
|
};
|
|
|
|
let job_id = server.create_job(job_params).await.unwrap();
|
|
|
|
// Get job output
|
|
let result = server.get_job_output(job_id).await;
|
|
assert!(result.is_ok());
|
|
|
|
let output = result.unwrap();
|
|
assert!(!output.is_empty());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_list_jobs() {
|
|
let server = create_test_server().await;
|
|
|
|
// Create a few jobs first
|
|
for i in 0..3 {
|
|
let job_params = JobParams {
|
|
script: format!("print('Job {}');", i),
|
|
script_type: ScriptType::OSIS,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(60),
|
|
prerequisites: None,
|
|
};
|
|
|
|
let _ = server.create_job(job_params).await.unwrap();
|
|
}
|
|
|
|
// List all jobs
|
|
let result = server.list_jobs().await;
|
|
assert!(result.is_ok());
|
|
|
|
let jobs = result.unwrap();
|
|
assert!(jobs.len() >= 3); // Should have at least the 3 jobs we created
|
|
|
|
// Verify job structure
|
|
for job in jobs {
|
|
assert!(!job.id.is_empty());
|
|
assert!(uuid::Uuid::parse_str(&job.id).is_ok());
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_stop_job() {
|
|
let server = create_test_server().await;
|
|
|
|
// First create and start a job
|
|
let job_params = JobParams {
|
|
script: "print('Stop test');".to_string(),
|
|
script_type: ScriptType::OSIS,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(60),
|
|
prerequisites: None,
|
|
};
|
|
|
|
let job_id = server.create_job(job_params).await.unwrap();
|
|
let _ = server.start_job(job_id.clone()).await.unwrap();
|
|
|
|
// Stop the job
|
|
let result = server.stop_job(job_id).await;
|
|
assert!(result.is_ok());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_delete_job() {
|
|
let server = create_test_server().await;
|
|
|
|
// First create a job
|
|
let job_params = JobParams {
|
|
script: "print('Delete test');".to_string(),
|
|
script_type: ScriptType::OSIS,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(60),
|
|
prerequisites: None,
|
|
};
|
|
|
|
let job_id = server.create_job(job_params).await.unwrap();
|
|
|
|
// Delete the job
|
|
let result = server.delete_job(job_id).await;
|
|
assert!(result.is_ok());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_clear_all_jobs() {
|
|
let server = create_test_server().await;
|
|
|
|
// Create a few jobs first
|
|
for i in 0..3 {
|
|
let job_params = JobParams {
|
|
script: format!("print('Clear test {}');", i),
|
|
script_type: ScriptType::OSIS,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(60),
|
|
prerequisites: None,
|
|
};
|
|
|
|
let _ = server.create_job(job_params).await.unwrap();
|
|
}
|
|
|
|
// Clear all jobs
|
|
let result = server.clear_all_jobs().await;
|
|
assert!(result.is_ok());
|
|
|
|
// Verify jobs are cleared
|
|
let jobs = server.list_jobs().await.unwrap();
|
|
assert_eq!(jobs.len(), 0);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_run_job() {
|
|
let server = create_test_server().await;
|
|
|
|
let script = "print('Run job test');".to_string();
|
|
let script_type = ScriptType::OSIS;
|
|
let prerequisites = None;
|
|
|
|
let result = server.run_job(script, script_type, prerequisites).await;
|
|
assert!(result.is_ok());
|
|
|
|
let output = result.unwrap();
|
|
assert!(!output.is_empty());
|
|
assert!(output.contains("Run job test"));
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
async fn test_play_script() {
|
|
let server = create_test_server().await;
|
|
|
|
let script = "print('Play script test');".to_string();
|
|
|
|
let result = server.play(script.clone()).await;
|
|
assert!(result.is_ok());
|
|
|
|
let play_result = result.unwrap();
|
|
assert!(!play_result.output.is_empty());
|
|
assert!(play_result.output.contains(&script));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_job_logs() {
|
|
let server = create_test_server().await;
|
|
|
|
// First create a job
|
|
let job_params = JobParams {
|
|
script: "print('Logs test');".to_string(),
|
|
script_type: ScriptType::OSIS,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(60),
|
|
prerequisites: None,
|
|
};
|
|
|
|
let job_id = server.create_job(job_params).await.unwrap();
|
|
|
|
// Get job logs
|
|
let result = server.get_job_logs(job_id).await;
|
|
assert!(result.is_ok());
|
|
|
|
let logs_result = result.unwrap();
|
|
assert!(!logs_result.logs.is_empty());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_job_builder_integration() {
|
|
// Test that JobBuilder is working correctly with all the fields
|
|
let job_params = JobParams {
|
|
script: "print('JobBuilder test');".to_string(),
|
|
script_type: ScriptType::V,
|
|
caller_id: "test_caller".to_string(),
|
|
context_id: "test_context".to_string(),
|
|
timeout: Some(300),
|
|
prerequisites: Some(vec!["prereq1".to_string(), "prereq2".to_string()]),
|
|
};
|
|
|
|
// Build job using JobBuilder (similar to what the server does)
|
|
let mut builder = JobBuilder::new()
|
|
.caller_id(&job_params.caller_id)
|
|
.context_id(&job_params.context_id)
|
|
.script(&job_params.script)
|
|
.script_type(job_params.script_type);
|
|
|
|
if let Some(timeout_secs) = job_params.timeout {
|
|
builder = builder.timeout(Duration::from_secs(timeout_secs));
|
|
}
|
|
|
|
if let Some(prerequisites) = job_params.prerequisites {
|
|
builder = builder.prerequisites(prerequisites);
|
|
}
|
|
|
|
let job = builder.build();
|
|
assert!(job.is_ok());
|
|
|
|
let job = job.unwrap();
|
|
assert_eq!(job.caller_id, "test_caller");
|
|
assert_eq!(job.context_id, "test_context");
|
|
assert_eq!(job.script, "print('JobBuilder test');");
|
|
assert_eq!(job.script_type, ScriptType::V);
|
|
assert_eq!(job.timeout, Duration::from_secs(300));
|
|
assert_eq!(job.prerequisites, vec!["prereq1".to_string(), "prereq2".to_string()]);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_error_handling() {
|
|
let server = create_test_server().await;
|
|
|
|
// Test getting status for non-existent job
|
|
let result = server.get_job_status("non_existent_job".to_string()).await;
|
|
// Should return an error or handle gracefully
|
|
match result {
|
|
Ok(_) => {
|
|
// Some implementations might return a default status
|
|
},
|
|
Err(error_code) => {
|
|
assert_eq!(error_code, ErrorCode::InvalidParams);
|
|
}
|
|
}
|
|
|
|
// Test getting output for non-existent job
|
|
let result = server.get_job_output("non_existent_job".to_string()).await;
|
|
match result {
|
|
Ok(output) => {
|
|
// Should return "No output available" or similar
|
|
assert!(output.contains("No output available") || output.is_empty());
|
|
},
|
|
Err(error_code) => {
|
|
assert_eq!(error_code, ErrorCode::InvalidParams);
|
|
}
|
|
}
|
|
}
|