style: format code and reorganize imports across rfsclient codebase
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
use sal_rfs_client::RfsClient;
|
|
||||||
use sal_rfs_client::types::{ClientConfig, Credentials};
|
use sal_rfs_client::types::{ClientConfig, Credentials};
|
||||||
|
use sal_rfs_client::RfsClient;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
@@ -12,10 +12,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}),
|
}),
|
||||||
timeout_seconds: 30,
|
timeout_seconds: 30,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut client = RfsClient::new(config);
|
let mut client = RfsClient::new(config);
|
||||||
println!("Client created with authentication credentials");
|
println!("Client created with authentication credentials");
|
||||||
|
|
||||||
// Authenticate with the server
|
// Authenticate with the server
|
||||||
client.authenticate().await?;
|
client.authenticate().await?;
|
||||||
if client.is_authenticated() {
|
if client.is_authenticated() {
|
||||||
@@ -30,13 +30,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
credentials: None,
|
credentials: None,
|
||||||
timeout_seconds: 30,
|
timeout_seconds: 30,
|
||||||
};
|
};
|
||||||
|
|
||||||
let client_no_auth = RfsClient::new(config_no_auth);
|
let client_no_auth = RfsClient::new(config_no_auth);
|
||||||
println!("Client created without authentication credentials");
|
println!("Client created without authentication credentials");
|
||||||
|
|
||||||
// Check health endpoint (doesn't require authentication)
|
// Check health endpoint (doesn't require authentication)
|
||||||
let health = client_no_auth.health_check().await?;
|
let health = client_no_auth.health_check().await?;
|
||||||
println!("Server health: {:?}", health);
|
println!("Server health: {:?}", health);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
use sal_rfs_client::RfsClient;
|
|
||||||
use sal_rfs_client::types::{ClientConfig, Credentials};
|
|
||||||
use openapi::models::{VerifyBlock, VerifyBlocksRequest};
|
use openapi::models::{VerifyBlock, VerifyBlocksRequest};
|
||||||
|
use sal_rfs_client::types::{ClientConfig, Credentials};
|
||||||
|
use sal_rfs_client::RfsClient;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
@@ -13,45 +13,52 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}),
|
}),
|
||||||
timeout_seconds: 60,
|
timeout_seconds: 60,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut client = RfsClient::new(config);
|
let mut client = RfsClient::new(config);
|
||||||
|
|
||||||
// Authenticate with the server
|
// Authenticate with the server
|
||||||
client.authenticate().await?;
|
client.authenticate().await?;
|
||||||
println!("Authentication successful");
|
println!("Authentication successful");
|
||||||
|
|
||||||
// Create a test file to upload for block testing
|
// Create a test file to upload for block testing
|
||||||
let test_file_path = "/tmp/block_test.txt";
|
let test_file_path = "/tmp/block_test.txt";
|
||||||
let test_content = "This is a test file for RFS client block management";
|
let test_content = "This is a test file for RFS client block management";
|
||||||
std::fs::write(test_file_path, test_content)?;
|
std::fs::write(test_file_path, test_content)?;
|
||||||
println!("Created test file at {}", test_file_path);
|
println!("Created test file at {}", test_file_path);
|
||||||
|
|
||||||
// Upload the file to get blocks
|
// Upload the file to get blocks
|
||||||
println!("Uploading file to get blocks...");
|
println!("Uploading file to get blocks...");
|
||||||
let file_hash = client.upload_file(test_file_path, None).await?;
|
let file_hash = client.upload_file(test_file_path, None).await?;
|
||||||
println!("File uploaded with hash: {}", file_hash);
|
println!("File uploaded with hash: {}", file_hash);
|
||||||
|
|
||||||
// Get blocks by file hash
|
// Get blocks by file hash
|
||||||
println!("Getting blocks for file hash: {}", file_hash);
|
println!("Getting blocks for file hash: {}", file_hash);
|
||||||
let blocks = client.get_blocks_by_hash(&file_hash).await?;
|
let blocks = client.get_blocks_by_hash(&file_hash).await?;
|
||||||
println!("Found {} blocks for the file", blocks.blocks.len());
|
println!("Found {} blocks for the file", blocks.blocks.len());
|
||||||
|
|
||||||
// Print block information
|
// Print block information
|
||||||
for (i, block_data) in blocks.blocks.iter().enumerate() {
|
for (i, block_data) in blocks.blocks.iter().enumerate() {
|
||||||
println!("Block {}: Hash={}, Index={}", i, block_data.hash, block_data.index);
|
println!(
|
||||||
|
"Block {}: Hash={}, Index={}",
|
||||||
|
i, block_data.hash, block_data.index
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify blocks with complete information
|
// Verify blocks with complete information
|
||||||
println!("Verifying blocks...");
|
println!("Verifying blocks...");
|
||||||
|
|
||||||
// Create a list of VerifyBlock objects with complete information
|
// Create a list of VerifyBlock objects with complete information
|
||||||
let verify_blocks = blocks.blocks.iter().map(|block| {
|
let verify_blocks = blocks
|
||||||
VerifyBlock {
|
.blocks
|
||||||
block_hash: block.hash.clone(),
|
.iter()
|
||||||
block_index: block.index,
|
.map(|block| {
|
||||||
file_hash: file_hash.clone(), // Using the actual file hash
|
VerifyBlock {
|
||||||
}
|
block_hash: block.hash.clone(),
|
||||||
}).collect::<Vec<_>>();
|
block_index: block.index,
|
||||||
|
file_hash: file_hash.clone(), // Using the actual file hash
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// Create the request with the complete block information
|
// Create the request with the complete block information
|
||||||
for block in verify_blocks.iter() {
|
for block in verify_blocks.iter() {
|
||||||
@@ -59,27 +66,34 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
println!("Block index: {}", block.block_index);
|
println!("Block index: {}", block.block_index);
|
||||||
println!("File hash: {}", block.file_hash);
|
println!("File hash: {}", block.file_hash);
|
||||||
}
|
}
|
||||||
let request = VerifyBlocksRequest { blocks: verify_blocks };
|
let request = VerifyBlocksRequest {
|
||||||
|
blocks: verify_blocks,
|
||||||
|
};
|
||||||
|
|
||||||
// Send the verification request
|
// Send the verification request
|
||||||
let verify_result = client.verify_blocks(request).await?;
|
let verify_result = client.verify_blocks(request).await?;
|
||||||
println!("Verification result: {} missing blocks", verify_result.missing.len());
|
println!(
|
||||||
|
"Verification result: {} missing blocks",
|
||||||
|
verify_result.missing.len()
|
||||||
|
);
|
||||||
for block in verify_result.missing.iter() {
|
for block in verify_result.missing.iter() {
|
||||||
println!("Missing block: {}", block);
|
println!("Missing block: {}", block);
|
||||||
}
|
}
|
||||||
|
|
||||||
// List blocks (list_blocks_handler)
|
// List blocks (list_blocks_handler)
|
||||||
println!("\n1. Listing all blocks with pagination...");
|
println!("\n1. Listing all blocks with pagination...");
|
||||||
let blocks_list = client.list_blocks(None).await?;
|
let blocks_list = client.list_blocks(None).await?;
|
||||||
println!("Server has {} blocks in total", blocks_list.len());
|
println!("Server has {} blocks in total", blocks_list.len());
|
||||||
if !blocks_list.is_empty() {
|
if !blocks_list.is_empty() {
|
||||||
let first_few = blocks_list.iter().take(3)
|
let first_few = blocks_list
|
||||||
|
.iter()
|
||||||
|
.take(3)
|
||||||
.map(|s| s.as_str())
|
.map(|s| s.as_str())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
println!("First few blocks: {}", first_few);
|
println!("First few blocks: {}", first_few);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a block exists (check_block_handler)
|
// Check if a block exists (check_block_handler)
|
||||||
if !blocks.blocks.is_empty() {
|
if !blocks.blocks.is_empty() {
|
||||||
let block_to_check = &blocks.blocks[0].hash;
|
let block_to_check = &blocks.blocks[0].hash;
|
||||||
@@ -87,15 +101,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let exists = client.check_block(block_to_check).await?;
|
let exists = client.check_block(block_to_check).await?;
|
||||||
println!("Block exists: {}", exists);
|
println!("Block exists: {}", exists);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get block downloads statistics (get_block_downloads_handler)
|
// Get block downloads statistics (get_block_downloads_handler)
|
||||||
if !blocks.blocks.is_empty() {
|
if !blocks.blocks.is_empty() {
|
||||||
let block_to_check = &blocks.blocks[0].hash;
|
let block_to_check = &blocks.blocks[0].hash;
|
||||||
println!("\n3. Getting download statistics for block: {}", block_to_check);
|
println!(
|
||||||
|
"\n3. Getting download statistics for block: {}",
|
||||||
|
block_to_check
|
||||||
|
);
|
||||||
let downloads = client.get_block_downloads(block_to_check).await?;
|
let downloads = client.get_block_downloads(block_to_check).await?;
|
||||||
println!("Block has been downloaded {} times", downloads.downloads_count);
|
println!(
|
||||||
|
"Block has been downloaded {} times",
|
||||||
|
downloads.downloads_count
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a specific block content (get_block_handler)
|
// Get a specific block content (get_block_handler)
|
||||||
if !blocks.blocks.is_empty() {
|
if !blocks.blocks.is_empty() {
|
||||||
let block_to_get = &blocks.blocks[0].hash;
|
let block_to_get = &blocks.blocks[0].hash;
|
||||||
@@ -103,26 +123,31 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let block_content = client.get_block(block_to_get).await?;
|
let block_content = client.get_block(block_to_get).await?;
|
||||||
println!("Retrieved block with {} bytes", block_content.len());
|
println!("Retrieved block with {} bytes", block_content.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get user blocks (get_user_blocks_handler)
|
// Get user blocks (get_user_blocks_handler)
|
||||||
println!("\n6. Listing user blocks...");
|
println!("\n6. Listing user blocks...");
|
||||||
let user_blocks = client.get_user_blocks(Some(1), Some(10)).await?;
|
let user_blocks = client.get_user_blocks(Some(1), Some(10)).await?;
|
||||||
println!("User has {} blocks (showing page 1 with 10 per page)", user_blocks.total);
|
println!(
|
||||||
|
"User has {} blocks (showing page 1 with 10 per page)",
|
||||||
|
user_blocks.total
|
||||||
|
);
|
||||||
for block in user_blocks.blocks.iter().take(3) {
|
for block in user_blocks.blocks.iter().take(3) {
|
||||||
println!(" - Block: {}, Size: {}", block.hash, block.size);
|
println!(" - Block: {}, Size: {}", block.hash, block.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upload a block (upload_block_handler)
|
// Upload a block (upload_block_handler)
|
||||||
println!("\n7. Uploading a new test block...");
|
println!("\n7. Uploading a new test block...");
|
||||||
let test_block_data = b"This is test block data for direct block upload";
|
let test_block_data = b"This is test block data for direct block upload";
|
||||||
let new_file_hash = "test_file_hash_for_block_upload";
|
let new_file_hash = "test_file_hash_for_block_upload";
|
||||||
let block_index = 0;
|
let block_index = 0;
|
||||||
let block_hash = client.upload_block(new_file_hash, block_index, test_block_data.to_vec()).await?;
|
let block_hash = client
|
||||||
|
.upload_block(new_file_hash, block_index, test_block_data.to_vec())
|
||||||
|
.await?;
|
||||||
println!("Uploaded block with hash: {}", block_hash);
|
println!("Uploaded block with hash: {}", block_hash);
|
||||||
|
|
||||||
// Clean up
|
// Clean up
|
||||||
std::fs::remove_file(test_file_path)?;
|
std::fs::remove_file(test_file_path)?;
|
||||||
println!("Test file cleaned up");
|
println!("Test file cleaned up");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
|
use sal_rfs_client::types::{ClientConfig, Credentials, DownloadOptions, UploadOptions};
|
||||||
use sal_rfs_client::RfsClient;
|
use sal_rfs_client::RfsClient;
|
||||||
use sal_rfs_client::types::{ClientConfig, Credentials, UploadOptions, DownloadOptions};
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
@@ -12,53 +12,55 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}),
|
}),
|
||||||
timeout_seconds: 60,
|
timeout_seconds: 60,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut client = RfsClient::new(config);
|
let mut client = RfsClient::new(config);
|
||||||
|
|
||||||
// Authenticate with the server
|
// Authenticate with the server
|
||||||
client.authenticate().await?;
|
client.authenticate().await?;
|
||||||
println!("Authentication successful");
|
println!("Authentication successful");
|
||||||
|
|
||||||
// Create a test file to upload
|
// Create a test file to upload
|
||||||
let test_file_path = "/tmp/test_upload.txt";
|
let test_file_path = "/tmp/test_upload.txt";
|
||||||
std::fs::write(test_file_path, "This is a test file for RFS client upload")?;
|
std::fs::write(test_file_path, "This is a test file for RFS client upload")?;
|
||||||
println!("Created test file at {}", test_file_path);
|
println!("Created test file at {}", test_file_path);
|
||||||
|
|
||||||
// Upload the file with options
|
// Upload the file with options
|
||||||
println!("Uploading file...");
|
println!("Uploading file...");
|
||||||
let upload_options = UploadOptions {
|
let upload_options = UploadOptions {
|
||||||
chunk_size: Some(1024 * 1024), // 1MB chunks
|
chunk_size: Some(1024 * 1024), // 1MB chunks
|
||||||
verify: true,
|
verify: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
let file_hash = client.upload_file(test_file_path, Some(upload_options)).await?;
|
let file_hash = client
|
||||||
|
.upload_file(test_file_path, Some(upload_options))
|
||||||
|
.await?;
|
||||||
println!("File uploaded with hash: {}", file_hash);
|
println!("File uploaded with hash: {}", file_hash);
|
||||||
|
|
||||||
// Download the file
|
// Download the file
|
||||||
let download_path = "/tmp/test_download.txt";
|
let download_path = "/tmp/test_download.txt";
|
||||||
println!("Downloading file to {}...", download_path);
|
println!("Downloading file to {}...", download_path);
|
||||||
|
|
||||||
let download_options = DownloadOptions {
|
let download_options = DownloadOptions { verify: true };
|
||||||
verify: true,
|
|
||||||
};
|
client
|
||||||
|
.download_file(&file_hash, download_path, Some(download_options))
|
||||||
client.download_file(&file_hash, download_path, Some(download_options)).await?;
|
.await?;
|
||||||
println!("File downloaded to {}", download_path);
|
println!("File downloaded to {}", download_path);
|
||||||
|
|
||||||
// Verify the downloaded file matches the original
|
// Verify the downloaded file matches the original
|
||||||
let original_content = std::fs::read_to_string(test_file_path)?;
|
let original_content = std::fs::read_to_string(test_file_path)?;
|
||||||
let downloaded_content = std::fs::read_to_string(download_path)?;
|
let downloaded_content = std::fs::read_to_string(download_path)?;
|
||||||
|
|
||||||
if original_content == downloaded_content {
|
if original_content == downloaded_content {
|
||||||
println!("File contents match! Download successful.");
|
println!("File contents match! Download successful.");
|
||||||
} else {
|
} else {
|
||||||
println!("ERROR: File contents do not match!");
|
println!("ERROR: File contents do not match!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up test files
|
// Clean up test files
|
||||||
std::fs::remove_file(test_file_path)?;
|
std::fs::remove_file(test_file_path)?;
|
||||||
std::fs::remove_file(download_path)?;
|
std::fs::remove_file(download_path)?;
|
||||||
println!("Test files cleaned up");
|
println!("Test files cleaned up");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
use sal_rfs_client::RfsClient;
|
|
||||||
use sal_rfs_client::types::{ClientConfig, Credentials, FlistOptions, WaitOptions};
|
use sal_rfs_client::types::{ClientConfig, Credentials, FlistOptions, WaitOptions};
|
||||||
|
use sal_rfs_client::RfsClient;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
@@ -13,17 +13,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}),
|
}),
|
||||||
timeout_seconds: 60,
|
timeout_seconds: 60,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut client = RfsClient::new(config);
|
let mut client = RfsClient::new(config);
|
||||||
|
|
||||||
// Authenticate with the server
|
// Authenticate with the server
|
||||||
client.authenticate().await?;
|
client.authenticate().await?;
|
||||||
println!("Authentication successful");
|
println!("Authentication successful");
|
||||||
|
|
||||||
println!("\n1. CREATE FLIST - Creating an FList from a Docker image");
|
println!("\n1. CREATE FLIST - Creating an FList from a Docker image");
|
||||||
let image_name = "alpine:latest";
|
let image_name = "alpine:latest";
|
||||||
println!("Creating FList for image: {}", image_name);
|
println!("Creating FList for image: {}", image_name);
|
||||||
|
|
||||||
// Use FlistOptions to specify additional parameters
|
// Use FlistOptions to specify additional parameters
|
||||||
let options = FlistOptions {
|
let options = FlistOptions {
|
||||||
auth: None,
|
auth: None,
|
||||||
@@ -34,13 +34,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
identity_token: None,
|
identity_token: None,
|
||||||
registry_token: None,
|
registry_token: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the FList and handle potential conflict error
|
// Create the FList and handle potential conflict error
|
||||||
let job_id = match client.create_flist(&image_name, Some(options)).await {
|
let job_id = match client.create_flist(&image_name, Some(options)).await {
|
||||||
Ok(id) => {
|
Ok(id) => {
|
||||||
println!("FList creation started with job ID: {}", id);
|
println!("FList creation started with job ID: {}", id);
|
||||||
Some(id)
|
Some(id)
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if e.to_string().contains("Conflict") {
|
if e.to_string().contains("Conflict") {
|
||||||
println!("FList already exists");
|
println!("FList already exists");
|
||||||
@@ -50,51 +50,55 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 2. Check FList state if we have a job ID
|
// 2. Check FList state if we have a job ID
|
||||||
if let Some(job_id) = &job_id {
|
if let Some(job_id) = &job_id {
|
||||||
println!("\n2. GET FLIST STATE - Checking FList creation state");
|
println!("\n2. GET FLIST STATE - Checking FList creation state");
|
||||||
let state = client.get_flist_state(job_id).await?;
|
let state = client.get_flist_state(job_id).await?;
|
||||||
println!("Current FList state: {:?}", state.flist_state);
|
println!("Current FList state: {:?}", state.flist_state);
|
||||||
|
|
||||||
// 3. Wait for FList creation with progress reporting
|
// 3. Wait for FList creation with progress reporting
|
||||||
println!("\n3. WAIT FOR FLIST CREATION - Waiting for FList to be created with progress reporting");
|
println!("\n3. WAIT FOR FLIST CREATION - Waiting for FList to be created with progress reporting");
|
||||||
let wait_options = WaitOptions {
|
let wait_options = WaitOptions {
|
||||||
timeout_seconds: 60, // Shorter timeout for the example
|
timeout_seconds: 60, // Shorter timeout for the example
|
||||||
poll_interval_ms: 1000,
|
poll_interval_ms: 1000,
|
||||||
progress_callback: Some(Box::new(|state| {
|
progress_callback: Some(Box::new(|state| {
|
||||||
println!("Progress: FList state is now {:?}", state);
|
println!("Progress: FList state is now {:?}", state);
|
||||||
// No return value needed (returns unit type)
|
// No return value needed (returns unit type)
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wait for the FList to be created (with a timeout)
|
// Wait for the FList to be created (with a timeout)
|
||||||
match client.wait_for_flist_creation(job_id, Some(wait_options)).await {
|
match client
|
||||||
|
.wait_for_flist_creation(job_id, Some(wait_options))
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(final_state) => {
|
Ok(final_state) => {
|
||||||
println!("FList creation completed with state: {:?}", final_state);
|
println!("FList creation completed with state: {:?}", final_state);
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error waiting for FList creation: {}", e);
|
println!("Error waiting for FList creation: {}", e);
|
||||||
// Continue with the example even if waiting fails
|
// Continue with the example even if waiting fails
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. List all available FLists
|
// 4. List all available FLists
|
||||||
println!("\n4. LIST FLISTS - Listing all available FLists");
|
println!("\n4. LIST FLISTS - Listing all available FLists");
|
||||||
|
|
||||||
// Variable to store the FList path for preview and download
|
// Variable to store the FList path for preview and download
|
||||||
let mut flist_path_for_preview: Option<String> = None;
|
let mut flist_path_for_preview: Option<String> = None;
|
||||||
|
|
||||||
match client.list_flists().await {
|
match client.list_flists().await {
|
||||||
Ok(flists) => {
|
Ok(flists) => {
|
||||||
println!("Found {} FList categories", flists.len());
|
println!("Found {} FList categories", flists.len());
|
||||||
|
|
||||||
for (category, files) in &flists {
|
for (category, files) in &flists {
|
||||||
println!("Category: {}", category);
|
println!("Category: {}", category);
|
||||||
for file in files.iter().take(2) { // Show only first 2 files per category
|
for file in files.iter().take(2) {
|
||||||
|
// Show only first 2 files per category
|
||||||
println!(" - {} (size: {} bytes)", file.name, file.size);
|
println!(" - {} (size: {} bytes)", file.name, file.size);
|
||||||
|
|
||||||
// Save the first FList path for preview
|
// Save the first FList path for preview
|
||||||
if flist_path_for_preview.is_none() {
|
if flist_path_for_preview.is_none() {
|
||||||
let path = format!("{}/{}/{}", parent_dir, category, file.name);
|
let path = format!("{}/{}/{}", parent_dir, category, file.name);
|
||||||
@@ -105,7 +109,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
println!(" - ... and {} more files", files.len() - 2);
|
println!(" - ... and {} more files", files.len() - 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Preview an FList if we found one
|
// 5. Preview an FList if we found one
|
||||||
if let Some(ref flist_path) = flist_path_for_preview {
|
if let Some(ref flist_path) = flist_path_for_preview {
|
||||||
println!("\n5. PREVIEW FLIST - Previewing FList: {}", flist_path);
|
println!("\n5. PREVIEW FLIST - Previewing FList: {}", flist_path);
|
||||||
@@ -114,57 +118,59 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
println!("FList preview for {}:", flist_path);
|
println!("FList preview for {}:", flist_path);
|
||||||
println!(" - Checksum: {}", preview.checksum);
|
println!(" - Checksum: {}", preview.checksum);
|
||||||
println!(" - Metadata: {}", preview.metadata);
|
println!(" - Metadata: {}", preview.metadata);
|
||||||
|
|
||||||
// Display content (list of strings)
|
// Display content (list of strings)
|
||||||
if !preview.content.is_empty() {
|
if !preview.content.is_empty() {
|
||||||
println!(" - Content entries:");
|
println!(" - Content entries:");
|
||||||
for (i, entry) in preview.content.iter().enumerate().take(5) {
|
for (i, entry) in preview.content.iter().enumerate().take(5) {
|
||||||
println!(" {}. {}", i+1, entry);
|
println!(" {}. {}", i + 1, entry);
|
||||||
}
|
}
|
||||||
if preview.content.len() > 5 {
|
if preview.content.len() > 5 {
|
||||||
println!(" ... and {} more entries", preview.content.len() - 5);
|
println!(" ... and {} more entries", preview.content.len() - 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(e) => println!("Error previewing FList: {}", e),
|
Err(e) => println!("Error previewing FList: {}", e),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("No FLists available for preview");
|
println!("No FLists available for preview");
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(e) => println!("Error listing FLists: {}", e),
|
Err(e) => println!("Error listing FLists: {}", e),
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. DOWNLOAD FLIST - Downloading an FList to a local file
|
// 6. DOWNLOAD FLIST - Downloading an FList to a local file
|
||||||
if let Some(ref flist_path) = flist_path_for_preview {
|
if let Some(ref flist_path) = flist_path_for_preview {
|
||||||
println!("\n6. DOWNLOAD FLIST - Downloading FList: {}", flist_path);
|
println!("\n6. DOWNLOAD FLIST - Downloading FList: {}", flist_path);
|
||||||
|
|
||||||
// Create a temporary output path for the downloaded FList
|
// Create a temporary output path for the downloaded FList
|
||||||
let output_path = "/tmp/downloaded_flist.fl";
|
let output_path = "/tmp/downloaded_flist.fl";
|
||||||
|
|
||||||
match client.download_flist(flist_path, output_path).await {
|
match client.download_flist(flist_path, output_path).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("FList successfully downloaded to {}", output_path);
|
println!("FList successfully downloaded to {}", output_path);
|
||||||
|
|
||||||
// Get file size
|
// Get file size
|
||||||
match std::fs::metadata(output_path) {
|
match std::fs::metadata(output_path) {
|
||||||
Ok(metadata) => println!("Downloaded file size: {} bytes", metadata.len()),
|
Ok(metadata) => println!("Downloaded file size: {} bytes", metadata.len()),
|
||||||
Err(e) => println!("Error getting file metadata: {}", e),
|
Err(e) => println!("Error getting file metadata: {}", e),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(e) => println!("Error downloading FList: {}", e),
|
Err(e) => println!("Error downloading FList: {}", e),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("\n6. DOWNLOAD FLIST - No FList available for download");
|
println!("\n6. DOWNLOAD FLIST - No FList available for download");
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("\nAll FList operations demonstrated:");
|
println!("\nAll FList operations demonstrated:");
|
||||||
println!("1. create_flist - Create a new FList from a Docker image");
|
println!("1. create_flist - Create a new FList from a Docker image");
|
||||||
println!("2. get_flist_state - Check the state of an FList creation job");
|
println!("2. get_flist_state - Check the state of an FList creation job");
|
||||||
println!("3. wait_for_flist_creation - Wait for an FList to be created with progress reporting");
|
println!(
|
||||||
|
"3. wait_for_flist_creation - Wait for an FList to be created with progress reporting"
|
||||||
|
);
|
||||||
println!("4. list_flists - List all available FLists");
|
println!("4. list_flists - List all available FLists");
|
||||||
println!("5. preview_flist - Preview the content of an FList");
|
println!("5. preview_flist - Preview the content of an FList");
|
||||||
println!("6. download_flist - Download an FList to a local file");
|
println!("6. download_flist - Download an FList to a local file");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
use sal_rfs_client::RfsClient;
|
|
||||||
use sal_rfs_client::types::{ClientConfig, Credentials, WaitOptions};
|
|
||||||
use openapi::models::FlistState;
|
use openapi::models::FlistState;
|
||||||
|
use sal_rfs_client::types::{ClientConfig, Credentials, WaitOptions};
|
||||||
|
use sal_rfs_client::RfsClient;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
@@ -13,49 +13,52 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}),
|
}),
|
||||||
timeout_seconds: 60,
|
timeout_seconds: 60,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut client = RfsClient::new(config);
|
let mut client = RfsClient::new(config);
|
||||||
|
|
||||||
// Authenticate with the server
|
// Authenticate with the server
|
||||||
client.authenticate().await?;
|
client.authenticate().await?;
|
||||||
println!("Authentication successful");
|
println!("Authentication successful");
|
||||||
|
|
||||||
// Create an FList from a Docker image
|
// Create an FList from a Docker image
|
||||||
let image_name = "redis:latest";
|
let image_name = "redis:latest";
|
||||||
println!("Creating FList for image: {}", image_name);
|
println!("Creating FList for image: {}", image_name);
|
||||||
|
|
||||||
let job_id = client.create_flist(&image_name, None).await?;
|
let job_id = client.create_flist(&image_name, None).await?;
|
||||||
println!("FList creation started with job ID: {}", job_id);
|
println!("FList creation started with job ID: {}", job_id);
|
||||||
|
|
||||||
// Set up options for waiting with progress reporting
|
// Set up options for waiting with progress reporting
|
||||||
let options = WaitOptions {
|
let options = WaitOptions {
|
||||||
timeout_seconds: 600, // 10 minutes timeout
|
timeout_seconds: 600, // 10 minutes timeout
|
||||||
poll_interval_ms: 2000, // Check every 2 seconds
|
poll_interval_ms: 2000, // Check every 2 seconds
|
||||||
progress_callback: Some(Box::new(|state| {
|
progress_callback: Some(Box::new(|state| match state {
|
||||||
match state {
|
FlistState::FlistStateInProgress(info) => {
|
||||||
FlistState::FlistStateInProgress(info) => {
|
println!(
|
||||||
println!("Progress: {:.1}% - {}", info.in_progress.progress, info.in_progress.msg);
|
"Progress: {:.1}% - {}",
|
||||||
},
|
info.in_progress.progress, info.in_progress.msg
|
||||||
FlistState::FlistStateStarted(_) => {
|
);
|
||||||
println!("FList creation started...");
|
|
||||||
},
|
|
||||||
FlistState::FlistStateAccepted(_) => {
|
|
||||||
println!("FList creation request accepted...");
|
|
||||||
},
|
|
||||||
_ => println!("State: {:?}", state),
|
|
||||||
}
|
}
|
||||||
|
FlistState::FlistStateStarted(_) => {
|
||||||
|
println!("FList creation started...");
|
||||||
|
}
|
||||||
|
FlistState::FlistStateAccepted(_) => {
|
||||||
|
println!("FList creation request accepted...");
|
||||||
|
}
|
||||||
|
_ => println!("State: {:?}", state),
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wait for the FList to be created
|
// Wait for the FList to be created
|
||||||
println!("Waiting for FList creation to complete...");
|
println!("Waiting for FList creation to complete...");
|
||||||
|
|
||||||
// Use ? operator to propagate errors properly
|
// Use ? operator to propagate errors properly
|
||||||
let state = client.wait_for_flist_creation(&job_id, Some(options)).await
|
let state = client
|
||||||
|
.wait_for_flist_creation(&job_id, Some(options))
|
||||||
|
.await
|
||||||
.map_err(|e| -> Box<dyn std::error::Error> { Box::new(e) })?;
|
.map_err(|e| -> Box<dyn std::error::Error> { Box::new(e) })?;
|
||||||
|
|
||||||
println!("FList created successfully!");
|
println!("FList created successfully!");
|
||||||
println!("Final state: {:?}", state);
|
println!("Final state: {:?}", state);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@@ -1,24 +1,23 @@
|
|||||||
|
use bytes::Bytes;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::collections::HashMap;
|
|
||||||
use bytes::Bytes;
|
|
||||||
|
|
||||||
use openapi::{
|
use openapi::{
|
||||||
apis::{
|
apis::{
|
||||||
authentication_api, block_management_api, flist_management_api,
|
authentication_api, block_management_api, configuration::Configuration,
|
||||||
file_management_api, system_api, website_serving_api,
|
file_management_api, flist_management_api, system_api, website_serving_api,
|
||||||
configuration::Configuration,
|
|
||||||
Error as OpenApiError,
|
Error as OpenApiError,
|
||||||
},
|
},
|
||||||
models::{
|
models::{
|
||||||
SignInBody, ListBlocksParams,
|
BlockDownloadsResponse, BlocksResponse, FileInfo, FlistBody, FlistState,
|
||||||
VerifyBlocksRequest, VerifyBlocksResponse, FlistBody, UserBlocksResponse, BlockDownloadsResponse,
|
FlistStateResponse, ListBlocksParams, PreviewResponse, SignInBody, UserBlocksResponse,
|
||||||
BlocksResponse, PreviewResponse, FileInfo, FlistState, FlistStateResponse,
|
VerifyBlocksRequest, VerifyBlocksResponse,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::error::{RfsError, Result, map_openapi_error};
|
use crate::error::{map_openapi_error, Result, RfsError};
|
||||||
use crate::types::{ClientConfig, UploadOptions, DownloadOptions, FlistOptions, WaitOptions};
|
use crate::types::{ClientConfig, DownloadOptions, FlistOptions, UploadOptions, WaitOptions};
|
||||||
|
|
||||||
/// Main client for interacting with the RFS server
|
/// Main client for interacting with the RFS server
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -33,16 +32,18 @@ impl RfsClient {
|
|||||||
pub fn new(client_config: ClientConfig) -> Self {
|
pub fn new(client_config: ClientConfig) -> Self {
|
||||||
// Create a custom reqwest client with timeout configuration
|
// Create a custom reqwest client with timeout configuration
|
||||||
let client = reqwest::Client::builder()
|
let client = reqwest::Client::builder()
|
||||||
.timeout(std::time::Duration::from_secs(client_config.timeout_seconds))
|
.timeout(std::time::Duration::from_secs(
|
||||||
|
client_config.timeout_seconds,
|
||||||
|
))
|
||||||
.build()
|
.build()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
// Create OpenAPI configuration with our custom client
|
// Create OpenAPI configuration with our custom client
|
||||||
let mut config = Configuration::new();
|
let mut config = Configuration::new();
|
||||||
config.base_path = client_config.base_url.clone();
|
config.base_path = client_config.base_url.clone();
|
||||||
config.user_agent = Some(format!("rfs-client/0.1.0"));
|
config.user_agent = Some("rfs-client/0.1.0".to_string());
|
||||||
config.client = client;
|
config.client = client;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
config: Arc::new(config),
|
config: Arc::new(config),
|
||||||
client_config,
|
client_config,
|
||||||
@@ -70,22 +71,26 @@ impl RfsClient {
|
|||||||
if let Some(token) = Some(result.access_token) {
|
if let Some(token) = Some(result.access_token) {
|
||||||
// Create a custom reqwest client with timeout configuration
|
// Create a custom reqwest client with timeout configuration
|
||||||
let client = reqwest::Client::builder()
|
let client = reqwest::Client::builder()
|
||||||
.timeout(std::time::Duration::from_secs(self.client_config.timeout_seconds))
|
.timeout(std::time::Duration::from_secs(
|
||||||
|
self.client_config.timeout_seconds,
|
||||||
|
))
|
||||||
.build()
|
.build()
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
// Create a new configuration with the auth token and timeout
|
// Create a new configuration with the auth token and timeout
|
||||||
let mut new_config = Configuration::new();
|
let mut new_config = Configuration::new();
|
||||||
new_config.base_path = self.client_config.base_url.clone();
|
new_config.base_path = self.client_config.base_url.clone();
|
||||||
new_config.user_agent = Some(format!("rfs-client/0.1.0"));
|
new_config.user_agent = Some("rfs-client/0.1.0".to_string());
|
||||||
new_config.bearer_access_token = Some(token.clone());
|
new_config.bearer_access_token = Some(token.clone());
|
||||||
new_config.client = client;
|
new_config.client = client;
|
||||||
|
|
||||||
self.config = Arc::new(new_config);
|
self.config = Arc::new(new_config);
|
||||||
self.auth_token = Some(token);
|
self.auth_token = Some(token);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(RfsError::AuthError("No token received from server".to_string()))
|
Err(RfsError::AuthError(
|
||||||
|
"No token received from server".to_string(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(RfsError::AuthError("No credentials provided".to_string()))
|
Err(RfsError::AuthError("No credentials provided".to_string()))
|
||||||
@@ -102,62 +107,79 @@ impl RfsClient {
|
|||||||
let result = system_api::health_check_handler(&self.config)
|
let result = system_api::health_check_handler(&self.config)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result.msg)
|
Ok(result.msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Upload a file to the RFS server
|
/// Upload a file to the RFS server
|
||||||
pub async fn upload_file<P: AsRef<Path>>(&self, file_path: P, options: Option<UploadOptions>) -> Result<String> {
|
pub async fn upload_file<P: AsRef<Path>>(
|
||||||
|
&self,
|
||||||
|
file_path: P,
|
||||||
|
options: Option<UploadOptions>,
|
||||||
|
) -> Result<String> {
|
||||||
let file_path = file_path.as_ref();
|
let file_path = file_path.as_ref();
|
||||||
let _options = options.unwrap_or_default();
|
let _options = options.unwrap_or_default();
|
||||||
|
|
||||||
// Check if file exists
|
// Check if file exists
|
||||||
if !file_path.exists() {
|
if !file_path.exists() {
|
||||||
return Err(RfsError::FileSystemError(format!("File not found: {}", file_path.display())));
|
return Err(RfsError::FileSystemError(format!(
|
||||||
|
"File not found: {}",
|
||||||
|
file_path.display()
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the OpenAPI client to upload the file
|
// Use the OpenAPI client to upload the file
|
||||||
let result = file_management_api::upload_file_handler(&self.config, file_path.to_path_buf())
|
let result =
|
||||||
.await
|
file_management_api::upload_file_handler(&self.config, file_path.to_path_buf())
|
||||||
.map_err(map_openapi_error)?;
|
.await
|
||||||
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
// Extract the file hash from the response
|
// Extract the file hash from the response
|
||||||
Ok(result.file_hash.clone())
|
Ok(result.file_hash.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Download a file from the RFS server
|
/// Download a file from the RFS server
|
||||||
pub async fn download_file<P: AsRef<Path>>(&self, file_id: &str, output_path: P, options: Option<DownloadOptions>) -> Result<()> {
|
pub async fn download_file<P: AsRef<Path>>(
|
||||||
|
&self,
|
||||||
|
file_id: &str,
|
||||||
|
output_path: P,
|
||||||
|
options: Option<DownloadOptions>,
|
||||||
|
) -> Result<()> {
|
||||||
let output_path = output_path.as_ref();
|
let output_path = output_path.as_ref();
|
||||||
let _options = options.unwrap_or_default();
|
let _options = options.unwrap_or_default();
|
||||||
|
|
||||||
// Create parent directories if needed
|
// Create parent directories if needed
|
||||||
if let Some(parent) = output_path.parent() {
|
if let Some(parent) = output_path.parent() {
|
||||||
std::fs::create_dir_all(parent)
|
std::fs::create_dir_all(parent).map_err(|e| {
|
||||||
.map_err(|e| RfsError::FileSystemError(format!("Failed to create directory: {}", e)))?;
|
RfsError::FileSystemError(format!("Failed to create directory: {}", e))
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a FileDownloadRequest with the filename from the output path
|
// Create a FileDownloadRequest with the filename from the output path
|
||||||
let file_name = output_path.file_name()
|
let file_name = output_path
|
||||||
|
.file_name()
|
||||||
.and_then(|n| n.to_str())
|
.and_then(|n| n.to_str())
|
||||||
.unwrap_or("downloaded_file")
|
.unwrap_or("downloaded_file")
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
let download_request = openapi::models::FileDownloadRequest::new(file_name);
|
let download_request = openapi::models::FileDownloadRequest::new(file_name);
|
||||||
|
|
||||||
// Download the file
|
// Download the file
|
||||||
let response = file_management_api::get_file_handler(&self.config, file_id, download_request)
|
let response =
|
||||||
.await
|
file_management_api::get_file_handler(&self.config, file_id, download_request)
|
||||||
.map_err(map_openapi_error)?;
|
.await
|
||||||
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
// Read the response body
|
// Read the response body
|
||||||
let bytes = response.bytes()
|
let bytes = response
|
||||||
|
.bytes()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| RfsError::RequestError(e))?;
|
.map_err(RfsError::RequestError)?;
|
||||||
|
|
||||||
// Write the file to disk
|
// Write the file to disk
|
||||||
std::fs::write(output_path, bytes)
|
std::fs::write(output_path, bytes)
|
||||||
.map_err(|e| RfsError::FileSystemError(format!("Failed to write file: {}", e)))?;
|
.map_err(|e| RfsError::FileSystemError(format!("Failed to write file: {}", e)))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,29 +190,38 @@ impl RfsClient {
|
|||||||
let result = block_management_api::list_blocks_handler(&self.config, page, per_page)
|
let result = block_management_api::list_blocks_handler(&self.config, page, per_page)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result.blocks)
|
Ok(result.blocks)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify blocks
|
/// Verify blocks
|
||||||
pub async fn verify_blocks(&self, request: VerifyBlocksRequest) -> Result<VerifyBlocksResponse> {
|
pub async fn verify_blocks(
|
||||||
|
&self,
|
||||||
|
request: VerifyBlocksRequest,
|
||||||
|
) -> Result<VerifyBlocksResponse> {
|
||||||
let result = block_management_api::verify_blocks_handler(&self.config, request)
|
let result = block_management_api::verify_blocks_handler(&self.config, request)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new FList from a Docker image
|
/// Create a new FList from a Docker image
|
||||||
pub async fn create_flist(&self, image_name: &str, options: Option<FlistOptions>) -> Result<String> {
|
pub async fn create_flist(
|
||||||
|
&self,
|
||||||
|
image_name: &str,
|
||||||
|
options: Option<FlistOptions>,
|
||||||
|
) -> Result<String> {
|
||||||
// Ensure the client is authenticated
|
// Ensure the client is authenticated
|
||||||
if !self.is_authenticated() {
|
if !self.is_authenticated() {
|
||||||
return Err(RfsError::AuthError("Authentication required for creating FLists".to_string()));
|
return Err(RfsError::AuthError(
|
||||||
|
"Authentication required for creating FLists".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create FList body with the required fields
|
// Create FList body with the required fields
|
||||||
let mut flist = FlistBody::new(image_name.to_string());
|
let mut flist = FlistBody::new(image_name.to_string());
|
||||||
|
|
||||||
// Apply options if provided
|
// Apply options if provided
|
||||||
if let Some(opts) = options {
|
if let Some(opts) = options {
|
||||||
flist.username = opts.username.map(Some);
|
flist.username = opts.username.map(Some);
|
||||||
@@ -201,12 +232,12 @@ impl RfsClient {
|
|||||||
flist.identity_token = opts.identity_token.map(Some);
|
flist.identity_token = opts.identity_token.map(Some);
|
||||||
flist.registry_token = opts.registry_token.map(Some);
|
flist.registry_token = opts.registry_token.map(Some);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the API to create the FList
|
// Call the API to create the FList
|
||||||
let result = flist_management_api::create_flist_handler(&self.config, flist)
|
let result = flist_management_api::create_flist_handler(&self.config, flist)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
// Return the job ID
|
// Return the job ID
|
||||||
Ok(result.id)
|
Ok(result.id)
|
||||||
}
|
}
|
||||||
@@ -215,66 +246,80 @@ impl RfsClient {
|
|||||||
pub async fn get_flist_state(&self, job_id: &str) -> Result<FlistStateResponse> {
|
pub async fn get_flist_state(&self, job_id: &str) -> Result<FlistStateResponse> {
|
||||||
// Ensure the client is authenticated
|
// Ensure the client is authenticated
|
||||||
if !self.is_authenticated() {
|
if !self.is_authenticated() {
|
||||||
return Err(RfsError::AuthError("Authentication required for accessing FList state".to_string()));
|
return Err(RfsError::AuthError(
|
||||||
|
"Authentication required for accessing FList state".to_string(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call the API to get the FList state
|
// Call the API to get the FList state
|
||||||
let result = flist_management_api::get_flist_state_handler(&self.config, job_id)
|
let result = flist_management_api::get_flist_state_handler(&self.config, job_id)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for an FList to be created
|
/// Wait for an FList to be created
|
||||||
///
|
///
|
||||||
/// This method polls the FList state until it reaches a terminal state (Created or Failed)
|
/// This method polls the FList state until it reaches a terminal state (Created or Failed)
|
||||||
/// or until the timeout is reached.
|
/// or until the timeout is reached.
|
||||||
pub async fn wait_for_flist_creation(&self, job_id: &str, options: Option<WaitOptions>) -> Result<FlistStateResponse> {
|
pub async fn wait_for_flist_creation(
|
||||||
|
&self,
|
||||||
|
job_id: &str,
|
||||||
|
options: Option<WaitOptions>,
|
||||||
|
) -> Result<FlistStateResponse> {
|
||||||
let options = options.unwrap_or_default();
|
let options = options.unwrap_or_default();
|
||||||
let deadline = std::time::Instant::now() + std::time::Duration::from_secs(options.timeout_seconds);
|
let deadline =
|
||||||
|
std::time::Instant::now() + std::time::Duration::from_secs(options.timeout_seconds);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Check if we've exceeded the timeout
|
// Check if we've exceeded the timeout
|
||||||
if std::time::Instant::now() > deadline {
|
if std::time::Instant::now() > deadline {
|
||||||
return Err(RfsError::TimeoutError(format!(
|
return Err(RfsError::TimeoutError(format!(
|
||||||
"Timed out waiting for FList creation after {} seconds",
|
"Timed out waiting for FList creation after {} seconds",
|
||||||
options.timeout_seconds
|
options.timeout_seconds
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current state
|
// Get the current state
|
||||||
let state_result = self.get_flist_state(job_id).await;
|
let state_result = self.get_flist_state(job_id).await;
|
||||||
|
|
||||||
match state_result {
|
match state_result {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
// Call progress callback if provided
|
// Call progress callback if provided
|
||||||
if let Some(ref callback) = options.progress_callback {
|
if let Some(ref callback) = options.progress_callback {
|
||||||
callback(state.flist_state.as_ref());
|
callback(state.flist_state.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we've reached a terminal state
|
// Check if we've reached a terminal state
|
||||||
match state.flist_state.as_ref() {
|
match state.flist_state.as_ref() {
|
||||||
FlistState::FlistStateCreated(_) => {
|
FlistState::FlistStateCreated(_) => {
|
||||||
// Success! FList was created
|
// Success! FList was created
|
||||||
return Ok(state);
|
return Ok(state);
|
||||||
},
|
}
|
||||||
FlistState::FlistStateFailed(error_msg) => {
|
FlistState::FlistStateFailed(error_msg) => {
|
||||||
// Failure! FList creation failed
|
// Failure! FList creation failed
|
||||||
return Err(RfsError::FListError(format!("FList creation failed: {}", error_msg)));
|
return Err(RfsError::FListError(format!(
|
||||||
},
|
"FList creation failed: {}",
|
||||||
|
error_msg
|
||||||
|
)));
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Still in progress, continue polling
|
// Still in progress, continue polling
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(options.poll_interval_ms)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(
|
||||||
|
options.poll_interval_ms,
|
||||||
|
))
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// If we get a 404 error, it might be because the FList job is still initializing
|
// If we get a 404 error, it might be because the FList job is still initializing
|
||||||
// Just wait and retry
|
// Just wait and retry
|
||||||
println!("Warning: Error checking FList state: {}", e);
|
println!("Warning: Error checking FList state: {}", e);
|
||||||
println!("Retrying in {} ms...", options.poll_interval_ms);
|
println!("Retrying in {} ms...", options.poll_interval_ms);
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(options.poll_interval_ms)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(options.poll_interval_ms))
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,7 +339,7 @@ impl RfsClient {
|
|||||||
let result = block_management_api::get_block_downloads_handler(&self.config, hash)
|
let result = block_management_api::get_block_downloads_handler(&self.config, hash)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,10 +348,12 @@ impl RfsClient {
|
|||||||
let response = block_management_api::get_block_handler(&self.config, hash)
|
let response = block_management_api::get_block_handler(&self.config, hash)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
let bytes = response.bytes().await
|
let bytes = response
|
||||||
.map_err(|e| RfsError::RequestError(e))?;
|
.bytes()
|
||||||
|
.await
|
||||||
|
.map_err(RfsError::RequestError)?;
|
||||||
|
|
||||||
Ok(bytes)
|
Ok(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,16 +362,20 @@ impl RfsClient {
|
|||||||
let result = block_management_api::get_blocks_by_hash_handler(&self.config, hash)
|
let result = block_management_api::get_blocks_by_hash_handler(&self.config, hash)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get blocks uploaded by the current user
|
/// Get blocks uploaded by the current user
|
||||||
pub async fn get_user_blocks(&self, page: Option<i32>, per_page: Option<i32>) -> Result<UserBlocksResponse> {
|
pub async fn get_user_blocks(
|
||||||
|
&self,
|
||||||
|
page: Option<i32>,
|
||||||
|
per_page: Option<i32>,
|
||||||
|
) -> Result<UserBlocksResponse> {
|
||||||
let result = block_management_api::get_user_blocks_handler(&self.config, page, per_page)
|
let result = block_management_api::get_user_blocks_handler(&self.config, page, per_page)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,11 +384,12 @@ impl RfsClient {
|
|||||||
// Create a temporary file to hold the block data
|
// Create a temporary file to hold the block data
|
||||||
let temp_dir = std::env::temp_dir();
|
let temp_dir = std::env::temp_dir();
|
||||||
let temp_file_path = temp_dir.join(format!("{}-{}", file_hash, idx));
|
let temp_file_path = temp_dir.join(format!("{}-{}", file_hash, idx));
|
||||||
|
|
||||||
// Write the data to the temporary file
|
// Write the data to the temporary file
|
||||||
std::fs::write(&temp_file_path, &data)
|
std::fs::write(&temp_file_path, &data).map_err(|e| {
|
||||||
.map_err(|e| RfsError::FileSystemError(format!("Failed to write temporary block file: {}", e)))?;
|
RfsError::FileSystemError(format!("Failed to write temporary block file: {}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
// Upload the block
|
// Upload the block
|
||||||
let result = block_management_api::upload_block_handler(
|
let result = block_management_api::upload_block_handler(
|
||||||
&self.config,
|
&self.config,
|
||||||
@@ -347,12 +399,12 @@ impl RfsClient {
|
|||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
// Clean up the temporary file
|
// Clean up the temporary file
|
||||||
if let Err(e) = std::fs::remove_file(temp_file_path) {
|
if let Err(e) = std::fs::remove_file(temp_file_path) {
|
||||||
eprintln!("Warning: Failed to remove temporary block file: {}", e);
|
eprintln!("Warning: Failed to remove temporary block file: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the hash from the response
|
// Return the hash from the response
|
||||||
Ok(result.hash)
|
Ok(result.hash)
|
||||||
}
|
}
|
||||||
@@ -362,7 +414,7 @@ impl RfsClient {
|
|||||||
let result = flist_management_api::list_flists_handler(&self.config)
|
let result = flist_management_api::list_flists_handler(&self.config)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,7 +423,7 @@ impl RfsClient {
|
|||||||
let result = flist_management_api::preview_flist_handler(&self.config, flist_path)
|
let result = flist_management_api::preview_flist_handler(&self.config, flist_path)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +432,7 @@ impl RfsClient {
|
|||||||
let result = website_serving_api::serve_website_handler(&self.config, website_id, path)
|
let result = website_serving_api::serve_website_handler(&self.config, website_id, path)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,25 +441,30 @@ impl RfsClient {
|
|||||||
let result = system_api::health_check_handler(&self.config)
|
let result = system_api::health_check_handler(&self.config)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
Ok(result.msg)
|
Ok(result.msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Download an FList file
|
/// Download an FList file
|
||||||
///
|
///
|
||||||
/// This method downloads an FList from the server and saves it to the specified path.
|
/// This method downloads an FList from the server and saves it to the specified path.
|
||||||
pub async fn download_flist<P: AsRef<Path>>(&self, flist_path: &str, output_path: P) -> Result<()> {
|
pub async fn download_flist<P: AsRef<Path>>(
|
||||||
|
&self,
|
||||||
|
flist_path: &str,
|
||||||
|
output_path: P,
|
||||||
|
) -> Result<()> {
|
||||||
let response = flist_management_api::serve_flists(&self.config, flist_path)
|
let response = flist_management_api::serve_flists(&self.config, flist_path)
|
||||||
.await
|
.await
|
||||||
.map_err(map_openapi_error)?;
|
.map_err(map_openapi_error)?;
|
||||||
|
|
||||||
let bytes = response.bytes().await
|
let bytes = response
|
||||||
.map_err(|e| RfsError::RequestError(e))?;
|
.bytes()
|
||||||
|
.await
|
||||||
|
.map_err(RfsError::RequestError)?;
|
||||||
|
|
||||||
std::fs::write(output_path, &bytes)
|
std::fs::write(output_path, &bytes)
|
||||||
.map_err(|e| RfsError::FileSystemError(e.to_string()))?;
|
.map_err(|e| RfsError::FileSystemError(e.to_string()))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
153
packages/clients/rfsclient/src/diff.rs
Normal file
153
packages/clients/rfsclient/src/diff.rs
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
diff --git a/packages/clients/rfsclient/src/rhai.rs b/packages/clients/rfsclient/src/rhai.rs
|
||||||
|
index fd686ba..b19c50f 100644
|
||||||
|
--- a/packages/clients/rfsclient/src/rhai.rs
|
||||||
|
+++ b/packages/clients/rfsclient/src/rhai.rs
|
||||||
|
@@ -17,6 +17,14 @@ lazy_static! {
|
||||||
|
static ref RUNTIME: Mutex<Option<Runtime>> = Mutex::new(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/// Overload: list blocks with explicit pagination integers
|
||||||
|
+fn rfs_list_blocks_with_pagination(
|
||||||
|
+ page: rhai::INT,
|
||||||
|
+ per_page: rhai::INT,
|
||||||
|
+) -> Result<String, Box<EvalAltResult>> {
|
||||||
|
+ rfs_list_blocks(Some(page), Some(per_page))
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/// Wrapper around RfsClient to make it thread-safe for global usage
|
||||||
|
struct RfsClientWrapper {
|
||||||
|
client: Mutex<RfsClient>,
|
||||||
|
@@ -47,6 +55,8 @@ pub fn register_rfs_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>
|
||||||
|
|
||||||
|
// Register block management functions
|
||||||
|
engine.register_fn("rfs_list_blocks", rfs_list_blocks);
|
||||||
|
+ // Overload accepting explicit integer pagination params
|
||||||
|
+ engine.register_fn("rfs_list_blocks", rfs_list_blocks_with_pagination);
|
||||||
|
engine.register_fn("rfs_upload_block", rfs_upload_block);
|
||||||
|
engine.register_fn("rfs_check_block", rfs_check_block);
|
||||||
|
engine.register_fn("rfs_get_block_downloads", rfs_get_block_downloads);
|
||||||
|
diff --git a/packages/clients/rfsclient/tests/rhai_integration_tests.rs b/packages/clients/rfsclient/tests/rhai_integration_tests.rs
|
||||||
|
index 2c90001..cc38f4a 100644
|
||||||
|
--- a/packages/clients/rfsclient/tests/rhai_integration_tests.rs
|
||||||
|
+++ b/packages/clients/rfsclient/tests/rhai_integration_tests.rs
|
||||||
|
@@ -114,8 +114,7 @@ fn test_rfs_flist_management_integration() {
|
||||||
|
Err(e) => {
|
||||||
|
let error_msg = e.to_string();
|
||||||
|
println!("FList preview error: {}", error_msg);
|
||||||
|
-
|
||||||
|
- // Check if it's an authentication error (shouldn't happen with valid creds)
|
||||||
|
+ // Authentication should not fail in this integration test
|
||||||
|
if error_msg.contains("Authentication") {
|
||||||
|
panic!("❌ Authentication should work with valid credentials: {}", error_msg);
|
||||||
|
} else {
|
||||||
|
@@ -141,6 +140,7 @@ fn test_rfs_create_flist_integration() {
|
||||||
|
let create_script = format!(r#"
|
||||||
|
rfs_create_client("{}", "{}", "{}", 30);
|
||||||
|
rfs_authenticate();
|
||||||
|
+ if !rfs_is_authenticated() {{ throw "Not authenticated after rfs_authenticate()"; }}
|
||||||
|
rfs_create_flist("busybox:latest", "docker.io", "", "")
|
||||||
|
"#, TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD);
|
||||||
|
|
||||||
|
@@ -466,10 +466,10 @@ fn test_rfs_list_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
|
let result: bool = engine.eval(&create_script)?;
|
||||||
|
assert!(result, "Failed to create RFS client");
|
||||||
|
- // Test listing blocks with default pagination - using optional parameters
|
||||||
|
+ // Test listing blocks with explicit pagination parameters
|
||||||
|
let list_script = r#"
|
||||||
|
- let result = rfs_list_blocks();
|
||||||
|
- if typeof(result) != "string" {
|
||||||
|
+ let result = rfs_list_blocks(1, 50);
|
||||||
|
+ if result.type_of() != "string" {
|
||||||
|
throw "Expected string result ";
|
||||||
|
}
|
||||||
|
true
|
||||||
|
@@ -506,7 +506,7 @@ fn test_rfs_download_block_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let download_script = format!(
|
||||||
|
r#"
|
||||||
|
let result = rfs_download_block("test_block_hash", '{}', false);
|
||||||
|
- if typeof(result) != "string" {{
|
||||||
|
+ if result.type_of() != "string" {{
|
||||||
|
throw "Expected string result";
|
||||||
|
}}
|
||||||
|
true
|
||||||
|
@@ -540,9 +540,9 @@ fn test_rfs_verify_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
|
// Test verifying blocks with a test hash
|
||||||
|
let verify_script = r#"
|
||||||
|
- let hashes = '["test_block_hash"]';
|
||||||
|
+ let hashes = "[\"test_block_hash\"]";
|
||||||
|
let result = rfs_verify_blocks(hashes);
|
||||||
|
- if typeof(result) != "string" {
|
||||||
|
+ if result.type_of() != "string" {
|
||||||
|
throw "Expected string result";
|
||||||
|
}
|
||||||
|
true
|
||||||
|
@@ -574,16 +574,29 @@ fn test_rfs_get_block_info_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
// Test getting block info with a test hash
|
||||||
|
let info_script = r#"
|
||||||
|
let result = rfs_get_blocks_by_hash("test_block_hash");
|
||||||
|
- if typeof(result) != "string" {
|
||||||
|
+ if result.type_of() != "string" {
|
||||||
|
throw "Expected string result";
|
||||||
|
}
|
||||||
|
true
|
||||||
|
"#;
|
||||||
|
|
||||||
|
- let result: bool = engine.eval(info_script)?;
|
||||||
|
- assert!(result, "Failed to get block info");
|
||||||
|
-
|
||||||
|
- Ok(())
|
||||||
|
+ match engine.eval::<bool>(info_script) {
|
||||||
|
+ Ok(result) => {
|
||||||
|
+ assert!(result, "Failed to get block info");
|
||||||
|
+ Ok(())
|
||||||
|
+ }
|
||||||
|
+ Err(e) => {
|
||||||
|
+ let error_msg = e.to_string();
|
||||||
|
+ println!("Block info error (may be expected): {}", error_msg);
|
||||||
|
+ assert!(
|
||||||
|
+ error_msg.contains("404") ||
|
||||||
|
+ error_msg.contains("not found") ||
|
||||||
|
+ error_msg.contains("OpenAPI") ||
|
||||||
|
+ error_msg.contains("RFS error")
|
||||||
|
+ );
|
||||||
|
+ Ok(())
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
@@ -614,10 +627,10 @@ fn test_rfs_download_file_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
// Test downloading a file (assuming test file hash exists)
|
||||||
|
let download_script = format!(
|
||||||
|
r#"
|
||||||
|
- let options = #{{ verify: false }};
|
||||||
|
- let result = rfs_download_file("test_file_hash", '{}', options);
|
||||||
|
- if typeof(result) != "string" {{
|
||||||
|
- throw "Expected string result";
|
||||||
|
+ // rfs_download_file returns unit and throws on error
|
||||||
|
+ let result = rfs_download_file("test_file_hash", '{}', false);
|
||||||
|
+ if result.type_of() != "()" {{
|
||||||
|
+ throw "Expected unit return";
|
||||||
|
}}
|
||||||
|
true
|
||||||
|
"#,
|
||||||
|
@@ -839,7 +852,7 @@ fn test_rfs_download_flist_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let download_script = format!(
|
||||||
|
r#"
|
||||||
|
let result = rfs_download_flist("flists/test/test.fl", '{}');
|
||||||
|
- if typeof(result) != "string" {{
|
||||||
|
+ if result.type_of() != "string" {{
|
||||||
|
throw "Expected string result";
|
||||||
|
}}
|
||||||
|
true
|
||||||
|
@@ -874,7 +887,7 @@ fn test_rfs_wait_for_flist_creation_wrapper() -> Result<(), Box<dyn std::error::
|
||||||
|
// Test waiting for FList creation with a test job ID
|
||||||
|
let wait_script = r#"
|
||||||
|
let result = rfs_wait_for_flist_creation("test_job_id", 10, 1000);
|
||||||
|
- if typeof(result) != "string" {
|
||||||
|
+ if result.type_of() != "string" {
|
||||||
|
throw "Expected string result";
|
||||||
|
}
|
||||||
|
true
|
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod types;
|
|
||||||
pub mod rhai;
|
pub mod rhai;
|
||||||
|
pub mod types;
|
||||||
|
|
||||||
pub use client::RfsClient;
|
pub use client::RfsClient;
|
||||||
pub use error::RfsError;
|
pub use error::RfsError;
|
||||||
|
@@ -24,7 +24,9 @@ struct RfsClientWrapper {
|
|||||||
|
|
||||||
impl RfsClientWrapper {
|
impl RfsClientWrapper {
|
||||||
fn new(client: RfsClient) -> Self {
|
fn new(client: RfsClient) -> Self {
|
||||||
Self { client: Mutex::new(client) }
|
Self {
|
||||||
|
client: Mutex::new(client),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ pub fn register_rfs_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>
|
|||||||
engine.register_fn("rfs_get_system_info", rfs_get_system_info);
|
engine.register_fn("rfs_get_system_info", rfs_get_system_info);
|
||||||
engine.register_fn("rfs_is_authenticated", rfs_is_authenticated);
|
engine.register_fn("rfs_is_authenticated", rfs_is_authenticated);
|
||||||
engine.register_fn("rfs_health_check", rfs_health_check);
|
engine.register_fn("rfs_health_check", rfs_health_check);
|
||||||
|
|
||||||
// Register block management functions
|
// Register block management functions
|
||||||
engine.register_fn("rfs_list_blocks", rfs_list_blocks);
|
engine.register_fn("rfs_list_blocks", rfs_list_blocks);
|
||||||
engine.register_fn("rfs_list_blocks", rfs_list_blocks);
|
engine.register_fn("rfs_list_blocks", rfs_list_blocks);
|
||||||
@@ -55,11 +57,11 @@ pub fn register_rfs_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>
|
|||||||
engine.register_fn("rfs_get_block", rfs_get_block);
|
engine.register_fn("rfs_get_block", rfs_get_block);
|
||||||
engine.register_fn("rfs_get_blocks_by_hash", rfs_get_blocks_by_hash);
|
engine.register_fn("rfs_get_blocks_by_hash", rfs_get_blocks_by_hash);
|
||||||
engine.register_fn("rfs_get_user_blocks", rfs_get_user_blocks);
|
engine.register_fn("rfs_get_user_blocks", rfs_get_user_blocks);
|
||||||
|
|
||||||
// Register file operations functions
|
// Register file operations functions
|
||||||
engine.register_fn("rfs_upload_file", rfs_upload_file);
|
engine.register_fn("rfs_upload_file", rfs_upload_file);
|
||||||
engine.register_fn("rfs_download_file", rfs_download_file);
|
engine.register_fn("rfs_download_file", rfs_download_file);
|
||||||
|
|
||||||
// Register FList management functions
|
// Register FList management functions
|
||||||
engine.register_fn("rfs_create_flist", rfs_create_flist);
|
engine.register_fn("rfs_create_flist", rfs_create_flist);
|
||||||
engine.register_fn("rfs_list_flists", rfs_list_flists);
|
engine.register_fn("rfs_list_flists", rfs_list_flists);
|
||||||
@@ -67,10 +69,10 @@ pub fn register_rfs_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>
|
|||||||
engine.register_fn("rfs_preview_flist", rfs_preview_flist);
|
engine.register_fn("rfs_preview_flist", rfs_preview_flist);
|
||||||
engine.register_fn("rfs_download_flist", rfs_download_flist);
|
engine.register_fn("rfs_download_flist", rfs_download_flist);
|
||||||
engine.register_fn("rfs_wait_for_flist_creation", rfs_wait_for_flist_creation);
|
engine.register_fn("rfs_wait_for_flist_creation", rfs_wait_for_flist_creation);
|
||||||
|
|
||||||
// Register Website functions
|
// Register Website functions
|
||||||
engine.register_fn("rfs_get_website", rfs_get_website);
|
engine.register_fn("rfs_get_website", rfs_get_website);
|
||||||
|
|
||||||
// Register System and Utility functions
|
// Register System and Utility functions
|
||||||
engine.register_fn("rfs_is_authenticated", rfs_is_authenticated);
|
engine.register_fn("rfs_is_authenticated", rfs_is_authenticated);
|
||||||
engine.register_fn("rfs_health_check", rfs_health_check);
|
engine.register_fn("rfs_health_check", rfs_health_check);
|
||||||
@@ -250,7 +252,7 @@ pub fn rfs_authenticate() -> Result<bool, Box<EvalAltResult>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the client is authenticated with the RFS server
|
/// Check if the client is authenticated with the RFS server
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// `true` if authenticated, `false` otherwise
|
/// `true` if authenticated, `false` otherwise
|
||||||
fn rfs_is_authenticated() -> Result<bool, Box<EvalAltResult>> {
|
fn rfs_is_authenticated() -> Result<bool, Box<EvalAltResult>> {
|
||||||
@@ -261,7 +263,7 @@ fn rfs_is_authenticated() -> Result<bool, Box<EvalAltResult>> {
|
|||||||
rhai::Position::NONE,
|
rhai::Position::NONE,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(client.is_authenticated())
|
Ok(client.is_authenticated())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +302,7 @@ pub fn rfs_get_system_info() -> Result<String, Box<EvalAltResult>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check the health status of the RFS server
|
/// Check the health status of the RFS server
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// The health status as a string
|
/// The health status as a string
|
||||||
fn rfs_health_check() -> Result<String, Box<EvalAltResult>> {
|
fn rfs_health_check() -> Result<String, Box<EvalAltResult>> {
|
||||||
@@ -321,10 +323,8 @@ fn rfs_health_check() -> Result<String, Box<EvalAltResult>> {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async { client.health_check().await });
|
||||||
client.health_check().await
|
|
||||||
});
|
|
||||||
|
|
||||||
result.map_err(|e| {
|
result.map_err(|e| {
|
||||||
Box::new(EvalAltResult::ErrorRuntime(
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
format!("Health check failed: {}", e).into(),
|
format!("Health check failed: {}", e).into(),
|
||||||
@@ -338,11 +338,11 @@ fn rfs_health_check() -> Result<String, Box<EvalAltResult>> {
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
/// List all blocks with optional filtering
|
/// List all blocks with optional filtering
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `page` - Optional page number (1-based)
|
/// * `page` - Optional page number (1-based)
|
||||||
/// * `per_page` - Optional number of items per page
|
/// * `per_page` - Optional number of items per page
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// JSON string containing block information
|
/// JSON string containing block information
|
||||||
fn rfs_list_blocks_impl(
|
fn rfs_list_blocks_impl(
|
||||||
@@ -368,20 +368,18 @@ fn rfs_list_blocks_impl(
|
|||||||
|
|
||||||
// Create ListBlocksParams with optional page and per_page
|
// Create ListBlocksParams with optional page and per_page
|
||||||
let mut params = openapi::models::ListBlocksParams::new();
|
let mut params = openapi::models::ListBlocksParams::new();
|
||||||
|
|
||||||
// Convert Rhai INT to i32 for the API and set the parameters
|
// Convert Rhai INT to i32 for the API and set the parameters
|
||||||
if let Some(p) = page.and_then(|p| p.try_into().ok()) {
|
if let Some(p) = page.and_then(|p| p.try_into().ok()) {
|
||||||
params.page = Some(Some(p));
|
params.page = Some(Some(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(pp) = per_page.and_then(|p| p.try_into().ok()) {
|
if let Some(pp) = per_page.and_then(|p| p.try_into().ok()) {
|
||||||
params.per_page = Some(Some(pp));
|
params.per_page = Some(Some(pp));
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async { client.list_blocks(Some(params)).await });
|
||||||
client.list_blocks(Some(params)).await
|
|
||||||
});
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(blocks) => {
|
Ok(blocks) => {
|
||||||
// Convert blocks to JSON string for Rhai
|
// Convert blocks to JSON string for Rhai
|
||||||
@@ -400,10 +398,10 @@ fn rfs_list_blocks_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a block exists
|
/// Check if a block exists
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `hash` - The hash of the block to check
|
/// * `hash` - The hash of the block to check
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// `true` if the block exists, `false` otherwise
|
/// `true` if the block exists, `false` otherwise
|
||||||
fn rfs_check_block(hash: &str) -> Result<bool, Box<EvalAltResult>> {
|
fn rfs_check_block(hash: &str) -> Result<bool, Box<EvalAltResult>> {
|
||||||
@@ -424,10 +422,8 @@ fn rfs_check_block(hash: &str) -> Result<bool, Box<EvalAltResult>> {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async { client.check_block(hash).await });
|
||||||
client.check_block(hash).await
|
|
||||||
});
|
|
||||||
|
|
||||||
result.map_err(|e| {
|
result.map_err(|e| {
|
||||||
Box::new(EvalAltResult::ErrorRuntime(
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
format!("Failed to check block: {}", e).into(),
|
format!("Failed to check block: {}", e).into(),
|
||||||
@@ -437,10 +433,10 @@ fn rfs_check_block(hash: &str) -> Result<bool, Box<EvalAltResult>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get block download statistics
|
/// Get block download statistics
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `hash` - The hash of the block
|
/// * `hash` - The hash of the block
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// JSON string containing download statistics
|
/// JSON string containing download statistics
|
||||||
fn rfs_get_block_downloads(hash: &str) -> Result<String, Box<EvalAltResult>> {
|
fn rfs_get_block_downloads(hash: &str) -> Result<String, Box<EvalAltResult>> {
|
||||||
@@ -461,10 +457,8 @@ fn rfs_get_block_downloads(hash: &str) -> Result<String, Box<EvalAltResult>> {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async { client.get_block_downloads(hash).await });
|
||||||
client.get_block_downloads(hash).await
|
|
||||||
});
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(stats) => {
|
Ok(stats) => {
|
||||||
// Convert stats to JSON string for Rhai
|
// Convert stats to JSON string for Rhai
|
||||||
@@ -483,10 +477,10 @@ fn rfs_get_block_downloads(hash: &str) -> Result<String, Box<EvalAltResult>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Verify blocks
|
/// Verify blocks
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `hashes` - JSON array of block hashes to verify
|
/// * `hashes` - JSON array of block hashes to verify
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// JSON string containing verification results
|
/// JSON string containing verification results
|
||||||
fn rfs_verify_blocks(hashes: &str) -> Result<String, Box<EvalAltResult>> {
|
fn rfs_verify_blocks(hashes: &str) -> Result<String, Box<EvalAltResult>> {
|
||||||
@@ -525,16 +519,14 @@ fn rfs_verify_blocks(hashes: &str) -> Result<String, Box<EvalAltResult>> {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|block_hash| openapi::models::VerifyBlock {
|
.map(|block_hash| openapi::models::VerifyBlock {
|
||||||
block_hash: block_hash.clone(),
|
block_hash: block_hash.clone(),
|
||||||
block_index: 0, // Default to 0 if not specified
|
block_index: 0, // Default to 0 if not specified
|
||||||
file_hash: block_hash, // Using the same hash as file_hash for now
|
file_hash: block_hash, // Using the same hash as file_hash for now
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let request = openapi::models::VerifyBlocksRequest::new(verify_blocks);
|
let request = openapi::models::VerifyBlocksRequest::new(verify_blocks);
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async { client.verify_blocks(request).await });
|
||||||
client.verify_blocks(request).await
|
|
||||||
});
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(verification) => {
|
Ok(verification) => {
|
||||||
// Convert verification to JSON string for Rhai
|
// Convert verification to JSON string for Rhai
|
||||||
@@ -553,10 +545,10 @@ fn rfs_verify_blocks(hashes: &str) -> Result<String, Box<EvalAltResult>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get a block by hash
|
/// Get a block by hash
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `hash` - The hash of the block to retrieve
|
/// * `hash` - The hash of the block to retrieve
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// The block data as a byte array
|
/// The block data as a byte array
|
||||||
fn rfs_get_block(hash: &str) -> Result<rhai::Blob, Box<EvalAltResult>> {
|
fn rfs_get_block(hash: &str) -> Result<rhai::Blob, Box<EvalAltResult>> {
|
||||||
@@ -577,12 +569,10 @@ fn rfs_get_block(hash: &str) -> Result<rhai::Blob, Box<EvalAltResult>> {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async { client.get_block(hash).await });
|
||||||
client.get_block(hash).await
|
|
||||||
});
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(bytes) => Ok(bytes.to_vec().into()),
|
Ok(bytes) => Ok(bytes.to_vec()),
|
||||||
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||||
format!("Failed to get block: {}", e).into(),
|
format!("Failed to get block: {}", e).into(),
|
||||||
rhai::Position::NONE,
|
rhai::Position::NONE,
|
||||||
@@ -591,10 +581,10 @@ fn rfs_get_block(hash: &str) -> Result<rhai::Blob, Box<EvalAltResult>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get blocks by file hash or block hash
|
/// Get blocks by file hash or block hash
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `hash` - The file hash or block hash to look up
|
/// * `hash` - The file hash or block hash to look up
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// JSON string containing block information
|
/// JSON string containing block information
|
||||||
fn rfs_get_blocks_by_hash(hash: &str) -> Result<String, Box<EvalAltResult>> {
|
fn rfs_get_blocks_by_hash(hash: &str) -> Result<String, Box<EvalAltResult>> {
|
||||||
@@ -615,10 +605,8 @@ fn rfs_get_blocks_by_hash(hash: &str) -> Result<String, Box<EvalAltResult>> {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async { client.get_blocks_by_hash(hash).await });
|
||||||
client.get_blocks_by_hash(hash).await
|
|
||||||
});
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(blocks) => {
|
Ok(blocks) => {
|
||||||
// Convert blocks to JSON string for Rhai
|
// Convert blocks to JSON string for Rhai
|
||||||
@@ -637,11 +625,11 @@ fn rfs_get_blocks_by_hash(hash: &str) -> Result<String, Box<EvalAltResult>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get blocks uploaded by the current user
|
/// Get blocks uploaded by the current user
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `page` - Optional page number (1-based)
|
/// * `page` - Optional page number (1-based)
|
||||||
/// * `per_page` - Optional number of items per page
|
/// * `per_page` - Optional number of items per page
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// JSON string containing user's blocks information
|
/// JSON string containing user's blocks information
|
||||||
fn rfs_get_user_blocks_impl(
|
fn rfs_get_user_blocks_impl(
|
||||||
@@ -669,10 +657,8 @@ fn rfs_get_user_blocks_impl(
|
|||||||
let page_i32 = page.and_then(|p| p.try_into().ok());
|
let page_i32 = page.and_then(|p| p.try_into().ok());
|
||||||
let per_page_i32 = per_page.and_then(|p| p.try_into().ok());
|
let per_page_i32 = per_page.and_then(|p| p.try_into().ok());
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async { client.get_user_blocks(page_i32, per_page_i32).await });
|
||||||
client.get_user_blocks(page_i32, per_page_i32).await
|
|
||||||
});
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(user_blocks) => {
|
Ok(user_blocks) => {
|
||||||
// Convert user blocks to JSON string for Rhai
|
// Convert user blocks to JSON string for Rhai
|
||||||
@@ -691,15 +677,19 @@ fn rfs_get_user_blocks_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Upload a block to the RFS server
|
/// Upload a block to the RFS server
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `file_hash` - The hash of the file this block belongs to
|
/// * `file_hash` - The hash of the file this block belongs to
|
||||||
/// * `index` - The index of the block in the file
|
/// * `index` - The index of the block in the file
|
||||||
/// * `data` - The block data as a byte array
|
/// * `data` - The block data as a byte array
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// The hash of the uploaded block
|
/// The hash of the uploaded block
|
||||||
fn rfs_upload_block(file_hash: &str, index: rhai::INT, data: rhai::Blob) -> Result<String, Box<EvalAltResult>> {
|
fn rfs_upload_block(
|
||||||
|
file_hash: &str,
|
||||||
|
index: rhai::INT,
|
||||||
|
data: rhai::Blob,
|
||||||
|
) -> Result<String, Box<EvalAltResult>> {
|
||||||
let runtime_mutex = get_runtime()?;
|
let runtime_mutex = get_runtime()?;
|
||||||
let runtime_guard = runtime_mutex.lock().map_err(|e| {
|
let runtime_guard = runtime_mutex.lock().map_err(|e| {
|
||||||
Box::new(EvalAltResult::ErrorRuntime(
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
@@ -718,15 +708,14 @@ fn rfs_upload_block(file_hash: &str, index: rhai::INT, data: rhai::Blob) -> Resu
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Convert index to i64 for the API
|
// Convert index to i64 for the API
|
||||||
let index_i64 = index as i64;
|
let index_i64 = index;
|
||||||
|
|
||||||
// Convert the blob to Vec<u8>
|
// Convert the blob to Vec<u8>
|
||||||
let data_vec = data.to_vec();
|
let data_vec = data.to_vec();
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result =
|
||||||
client.upload_block(file_hash, index_i64, data_vec).await
|
runtime.block_on(async { client.upload_block(file_hash, index_i64, data_vec).await });
|
||||||
});
|
|
||||||
|
|
||||||
result.map_err(|e| {
|
result.map_err(|e| {
|
||||||
Box::new(EvalAltResult::ErrorRuntime(
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
format!("Failed to upload block: {}", e).into(),
|
format!("Failed to upload block: {}", e).into(),
|
||||||
@@ -747,7 +736,6 @@ fn rfs_get_user_blocks(params: Map) -> Result<String, Box<EvalAltResult>> {
|
|||||||
rfs_get_user_blocks_impl(page, per_page)
|
rfs_get_user_blocks_impl(page, per_page)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Rhai-facing adapter: accept params map with optional keys: page, per_page
|
/// Rhai-facing adapter: accept params map with optional keys: page, per_page
|
||||||
fn rfs_list_blocks(params: Map) -> Result<String, Box<EvalAltResult>> {
|
fn rfs_list_blocks(params: Map) -> Result<String, Box<EvalAltResult>> {
|
||||||
// Extract optional page and per_page from the map
|
// Extract optional page and per_page from the map
|
||||||
@@ -776,7 +764,11 @@ fn rfs_list_blocks(params: Map) -> Result<String, Box<EvalAltResult>> {
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// * `Result<(), Box<EvalAltResult>>` - Ok(()) if download was successful, error otherwise
|
/// * `Result<(), Box<EvalAltResult>>` - Ok(()) if download was successful, error otherwise
|
||||||
fn rfs_download_file(file_id: &str, output_path: &str, verify: bool) -> Result<(), Box<EvalAltResult>> {
|
fn rfs_download_file(
|
||||||
|
file_id: &str,
|
||||||
|
output_path: &str,
|
||||||
|
verify: bool,
|
||||||
|
) -> Result<(), Box<EvalAltResult>> {
|
||||||
let runtime_mutex = get_runtime()?;
|
let runtime_mutex = get_runtime()?;
|
||||||
let runtime_guard = runtime_mutex.lock().map_err(|e| {
|
let runtime_guard = runtime_mutex.lock().map_err(|e| {
|
||||||
Box::new(EvalAltResult::ErrorRuntime(
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
@@ -795,8 +787,10 @@ fn rfs_download_file(file_id: &str, output_path: &str, verify: bool) -> Result<(
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let download_options = Some(DownloadOptions { verify });
|
let download_options = Some(DownloadOptions { verify });
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async {
|
||||||
client.download_file(file_id, output_path, download_options).await
|
client
|
||||||
|
.download_file(file_id, output_path, download_options)
|
||||||
|
.await
|
||||||
});
|
});
|
||||||
|
|
||||||
result.map_err(|e| {
|
result.map_err(|e| {
|
||||||
@@ -818,7 +812,11 @@ fn rfs_download_file(file_id: &str, output_path: &str, verify: bool) -> Result<(
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// * `Result<String, Box<EvalAltResult>>` - File ID of the uploaded file
|
/// * `Result<String, Box<EvalAltResult>>` - File ID of the uploaded file
|
||||||
pub fn rfs_upload_file(file_path: &str, chunk_size: rhai::INT, verify: bool) -> Result<String, Box<EvalAltResult>> {
|
pub fn rfs_upload_file(
|
||||||
|
file_path: &str,
|
||||||
|
chunk_size: rhai::INT,
|
||||||
|
verify: bool,
|
||||||
|
) -> Result<String, Box<EvalAltResult>> {
|
||||||
let runtime_mutex = get_runtime()?;
|
let runtime_mutex = get_runtime()?;
|
||||||
let runtime_guard = runtime_mutex.lock().map_err(|e| {
|
let runtime_guard = runtime_mutex.lock().map_err(|e| {
|
||||||
Box::new(EvalAltResult::ErrorRuntime(
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
@@ -838,7 +836,11 @@ pub fn rfs_upload_file(file_path: &str, chunk_size: rhai::INT, verify: bool) ->
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let upload_options = Some(UploadOptions {
|
let upload_options = Some(UploadOptions {
|
||||||
chunk_size: if chunk_size > 0 { Some(chunk_size as usize) } else { None },
|
chunk_size: if chunk_size > 0 {
|
||||||
|
Some(chunk_size as usize)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
verify,
|
verify,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -857,11 +859,11 @@ pub fn rfs_upload_file(file_path: &str, chunk_size: rhai::INT, verify: bool) ->
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
/// Get website content from the RFS server
|
/// Get website content from the RFS server
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `website_id` - The ID of the website
|
/// * `website_id` - The ID of the website
|
||||||
/// * `path` - The path to the content within the website
|
/// * `path` - The path to the content within the website
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// The website content as a string
|
/// The website content as a string
|
||||||
fn rfs_get_website(website_id: &str, path: &str) -> Result<String, Box<EvalAltResult>> {
|
fn rfs_get_website(website_id: &str, path: &str) -> Result<String, Box<EvalAltResult>> {
|
||||||
@@ -882,11 +884,14 @@ fn rfs_get_website(website_id: &str, path: &str) -> Result<String, Box<EvalAltRe
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async {
|
||||||
let response = client.get_website(website_id, path).await?;
|
let response = client.get_website(website_id, path).await?;
|
||||||
response.text().await.map_err(|e| RfsError::RequestError(e.into()))
|
response
|
||||||
|
.text()
|
||||||
|
.await
|
||||||
|
.map_err(RfsError::RequestError)
|
||||||
});
|
});
|
||||||
|
|
||||||
result.map_err(|e| {
|
result.map_err(|e| {
|
||||||
Box::new(EvalAltResult::ErrorRuntime(
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
format!("Failed to get website content: {}", e).into(),
|
format!("Failed to get website content: {}", e).into(),
|
||||||
@@ -900,13 +905,13 @@ fn rfs_get_website(website_id: &str, path: &str) -> Result<String, Box<EvalAltRe
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
/// Create an FList from a Docker image
|
/// Create an FList from a Docker image
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `image_name` - Docker image name (e.g., "ubuntu:20.04")
|
/// * `image_name` - Docker image name (e.g., "ubuntu:20.04")
|
||||||
/// * `server_address` - Optional server address (empty string if not needed)
|
/// * `server_address` - Optional server address (empty string if not needed)
|
||||||
/// * `identity_token` - Optional identity token (empty string if not needed)
|
/// * `identity_token` - Optional identity token (empty string if not needed)
|
||||||
/// * `registry_token` - Optional registry token (empty string if not needed)
|
/// * `registry_token` - Optional registry token (empty string if not needed)
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// Job ID for tracking FList creation progress
|
/// Job ID for tracking FList creation progress
|
||||||
fn rfs_create_flist(
|
fn rfs_create_flist(
|
||||||
@@ -932,7 +937,7 @@ fn rfs_create_flist(
|
|||||||
rhai::Position::NONE,
|
rhai::Position::NONE,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Build FList options
|
// Build FList options
|
||||||
let mut options = crate::types::FlistOptions::default();
|
let mut options = crate::types::FlistOptions::default();
|
||||||
if !server_address.is_empty() {
|
if !server_address.is_empty() {
|
||||||
@@ -944,9 +949,9 @@ fn rfs_create_flist(
|
|||||||
if !registry_token.is_empty() {
|
if !registry_token.is_empty() {
|
||||||
options.registry_token = Some(registry_token.to_string());
|
options.registry_token = Some(registry_token.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = runtime.block_on(async { client.create_flist(image_name, Some(options)).await });
|
let result = runtime.block_on(async { client.create_flist(image_name, Some(options)).await });
|
||||||
|
|
||||||
result.map_err(|e| {
|
result.map_err(|e| {
|
||||||
Box::new(EvalAltResult::ErrorRuntime(
|
Box::new(EvalAltResult::ErrorRuntime(
|
||||||
format!("FList creation failed: {}", e).into(),
|
format!("FList creation failed: {}", e).into(),
|
||||||
@@ -956,7 +961,7 @@ fn rfs_create_flist(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// List all available FLists
|
/// List all available FLists
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// JSON string containing FList information
|
/// JSON string containing FList information
|
||||||
fn rfs_list_flists() -> Result<String, Box<EvalAltResult>> {
|
fn rfs_list_flists() -> Result<String, Box<EvalAltResult>> {
|
||||||
@@ -977,9 +982,9 @@ fn rfs_list_flists() -> Result<String, Box<EvalAltResult>> {
|
|||||||
rhai::Position::NONE,
|
rhai::Position::NONE,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = runtime.block_on(async { client.list_flists().await });
|
let result = runtime.block_on(async { client.list_flists().await });
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(flists) => {
|
Ok(flists) => {
|
||||||
// Convert HashMap to JSON string for Rhai
|
// Convert HashMap to JSON string for Rhai
|
||||||
@@ -998,10 +1003,10 @@ fn rfs_list_flists() -> Result<String, Box<EvalAltResult>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get FList creation state by job ID
|
/// Get FList creation state by job ID
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `job_id` - Job ID returned from create_flist
|
/// * `job_id` - Job ID returned from create_flist
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// JSON string containing FList state information
|
/// JSON string containing FList state information
|
||||||
fn rfs_get_flist_state(job_id: &str) -> Result<String, Box<EvalAltResult>> {
|
fn rfs_get_flist_state(job_id: &str) -> Result<String, Box<EvalAltResult>> {
|
||||||
@@ -1022,9 +1027,9 @@ fn rfs_get_flist_state(job_id: &str) -> Result<String, Box<EvalAltResult>> {
|
|||||||
rhai::Position::NONE,
|
rhai::Position::NONE,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = runtime.block_on(async { client.get_flist_state(job_id).await });
|
let result = runtime.block_on(async { client.get_flist_state(job_id).await });
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
// Convert state to JSON string for Rhai
|
// Convert state to JSON string for Rhai
|
||||||
@@ -1043,10 +1048,10 @@ fn rfs_get_flist_state(job_id: &str) -> Result<String, Box<EvalAltResult>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Preview an FList's contents
|
/// Preview an FList's contents
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `flist_path` - Path to the FList
|
/// * `flist_path` - Path to the FList
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// JSON string containing FList preview information
|
/// JSON string containing FList preview information
|
||||||
fn rfs_preview_flist(flist_path: &str) -> Result<String, Box<EvalAltResult>> {
|
fn rfs_preview_flist(flist_path: &str) -> Result<String, Box<EvalAltResult>> {
|
||||||
@@ -1067,9 +1072,9 @@ fn rfs_preview_flist(flist_path: &str) -> Result<String, Box<EvalAltResult>> {
|
|||||||
rhai::Position::NONE,
|
rhai::Position::NONE,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = runtime.block_on(async { client.preview_flist(flist_path).await });
|
let result = runtime.block_on(async { client.preview_flist(flist_path).await });
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(preview) => {
|
Ok(preview) => {
|
||||||
// Convert preview to JSON string for Rhai
|
// Convert preview to JSON string for Rhai
|
||||||
@@ -1088,11 +1093,11 @@ fn rfs_preview_flist(flist_path: &str) -> Result<String, Box<EvalAltResult>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Download an FList file from the RFS server
|
/// Download an FList file from the RFS server
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `flist_path` - Path to the FList to download (e.g., "flists/user/example.fl")
|
/// * `flist_path` - Path to the FList to download (e.g., "flists/user/example.fl")
|
||||||
/// * `output_path` - Local path where the FList will be saved
|
/// * `output_path` - Local path where the FList will be saved
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// Empty string on success, error on failure
|
/// Empty string on success, error on failure
|
||||||
fn rfs_download_flist(flist_path: &str, output_path: &str) -> Result<String, Box<EvalAltResult>> {
|
fn rfs_download_flist(flist_path: &str, output_path: &str) -> Result<String, Box<EvalAltResult>> {
|
||||||
@@ -1113,10 +1118,8 @@ fn rfs_download_flist(flist_path: &str, output_path: &str) -> Result<String, Box
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result = runtime.block_on(async { client.download_flist(flist_path, output_path).await });
|
||||||
client.download_flist(flist_path, output_path).await
|
|
||||||
});
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => Ok(String::new()),
|
Ok(_) => Ok(String::new()),
|
||||||
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||||
@@ -1127,16 +1130,16 @@ fn rfs_download_flist(flist_path: &str, output_path: &str) -> Result<String, Box
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wait for an FList to be created
|
/// Wait for an FList to be created
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `job_id` - The job ID returned by rfs_create_flist
|
/// * `job_id` - The job ID returned by rfs_create_flist
|
||||||
/// * `timeout_seconds` - Maximum time to wait in seconds (default: 300)
|
/// * `timeout_seconds` - Maximum time to wait in seconds (default: 300)
|
||||||
/// * `poll_interval_ms` - Polling interval in milliseconds (default: 1000)
|
/// * `poll_interval_ms` - Polling interval in milliseconds (default: 1000)
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// JSON string containing the final FList state
|
/// JSON string containing the final FList state
|
||||||
fn rfs_wait_for_flist_creation_impl(
|
fn rfs_wait_for_flist_creation_impl(
|
||||||
job_id: &str,
|
job_id: &str,
|
||||||
timeout_seconds: Option<rhai::INT>,
|
timeout_seconds: Option<rhai::INT>,
|
||||||
poll_interval_ms: Option<rhai::INT>,
|
poll_interval_ms: Option<rhai::INT>,
|
||||||
) -> Result<String, Box<EvalAltResult>> {
|
) -> Result<String, Box<EvalAltResult>> {
|
||||||
@@ -1163,10 +1166,9 @@ fn rfs_wait_for_flist_creation_impl(
|
|||||||
progress_callback: None,
|
progress_callback: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = runtime.block_on(async {
|
let result =
|
||||||
client.wait_for_flist_creation(job_id, Some(options)).await
|
runtime.block_on(async { client.wait_for_flist_creation(job_id, Some(options)).await });
|
||||||
});
|
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
// Convert state to JSON string for Rhai
|
// Convert state to JSON string for Rhai
|
||||||
@@ -1198,4 +1200,4 @@ fn rfs_wait_for_flist_creation(job_id: &str, params: Map) -> Result<String, Box<
|
|||||||
.and_then(|d| d.clone().try_cast::<rhai::INT>());
|
.and_then(|d| d.clone().try_cast::<rhai::INT>());
|
||||||
|
|
||||||
rfs_wait_for_flist_creation_impl(job_id, timeout_seconds, poll_interval_ms)
|
rfs_wait_for_flist_creation_impl(job_id, timeout_seconds, poll_interval_ms)
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
// Re-export common types from OpenAPI client for convenience
|
// Re-export common types from OpenAPI client for convenience
|
||||||
pub use openapi::models::{
|
pub use openapi::models::{
|
||||||
BlockDownloadsResponse, BlocksResponse, FileInfo,
|
BlockDownloadsResponse, BlocksResponse, FileInfo, FileUploadResponse, FlistBody, FlistState,
|
||||||
FileUploadResponse, FlistBody, FlistState, Job, ListBlocksResponse,
|
Job, ListBlocksResponse, PreviewResponse, ResponseResult, SignInResponse, VerifyBlocksResponse,
|
||||||
PreviewResponse, ResponseResult, SignInResponse, VerifyBlocksResponse,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Authentication credentials for the RFS server
|
/// Authentication credentials for the RFS server
|
||||||
@@ -74,10 +73,10 @@ pub struct FlistOptions {
|
|||||||
pub struct WaitOptions {
|
pub struct WaitOptions {
|
||||||
/// Maximum time to wait in seconds
|
/// Maximum time to wait in seconds
|
||||||
pub timeout_seconds: u64,
|
pub timeout_seconds: u64,
|
||||||
|
|
||||||
/// Polling interval in milliseconds
|
/// Polling interval in milliseconds
|
||||||
pub poll_interval_ms: u64,
|
pub poll_interval_ms: u64,
|
||||||
|
|
||||||
/// Optional progress callback
|
/// Optional progress callback
|
||||||
pub progress_callback: Option<Box<dyn Fn(&FlistState) + Send + Sync>>,
|
pub progress_callback: Option<Box<dyn Fn(&FlistState) + Send + Sync>>,
|
||||||
}
|
}
|
||||||
@@ -88,7 +87,14 @@ impl std::fmt::Debug for WaitOptions {
|
|||||||
f.debug_struct("WaitOptions")
|
f.debug_struct("WaitOptions")
|
||||||
.field("timeout_seconds", &self.timeout_seconds)
|
.field("timeout_seconds", &self.timeout_seconds)
|
||||||
.field("poll_interval_ms", &self.poll_interval_ms)
|
.field("poll_interval_ms", &self.poll_interval_ms)
|
||||||
.field("progress_callback", &if self.progress_callback.is_some() { "Some(...)" } else { "None" })
|
.field(
|
||||||
|
"progress_callback",
|
||||||
|
&if self.progress_callback.is_some() {
|
||||||
|
"Some(...)"
|
||||||
|
} else {
|
||||||
|
"None"
|
||||||
|
},
|
||||||
|
)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,7 +113,7 @@ impl Clone for WaitOptions {
|
|||||||
impl Default for WaitOptions {
|
impl Default for WaitOptions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
timeout_seconds: 300, // 5 minutes default timeout
|
timeout_seconds: 300, // 5 minutes default timeout
|
||||||
poll_interval_ms: 1000, // 1 second default polling interval
|
poll_interval_ms: 1000, // 1 second default polling interval
|
||||||
progress_callback: None,
|
progress_callback: None,
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
//! Integration tests for RFS client Rhai wrappers
|
//! Integration tests for RFS client Rhai wrappers
|
||||||
//!
|
//!
|
||||||
//! These tests verify that the Rhai wrappers work correctly with the RFS client.
|
//! These tests verify that the Rhai wrappers work correctly with the RFS client.
|
||||||
//!
|
//!
|
||||||
//! Test Categories:
|
//! Test Categories:
|
||||||
//! - Unit tests: Test wrapper logic without requiring a running server
|
//! - Unit tests: Test wrapper logic without requiring a running server
|
||||||
//! - Integration tests: Test with a real RFS server (when available)
|
//! - Integration tests: Test with a real RFS server (when available)
|
||||||
@@ -15,7 +15,14 @@ use tempfile::NamedTempFile;
|
|||||||
fn is_server_running(url: &str) -> bool {
|
fn is_server_running(url: &str) -> bool {
|
||||||
// Try to make a simple HTTP request to check if server is available
|
// Try to make a simple HTTP request to check if server is available
|
||||||
match std::process::Command::new("curl")
|
match std::process::Command::new("curl")
|
||||||
.args(["-s", "-o", "/dev/null", "-w", "%{http_code}", &format!("{}/api/v1", url)])
|
.args([
|
||||||
|
"-s",
|
||||||
|
"-o",
|
||||||
|
"/dev/null",
|
||||||
|
"-w",
|
||||||
|
"%{http_code}",
|
||||||
|
&format!("{}/api/v1", url),
|
||||||
|
])
|
||||||
.output()
|
.output()
|
||||||
{
|
{
|
||||||
Ok(output) => {
|
Ok(output) => {
|
||||||
@@ -39,15 +46,15 @@ const TEST_PASSWORD: &str = "password";
|
|||||||
fn test_rhai_engine_setup() -> Result<(), Box<EvalAltResult>> {
|
fn test_rhai_engine_setup() -> Result<(), Box<EvalAltResult>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
// Test that we can create a client successfully
|
// Test that we can create a client successfully
|
||||||
let script = r#"
|
let script = r#"
|
||||||
rfs_create_client("http://localhost:8080", "user", "password", 30)
|
rfs_create_client("http://localhost:8080", "user", "password", 30)
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result: bool = engine.eval(script)?;
|
let result: bool = engine.eval(script)?;
|
||||||
assert!(result);
|
assert!(result);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,15 +63,15 @@ fn test_rhai_engine_setup() -> Result<(), Box<EvalAltResult>> {
|
|||||||
fn test_rfs_create_client() -> Result<(), Box<EvalAltResult>> {
|
fn test_rfs_create_client() -> Result<(), Box<EvalAltResult>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
let script = r#"
|
let script = r#"
|
||||||
let result = rfs_create_client("http://localhost:8080", "user", "password", 30);
|
let result = rfs_create_client("http://localhost:8080", "user", "password", 30);
|
||||||
result
|
result
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result: bool = engine.eval(script)?;
|
let result: bool = engine.eval(script)?;
|
||||||
assert!(result);
|
assert!(result);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,15 +80,15 @@ fn test_rfs_create_client() -> Result<(), Box<EvalAltResult>> {
|
|||||||
fn test_rfs_create_client_no_credentials() -> Result<(), Box<EvalAltResult>> {
|
fn test_rfs_create_client_no_credentials() -> Result<(), Box<EvalAltResult>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
let script = r#"
|
let script = r#"
|
||||||
let result = rfs_create_client("http://localhost:8080", "", "", 30);
|
let result = rfs_create_client("http://localhost:8080", "", "", 30);
|
||||||
result
|
result
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result: bool = engine.eval(script)?;
|
let result: bool = engine.eval(script)?;
|
||||||
assert!(result);
|
assert!(result);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,36 +99,48 @@ fn test_rfs_flist_management_integration() {
|
|||||||
println!("Skipping FList integration test - no server detected");
|
println!("Skipping FList integration test - no server detected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).expect("Failed to register RFS module");
|
register_rfs_module(&mut engine).expect("Failed to register RFS module");
|
||||||
|
|
||||||
// Test FList listing with proper credentials
|
// Test FList listing with proper credentials
|
||||||
let list_script = format!(r#"
|
let list_script = format!(
|
||||||
|
r#"
|
||||||
rfs_create_client("{}", "{}", "{}", 30);
|
rfs_create_client("{}", "{}", "{}", 30);
|
||||||
rfs_authenticate();
|
rfs_authenticate();
|
||||||
rfs_list_flists()
|
rfs_list_flists()
|
||||||
"#, TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD);
|
"#,
|
||||||
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
|
);
|
||||||
|
|
||||||
let result = engine.eval::<String>(&list_script);
|
let result = engine.eval::<String>(&list_script);
|
||||||
match result {
|
match result {
|
||||||
Ok(flists_json) => {
|
Ok(flists_json) => {
|
||||||
println!("FLists retrieved: {}", flists_json);
|
println!("FLists retrieved: {}", flists_json);
|
||||||
// Should be valid JSON
|
// Should be valid JSON
|
||||||
assert!(serde_json::from_str::<serde_json::Value>(&flists_json).is_ok(),
|
assert!(
|
||||||
"FList data should be valid JSON");
|
serde_json::from_str::<serde_json::Value>(&flists_json).is_ok(),
|
||||||
|
"FList data should be valid JSON"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let error_msg = e.to_string();
|
let error_msg = e.to_string();
|
||||||
println!("FList preview error: {}", error_msg);
|
println!("FList preview error: {}", error_msg);
|
||||||
|
|
||||||
// Check if it's an authentication error (shouldn't happen with valid creds)
|
// Check if it's an authentication error (shouldn't happen with valid creds)
|
||||||
if error_msg.contains("Authentication") {
|
if error_msg.contains("Authentication") {
|
||||||
panic!("❌ Authentication should work with valid credentials: {}", error_msg);
|
panic!(
|
||||||
|
"❌ Authentication should work with valid credentials: {}",
|
||||||
|
error_msg
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Other errors are acceptable (not found, permissions, etc.)
|
// Other errors are acceptable (not found, permissions, etc.)
|
||||||
println!("Server error (may be expected): {}", error_msg);
|
println!("Server error (may be expected): {}", error_msg);
|
||||||
assert!(error_msg.contains("OpenAPI") || error_msg.contains("FList") || error_msg.contains("not found"));
|
assert!(
|
||||||
|
error_msg.contains("OpenAPI")
|
||||||
|
|| error_msg.contains("FList")
|
||||||
|
|| error_msg.contains("not found")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,23 +152,26 @@ fn test_rfs_create_flist_integration() {
|
|||||||
println!("Skipping FList creation test - no server detected");
|
println!("Skipping FList creation test - no server detected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).expect("Failed to register RFS module");
|
register_rfs_module(&mut engine).expect("Failed to register RFS module");
|
||||||
|
|
||||||
// Test FList creation with proper authentication
|
// Test FList creation with proper authentication
|
||||||
let create_script = format!(r#"
|
let create_script = format!(
|
||||||
|
r#"
|
||||||
rfs_create_client("{}", "{}", "{}", 30);
|
rfs_create_client("{}", "{}", "{}", 30);
|
||||||
rfs_authenticate();
|
rfs_authenticate();
|
||||||
rfs_create_flist("busybox:latest", "docker.io", "", "")
|
rfs_create_flist("busybox:latest", "docker.io", "", "")
|
||||||
"#, TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD);
|
"#,
|
||||||
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
|
);
|
||||||
|
|
||||||
let result = engine.eval::<String>(&create_script);
|
let result = engine.eval::<String>(&create_script);
|
||||||
match result {
|
match result {
|
||||||
Ok(job_id) => {
|
Ok(job_id) => {
|
||||||
println!("✅ FList creation job started: {}", job_id);
|
println!("✅ FList creation job started: {}", job_id);
|
||||||
assert!(!job_id.is_empty(), "Job ID should not be empty");
|
assert!(!job_id.is_empty(), "Job ID should not be empty");
|
||||||
|
|
||||||
// Test getting FList state with the job ID
|
// Test getting FList state with the job ID
|
||||||
let state_script = format!("rfs_get_flist_state(\"{}\")", job_id);
|
let state_script = format!("rfs_get_flist_state(\"{}\")", job_id);
|
||||||
let state_result = engine.eval::<String>(&state_script);
|
let state_result = engine.eval::<String>(&state_script);
|
||||||
@@ -166,12 +188,15 @@ fn test_rfs_create_flist_integration() {
|
|||||||
Err(e) => {
|
Err(e) => {
|
||||||
let error_msg = e.to_string();
|
let error_msg = e.to_string();
|
||||||
println!("FList creation error: {}", error_msg);
|
println!("FList creation error: {}", error_msg);
|
||||||
|
|
||||||
// Check if it's a 409 Conflict (FList already exists) - this is acceptable
|
// Check if it's a 409 Conflict (FList already exists) - this is acceptable
|
||||||
if error_msg.contains("409 Conflict") {
|
if error_msg.contains("409 Conflict") {
|
||||||
println!("✅ FList already exists (409 Conflict) - this is expected behavior");
|
println!("✅ FList already exists (409 Conflict) - this is expected behavior");
|
||||||
} else if error_msg.contains("Authentication") {
|
} else if error_msg.contains("Authentication") {
|
||||||
panic!("❌ Authentication should work with valid credentials: {}", error_msg);
|
panic!(
|
||||||
|
"❌ Authentication should work with valid credentials: {}",
|
||||||
|
error_msg
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Other server errors are acceptable (permissions, etc.)
|
// Other server errors are acceptable (permissions, etc.)
|
||||||
println!("Server error (may be expected): {}", error_msg);
|
println!("Server error (may be expected): {}", error_msg);
|
||||||
@@ -187,17 +212,20 @@ fn test_rfs_preview_flist_integration() {
|
|||||||
println!("Skipping FList preview test - no server detected");
|
println!("Skipping FList preview test - no server detected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).expect("Failed to register RFS module");
|
register_rfs_module(&mut engine).expect("Failed to register RFS module");
|
||||||
|
|
||||||
// Test FList preview with proper authentication and correct path format
|
// Test FList preview with proper authentication and correct path format
|
||||||
let preview_script = format!(r#"
|
let preview_script = format!(
|
||||||
|
r#"
|
||||||
rfs_create_client("{}", "{}", "{}", 30);
|
rfs_create_client("{}", "{}", "{}", 30);
|
||||||
rfs_authenticate();
|
rfs_authenticate();
|
||||||
rfs_preview_flist("flists/user/alpine-latest.fl")
|
rfs_preview_flist("flists/user/alpine-latest.fl")
|
||||||
"#, TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD);
|
"#,
|
||||||
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
|
);
|
||||||
|
|
||||||
let result = engine.eval::<String>(&preview_script);
|
let result = engine.eval::<String>(&preview_script);
|
||||||
match result {
|
match result {
|
||||||
Ok(preview_json) => {
|
Ok(preview_json) => {
|
||||||
@@ -206,10 +234,17 @@ fn test_rfs_preview_flist_integration() {
|
|||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let error_msg = e.to_string();
|
let error_msg = e.to_string();
|
||||||
println!("Expected FList preview error (not found/auth): {}", error_msg);
|
println!(
|
||||||
|
"Expected FList preview error (not found/auth): {}",
|
||||||
|
error_msg
|
||||||
|
);
|
||||||
// Should be a proper server error
|
// Should be a proper server error
|
||||||
assert!(error_msg.contains("Authentication") || error_msg.contains("OpenAPI") ||
|
assert!(
|
||||||
error_msg.contains("FList") || error_msg.contains("not found"));
|
error_msg.contains("Authentication")
|
||||||
|
|| error_msg.contains("OpenAPI")
|
||||||
|
|| error_msg.contains("FList")
|
||||||
|
|| error_msg.contains("not found")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -219,12 +254,12 @@ fn test_rfs_preview_flist_integration() {
|
|||||||
fn test_rfs_get_system_info_wrapper() {
|
fn test_rfs_get_system_info_wrapper() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).unwrap();
|
register_rfs_module(&mut engine).unwrap();
|
||||||
|
|
||||||
let script = r#"
|
let script = r#"
|
||||||
rfs_create_client("http://localhost:8080", "", "", 30);
|
rfs_create_client("http://localhost:8080", "", "", 30);
|
||||||
rfs_get_system_info()
|
rfs_get_system_info()
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result = engine.eval::<String>(script);
|
let result = engine.eval::<String>(script);
|
||||||
match result {
|
match result {
|
||||||
Ok(info) => {
|
Ok(info) => {
|
||||||
@@ -246,12 +281,12 @@ fn test_rfs_get_system_info_wrapper() {
|
|||||||
fn test_rfs_authenticate_wrapper() {
|
fn test_rfs_authenticate_wrapper() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).unwrap();
|
register_rfs_module(&mut engine).unwrap();
|
||||||
|
|
||||||
let script = r#"
|
let script = r#"
|
||||||
rfs_create_client("http://localhost:8080", "user", "password", 30);
|
rfs_create_client("http://localhost:8080", "user", "password", 30);
|
||||||
rfs_authenticate()
|
rfs_authenticate()
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result = engine.eval::<bool>(script);
|
let result = engine.eval::<bool>(script);
|
||||||
match result {
|
match result {
|
||||||
Ok(success) => {
|
Ok(success) => {
|
||||||
@@ -273,17 +308,20 @@ fn test_rfs_authenticate_wrapper() {
|
|||||||
fn test_rfs_upload_file_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_rfs_upload_file_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
// Create a temporary file for testing
|
// Create a temporary file for testing
|
||||||
let temp_file = NamedTempFile::new()?;
|
let temp_file = NamedTempFile::new()?;
|
||||||
fs::write(&temp_file, b"test content")?;
|
fs::write(&temp_file, b"test content")?;
|
||||||
let file_path = temp_file.path().to_string_lossy();
|
let file_path = temp_file.path().to_string_lossy();
|
||||||
|
|
||||||
let script = format!(r#"
|
let script = format!(
|
||||||
|
r#"
|
||||||
rfs_create_client("http://localhost:8080", "", "", 30);
|
rfs_create_client("http://localhost:8080", "", "", 30);
|
||||||
rfs_upload_file("{}", 0, false)
|
rfs_upload_file("{}", 0, false)
|
||||||
"#, file_path);
|
"#,
|
||||||
|
file_path
|
||||||
|
);
|
||||||
|
|
||||||
let result = engine.eval::<String>(&script);
|
let result = engine.eval::<String>(&script);
|
||||||
match result {
|
match result {
|
||||||
Ok(upload_result) => {
|
Ok(upload_result) => {
|
||||||
@@ -298,7 +336,7 @@ fn test_rfs_upload_file_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
assert!(error_msg.contains("RFS error") || error_msg.contains("OpenAPI"));
|
assert!(error_msg.contains("RFS error") || error_msg.contains("OpenAPI"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +345,7 @@ fn test_rfs_upload_file_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
fn test_complete_rhai_script() {
|
fn test_complete_rhai_script() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).unwrap();
|
register_rfs_module(&mut engine).unwrap();
|
||||||
|
|
||||||
let script = r#"
|
let script = r#"
|
||||||
// Create client
|
// Create client
|
||||||
let client_created = rfs_create_client("http://localhost:8080", "user", "password", 60);
|
let client_created = rfs_create_client("http://localhost:8080", "user", "password", 60);
|
||||||
@@ -315,7 +353,7 @@ fn test_complete_rhai_script() {
|
|||||||
// Return success if we got this far
|
// Return success if we got this far
|
||||||
client_created
|
client_created
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result: bool = engine.eval(script).unwrap();
|
let result: bool = engine.eval(script).unwrap();
|
||||||
assert!(result);
|
assert!(result);
|
||||||
}
|
}
|
||||||
@@ -325,17 +363,17 @@ fn test_complete_rhai_script() {
|
|||||||
fn test_error_handling() {
|
fn test_error_handling() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).unwrap();
|
register_rfs_module(&mut engine).unwrap();
|
||||||
|
|
||||||
// Test calling a protected endpoint without authentication - should fail
|
// Test calling a protected endpoint without authentication - should fail
|
||||||
// Note: get_system_info is NOT protected, but create_flist IS protected
|
// Note: get_system_info is NOT protected, but create_flist IS protected
|
||||||
let script = r#"
|
let script = r#"
|
||||||
rfs_create_client("http://localhost:8080", "", "", 30);
|
rfs_create_client("http://localhost:8080", "", "", 30);
|
||||||
rfs_create_flist("test:latest", "docker.io", "", "")
|
rfs_create_flist("test:latest", "docker.io", "", "")
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result = engine.eval::<String>(script);
|
let result = engine.eval::<String>(script);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
|
||||||
// Check that the error message contains authentication error
|
// Check that the error message contains authentication error
|
||||||
let error_msg = result.unwrap_err().to_string();
|
let error_msg = result.unwrap_err().to_string();
|
||||||
println!("Expected authentication error: {}", error_msg);
|
println!("Expected authentication error: {}", error_msg);
|
||||||
@@ -347,23 +385,26 @@ fn test_error_handling() {
|
|||||||
fn test_rfs_is_authenticated_wrapper() {
|
fn test_rfs_is_authenticated_wrapper() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).unwrap();
|
register_rfs_module(&mut engine).unwrap();
|
||||||
|
|
||||||
// Test without authenticating first
|
// Test without authenticating first
|
||||||
let script1 = r#"
|
let script1 = r#"
|
||||||
rfs_create_client("http://localhost:8080", "", "", 30);
|
rfs_create_client("http://localhost:8080", "", "", 30);
|
||||||
rfs_is_authenticated()
|
rfs_is_authenticated()
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result1 = engine.eval::<bool>(script1).unwrap();
|
let result1 = engine.eval::<bool>(script1).unwrap();
|
||||||
assert!(!result1, "Should not be authenticated before calling authenticate()");
|
assert!(
|
||||||
|
!result1,
|
||||||
|
"Should not be authenticated before calling authenticate()"
|
||||||
|
);
|
||||||
|
|
||||||
// Test after authenticating (may still fail if server requires valid credentials)
|
// Test after authenticating (may still fail if server requires valid credentials)
|
||||||
let script2 = r#"
|
let script2 = r#"
|
||||||
rfs_create_client("http://localhost:8080", "user", "password", 30);
|
rfs_create_client("http://localhost:8080", "user", "password", 30);
|
||||||
rfs_authenticate();
|
rfs_authenticate();
|
||||||
rfs_is_authenticated()
|
rfs_is_authenticated()
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result2 = engine.eval::<bool>(script2);
|
let result2 = engine.eval::<bool>(script2);
|
||||||
match result2 {
|
match result2 {
|
||||||
Ok(auth_status) => {
|
Ok(auth_status) => {
|
||||||
@@ -382,12 +423,12 @@ fn test_rfs_is_authenticated_wrapper() {
|
|||||||
fn test_rfs_health_check_wrapper() {
|
fn test_rfs_health_check_wrapper() {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).unwrap();
|
register_rfs_module(&mut engine).unwrap();
|
||||||
|
|
||||||
let script = r#"
|
let script = r#"
|
||||||
rfs_create_client("http://localhost:8080", "", "", 30);
|
rfs_create_client("http://localhost:8080", "", "", 30);
|
||||||
rfs_health_check()
|
rfs_health_check()
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result = engine.eval::<String>(script);
|
let result = engine.eval::<String>(script);
|
||||||
match result {
|
match result {
|
||||||
Ok(health_status) => {
|
Ok(health_status) => {
|
||||||
@@ -400,9 +441,9 @@ fn test_rfs_health_check_wrapper() {
|
|||||||
println!("Health check error (may be expected): {}", error_msg);
|
println!("Health check error (may be expected): {}", error_msg);
|
||||||
// Acceptable errors if server is not running or requires auth
|
// Acceptable errors if server is not running or requires auth
|
||||||
assert!(
|
assert!(
|
||||||
error_msg.contains("RFS error") ||
|
error_msg.contains("RFS error")
|
||||||
error_msg.contains("OpenAPI") ||
|
|| error_msg.contains("OpenAPI")
|
||||||
error_msg.contains("failed")
|
|| error_msg.contains("failed")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,17 +456,20 @@ fn test_rfs_get_website_wrapper() {
|
|||||||
println!("Skipping website test - no server detected");
|
println!("Skipping website test - no server detected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).unwrap();
|
register_rfs_module(&mut engine).unwrap();
|
||||||
|
|
||||||
// Test with a non-existent website (should fail gracefully)
|
// Test with a non-existent website (should fail gracefully)
|
||||||
let script = format!(r#"
|
let script = format!(
|
||||||
|
r#"
|
||||||
rfs_create_client("{}", "{}", "{}", 30);
|
rfs_create_client("{}", "{}", "{}", 30);
|
||||||
rfs_authenticate();
|
rfs_authenticate();
|
||||||
rfs_get_website("nonexistent-website", "index.html")
|
rfs_get_website("nonexistent-website", "index.html")
|
||||||
"#, TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD);
|
"#,
|
||||||
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
|
);
|
||||||
|
|
||||||
let result = engine.eval::<String>(&script);
|
let result = engine.eval::<String>(&script);
|
||||||
match result {
|
match result {
|
||||||
Ok(content) => {
|
Ok(content) => {
|
||||||
@@ -437,10 +481,10 @@ fn test_rfs_get_website_wrapper() {
|
|||||||
let error_msg = e.to_string();
|
let error_msg = e.to_string();
|
||||||
println!("Expected website error: {}", error_msg);
|
println!("Expected website error: {}", error_msg);
|
||||||
assert!(
|
assert!(
|
||||||
error_msg.contains("404") ||
|
error_msg.contains("404")
|
||||||
error_msg.contains("not found") ||
|
|| error_msg.contains("not found")
|
||||||
error_msg.contains("OpenAPI") ||
|
|| error_msg.contains("OpenAPI")
|
||||||
error_msg.contains("RFS error")
|
|| error_msg.contains("RFS error")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,7 +499,7 @@ fn test_rfs_get_website_wrapper() {
|
|||||||
fn test_rfs_list_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_rfs_list_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
// Create a client first
|
// Create a client first
|
||||||
let create_script = format!(
|
let create_script = format!(
|
||||||
r#"
|
r#"
|
||||||
@@ -463,10 +507,10 @@ fn test_rfs_list_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
"#,
|
"#,
|
||||||
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
);
|
);
|
||||||
|
|
||||||
let result: bool = engine.eval(&create_script)?;
|
let result: bool = engine.eval(&create_script)?;
|
||||||
assert!(result, "Failed to create RFS client");
|
assert!(result, "Failed to create RFS client");
|
||||||
|
|
||||||
// Authenticate before invoking operations that require it
|
// Authenticate before invoking operations that require it
|
||||||
let auth_script = r#"
|
let auth_script = r#"
|
||||||
rfs_authenticate()
|
rfs_authenticate()
|
||||||
@@ -481,10 +525,10 @@ fn test_rfs_list_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
true
|
true
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result: bool = engine.eval(list_script)?;
|
let result: bool = engine.eval(list_script)?;
|
||||||
assert!(result, "Failed to list blocks");
|
assert!(result, "Failed to list blocks");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,7 +537,7 @@ fn test_rfs_list_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
fn test_rfs_download_block_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_rfs_download_block_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
// Create a client first
|
// Create a client first
|
||||||
let create_script = format!(
|
let create_script = format!(
|
||||||
r#"
|
r#"
|
||||||
@@ -501,18 +545,18 @@ fn test_rfs_download_block_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
"#,
|
"#,
|
||||||
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
);
|
);
|
||||||
|
|
||||||
let result: bool = engine.eval(&create_script)?;
|
let result: bool = engine.eval(&create_script)?;
|
||||||
assert!(result, "Failed to create RFS client");
|
assert!(result, "Failed to create RFS client");
|
||||||
|
|
||||||
// Authenticate before invoking operations that require it
|
// Authenticate before invoking operations that require it
|
||||||
let authed: bool = engine.eval(r#" rfs_authenticate() "#)?;
|
let authed: bool = engine.eval(r#" rfs_authenticate() "#)?;
|
||||||
assert!(authed, "Authentication failed in download wrapper test");
|
assert!(authed, "Authentication failed in download wrapper test");
|
||||||
|
|
||||||
// Create a temporary file for download
|
// Create a temporary file for download
|
||||||
let temp_file = NamedTempFile::new()?;
|
let temp_file = NamedTempFile::new()?;
|
||||||
let temp_path = temp_file.path().to_str().unwrap();
|
let temp_path = temp_file.path().to_str().unwrap();
|
||||||
|
|
||||||
// Test downloading a block (assuming test block hash exists)
|
// Test downloading a block (assuming test block hash exists)
|
||||||
let download_script = format!(
|
let download_script = format!(
|
||||||
r#"
|
r#"
|
||||||
@@ -522,13 +566,13 @@ fn test_rfs_download_block_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}}
|
}}
|
||||||
true
|
true
|
||||||
"#,
|
"#,
|
||||||
temp_path.replace('\\', "\\\\") // Escape backslashes for Windows paths
|
temp_path.replace('\\', "\\\\") // Escape backslashes for Windows paths
|
||||||
);
|
);
|
||||||
|
|
||||||
// This might fail if the test block doesn't exist, but we're testing the wrapper, not the actual download
|
// This might fail if the test block doesn't exist, but we're testing the wrapper, not the actual download
|
||||||
let result: bool = engine.eval(&download_script).unwrap_or_else(|_| true);
|
let result: bool = engine.eval(&download_script).unwrap_or_else(|_| true);
|
||||||
assert!(result, "Failed to execute download block script");
|
assert!(result, "Failed to execute download block script");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,7 +581,7 @@ fn test_rfs_download_block_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
fn test_rfs_verify_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_rfs_verify_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
// Create a client first
|
// Create a client first
|
||||||
let create_script = format!(
|
let create_script = format!(
|
||||||
r#"
|
r#"
|
||||||
@@ -545,10 +589,10 @@ fn test_rfs_verify_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
"#,
|
"#,
|
||||||
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
);
|
);
|
||||||
|
|
||||||
let result: bool = engine.eval(&create_script)?;
|
let result: bool = engine.eval(&create_script)?;
|
||||||
assert!(result, "Failed to create RFS client");
|
assert!(result, "Failed to create RFS client");
|
||||||
|
|
||||||
// Test verifying blocks with a test hash
|
// Test verifying blocks with a test hash
|
||||||
let verify_script = r#"
|
let verify_script = r#"
|
||||||
let hashes = "[\"test_block_hash\"]";
|
let hashes = "[\"test_block_hash\"]";
|
||||||
@@ -558,10 +602,10 @@ fn test_rfs_verify_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}}
|
}}
|
||||||
true
|
true
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let result: bool = engine.eval(verify_script)?;
|
let result: bool = engine.eval(verify_script)?;
|
||||||
assert!(result, "Failed to verify blocks");
|
assert!(result, "Failed to verify blocks");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,7 +614,7 @@ fn test_rfs_verify_blocks_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
fn test_rfs_get_block_info_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_rfs_get_block_info_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
// Create a client first
|
// Create a client first
|
||||||
let create_script = format!(
|
let create_script = format!(
|
||||||
r#"
|
r#"
|
||||||
@@ -578,10 +622,10 @@ fn test_rfs_get_block_info_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
"#,
|
"#,
|
||||||
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
);
|
);
|
||||||
|
|
||||||
let result: bool = engine.eval(&create_script)?;
|
let result: bool = engine.eval(&create_script)?;
|
||||||
assert!(result, "Failed to create RFS client");
|
assert!(result, "Failed to create RFS client");
|
||||||
|
|
||||||
// Test getting block info with a test hash
|
// Test getting block info with a test hash
|
||||||
let info_script = r#"
|
let info_script = r#"
|
||||||
let result = rfs_get_blocks_by_hash("test_block_hash");
|
let result = rfs_get_blocks_by_hash("test_block_hash");
|
||||||
@@ -590,7 +634,7 @@ fn test_rfs_get_block_info_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
true
|
true
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
match engine.eval::<bool>(info_script) {
|
match engine.eval::<bool>(info_script) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
assert!(result, "Failed to get block info");
|
assert!(result, "Failed to get block info");
|
||||||
@@ -600,10 +644,10 @@ fn test_rfs_get_block_info_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let error_msg = e.to_string();
|
let error_msg = e.to_string();
|
||||||
println!("Block info error (may be expected): {}", error_msg);
|
println!("Block info error (may be expected): {}", error_msg);
|
||||||
assert!(
|
assert!(
|
||||||
error_msg.contains("404") ||
|
error_msg.contains("404")
|
||||||
error_msg.contains("not found") ||
|
|| error_msg.contains("not found")
|
||||||
error_msg.contains("OpenAPI") ||
|
|| error_msg.contains("OpenAPI")
|
||||||
error_msg.contains("RFS error")
|
|| error_msg.contains("RFS error")
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -619,7 +663,7 @@ fn test_rfs_get_block_info_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
fn test_rfs_download_file_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_rfs_download_file_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
// Create a client first
|
// Create a client first
|
||||||
let create_script = format!(
|
let create_script = format!(
|
||||||
r#"
|
r#"
|
||||||
@@ -627,14 +671,14 @@ fn test_rfs_download_file_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
"#,
|
"#,
|
||||||
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
);
|
);
|
||||||
|
|
||||||
let result: bool = engine.eval(&create_script)?;
|
let result: bool = engine.eval(&create_script)?;
|
||||||
assert!(result, "Failed to create RFS client");
|
assert!(result, "Failed to create RFS client");
|
||||||
|
|
||||||
// Create a temporary file for download
|
// Create a temporary file for download
|
||||||
let temp_file = NamedTempFile::new()?;
|
let temp_file = NamedTempFile::new()?;
|
||||||
let temp_path = temp_file.path().to_str().unwrap();
|
let temp_path = temp_file.path().to_str().unwrap();
|
||||||
|
|
||||||
// Test downloading a file (assuming test file hash exists)
|
// Test downloading a file (assuming test file hash exists)
|
||||||
let download_script = format!(
|
let download_script = format!(
|
||||||
r#"
|
r#"
|
||||||
@@ -645,13 +689,13 @@ fn test_rfs_download_file_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}}
|
}}
|
||||||
true
|
true
|
||||||
"#,
|
"#,
|
||||||
temp_path.replace('\\', "\\\\") // Escape backslashes for Windows paths
|
temp_path.replace('\\', "\\\\") // Escape backslashes for Windows paths
|
||||||
);
|
);
|
||||||
|
|
||||||
// This might fail if the test file doesn't exist, but we're testing the wrapper
|
// This might fail if the test file doesn't exist, but we're testing the wrapper
|
||||||
let result: bool = engine.eval(&download_script).unwrap_or_else(|_| true);
|
let result: bool = engine.eval(&download_script).unwrap_or_else(|_| true);
|
||||||
assert!(result, "Failed to execute download file script");
|
assert!(result, "Failed to execute download file script");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,7 +722,7 @@ fn test_flist_operations_workflow() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let temp_dir = tempfile::tempdir()?;
|
let temp_dir = tempfile::tempdir()?;
|
||||||
let output_path = temp_dir.path().join("downloaded_flist.fl");
|
let output_path = temp_dir.path().join("downloaded_flist.fl");
|
||||||
let output_path_str = output_path.to_str().unwrap();
|
let output_path_str = output_path.to_str().unwrap();
|
||||||
|
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).expect("Failed to register RFS module");
|
register_rfs_module(&mut engine).expect("Failed to register RFS module");
|
||||||
|
|
||||||
@@ -808,19 +852,19 @@ fn test_flist_operations_workflow() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
"#,
|
"#,
|
||||||
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add a helper function to parse JSON in Rhai
|
// Add a helper function to parse JSON in Rhai
|
||||||
engine.register_fn("parse_json", |json_str: &str| -> String {
|
engine.register_fn("parse_json", |json_str: &str| -> String {
|
||||||
// Just return the JSON string as is - Rhai can work with it directly
|
// Just return the JSON string as is - Rhai can work with it directly
|
||||||
json_str.to_string()
|
json_str.to_string()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Execute the script
|
// Execute the script
|
||||||
match engine.eval::<bool>(&script) {
|
match engine.eval::<bool>(&script) {
|
||||||
Ok(success) => {
|
Ok(success) => {
|
||||||
assert!(success, "FList operations workflow test failed");
|
assert!(success, "FList operations workflow test failed");
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error in FList operations workflow test: {}", e);
|
println!("Error in FList operations workflow test: {}", e);
|
||||||
// Don't fail the test if the server doesn't have the expected data
|
// Don't fail the test if the server doesn't have the expected data
|
||||||
@@ -843,7 +887,7 @@ fn test_flist_operations_workflow() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
fn test_rfs_download_flist_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_rfs_download_flist_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
// Create a client first
|
// Create a client first
|
||||||
let create_script = format!(
|
let create_script = format!(
|
||||||
r#"
|
r#"
|
||||||
@@ -851,14 +895,14 @@ fn test_rfs_download_flist_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
"#,
|
"#,
|
||||||
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
);
|
);
|
||||||
|
|
||||||
let result: bool = engine.eval(&create_script)?;
|
let result: bool = engine.eval(&create_script)?;
|
||||||
assert!(result, "Failed to create RFS client");
|
assert!(result, "Failed to create RFS client");
|
||||||
|
|
||||||
// Create a temporary file for download
|
// Create a temporary file for download
|
||||||
let temp_file = NamedTempFile::new()?;
|
let temp_file = NamedTempFile::new()?;
|
||||||
let temp_path = temp_file.path().to_str().unwrap();
|
let temp_path = temp_file.path().to_str().unwrap();
|
||||||
|
|
||||||
// Test downloading an FList (assuming test flist exists)
|
// Test downloading an FList (assuming test flist exists)
|
||||||
let download_script = format!(
|
let download_script = format!(
|
||||||
r#"
|
r#"
|
||||||
@@ -868,13 +912,13 @@ fn test_rfs_download_flist_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}}
|
}}
|
||||||
true
|
true
|
||||||
"#,
|
"#,
|
||||||
temp_path.replace('\\', "\\\\") // Escape backslashes for Windows paths
|
temp_path.replace('\\', "\\\\") // Escape backslashes for Windows paths
|
||||||
);
|
);
|
||||||
|
|
||||||
// This might fail if the test flist doesn't exist, but we're testing the wrapper
|
// This might fail if the test flist doesn't exist, but we're testing the wrapper
|
||||||
let result: bool = engine.eval(&download_script).unwrap_or_else(|_| true);
|
let result: bool = engine.eval(&download_script).unwrap_or_else(|_| true);
|
||||||
assert!(result, "Failed to execute download flist script");
|
assert!(result, "Failed to execute download flist script");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -883,7 +927,7 @@ fn test_rfs_download_flist_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
fn test_rfs_wait_for_flist_creation_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_rfs_wait_for_flist_creation_wrapper() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine)?;
|
register_rfs_module(&mut engine)?;
|
||||||
|
|
||||||
// Create a client first
|
// Create a client first
|
||||||
let create_script = format!(
|
let create_script = format!(
|
||||||
r#"
|
r#"
|
||||||
@@ -891,14 +935,14 @@ fn test_rfs_wait_for_flist_creation_wrapper() -> Result<(), Box<dyn std::error::
|
|||||||
"#,
|
"#,
|
||||||
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
);
|
);
|
||||||
|
|
||||||
let result: bool = engine.eval(&create_script)?;
|
let result: bool = engine.eval(&create_script)?;
|
||||||
assert!(result, "Failed to create RFS client");
|
assert!(result, "Failed to create RFS client");
|
||||||
|
|
||||||
// Authenticate before invoking operations that require it
|
// Authenticate before invoking operations that require it
|
||||||
let authed: bool = engine.eval(r#" rfs_authenticate() "#)?;
|
let authed: bool = engine.eval(r#" rfs_authenticate() "#)?;
|
||||||
assert!(authed, "Authentication failed in wait wrapper test");
|
assert!(authed, "Authentication failed in wait wrapper test");
|
||||||
|
|
||||||
// Intentionally use a dummy job id and assert the wrapper returns a meaningful error
|
// Intentionally use a dummy job id and assert the wrapper returns a meaningful error
|
||||||
let wait_script = r#"
|
let wait_script = r#"
|
||||||
// This call should fail because the job id is dummy; we want to see the error path
|
// This call should fail because the job id is dummy; we want to see the error path
|
||||||
@@ -907,13 +951,20 @@ fn test_rfs_wait_for_flist_creation_wrapper() -> Result<(), Box<dyn std::error::
|
|||||||
|
|
||||||
let eval_res = engine.eval::<String>(wait_script);
|
let eval_res = engine.eval::<String>(wait_script);
|
||||||
match eval_res {
|
match eval_res {
|
||||||
Ok(s) => panic!("Expected failure for dummy job id, but got success with result: {}", s),
|
Ok(s) => panic!(
|
||||||
|
"Expected failure for dummy job id, but got success with result: {}",
|
||||||
|
s
|
||||||
|
),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let msg = e.to_string();
|
let msg = e.to_string();
|
||||||
assert!(msg.contains("Operation timed out"), "Unexpected error message: {}", msg);
|
assert!(
|
||||||
|
msg.contains("Operation timed out"),
|
||||||
|
"Unexpected error message: {}",
|
||||||
|
msg
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -925,18 +976,24 @@ fn test_rfs_wait_for_flist_creation_wrapper() -> Result<(), Box<dyn std::error::
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_rfs_get_system_info_with_server() {
|
fn test_rfs_get_system_info_with_server() {
|
||||||
if !is_server_running(TEST_SERVER_URL) {
|
if !is_server_running(TEST_SERVER_URL) {
|
||||||
println!("Skipping integration test - no RFS server running at {}", TEST_SERVER_URL);
|
println!(
|
||||||
|
"Skipping integration test - no RFS server running at {}",
|
||||||
|
TEST_SERVER_URL
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).unwrap();
|
register_rfs_module(&mut engine).unwrap();
|
||||||
|
|
||||||
let script = format!(r#"
|
let script = format!(
|
||||||
|
r#"
|
||||||
rfs_create_client("{}", "", "", 30);
|
rfs_create_client("{}", "", "", 30);
|
||||||
rfs_get_system_info()
|
rfs_get_system_info()
|
||||||
"#, TEST_SERVER_URL);
|
"#,
|
||||||
|
TEST_SERVER_URL
|
||||||
|
);
|
||||||
|
|
||||||
let result = engine.eval::<String>(&script);
|
let result = engine.eval::<String>(&script);
|
||||||
match result {
|
match result {
|
||||||
Ok(info) => {
|
Ok(info) => {
|
||||||
@@ -954,19 +1011,25 @@ fn test_rfs_get_system_info_with_server() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_rfs_authenticate_with_server() {
|
fn test_rfs_authenticate_with_server() {
|
||||||
if !is_server_running(TEST_SERVER_URL) {
|
if !is_server_running(TEST_SERVER_URL) {
|
||||||
println!("Skipping integration test - no RFS server running at {}", TEST_SERVER_URL);
|
println!(
|
||||||
|
"Skipping integration test - no RFS server running at {}",
|
||||||
|
TEST_SERVER_URL
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).unwrap();
|
register_rfs_module(&mut engine).unwrap();
|
||||||
|
|
||||||
// Test with dummy credentials (will likely fail, but tests the flow)
|
// Test with dummy credentials (will likely fail, but tests the flow)
|
||||||
let script = format!(r#"
|
let script = format!(
|
||||||
|
r#"
|
||||||
rfs_create_client("{}", "{}", "{}", 30);
|
rfs_create_client("{}", "{}", "{}", 30);
|
||||||
rfs_authenticate()
|
rfs_authenticate()
|
||||||
"#, TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD);
|
"#,
|
||||||
|
TEST_SERVER_URL, TEST_USERNAME, TEST_PASSWORD
|
||||||
|
);
|
||||||
|
|
||||||
let result = engine.eval::<bool>(&script);
|
let result = engine.eval::<bool>(&script);
|
||||||
match result {
|
match result {
|
||||||
Ok(success) => {
|
Ok(success) => {
|
||||||
@@ -974,7 +1037,10 @@ fn test_rfs_authenticate_with_server() {
|
|||||||
assert!(success);
|
assert!(success);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Expected authentication failure with dummy credentials: {}", e);
|
println!(
|
||||||
|
"Expected authentication failure with dummy credentials: {}",
|
||||||
|
e
|
||||||
|
);
|
||||||
// This is expected with dummy credentials
|
// This is expected with dummy credentials
|
||||||
assert!(e.to_string().contains("Authentication failed"));
|
assert!(e.to_string().contains("Authentication failed"));
|
||||||
}
|
}
|
||||||
@@ -985,14 +1051,18 @@ fn test_rfs_authenticate_with_server() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_complete_workflow_with_server() {
|
fn test_complete_workflow_with_server() {
|
||||||
if !is_server_running(TEST_SERVER_URL) {
|
if !is_server_running(TEST_SERVER_URL) {
|
||||||
println!("Skipping integration test - no RFS server running at {}", TEST_SERVER_URL);
|
println!(
|
||||||
|
"Skipping integration test - no RFS server running at {}",
|
||||||
|
TEST_SERVER_URL
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut engine = Engine::new();
|
let mut engine = Engine::new();
|
||||||
register_rfs_module(&mut engine).unwrap();
|
register_rfs_module(&mut engine).unwrap();
|
||||||
|
|
||||||
let script = format!(r#"
|
let script = format!(
|
||||||
|
r#"
|
||||||
// Create client
|
// Create client
|
||||||
let client_created = rfs_create_client("{}", "", "", 60);
|
let client_created = rfs_create_client("{}", "", "", 60);
|
||||||
print("Client created: " + client_created);
|
print("Client created: " + client_created);
|
||||||
@@ -1003,8 +1073,10 @@ fn test_complete_workflow_with_server() {
|
|||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
client_created && info_result.len() > 0
|
client_created && info_result.len() > 0
|
||||||
"#, TEST_SERVER_URL);
|
"#,
|
||||||
|
TEST_SERVER_URL
|
||||||
|
);
|
||||||
|
|
||||||
let result = engine.eval::<bool>(&script);
|
let result = engine.eval::<bool>(&script);
|
||||||
match result {
|
match result {
|
||||||
Ok(success) => {
|
Ok(success) => {
|
||||||
|
Reference in New Issue
Block a user