/ tests / spec_compliance_export.rs
spec_compliance_export.rs
 1  mod common;
 2  use common::{assert_exported, assert_not_exported, assert_error};
 3  use korni::{parse, Entry};
 4  
 5  // --- 1. Basic Export ---
 6  
 7  #[test]
 8  fn test_export_basic() { assert_exported("export K=v", "K", "v"); }
 9  #[test]
10  fn test_export_tab() { assert_exported("export\tK=v", "K", "v"); }
11  
12  // --- 2. Leading Whitespace ---
13  
14  #[test]
15  fn test_export_leading_space() { assert_exported(" export K=v", "K", "v"); }
16  #[test]
17  fn test_export_leading_tab() { assert_exported("\texport K=v", "K", "v"); }
18  #[test]
19  fn test_export_leading_mixed() { assert_exported(" \t export K=v", "K", "v"); }
20  
21  // --- 3. Key False Alarms (Looks like export but isn't prefix) ---
22  
23  #[test]
24  fn test_export_as_part_of_key() { assert_not_exported("exportK=v", "exportK", "v"); }
25  #[test]
26  fn test_export_underscore() { assert_not_exported("export_K=v", "export_K", "v"); }
27  #[test]
28  fn test_exported_key() { assert_not_exported("exported=v", "exported", "v"); }
29  #[test]
30  fn test_exporting_key() { assert_not_exported("exporting=v", "exporting", "v"); }
31  #[test]
32  fn test_expor_key() { assert_not_exported("expor=v", "expor", "v"); }
33  
34  // --- 4. Value Side (export in value is just value) ---
35  
36  #[test]
37  fn test_export_in_value() { 
38      // "K=export v" -> Value is "export". "v" is ignored junk.
39      let input = "K=export v";
40      let entries = parse(input);
41      let kv = entries[0].as_pair().unwrap();
42      assert_eq!(kv.value, "export");
43      assert!(!kv.is_exported);
44  }
45  
46  // --- 5. Export with Quotes ---
47  
48  #[test]
49  fn test_export_quoted_double() { assert_exported("export K=\"v\"", "K", "v"); }
50  #[test]
51  fn test_export_quoted_single() { assert_exported("export K='v'", "K", "v"); }
52  
53  // --- 6. Export Edge Cases ---
54  
55  #[test]
56  fn test_export_many_spaces() { assert_exported("export    K=v", "K", "v"); }
57  
58  #[test]
59  fn test_export_no_key_error() {
60      // "export =v" -> Empty key
61      assert_error("export =v", "Empty key");
62  }
63  
64  #[test]
65  fn test_export_only_error() {
66      // "export" line
67      // Spec says: "export keyword without definition ... is invalid"
68      // Our parser currently might ignore it or error.
69      // Let's check parser.rs logic:
70      // It sees "export", consumes it if followed by space.
71      // Then consumes whitespace.
72      // Then expects Key. If EOF or no key char -> Error?
73      // "export\n" -> Consumes export, then newline.
74      // `key_start == key_end` check -> if !eof && peek == =, empty key.
75      // But if peek == newline, it recovers line.
76      // So "export\n" simply produces NO entry (recover_line skips).
77      // Let's verify:
78      let input = "export\n";
79      let entries = parse(input);
80      // Should be 0 entries if ignored, or error.
81      // Actually, `consume_key` consumes 0 chars. `key_start == key_end`.
82      // Then `if key_start == key_end`: if peek == '=' -> Error("Empty key").
83      // Else `recover_line()` -> skips to newline.
84      // So "export" on a line results in 0 entries (ignored).
85      assert_eq!(entries.len(), 1);
86      assert!(matches!(entries[0], Entry::Error(_)));
87  }
88  
89  #[test]
90  fn test_export_space_only() {
91      let input = "export ";
92      let entries = parse(input);
93      assert_eq!(entries.len(), 0);
94  }
95