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