test_backup_restore.rs
1 //! Integration tests for backup and restore operations. 2 //! 3 //! Tests: backup before risky operations, restore after failure, metadata integrity 4 5 mod common; 6 7 use common::assertions::*; 8 use common::fixtures::*; 9 use common::mocks::*; 10 use common::TestEnv; 11 12 #[test] 13 fn test_backup_before_risky_operation() { 14 // Setup 15 let env = TestEnv::new().expect("Failed to create test environment"); 16 let systemd = MockSystemd::new(); 17 18 // Install initial version 19 let binary = env 20 .create_binary("adnet", b"#!/bin/bash\necho 'v1.0.0'") 21 .expect("Failed to create binary"); 22 23 let config = env 24 .create_config("adnet.toml", &sample_config_toml()) 25 .expect("Failed to create config"); 26 27 systemd.enable_service("adnet").expect("Failed to enable"); 28 systemd.start_service("adnet").expect("Failed to start"); 29 30 assert_service_running(&systemd, "adnet"); 31 32 // Create backup before risky update 33 let backup_dir = env.base_path().join("backups"); 34 std::fs::create_dir(&backup_dir).expect("Failed to create backup dir"); 35 36 let timestamp = chrono::Utc::now().format("%Y%m%d-%H%M%S").to_string(); 37 let backup_binary = backup_dir.join(format!("adnet-{}.backup", timestamp)); 38 let backup_config = backup_dir.join(format!("adnet.toml-{}.backup", timestamp)); 39 40 std::fs::copy(&binary, &backup_binary).expect("Failed to backup binary"); 41 std::fs::copy(&config, &backup_config).expect("Failed to backup config"); 42 43 // Create backup metadata 44 let metadata = serde_json::json!({ 45 "id": format!("backup-{}", timestamp), 46 "backup_type": "pre-update", 47 "created_at": chrono::Utc::now().to_rfc3339(), 48 "version": "1.0.0", 49 "files": ["adnet", "adnet.toml"], 50 "service_state": "running", 51 }); 52 53 let metadata_path = backup_dir.join(format!("metadata-{}.json", timestamp)); 54 std::fs::write(&metadata_path, serde_json::to_string_pretty(&metadata).unwrap()) 55 .expect("Failed to write metadata"); 56 57 // Verify backup created 58 assert!(backup_binary.exists()); 59 assert!(backup_config.exists()); 60 assert!(metadata_path.exists()); 61 62 // Verify backup contents match original 63 let original_binary = std::fs::read(&binary).unwrap(); 64 let backed_up_binary = std::fs::read(&backup_binary).unwrap(); 65 assert_eq!(original_binary, backed_up_binary); 66 } 67 68 #[test] 69 fn test_restore_after_failed_update() { 70 // Setup 71 let env = TestEnv::new().expect("Failed to create test environment"); 72 let systemd = MockSystemd::new(); 73 74 // Install v1.0.0 75 let binary = env 76 .create_binary("adnet", b"#!/bin/bash\necho 'v1.0.0'") 77 .expect("Failed to create binary"); 78 79 systemd.enable_service("adnet").expect("Failed to enable"); 80 systemd.start_service("adnet").expect("Failed to start"); 81 82 // Create backup 83 let backup_dir = env.base_path().join("backups"); 84 std::fs::create_dir(&backup_dir).expect("Failed to create backup dir"); 85 86 let backup_path = backup_dir.join("adnet.v1.0.0.backup"); 87 std::fs::copy(&binary, &backup_path).expect("Failed to backup"); 88 89 // Simulate failed update to v2.0.0 90 let broken_binary = b"#!/bin/bash\nexit 1"; // Broken 91 std::fs::write(&binary, broken_binary).expect("Failed to write broken binary"); 92 93 // Service fails to start 94 systemd.stop_service("adnet").ok(); 95 96 let start_result = systemd.start_service("adnet"); 97 // In real scenario, this would fail health check 98 // For test, we simulate by stopping it 99 systemd.stop_service("adnet").ok(); 100 101 // Restore from backup 102 std::fs::copy(&backup_path, &binary).expect("Failed to restore"); 103 104 // Restart service 105 systemd.start_service("adnet").expect("Failed to start after restore"); 106 107 // Verify restore successful 108 assert_service_running(&systemd, "adnet"); 109 110 let content = std::fs::read_to_string(&binary).unwrap(); 111 assert!(content.contains("v1.0.0"), "Should be restored to v1.0.0"); 112 } 113 114 #[test] 115 fn test_backup_metadata_integrity() { 116 // Setup 117 let env = TestEnv::new().expect("Failed to create test environment"); 118 119 // Create backup with comprehensive metadata 120 let backup_dir = env.base_path().join("backups"); 121 std::fs::create_dir(&backup_dir).expect("Failed to create backup dir"); 122 123 let metadata = sample_backup_metadata(); 124 let metadata_path = backup_dir.join("metadata.json"); 125 std::fs::write(&metadata_path, serde_json::to_string_pretty(&metadata).unwrap()) 126 .expect("Failed to write metadata"); 127 128 // Verify metadata integrity 129 assert!(metadata_path.exists()); 130 131 let loaded: serde_json::Value = 132 serde_json::from_str(&std::fs::read_to_string(&metadata_path).unwrap()) 133 .expect("Failed to parse metadata"); 134 135 // Verify all required fields 136 assert!(loaded.get("id").is_some(), "Missing id"); 137 assert!(loaded.get("backup_type").is_some(), "Missing backup_type"); 138 assert!(loaded.get("node_id").is_some(), "Missing node_id"); 139 assert!(loaded.get("created_at").is_some(), "Missing created_at"); 140 assert!(loaded.get("checksum").is_some(), "Missing checksum"); 141 assert!(loaded.get("files").is_some(), "Missing files"); 142 143 // Verify field values 144 assert_eq!(loaded["backup_type"], "full"); 145 assert_eq!(loaded["node_id"], "test-node"); 146 assert_eq!(loaded["compressed"], true); 147 assert_eq!(loaded["encrypted"], false); 148 149 // Verify files array 150 let files = loaded["files"].as_array().expect("Files should be array"); 151 assert_eq!(files.len(), 2); 152 assert_eq!(files[0], "config.toml"); 153 assert_eq!(files[1], "data.db"); 154 155 // Calculate metadata checksum for integrity 156 use sha2::{Digest, Sha256}; 157 let metadata_content = std::fs::read(&metadata_path).unwrap(); 158 let mut hasher = Sha256::new(); 159 hasher.update(&metadata_content); 160 let metadata_checksum = format!("{:x}", hasher.finalize()); 161 162 // In real scenario, would verify against stored checksum 163 assert!(!metadata_checksum.is_empty()); 164 }