use std::future::Future;
use std::sync::Arc;
use std::thread;
use tempfile::TempDir;
#[tokio::test]
async fn test_storage_node_new_returns_send_future() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let config = storage_bindings::StorageConfig::new()
.log_level(storage_bindings::LogLevel::Error)
.data_dir(temp_dir.path());
let future = storage_bindings::StorageNode::new(config);
let handle = thread::spawn(move || {
std::mem::drop(future);
});
handle.join().expect("Thread panicked");
}
#[tokio::test(flavor = "multi_thread")]
async fn test_storage_node_new_in_tokio_spawn() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let config = storage_bindings::StorageConfig::new()
.log_level(storage_bindings::LogLevel::Error)
.data_dir(temp_dir.path());
let handle = tokio::spawn(async move {
let _node = storage_bindings::StorageNode::new(config).await;
});
let result = handle.await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_storage_node_start_returns_send_future() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let config = storage_bindings::StorageConfig::new()
.log_level(storage_bindings::LogLevel::Error)
.data_dir(temp_dir.path());
let node_result = storage_bindings::StorageNode::new(config).await;
if let Ok(node) = node_result {
let handle = thread::spawn(move || {
std::mem::drop(node.start());
});
handle.join().expect("Thread panicked");
}
}
#[tokio::test]
async fn test_storage_node_stop_returns_send_future() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let config = storage_bindings::StorageConfig::new()
.log_level(storage_bindings::LogLevel::Error)
.data_dir(temp_dir.path());
let node_result = storage_bindings::StorageNode::new(config).await;
if let Ok(node) = node_result {
let handle = thread::spawn(move || {
std::mem::drop(node.stop());
});
handle.join().expect("Thread panicked");
}
}
#[tokio::test]
async fn test_storage_node_peer_id_returns_send_future() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let config = storage_bindings::StorageConfig::new()
.log_level(storage_bindings::LogLevel::Error)
.data_dir(temp_dir.path());
let node_result = storage_bindings::StorageNode::new(config).await;
if let Ok(node) = node_result {
let handle = thread::spawn(move || {
std::mem::drop(node.peer_id());
});
handle.join().expect("Thread panicked");
}
}
#[tokio::test(flavor = "multi_thread")]
async fn test_multi_threaded_command_scenario() {
let temp_dir = Arc::new(TempDir::new().expect("Failed to create temp directory"));
let temp_dir_clone = temp_dir.clone();
async fn start_node_command(data_dir: std::path::PathBuf) -> Result<(), String> {
let config = storage_bindings::StorageConfig::new()
.log_level(storage_bindings::LogLevel::Error)
.data_dir(&data_dir);
let node = storage_bindings::StorageNode::new(config)
.await
.map_err(|e| e.to_string())?;
node.start().await.map_err(|e| e.to_string())?;
Ok(())
}
let handle =
tokio::spawn(async move { start_node_command(temp_dir_clone.path().to_path_buf()).await });
let result = handle.await;
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_future_is_send_trait_bound() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let config = storage_bindings::StorageConfig::new()
.log_level(storage_bindings::LogLevel::Error)
.data_dir(temp_dir.path());
let future = storage_bindings::StorageNode::new(config);
fn assert_send<F: Future + Send>(_: F) {}
assert_send(future);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_concurrent_send_futures() {
let temp_dir1 = TempDir::new().expect("Failed to create temp directory");
let temp_dir2 = TempDir::new().expect("Failed to create temp directory");
let config1 = storage_bindings::StorageConfig::new()
.log_level(storage_bindings::LogLevel::Error)
.data_dir(temp_dir1.path());
let config2 = storage_bindings::StorageConfig::new()
.log_level(storage_bindings::LogLevel::Error)
.data_dir(temp_dir2.path());
let handle1 = tokio::spawn(async move { storage_bindings::StorageNode::new(config1).await });
let handle2 = tokio::spawn(async move { storage_bindings::StorageNode::new(config2).await });
let _ = handle1.await;
let _ = handle2.await;
}
#[tokio::test]
async fn test_arc_storage_node_is_send() {
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let config = storage_bindings::StorageConfig::new()
.log_level(storage_bindings::LogLevel::Error)
.data_dir(temp_dir.path());
let node_result = storage_bindings::StorageNode::new(config).await;
if let Ok(node) = node_result {
let node_arc = Arc::new(node);
let handle = thread::spawn(move || {
let _ = node_arc;
});
handle.join().expect("Thread panicked");
}
}
#[tokio::test]
async fn test_send_safe_cstring_in_async_context() {
use storage_bindings::ffi::SendSafeCString;
let json_config = r#"{"log_level":"error","data_dir":"/tmp"}"#;
let c_json_config = SendSafeCString::new(json_config);
let future = async move {
let _ptr = c_json_config;
};
let handle = thread::spawn(move || {
std::mem::drop(Box::pin(future));
});
handle.join().expect("Thread panicked");
}