/ tests / source_traits_tests.rs
source_traits_tests.rs
  1  use abundantis::source::{
  2      ParsedVariable, Priority, SourceCapabilities, SourceId, SourceSnapshot, SourceType,
  3      VariableSource,
  4  };
  5  use std::path::PathBuf;
  6  
  7  #[test]
  8  fn test_source_id_creation() {
  9      let id = SourceId::new("test-source");
 10      assert_eq!(id.as_str(), "test-source");
 11  
 12      let id2: SourceId = "test-source".into();
 13      assert_eq!(id, id2);
 14  
 15      let id3: SourceId = String::from("test-source").into();
 16      assert_eq!(id, id3);
 17  }
 18  
 19  #[test]
 20  fn test_source_id_display() {
 21      let id = SourceId::new("test");
 22      let s = format!("{}", id);
 23      assert_eq!(s, "test");
 24  }
 25  
 26  #[test]
 27  fn test_source_priorities() {
 28      assert!(Priority::SHELL > Priority::FILE);
 29      assert!(Priority::FILE > Priority::MEMORY);
 30      assert_eq!(Priority::SHELL.0, 100);
 31      assert_eq!(Priority::FILE.0, 50);
 32      assert_eq!(Priority::MEMORY.0, 30);
 33      assert_eq!(Priority::REMOTE.0, 75);
 34  }
 35  
 36  #[test]
 37  fn test_source_capabilities() {
 38      let caps = SourceCapabilities::READ | SourceCapabilities::CACHEABLE;
 39      assert!(caps.contains(SourceCapabilities::READ));
 40      assert!(caps.contains(SourceCapabilities::CACHEABLE));
 41      assert!(!caps.contains(SourceCapabilities::WRITE));
 42      assert!(!caps.contains(SourceCapabilities::ASYNC_ONLY));
 43  }
 44  
 45  #[test]
 46  fn test_source_capabilities_defaults() {
 47      let caps = SourceCapabilities::default();
 48      assert!(caps.contains(SourceCapabilities::READ));
 49      assert!(caps.contains(SourceCapabilities::CACHEABLE));
 50      assert!(!caps.contains(SourceCapabilities::WRITE));
 51  }
 52  
 53  #[test]
 54  fn test_source_type_equality() {
 55      assert_eq!(SourceType::File, SourceType::File);
 56      assert_eq!(SourceType::Shell, SourceType::Shell);
 57      assert_eq!(SourceType::Memory, SourceType::Memory);
 58      assert_eq!(SourceType::Remote, SourceType::Remote);
 59  }
 60  
 61  #[test]
 62  fn test_source_type_hashing() {
 63      use std::collections::HashSet;
 64      let mut set = HashSet::new();
 65      set.insert(SourceType::File);
 66      set.insert(SourceType::Shell);
 67      set.insert(SourceType::Memory);
 68      set.insert(SourceType::Remote);
 69      assert_eq!(set.len(), 4);
 70  }
 71  
 72  #[test]
 73  fn test_parsed_variable_simple() {
 74      let var = ParsedVariable::simple("KEY", "value", VariableSource::Memory);
 75  
 76      assert_eq!(var.key.as_str(), "KEY");
 77      assert_eq!(var.raw_value.as_str(), "value");
 78      assert!(matches!(var.source, VariableSource::Memory));
 79      assert_eq!(var.description, None);
 80      assert!(!var.is_commented);
 81  }
 82  
 83  #[test]
 84  fn test_parsed_variable_with_description() {
 85      let var = ParsedVariable {
 86          key: "KEY".into(),
 87          raw_value: "value".into(),
 88          source: VariableSource::Memory,
 89          description: Some("Test description".into()),
 90          is_commented: false,
 91      };
 92  
 93      assert_eq!(var.description.as_deref(), Some("Test description"));
 94  }
 95  
 96  #[test]
 97  fn test_variable_source_file() {
 98      let source = VariableSource::File {
 99          path: PathBuf::from("/path/to/.env"),
100          offset: 42,
101      };
102  
103      assert_eq!(source.file_path(), Some(&PathBuf::from("/path/to/.env")));
104      assert_eq!(
105          source.file_path().unwrap().display().to_string(),
106          "/path/to/.env"
107      );
108  }
109  
110  #[test]
111  fn test_variable_source_shell() {
112      let source = VariableSource::Shell;
113      assert_eq!(source.file_path(), None);
114  }
115  
116  #[test]
117  fn test_variable_source_remote() {
118      let source = VariableSource::Remote {
119          provider: "doppler".into(),
120          path: Some("secret/path".into()),
121      };
122  
123      assert_eq!(source.file_path(), None);
124  }
125  
126  #[test]
127  fn test_source_snapshot_creation() {
128      let vars = vec![
129          ParsedVariable::simple("KEY1", "val1", VariableSource::Memory),
130          ParsedVariable::simple("KEY2", "val2", VariableSource::Memory),
131      ];
132  
133      let snapshot = SourceSnapshot {
134          source_id: SourceId::new("test"),
135          variables: vars.into(),
136          timestamp: std::time::Instant::now(),
137          version: Some(1),
138      };
139  
140      assert_eq!(snapshot.variables.len(), 2);
141      assert_eq!(snapshot.source_id.as_str(), "test");
142      assert_eq!(snapshot.version, Some(1));
143      assert!(snapshot.timestamp.elapsed().as_secs() < 1);
144  }
145  
146  #[test]
147  fn test_source_snapshot_arc_conversion() {
148      let vars = vec![ParsedVariable::simple(
149          "KEY",
150          "value",
151          VariableSource::Memory,
152      )];
153  
154      let snapshot = SourceSnapshot {
155          source_id: SourceId::new("test"),
156          variables: vars.into(),
157          timestamp: std::time::Instant::now(),
158          version: None,
159      };
160  
161      let arc_vars = std::sync::Arc::clone(&snapshot.variables);
162      assert_eq!(arc_vars.len(), 1);
163      assert_eq!(arc_vars[0].key.as_str(), "KEY");
164  }
165  
166  #[test]
167  fn test_source_id_clone() {
168      let id1 = SourceId::new("test");
169      let id2 = id1.clone();
170      assert_eq!(id1, id2);
171      assert_eq!(id1.as_str(), id2.as_str());
172  }
173  
174  #[test]
175  fn test_source_id_hash() {
176      use std::collections::HashMap;
177      let id1 = SourceId::new("test1");
178      let id2 = SourceId::new("test2");
179  
180      let mut map = HashMap::new();
181      map.insert(id1.clone(), "value1");
182      map.insert(id2.clone(), "value2");
183  
184      assert_eq!(map.get(&id1), Some(&"value1"));
185      assert_eq!(map.get(&id2), Some(&"value2"));
186  }
187  
188  #[test]
189  fn test_priority_ordering() {
190      let priorities = [Priority::MEMORY, Priority::FILE, Priority::SHELL];
191  
192      let mut sorted = priorities.to_vec();
193      sorted.sort();
194  
195      assert_eq!(sorted[0], Priority::MEMORY);
196      assert_eq!(sorted[1], Priority::FILE);
197      assert_eq!(sorted[2], Priority::SHELL);
198  }
199  
200  #[test]
201  fn test_priority_comparison() {
202      assert!(Priority::SHELL > Priority::FILE);
203      assert!(Priority::FILE > Priority::MEMORY);
204      assert!(Priority::REMOTE > Priority::FILE);
205      assert!(Priority::SHELL > Priority::MEMORY);
206  
207      assert_eq!(Priority::SHELL, Priority::SHELL);
208      assert_ne!(Priority::SHELL, Priority::FILE);
209  }
210  
211  #[test]
212  fn test_source_capabilities_combinations() {
213      let _all_caps = SourceCapabilities::all();
214  
215      let read_caps = SourceCapabilities::READ;
216      let write_caps = SourceCapabilities::WRITE;
217      let combined = read_caps | write_caps;
218  
219      assert!(combined.contains(SourceCapabilities::READ));
220      assert!(combined.contains(SourceCapabilities::WRITE));
221      assert!(!combined.contains(SourceCapabilities::WATCH));
222  }
223  
224  #[test]
225  fn test_source_capabilities_bits() {
226      let caps = SourceCapabilities::READ | SourceCapabilities::WRITE | SourceCapabilities::WATCH;
227      assert_eq!(caps.bits(), 0b00000111);
228  }
229  
230  #[test]
231  fn test_variable_source_debug() {
232      let source = VariableSource::File {
233          path: PathBuf::from("/test/.env"),
234          offset: 42,
235      };
236  
237      let debug_str = format!("{:?}", source);
238      assert!(debug_str.contains("File"));
239      assert!(debug_str.contains("/test/.env"));
240  }
241  
242  #[test]
243  fn test_parsed_variable_debug() {
244      let var = ParsedVariable::simple("KEY", "value", VariableSource::Memory);
245      let debug_str = format!("{:?}", var);
246      assert!(debug_str.contains("KEY"));
247      assert!(debug_str.contains("value"));
248      assert!(debug_str.contains("Memory"));
249  }
250  
251  #[test]
252  fn test_source_snapshot_display() {
253      let snapshot = SourceSnapshot {
254          source_id: SourceId::new("test-source"),
255          variables: vec![].into(),
256          timestamp: std::time::Instant::now(),
257          version: Some(42),
258      };
259  
260      let display = format!("{:?}", snapshot);
261      assert!(display.contains("test-source"));
262  }
263  
264  #[test]
265  fn test_multiple_source_ids() {
266      let ids = [
267          SourceId::new("source1"),
268          SourceId::new("source2"),
269          SourceId::new("source3"),
270      ];
271  
272      assert_eq!(ids.len(), 3);
273      assert_ne!(ids[0], ids[1]);
274      assert_ne!(ids[1], ids[2]);
275      assert_ne!(ids[0], ids[2]);
276  }
277  
278  #[test]
279  fn test_source_id_with_special_chars() {
280      let id = SourceId::new("my-source_v1");
281      assert_eq!(id.as_str(), "my-source_v1");
282  }
283  
284  #[test]
285  fn test_source_timestamp_creation() {
286      let snapshot = SourceSnapshot {
287          source_id: SourceId::new("test"),
288          variables: vec![].into(),
289          timestamp: std::time::Instant::now(),
290          version: None,
291      };
292  
293      let elapsed = snapshot.timestamp.elapsed();
294      assert!(elapsed.as_millis() < 100);
295  }
296  
297  #[test]
298  fn test_variable_source_equality() {
299      let source1 = VariableSource::Shell;
300      let source2 = VariableSource::Shell;
301      assert_eq!(source1, source2);
302  
303      let source3 = VariableSource::Memory;
304      assert_ne!(source1, source3);
305  }
306  
307  #[test]
308  fn test_parsed_variable_with_commented() {
309      let var = ParsedVariable {
310          key: "KEY".into(),
311          raw_value: "value".into(),
312          source: VariableSource::Memory,
313          description: None,
314          is_commented: true,
315      };
316  
317      assert!(var.is_commented);
318  }
319  
320  #[test]
321  fn test_source_version_tracking() {
322      let snapshot1 = SourceSnapshot {
323          source_id: SourceId::new("test"),
324          variables: vec![].into(),
325          timestamp: std::time::Instant::now(),
326          version: Some(1),
327      };
328  
329      let snapshot2 = SourceSnapshot {
330          source_id: SourceId::new("test"),
331          variables: vec![].into(),
332          timestamp: std::time::Instant::now(),
333          version: Some(2),
334      };
335  
336      assert!(snapshot1.version.unwrap() < snapshot2.version.unwrap());
337  }
338  
339  #[test]
340  fn test_source_capabilities_iterators() {
341      let caps = SourceCapabilities::READ | SourceCapabilities::WRITE;
342  
343      assert!(caps.contains(SourceCapabilities::READ));
344      assert!(caps.contains(SourceCapabilities::WRITE));
345  }
346  
347  #[test]
348  fn test_priority_ord() {
349      assert!(Priority::SHELL > Priority::FILE);
350      assert!(Priority::FILE > Priority::MEMORY);
351      assert!(Priority::REMOTE > Priority::FILE);
352  
353      let mut vec = vec![Priority::FILE, Priority::SHELL, Priority::MEMORY];
354      vec.sort();
355  
356      assert_eq!(vec, vec![Priority::MEMORY, Priority::FILE, Priority::SHELL]);
357  }
358  
359  #[test]
360  fn test_source_id_partial_eq() {
361      let id = SourceId::new("test-source-123");
362      assert!(id.as_str().starts_with("test-source"));
363      assert!(id.as_str().ends_with("123"));
364  }