1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
|
use std::io::Error;
use cfg_file::config::ConfigFile;
use vcs_data::{
constants::{SERVER_FILE_SHEET, SERVER_FILE_VAULT},
data::{
member::{Member, MemberId},
sheet::SheetName,
vault::{Vault, vault_config::VaultConfig, virtual_file::VirtualFileId},
},
};
use crate::get_test_dir;
#[tokio::test]
async fn test_sheet_creation_management_and_persistence() -> Result<(), std::io::Error> {
let dir = get_test_dir("sheet_management").await?;
// Setup vault
Vault::setup_vault(dir.clone(), "TestVault").await?;
// Get vault
let config = VaultConfig::read_from(dir.join(SERVER_FILE_VAULT)).await?;
let Some(vault) = Vault::init(config, &dir) else {
return Err(Error::new(std::io::ErrorKind::NotFound, "Vault not found!"));
};
// Add a member to use as sheet holder
let member_id: MemberId = "test_member".to_string();
vault
.register_member_to_vault(Member::new(&member_id))
.await?;
// Test 1: Create a new sheet
let sheet_name: SheetName = "test_sheet".to_string();
let sheet = vault.create_sheet(&sheet_name, &member_id).await?;
// Verify sheet properties
assert_eq!(sheet.holder(), Some(&member_id));
assert_eq!(sheet.holder(), Some(&member_id));
assert!(sheet.mapping().is_empty());
// Verify sheet file was created
let sheet_path = dir.join(SERVER_FILE_SHEET.replace("{sheet_name}", &sheet_name));
assert!(sheet_path.exists());
// Test 2: Add mapping entries to the sheet
let mut sheet = vault.sheet(&sheet_name).await?;
// Add mapping entries for the files
let main_rs_path = vcs_data::data::sheet::SheetPathBuf::from("src/main.rs");
let lib_rs_path = vcs_data::data::sheet::SheetPathBuf::from("src/lib.rs");
let main_rs_id = VirtualFileId::new();
let lib_rs_id = VirtualFileId::new();
sheet
.add_mapping(
main_rs_path.clone(),
main_rs_id.clone(),
"1.0.0".to_string(),
)
.await?;
sheet
.add_mapping(lib_rs_path.clone(), lib_rs_id.clone(), "1.0.0".to_string())
.await?;
// Verify mappings were added
assert_eq!(sheet.mapping().len(), 2);
// Test 3: Add more mapping entries
let mapping_path = vcs_data::data::sheet::SheetPathBuf::from("output/build.exe");
let virtual_file_id = VirtualFileId::new();
sheet
.add_mapping(
mapping_path.clone(),
virtual_file_id.clone(),
"1.0.0".to_string(),
)
.await?;
// Verify mapping was added
assert_eq!(sheet.mapping().len(), 3);
assert_eq!(
sheet.mapping().get(&mapping_path).map(|meta| &meta.id),
Some(&virtual_file_id)
);
// Test 4: Persist sheet to disk
sheet.persist().await?;
// Verify persistence by reloading the sheet
let reloaded_sheet = vault.sheet(&sheet_name).await?;
assert_eq!(reloaded_sheet.holder(), Some(&member_id));
assert_eq!(reloaded_sheet.mapping().len(), 3);
// Test 5: Remove mapping entry
let mut sheet_for_removal = vault.sheet(&sheet_name).await?;
let _removed_virtual_file_id = sheet_for_removal.remove_mapping(&mapping_path).await;
// Don't check the return value since it depends on virtual file existence
assert_eq!(sheet_for_removal.mapping().len(), 2);
// Test 6: List all sheets in vault
let sheet_names = vault.sheet_names()?;
assert_eq!(sheet_names.len(), 2);
assert!(sheet_names.contains(&sheet_name));
assert!(sheet_names.contains(&"ref".to_string()));
let all_sheets = vault.sheets().await?;
assert_eq!(all_sheets.len(), 2);
// One sheet should be the test sheet, the other should be the ref sheet with host as holder
let test_sheet_holder = all_sheets
.iter()
.find(|s| s.holder() == Some(&member_id))
.map(|s| s.holder())
.unwrap();
let ref_sheet_holder = all_sheets
.iter()
.find(|s| s.holder() == Some(&"host".to_string()))
.map(|s| s.holder())
.unwrap();
assert_eq!(test_sheet_holder, Some(&member_id));
assert_eq!(ref_sheet_holder, Some(&"host".to_string()));
// Test 7: Safe deletion (move to trash)
vault.delete_sheet_safely(&sheet_name).await?;
// Verify sheet is not in normal listing but can be restored
let sheet_names_after_deletion = vault.sheet_names()?;
assert_eq!(sheet_names_after_deletion.len(), 1);
assert_eq!(sheet_names_after_deletion[0], "ref");
// Test 8: Restore sheet from trash
let restored_sheet = vault.sheet(&sheet_name).await?;
assert_eq!(restored_sheet.holder(), Some(&member_id));
assert_eq!(restored_sheet.holder(), Some(&member_id));
// Verify sheet is back in normal listing
let sheet_names_after_restore = vault.sheet_names()?;
assert_eq!(sheet_names_after_restore.len(), 2);
assert!(sheet_names_after_restore.contains(&sheet_name));
assert!(sheet_names_after_restore.contains(&"ref".to_string()));
// Test 9: Permanent deletion
vault.delete_sheet(&sheet_name).await?;
// Verify sheet is permanently gone
let sheet_names_final = vault.sheet_names()?;
assert_eq!(sheet_names_final.len(), 1);
assert_eq!(sheet_names_final[0], "ref");
// Attempt to access deleted sheet should fail
let result = vault.sheet(&sheet_name).await;
assert!(result.is_err());
// Clean up: Remove member
vault.remove_member_from_vault(&member_id)?;
Ok(())
}
#[tokio::test]
async fn test_sheet_error_conditions() -> Result<(), std::io::Error> {
let dir = get_test_dir("sheet_error_conditions").await?;
// Setup vault
Vault::setup_vault(dir.clone(), "TestVault").await?;
// Get vault
let config = VaultConfig::read_from(dir.join(SERVER_FILE_VAULT)).await?;
let Some(vault) = Vault::init(config, &dir) else {
return Err(Error::new(std::io::ErrorKind::NotFound, "Vault not found!"));
};
// Test 1: Create sheet with non-existent member should fail
let non_existent_member: MemberId = "non_existent_member".to_string();
let sheet_name: SheetName = "test_sheet".to_string();
let result = vault.create_sheet(&sheet_name, &non_existent_member).await;
assert!(result.is_err());
// Add a member first
let member_id: MemberId = "test_member".to_string();
vault
.register_member_to_vault(Member::new(&member_id))
.await?;
// Test 2: Create duplicate sheet should fail
vault.create_sheet(&sheet_name, &member_id).await?;
let result = vault.create_sheet(&sheet_name, &member_id).await;
assert!(result.is_err());
// Test 3: Delete non-existent sheet should fail
let non_existent_sheet: SheetName = "non_existent_sheet".to_string();
let result = vault.delete_sheet(&non_existent_sheet).await;
assert!(result.is_err());
// Test 4: Safe delete non-existent sheet should fail
let result = vault.delete_sheet_safely(&non_existent_sheet).await;
assert!(result.is_err());
// Test 5: Restore non-existent sheet from trash should fail
let result = vault.restore_sheet(&non_existent_sheet).await;
assert!(result.is_err());
// Clean up
vault.remove_member_from_vault(&member_id)?;
Ok(())
}
#[tokio::test]
async fn test_sheet_data_serialization() -> Result<(), std::io::Error> {
let dir = get_test_dir("sheet_serialization").await?;
// Test serialization by creating a sheet through the vault
// Setup vault
Vault::setup_vault(dir.clone(), "TestVault").await?;
// Get vault
let config = VaultConfig::read_from(dir.join(SERVER_FILE_VAULT)).await?;
let Some(vault) = Vault::init(config, &dir) else {
return Err(Error::new(std::io::ErrorKind::NotFound, "Vault not found!"));
};
// Add a member
let member_id: MemberId = "test_member".to_string();
vault
.register_member_to_vault(Member::new(&member_id))
.await?;
// Create a sheet
let sheet_name: SheetName = "test_serialization_sheet".to_string();
let mut sheet = vault.create_sheet(&sheet_name, &member_id).await?;
// Add some mappings
let main_rs_path = vcs_data::data::sheet::SheetPathBuf::from("src/main.rs");
let lib_rs_path = vcs_data::data::sheet::SheetPathBuf::from("src/lib.rs");
let main_rs_id = VirtualFileId::new();
let lib_rs_id = VirtualFileId::new();
sheet
.add_mapping(
main_rs_path.clone(),
main_rs_id.clone(),
"1.0.0".to_string(),
)
.await?;
sheet
.add_mapping(lib_rs_path.clone(), lib_rs_id.clone(), "1.0.0".to_string())
.await?;
// Add more mappings
let build_exe_id = VirtualFileId::new();
sheet
.add_mapping(
vcs_data::data::sheet::SheetPathBuf::from("output/build.exe"),
build_exe_id,
"1.0.0".to_string(),
)
.await?;
// Persist the sheet
sheet.persist().await?;
// Verify the sheet file was created
let sheet_path = dir.join(SERVER_FILE_SHEET.replace("{sheet_name}", &sheet_name));
assert!(sheet_path.exists());
// Clean up
vault.remove_member_from_vault(&member_id)?;
Ok(())
}
|