/ tests / integration / test_backup_restore.rs
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  }