use std::path::Path;
use std::sync::Arc;
use tempfile::TempDir;
use tokio::fs;
use cqlite_core::platform::Platform;
use cqlite_core::storage::sstable::{
index_reader::IndexReader, statistics_reader::StatisticsReader, summary_reader::SummaryReader,
SSTableReader,
};
use cqlite_core::Config;
#[tokio::test]
async fn test_component_path_building() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
let data_file = base_path.join("nb-1-big-Data.db");
let index_file = base_path.join("nb-1-big-Index.db");
let summary_file = base_path.join("nb-1-big-Summary.db");
let statistics_file = base_path.join("nb-1-big-Statistics.db");
fs::write(&data_file, b"mock_data").await.unwrap();
fs::write(&index_file, b"mock_index").await.unwrap();
fs::write(&summary_file, b"mock_summary").await.unwrap();
fs::write(&statistics_file, b"mock_statistics")
.await
.unwrap();
let stem = data_file.file_stem().unwrap().to_str().unwrap();
assert_eq!(stem, "nb-1-big-Data");
let base_name = stem.strip_suffix("-Data").unwrap();
assert_eq!(base_name, "nb-1-big");
assert!(index_file.exists());
assert!(summary_file.exists());
assert!(statistics_file.exists());
}
#[tokio::test]
async fn test_file_naming_patterns() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
let test_patterns = vec![
("nb-1-big", "nb-1-big-Data.db"),
("mc-1-big", "mc-1-big-Data.db"),
("la-1-big", "la-1-big-Data.db"),
("users-123abc", "users-123abc-Data.db"),
(
"collections_table-456def",
"collections_table-456def-Data.db",
),
];
for (base_name, data_filename) in test_patterns {
let data_path = base_path.join(data_filename);
fs::write(&data_path, b"mock_data").await.unwrap();
let index_path = base_path.join(format!("{}-Index.db", base_name));
let summary_path = base_path.join(format!("{}-Summary.db", base_name));
let statistics_path = base_path.join(format!("{}-Statistics.db", base_name));
fs::write(&index_path, b"mock_index").await.unwrap();
fs::write(&summary_path, b"mock_summary").await.unwrap();
fs::write(&statistics_path, b"mock_statistics")
.await
.unwrap();
assert!(
data_path.exists(),
"Data file should exist: {}",
data_filename
);
assert!(
index_path.exists(),
"Index file should exist for {}",
base_name
);
assert!(
summary_path.exists(),
"Summary file should exist for {}",
base_name
);
assert!(
statistics_path.exists(),
"Statistics file should exist for {}",
base_name
);
fs::remove_file(&data_path).await.unwrap();
fs::remove_file(&index_path).await.unwrap();
fs::remove_file(&summary_path).await.unwrap();
fs::remove_file(&statistics_path).await.unwrap();
}
}
#[tokio::test]
async fn test_sstable_reader_component_loading() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
let data_file = base_path.join("nb-1-big-Data.db");
let index_file = base_path.join("nb-1-big-Index.db");
let summary_file = base_path.join("nb-1-big-Summary.db");
let statistics_file = base_path.join("nb-1-big-Statistics.db");
create_mock_data_file(&data_file).await;
create_mock_index_file(&index_file).await;
create_mock_summary_file(&summary_file).await;
create_mock_statistics_file(&statistics_file).await;
let config = Config::default();
let platform = Arc::new(Platform::new(&config).await.unwrap());
test_index_reader_loading(&index_file, &platform).await;
test_summary_reader_loading(&summary_file, &platform).await;
test_statistics_reader_loading(&statistics_file, &platform).await;
}
async fn test_index_reader_loading(index_path: &Path, platform: &Arc<Platform>) {
let result = IndexReader::open(index_path, platform.clone()).await;
match result {
Ok(_) => {
println!("Index reader successfully opened mock file");
}
Err(e) => {
println!("Index reader failed as expected with mock data: {}", e);
}
}
}
async fn test_summary_reader_loading(summary_path: &Path, platform: &Arc<Platform>) {
let result = SummaryReader::open(summary_path, platform.clone()).await;
match result {
Ok(_) => {
println!("Summary reader successfully opened mock file");
}
Err(e) => {
println!("Summary reader failed as expected with mock data: {}", e);
}
}
}
async fn test_statistics_reader_loading(statistics_path: &Path, platform: &Arc<Platform>) {
let result = StatisticsReader::open(statistics_path, platform.clone()).await;
match result {
Ok(_) => {
println!("Statistics reader successfully opened mock file");
}
Err(e) => {
println!("Statistics reader failed as expected with mock data: {}", e);
}
}
}
#[tokio::test]
async fn test_missing_component_files() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
let data_file = base_path.join("nb-1-big-Data.db");
create_mock_data_file(&data_file).await;
let config = Config::default();
let platform = Arc::new(Platform::new(&config).await.unwrap());
let index_path = base_path.join("nb-1-big-Index.db");
let summary_path = base_path.join("nb-1-big-Summary.db");
let statistics_path = base_path.join("nb-1-big-Statistics.db");
assert!(IndexReader::open(&index_path, platform.clone())
.await
.is_err());
assert!(SummaryReader::open(&summary_path, platform.clone())
.await
.is_err());
assert!(StatisticsReader::open(&statistics_path, platform.clone())
.await
.is_err());
}
#[tokio::test]
async fn test_malformed_component_files() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
let index_file = base_path.join("nb-1-big-Index.db");
let summary_file = base_path.join("nb-1-big-Summary.db");
let statistics_file = base_path.join("nb-1-big-Statistics.db");
fs::write(&index_file, b"").await.unwrap(); fs::write(&summary_file, b"corrupted_summary")
.await
.unwrap();
fs::write(&statistics_file, b"bad_statistics")
.await
.unwrap();
let config = Config::default();
let platform = Arc::new(Platform::new(&config).await.unwrap());
let index_result = IndexReader::open(&index_file, platform.clone()).await;
let summary_result = SummaryReader::open(&summary_file, platform.clone()).await;
let statistics_result = StatisticsReader::open(&statistics_file, platform.clone()).await;
assert!(index_result.is_err());
assert!(summary_result.is_err());
assert!(statistics_result.is_err());
}
#[tokio::test]
async fn test_path_building_edge_cases() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
let edge_cases = vec![
"nb-1-big-Data.db",
"mc-123-large-Data.db",
"table_name-abc123def-Data.db",
"users-46436710673711f0b2cf19d64e7cbecb-Data.db", ];
for data_filename in edge_cases {
let data_path = base_path.join(data_filename);
fs::write(&data_path, b"test").await.unwrap();
let file_stem = data_path.file_stem().unwrap().to_str().unwrap();
if let Some(base_name) = file_stem.strip_suffix("-Data") {
let index_path = base_path.join(format!("{}-Index.db", base_name));
let summary_path = base_path.join(format!("{}-Summary.db", base_name));
let statistics_path = base_path.join(format!("{}-Statistics.db", base_name));
assert!(index_path.to_string_lossy().ends_with("-Index.db"));
assert!(summary_path.to_string_lossy().ends_with("-Summary.db"));
assert!(statistics_path
.to_string_lossy()
.ends_with("-Statistics.db"));
println!("✓ Path building works for: {}", data_filename);
}
fs::remove_file(&data_path).await.unwrap();
}
}
async fn create_mock_data_file(path: &Path) {
let mock_header = vec![
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
fs::write(path, mock_header).await.unwrap();
}
async fn create_mock_index_file(path: &Path) {
let mock_index = vec![
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, ];
fs::write(path, mock_index).await.unwrap();
}
async fn create_mock_summary_file(path: &Path) {
let mock_summary = vec![
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, ];
fs::write(path, mock_summary).await.unwrap();
}
async fn create_mock_statistics_file(path: &Path) {
let mock_stats = vec![
0x00, 0x00, 0x00, 0x10, 0x74, 0x65, 0x73, 0x74, ];
fs::write(path, mock_stats).await.unwrap();
}
#[cfg(test)]
mod component_integration_tests {
use super::*;
#[tokio::test]
async fn test_full_sstable_workflow_with_components() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
let data_file = base_path.join("nb-1-big-Data.db");
let index_file = base_path.join("nb-1-big-Index.db");
let summary_file = base_path.join("nb-1-big-Summary.db");
let statistics_file = base_path.join("nb-1-big-Statistics.db");
create_mock_data_file(&data_file).await;
create_mock_index_file(&index_file).await;
create_mock_summary_file(&summary_file).await;
create_mock_statistics_file(&statistics_file).await;
let config = Config::default();
let platform = Arc::new(Platform::new(&config).await.unwrap());
let reader_result = SSTableReader::open(&data_file, &config, platform).await;
match reader_result {
Ok(reader) => {
println!("✓ SSTableReader successfully created with all components");
let _ = reader.get_timestamp_range().await;
}
Err(e) => {
println!(
"✓ SSTableReader creation failed as expected with mock data: {}",
e
);
}
}
}
#[tokio::test]
async fn test_index_derived_operations_not_dead_code() {
let temp_dir = TempDir::new().unwrap();
let base_path = temp_dir.path();
let data_file = base_path.join("nb-1-big-Data.db");
create_mock_data_file(&data_file).await;
let config = Config::default();
let platform = Arc::new(Platform::new(&config).await.unwrap());
if let Ok(reader) = SSTableReader::open(&data_file, &config, platform).await {
let test_key = b"test_partition_key";
let _lookup_result = reader.lookup_partition_with_index(test_key).await;
let _partitions = reader.iterate_all_partitions().await;
println!("✓ Index-derived operations are accessible and not dead code");
}
}
}