Files
projectmycelium/tests/tests_archive/test_json_parsing_fix.rs
2025-09-01 21:37:01 -04:00

243 lines
7.5 KiB
Rust

use std::fs;
use serde_json;
// Since this is an integration test, we need to include the modules directly
// or create a simple test that doesn't rely on the full crate structure
// Let's create a simple JSON parsing test using serde_json directly
use serde::{Deserialize, Serialize};
use rust_decimal::Decimal;
use chrono::{DateTime, Utc};
// Copy the essential structs for testing
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserPersistentData {
pub user_email: String,
#[serde(default)]
pub wallet_balance: Decimal,
#[serde(default)]
pub nodes: Vec<FarmNode>,
#[serde(default)]
pub slas: Vec<ServiceLevelAgreement>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FarmNode {
pub id: String,
pub name: String,
pub location: String,
#[serde(deserialize_with = "deserialize_node_status")]
pub status: NodeStatus,
pub capacity: NodeCapacity,
pub used_capacity: NodeCapacity,
pub uptime_percentage: f32,
#[serde(deserialize_with = "deserialize_earnings", alias = "earnings_today_usd")]
pub earnings_today: Decimal,
#[serde(deserialize_with = "deserialize_datetime")]
pub last_seen: DateTime<Utc>,
pub health_score: f32,
pub region: String,
pub node_type: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NodeCapacity {
pub cpu_cores: i32,
pub memory_gb: i32,
pub storage_gb: i32,
pub bandwidth_mbps: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum NodeStatus {
Online,
Offline,
Maintenance,
Error,
Standby,
}
impl std::fmt::Display for NodeStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
NodeStatus::Online => write!(f, "Online"),
NodeStatus::Offline => write!(f, "Offline"),
NodeStatus::Maintenance => write!(f, "Maintenance"),
NodeStatus::Error => write!(f, "Error"),
NodeStatus::Standby => write!(f, "Standby"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceLevelAgreement {
pub id: String,
#[serde(alias = "client_name")]
pub name: String,
#[serde(alias = "service_type")]
pub description: String,
#[serde(default)]
pub service_id: Option<String>,
pub response_time_hours: i32,
pub resolution_time_hours: i32,
#[serde(alias = "uptime_guarantee")]
pub availability_percentage: f32,
#[serde(default = "default_support_hours")]
pub support_hours: String,
#[serde(default = "default_escalation_procedure")]
pub escalation_procedure: String,
#[serde(default)]
pub penalties: Vec<SLAPenalty>,
#[serde(alias = "created_date")]
pub created_at: String,
pub status: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SLAPenalty {
pub breach_type: String,
pub threshold: String,
pub penalty_amount: i32,
pub penalty_type: String,
}
fn default_support_hours() -> String {
"Business Hours".to_string()
}
fn default_escalation_procedure() -> String {
"Standard escalation procedure".to_string()
}
// Custom deserializers
fn deserialize_node_status<'de, D>(deserializer: D) -> Result<NodeStatus, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
match s.as_str() {
"Online" => Ok(NodeStatus::Online),
"Offline" => Ok(NodeStatus::Offline),
"Maintenance" => Ok(NodeStatus::Maintenance),
"Error" => Ok(NodeStatus::Error),
"Standby" => Ok(NodeStatus::Standby),
_ => Ok(NodeStatus::Online),
}
}
fn deserialize_earnings<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
use std::str::FromStr;
#[derive(Deserialize)]
#[serde(untagged)]
enum EarningsValue {
Number(f64),
String(String),
}
let value = EarningsValue::deserialize(deserializer)?;
match value {
EarningsValue::Number(n) => {
Decimal::from_str(&n.to_string()).map_err(D::Error::custom)
}
EarningsValue::String(s) => {
Decimal::from_str(&s).map_err(D::Error::custom)
}
}
}
fn deserialize_datetime<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
let s = String::deserialize(deserializer)?;
DateTime::parse_from_rfc3339(&s)
.map(|dt| dt.with_timezone(&Utc))
.map_err(D::Error::custom)
}
#[test]
fn test_user1_json_parsing() {
println!("Testing JSON parsing fixes for user1...");
// Test parsing user1 data
let user1_path = "./user_data/user1_at_example_com.json";
let json_content = fs::read_to_string(user1_path)
.expect("Should be able to read user1 JSON file");
println!("✓ Successfully read user1 JSON file");
let user_data: UserPersistentData = serde_json::from_str(&json_content)
.expect("Should be able to parse user1 JSON without errors");
println!("✅ SUCCESS: JSON parsing completed without errors!");
println!(" - User email: {}", user_data.user_email);
println!(" - Number of nodes: {}", user_data.nodes.len());
println!(" - Number of SLAs: {}", user_data.slas.len());
// Verify we have the expected data
assert_eq!(user_data.user_email, "user1@example.com");
assert_eq!(user_data.nodes.len(), 2, "Should have 2 farm nodes");
assert!(user_data.slas.len() >= 1, "Should have at least 1 SLA");
let has_expected_sla = user_data
.slas
.iter()
.any(|s| s.id == "SLA-1001" && s.name == "RetailCorp" && s.description == "E-commerce Development");
assert!(
has_expected_sla,
"Expected SLA 'SLA-1001' (RetailCorp - E-commerce Development) not found"
);
// Check first node details
let first_node = &user_data.nodes[0];
assert_eq!(first_node.id, "TF-US-001");
assert_eq!(first_node.name, "New York Data Center");
println!(" - First node: {} ({})", first_node.name, first_node.status);
println!(" - Earnings today: {}", first_node.earnings_today);
// Check expected SLA details (by ID)
let expected_sla = user_data
.slas
.iter()
.find(|s| s.id == "SLA-1001")
.expect("Expected SLA 'SLA-1001' to be present");
assert_eq!(expected_sla.name, "RetailCorp");
assert_eq!(expected_sla.description, "E-commerce Development");
println!(" - Expected SLA: {} ({})", expected_sla.name, expected_sla.status);
println!("\n🎉 All assertions passed! The JSON parsing fixes are working correctly.");
}
#[test]
fn test_all_user_json_files() {
println!("Testing JSON parsing for all user files...");
let user_files = [
"user1_at_example_com.json",
"user2_at_example_com.json",
"user3_at_example_com.json",
"user4_at_example_com.json",
"user5_at_example_com.json",
"user6_at_example_com.json",
];
for file in &user_files {
let path = format!("./user_data/{}", file);
println!("Testing {}", file);
let json_content = fs::read_to_string(&path)
.unwrap_or_else(|_| panic!("Should be able to read {}", file));
let _user_data: UserPersistentData = serde_json::from_str(&json_content)
.unwrap_or_else(|e| panic!("Should be able to parse {} without errors: {}", file, e));
println!("{} parsed successfully", file);
}
println!("🎉 All user JSON files parsed successfully!");
}