- Simplified RunnerConfig to just name, command, and optional env - Removed RunnerType and ProcessManagerType enums - Removed db_path, redis_url, binary_path from config - Made runner name also serve as queue name (no separate queue param) - Added secret-based authentication to all runner management methods - Created comprehensive osiris_openrpc example - Archived old examples to _archive/ - Updated client API to match simplified supervisor interface
		
			
				
	
	
		
			197 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
//! Integration test for the new job API
 | 
						|
//! 
 | 
						|
//! This test demonstrates the complete job lifecycle and validates
 | 
						|
//! that all new API methods work correctly together.
 | 
						|
 | 
						|
use hero_supervisor_openrpc_client::{SupervisorClient, JobBuilder, JobResult};
 | 
						|
use std::time::Duration;
 | 
						|
use tokio::time::sleep;
 | 
						|
 | 
						|
#[tokio::test]
 | 
						|
async fn test_complete_job_lifecycle() -> Result<(), Box<dyn std::error::Error>> {
 | 
						|
    // Skip test if supervisor is not running
 | 
						|
    let client = match SupervisorClient::new("http://localhost:3030") {
 | 
						|
        Ok(c) => c,
 | 
						|
        Err(_) => {
 | 
						|
            println!("Skipping integration test - supervisor not available");
 | 
						|
            return Ok(());
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    // Test connection
 | 
						|
    if client.discover().await.is_err() {
 | 
						|
        println!("Skipping integration test - supervisor not responding");
 | 
						|
        return Ok(());
 | 
						|
    }
 | 
						|
 | 
						|
    let secret = "user-secret-456";
 | 
						|
 | 
						|
    // Test 1: Create job
 | 
						|
    let job = JobBuilder::new()
 | 
						|
        .caller_id("integration_test")
 | 
						|
        .context_id("test_lifecycle")
 | 
						|
        .payload("echo 'Integration test job'")
 | 
						|
        .executor("osis")
 | 
						|
        .runner("osis_runner_1")
 | 
						|
        .timeout(30)
 | 
						|
        .build()?;
 | 
						|
 | 
						|
    let job_id = client.jobs_create(secret, job).await?;
 | 
						|
    assert!(!job_id.is_empty());
 | 
						|
 | 
						|
    // Test 2: Start job
 | 
						|
    client.job_start(secret, &job_id).await?;
 | 
						|
 | 
						|
    // Test 3: Monitor status
 | 
						|
    let mut attempts = 0;
 | 
						|
    let max_attempts = 15; // 15 seconds max
 | 
						|
    let mut final_status = String::new();
 | 
						|
 | 
						|
    while attempts < max_attempts {
 | 
						|
        let status = client.job_status(&job_id).await?;
 | 
						|
        final_status = status.status.clone();
 | 
						|
        
 | 
						|
        if final_status == "completed" || final_status == "failed" || final_status == "timeout" {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        
 | 
						|
        attempts += 1;
 | 
						|
        sleep(Duration::from_secs(1)).await;
 | 
						|
    }
 | 
						|
 | 
						|
    // Test 4: Get result
 | 
						|
    let result = client.job_result(&job_id).await?;
 | 
						|
    match result {
 | 
						|
        JobResult::Success { success: _ } => {
 | 
						|
            assert_eq!(final_status, "completed");
 | 
						|
        },
 | 
						|
        JobResult::Error { error: _ } => {
 | 
						|
            assert!(final_status == "failed" || final_status == "timeout");
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    Ok(())
 | 
						|
}
 | 
						|
 | 
						|
#[tokio::test]
 | 
						|
async fn test_job_run_immediate() -> Result<(), Box<dyn std::error::Error>> {
 | 
						|
    let client = match SupervisorClient::new("http://localhost:3030") {
 | 
						|
        Ok(c) => c,
 | 
						|
        Err(_) => return Ok(()), // Skip if not available
 | 
						|
    };
 | 
						|
 | 
						|
    if client.discover().await.is_err() {
 | 
						|
        return Ok(()); // Skip if not responding
 | 
						|
    }
 | 
						|
 | 
						|
    let secret = "user-secret-456";
 | 
						|
 | 
						|
    let job = JobBuilder::new()
 | 
						|
        .caller_id("integration_test")
 | 
						|
        .context_id("test_immediate")
 | 
						|
        .payload("echo 'Immediate job test'")
 | 
						|
        .executor("osis")
 | 
						|
        .runner("osis_runner_1")
 | 
						|
        .timeout(30)
 | 
						|
        .build()?;
 | 
						|
 | 
						|
    // Test immediate execution
 | 
						|
    let result = client.job_run(secret, job).await?;
 | 
						|
    
 | 
						|
    // Should get either success or error, but not panic
 | 
						|
    match result {
 | 
						|
        JobResult::Success { success } => {
 | 
						|
            assert!(!success.is_empty());
 | 
						|
        },
 | 
						|
        JobResult::Error { error } => {
 | 
						|
            assert!(!error.is_empty());
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    Ok(())
 | 
						|
}
 | 
						|
 | 
						|
#[tokio::test]
 | 
						|
async fn test_jobs_list() -> Result<(), Box<dyn std::error::Error>> {
 | 
						|
    let client = match SupervisorClient::new("http://localhost:3030") {
 | 
						|
        Ok(c) => c,
 | 
						|
        Err(_) => return Ok(()), // Skip if not available
 | 
						|
    };
 | 
						|
 | 
						|
    if client.discover().await.is_err() {
 | 
						|
        return Ok(()); // Skip if not responding
 | 
						|
    }
 | 
						|
 | 
						|
    // Test listing jobs
 | 
						|
    let job_ids = client.jobs_list().await?;
 | 
						|
    
 | 
						|
    // Should return a vector (might be empty)
 | 
						|
    assert!(job_ids.len() >= 0);
 | 
						|
 | 
						|
    Ok(())
 | 
						|
}
 | 
						|
 | 
						|
#[tokio::test]
 | 
						|
async fn test_authentication_errors() -> Result<(), Box<dyn std::error::Error>> {
 | 
						|
    let client = match SupervisorClient::new("http://localhost:3030") {
 | 
						|
        Ok(c) => c,
 | 
						|
        Err(_) => return Ok(()), // Skip if not available
 | 
						|
    };
 | 
						|
 | 
						|
    if client.discover().await.is_err() {
 | 
						|
        return Ok(()); // Skip if not responding
 | 
						|
    }
 | 
						|
 | 
						|
    let invalid_secret = "invalid-secret";
 | 
						|
 | 
						|
    let job = JobBuilder::new()
 | 
						|
        .caller_id("integration_test")
 | 
						|
        .context_id("test_auth")
 | 
						|
        .payload("echo 'Auth test'")
 | 
						|
        .executor("osis")
 | 
						|
        .runner("osis_runner_1")
 | 
						|
        .timeout(30)
 | 
						|
        .build()?;
 | 
						|
 | 
						|
    // Test that invalid secret fails
 | 
						|
    let result = client.jobs_create(invalid_secret, job.clone()).await;
 | 
						|
    assert!(result.is_err());
 | 
						|
 | 
						|
    let result = client.job_run(invalid_secret, job.clone()).await;
 | 
						|
    assert!(result.is_err());
 | 
						|
 | 
						|
    let result = client.job_start(invalid_secret, "fake-job-id").await;
 | 
						|
    assert!(result.is_err());
 | 
						|
 | 
						|
    Ok(())
 | 
						|
}
 | 
						|
 | 
						|
#[tokio::test]
 | 
						|
async fn test_nonexistent_job_operations() -> Result<(), Box<dyn std::error::Error>> {
 | 
						|
    let client = match SupervisorClient::new("http://localhost:3030") {
 | 
						|
        Ok(c) => c,
 | 
						|
        Err(_) => return Ok(()), // Skip if not available
 | 
						|
    };
 | 
						|
 | 
						|
    if client.discover().await.is_err() {
 | 
						|
        return Ok(()); // Skip if not responding
 | 
						|
    }
 | 
						|
 | 
						|
    let fake_job_id = "nonexistent-job-id";
 | 
						|
 | 
						|
    // Test operations on nonexistent job
 | 
						|
    let result = client.job_status(fake_job_id).await;
 | 
						|
    assert!(result.is_err());
 | 
						|
 | 
						|
    let result = client.job_result(fake_job_id).await;
 | 
						|
    assert!(result.is_err());
 | 
						|
 | 
						|
    Ok(())
 | 
						|
}
 | 
						|
 | 
						|
#[tokio::main]
 | 
						|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
 | 
						|
    println!("Integration test example - this would contain test logic");
 | 
						|
    Ok(())
 | 
						|
}
 |