Skip to content

Commit f473551

Browse files
Add comprehensive error handling and edge case tests
New test suite test_errors.mojo with 11 tests: - Error detection: unclosed sections, duplicate keys, missing equals - Edge cases: empty sections, special characters, Unicode - Stress tests: very long lines (10K chars), many sections (100+) - Robustness: empty files, comment-only files, quoted section names All tests verify proper error messages and graceful handling. Total: 46 tests passing (35 original + 11 error tests) Co-Authored-By: Warp <agent@warp.dev>
1 parent 007eaf0 commit f473551

File tree

1 file changed

+144
-0
lines changed

1 file changed

+144
-0
lines changed

tests/test_errors.mojo

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
"""Tests for error handling and edge cases.
2+
3+
These tests verify that the parser properly detects and reports errors
4+
for invalid INI syntax, matching Python configparser behavior where appropriate.
5+
"""
6+
7+
from testing import assert_true, TestSuite
8+
from ini.parser import parse
9+
10+
11+
fn test_unclosed_section_header() raises:
12+
"""Test that unclosed section header raises error."""
13+
var input = "[Section"
14+
15+
try:
16+
var _ = parse(input)
17+
assert_true(False, "Should raise error for unclosed section")
18+
except e:
19+
# Expected - should contain "Unclosed"
20+
var err_msg = String(e)
21+
assert_true("Unclosed" in err_msg, "Error should mention unclosed section")
22+
23+
24+
fn test_duplicate_key_in_section() raises:
25+
"""Test that duplicate keys in same section raise error."""
26+
var input = """[Test]
27+
key = value1
28+
key = value2"""
29+
30+
try:
31+
var _ = parse(input)
32+
assert_true(False, "Should raise error for duplicate key")
33+
except e:
34+
# Expected - should mention "Duplicate"
35+
var err_msg = String(e)
36+
assert_true("Duplicate" in err_msg, "Error should mention duplicate key")
37+
38+
39+
fn test_missing_equals_sign() raises:
40+
"""Test that missing equals sign raises error."""
41+
var input = """[Test]
42+
key_without_equals"""
43+
44+
try:
45+
var _ = parse(input)
46+
assert_true(False, "Should raise error for missing equals")
47+
except e:
48+
# Expected - should mention expecting '='
49+
var err_msg = String(e)
50+
assert_true("=" in err_msg or "Expected" in err_msg, "Error should mention missing =")
51+
52+
53+
fn test_empty_section_name() raises:
54+
"""Test that empty section name is handled."""
55+
var input = "[]\nkey = value"
56+
57+
# Python configparser allows empty section names
58+
var config = parse(input)
59+
# Just check that it doesn't crash - empty string key should exist
60+
assert_true("" in config, "Should handle empty section name")
61+
62+
63+
fn test_special_characters_in_values() raises:
64+
"""Test that special characters in values are preserved."""
65+
var input = """[Test]
66+
url = https://example.com/path?query=value&other=123
67+
path = /path/with spaces/file.txt
68+
email = user@example.com
69+
brackets = [not a section]
70+
equals = key=value inside value"""
71+
72+
var config = parse(input)
73+
assert_true("?" in config["Test"]["url"], "Should preserve ? in URL")
74+
assert_true("&" in config["Test"]["url"], "Should preserve & in URL")
75+
assert_true(" " in config["Test"]["path"], "Should preserve spaces in path")
76+
assert_true("@" in config["Test"]["email"], "Should preserve @ in email")
77+
assert_true("[" in config["Test"]["brackets"], "Should preserve [ in value")
78+
assert_true("=" in config["Test"]["equals"], "Should preserve = in value")
79+
80+
81+
fn test_unicode_values() raises:
82+
"""Test that Unicode characters are handled correctly."""
83+
var input = """[Test]
84+
greeting = Hello, 世界!
85+
emoji = 🔥 mojo-ini 🚀
86+
cyrillic = Привет мир"""
87+
88+
var config = parse(input)
89+
assert_true("世界" in config["Test"]["greeting"], "Should handle Chinese characters")
90+
assert_true("🔥" in config["Test"]["emoji"], "Should handle emoji")
91+
assert_true("Привет" in config["Test"]["cyrillic"], "Should handle Cyrillic")
92+
93+
94+
fn test_very_long_lines() raises:
95+
"""Test that very long lines are handled."""
96+
var long_value = "x" * 10000
97+
var input = "[Test]\nkey = " + long_value
98+
99+
var config = parse(input)
100+
assert_true(len(config["Test"]["key"]) == 10000, "Should handle very long values")
101+
102+
103+
fn test_many_sections() raises:
104+
"""Test that many sections can be parsed."""
105+
var input = String("")
106+
for i in range(100):
107+
input += "[Section" + String(i) + "]\n"
108+
input += "key = value" + String(i) + "\n"
109+
110+
var config = parse(input)
111+
# Should have 100 sections + default section
112+
assert_true(len(config) >= 100, "Should handle many sections (got " + String(len(config)) + ")")
113+
114+
115+
fn test_empty_file() raises:
116+
"""Test that empty file is handled gracefully."""
117+
var config = parse("")
118+
# Should have at least the default section
119+
assert_true("" in config, "Empty file should have default section")
120+
121+
122+
fn test_only_comments() raises:
123+
"""Test that file with only comments is handled."""
124+
var input = """# Comment 1
125+
; Comment 2
126+
# Comment 3"""
127+
128+
var config = parse(input)
129+
assert_true("" in config, "Comment-only file should have default section")
130+
131+
132+
fn test_section_with_quotes() raises:
133+
"""Test section names with quotes (Git config style)."""
134+
var input = """[remote "origin"]
135+
url = https://github.com/user/repo.git"""
136+
137+
var config = parse(input)
138+
# Section name should include the quotes
139+
assert_true('remote "origin"' in config, "Should preserve quotes in section name")
140+
141+
142+
fn main() raises:
143+
"""Run all error handling tests using TestSuite."""
144+
TestSuite.discover_tests[__functions_in_module()]().run()

0 commit comments

Comments
 (0)