|
1 | 1 | package config |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "strings" |
| 4 | + "reflect" |
5 | 5 | "testing" |
6 | 6 | ) |
7 | 7 |
|
8 | | -func TestJSON5Preprocessor_RemoveComments(t *testing.T) { |
| 8 | +func TestParseJSON5_BasicFeatures(t *testing.T) { |
9 | 9 | tests := []struct { |
10 | 10 | name string |
11 | 11 | input string |
12 | | - expected string |
| 12 | + expected map[string]interface{} |
13 | 13 | }{ |
14 | 14 | { |
15 | | - name: "single line comments", |
16 | | - input: `{ |
17 | | - // This is a comment |
18 | | - "key": "value" // Inline comment |
19 | | -}`, |
20 | | - expected: `{ |
21 | | -
|
22 | | -"key": "value" |
23 | | -}`, |
24 | | - }, |
25 | | - { |
26 | | - name: "multi-line comments", |
27 | | - input: `{ |
28 | | - /* Multi-line |
29 | | - comment */ |
30 | | - "key": "value" |
31 | | -}`, |
32 | | - expected: `{ |
33 | | -
|
34 | | -"key": "value" |
35 | | -}`, |
36 | | - }, |
37 | | - { |
38 | | - name: "comments in strings should be preserved", |
39 | | - input: `{ |
40 | | - "url": "https://example.com/path", // This comment should be removed |
41 | | - "comment": "This // is not a comment" |
42 | | -}`, |
43 | | - expected: `{ |
44 | | -"url": "https://example.com/path", |
45 | | -"comment": "This // is not a comment" |
46 | | -}`, |
47 | | - }, |
48 | | - { |
49 | | - name: "mixed comments", |
50 | | - input: `{ |
51 | | - // Single line comment |
52 | | - /* Multi-line comment */ |
53 | | - "key": "value", // Inline comment |
54 | | - /* Another |
55 | | - multi-line */ "key2": "value2" |
56 | | -}`, |
57 | | - expected: `{ |
58 | | -
|
59 | | -
|
60 | | -"key": "value", |
61 | | -"key2": "value2" |
62 | | -}`, |
63 | | - }, |
64 | | - } |
65 | | - |
66 | | - preprocessor := NewJSON5Preprocessor() |
67 | | - for _, tt := range tests { |
68 | | - t.Run(tt.name, func(t *testing.T) { |
69 | | - result := preprocessor.removeComments(tt.input) |
70 | | - // Normalize whitespace for comparison |
71 | | - result = strings.TrimSpace(result) |
72 | | - expected := strings.TrimSpace(tt.expected) |
73 | | - if result != expected { |
74 | | - t.Errorf("removeComments() = %q, want %q", result, expected) |
75 | | - } |
76 | | - }) |
77 | | - } |
78 | | -} |
79 | | - |
80 | | -func TestJSON5Preprocessor_QuoteKeys(t *testing.T) { |
81 | | - tests := []struct { |
82 | | - name string |
83 | | - input string |
84 | | - expected string |
85 | | - }{ |
86 | | - { |
87 | | - name: "unquoted keys", |
88 | | - input: `{ |
89 | | - key: "value", |
90 | | - anotherKey: "value2" |
91 | | -}`, |
92 | | - expected: `{ |
93 | | - "key": "value", |
94 | | - "anotherKey": "value2" |
95 | | -}`, |
| 15 | + name: "simple JSON", |
| 16 | + input: `{"key": "value"}`, |
| 17 | + expected: map[string]interface{}{ |
| 18 | + "key": "value", |
| 19 | + }, |
96 | 20 | }, |
97 | 21 | { |
98 | | - name: "already quoted keys should remain unchanged", |
| 22 | + name: "comments and unquoted keys", |
99 | 23 | input: `{ |
100 | | - "key": "value", |
101 | | - "anotherKey": "value2" |
102 | | -}`, |
103 | | - expected: `{ |
104 | | - "key": "value", |
105 | | - "anotherKey": "value2" |
106 | | -}`, |
| 24 | + // This is a comment |
| 25 | + name: "test-project", |
| 26 | + version: "1.0.0" // Another comment |
| 27 | + }`, |
| 28 | + expected: map[string]interface{}{ |
| 29 | + "name": "test-project", |
| 30 | + "version": "1.0.0", |
| 31 | + }, |
107 | 32 | }, |
108 | 33 | { |
109 | | - name: "mixed quoted and unquoted keys", |
| 34 | + name: "trailing commas", |
110 | 35 | input: `{ |
111 | | - "quotedKey": "value", |
112 | | - unquotedKey: "value2" |
113 | | -}`, |
114 | | - expected: `{ |
115 | | - "quotedKey": "value", |
116 | | - "unquotedKey": "value2" |
117 | | -}`, |
118 | | - }, |
119 | | - { |
120 | | - name: "reserved words should not be quoted", |
121 | | - input: `{ |
122 | | - key: true, |
123 | | - key2: false, |
124 | | - key3: null |
125 | | -}`, |
126 | | - expected: `{ |
127 | | - "key": true, |
128 | | - "key2": false, |
129 | | - "key3": null |
130 | | -}`, |
| 36 | + "key1": "value1", |
| 37 | + "key2": "value2", |
| 38 | + }`, |
| 39 | + expected: map[string]interface{}{ |
| 40 | + "key1": "value1", |
| 41 | + "key2": "value2", |
| 42 | + }, |
131 | 43 | }, |
132 | 44 | } |
133 | 45 |
|
134 | | - preprocessor := NewJSON5Preprocessor() |
135 | 46 | for _, tt := range tests { |
136 | 47 | t.Run(tt.name, func(t *testing.T) { |
137 | | - result := preprocessor.quoteKeys(tt.input) |
138 | | - if result != tt.expected { |
139 | | - t.Errorf("quoteKeys() = %q, want %q", result, tt.expected) |
| 48 | + var result map[string]interface{} |
| 49 | + err := ParseJSON5([]byte(tt.input), &result) |
| 50 | + if err != nil { |
| 51 | + t.Fatalf("ParseJSON5() error = %v", err) |
140 | 52 | } |
141 | | - }) |
142 | | - } |
143 | | -} |
144 | 53 |
|
145 | | -func TestJSON5Preprocessor_RemoveTrailingCommas(t *testing.T) { |
146 | | - tests := []struct { |
147 | | - name string |
148 | | - input string |
149 | | - expected string |
150 | | - }{ |
151 | | - { |
152 | | - name: "trailing comma in object", |
153 | | - input: `{ |
154 | | - "key": "value", |
155 | | - "key2": "value2", |
156 | | -}`, |
157 | | - expected: `{ |
158 | | - "key": "value", |
159 | | - "key2": "value2" |
160 | | -}`, |
161 | | - }, |
162 | | - { |
163 | | - name: "trailing comma in array", |
164 | | - input: `{ |
165 | | - "array": ["item1", "item2",] |
166 | | -}`, |
167 | | - expected: `{ |
168 | | - "array": ["item1", "item2"] |
169 | | -}`, |
170 | | - }, |
171 | | - { |
172 | | - name: "no trailing commas", |
173 | | - input: `{ |
174 | | - "key": "value", |
175 | | - "array": ["item1", "item2"] |
176 | | -}`, |
177 | | - expected: `{ |
178 | | - "key": "value", |
179 | | - "array": ["item1", "item2"] |
180 | | -}`, |
181 | | - }, |
182 | | - { |
183 | | - name: "nested objects with trailing commas", |
184 | | - input: `{ |
185 | | - "nested": { |
186 | | - "key": "value", |
187 | | - }, |
188 | | - "array": [ |
189 | | - {"item": "value",}, |
190 | | - ], |
191 | | -}`, |
192 | | - expected: `{ |
193 | | - "nested": { |
194 | | - "key": "value" |
195 | | - }, |
196 | | - "array": [ |
197 | | - {"item": "value"} |
198 | | - ] |
199 | | -}`, |
200 | | - }, |
201 | | - } |
202 | | - |
203 | | - preprocessor := NewJSON5Preprocessor() |
204 | | - for _, tt := range tests { |
205 | | - t.Run(tt.name, func(t *testing.T) { |
206 | | - result := preprocessor.removeTrailingCommas(tt.input) |
207 | | - if result != tt.expected { |
208 | | - t.Errorf("removeTrailingCommas() = %q, want %q", result, tt.expected) |
| 54 | + // Compare the results |
| 55 | + if !reflect.DeepEqual(result, tt.expected) { |
| 56 | + t.Errorf("ParseJSON5() = %v, want %v", result, tt.expected) |
209 | 57 | } |
210 | 58 | }) |
211 | 59 | } |
212 | 60 | } |
213 | 61 |
|
214 | | -func TestJSON5Preprocessor_Process(t *testing.T) { |
| 62 | +func TestParseJSON5_ErrorHandling(t *testing.T) { |
215 | 63 | tests := []struct { |
216 | | - name string |
217 | | - input string |
218 | | - wantErr bool |
| 64 | + name string |
| 65 | + input string |
219 | 66 | }{ |
220 | 67 | { |
221 | | - name: "complete JSON5 example", |
222 | | - input: `{ |
223 | | - // Configuration file |
224 | | - project: { |
225 | | - name: "test-project", // Project name |
226 | | - version: "1.0.0", |
227 | | - }, |
228 | | - |
229 | | - /* Multi-line |
230 | | - comment */ |
231 | | - tools: { |
232 | | - java: { |
233 | | - version: "21", |
234 | | - distribution: "temurin", // Eclipse Temurin |
235 | | - }, |
236 | | - }, |
237 | | -}`, |
238 | | - wantErr: false, |
| 68 | + name: "invalid JSON5", |
| 69 | + input: `{ invalid json5 }`, |
239 | 70 | }, |
240 | 71 | { |
241 | | - name: "invalid JSON after preprocessing", |
242 | | - input: `{ |
243 | | - key: "unclosed string |
244 | | -}`, |
245 | | - wantErr: true, |
246 | | - }, |
247 | | - { |
248 | | - name: "empty object", |
249 | | - input: `{ |
250 | | - // Just comments |
251 | | -}`, |
252 | | - wantErr: false, |
| 72 | + name: "unclosed brace", |
| 73 | + input: `{ "key": "value"`, |
253 | 74 | }, |
254 | 75 | } |
255 | 76 |
|
256 | | - preprocessor := NewJSON5Preprocessor() |
257 | 77 | for _, tt := range tests { |
258 | 78 | t.Run(tt.name, func(t *testing.T) { |
259 | | - _, err := preprocessor.Process([]byte(tt.input)) |
260 | | - if (err != nil) != tt.wantErr { |
261 | | - t.Errorf("Process() error = %v, wantErr %v", err, tt.wantErr) |
| 79 | + var result map[string]interface{} |
| 80 | + err := ParseJSON5([]byte(tt.input), &result) |
| 81 | + if err == nil { |
| 82 | + t.Error("ParseJSON5() expected error, got nil") |
262 | 83 | } |
263 | 84 | }) |
264 | 85 | } |
265 | 86 | } |
266 | | - |
267 | | -func TestParseJSON5(t *testing.T) { |
268 | | - input := `{ |
269 | | - // mvx configuration |
270 | | - project: { |
271 | | - name: "test-project", // Project name |
272 | | - description: "A test project", |
273 | | - }, |
274 | | - |
275 | | - tools: { |
276 | | - java: { |
277 | | - version: "21", |
278 | | - distribution: "temurin", // Eclipse Temurin |
279 | | - }, |
280 | | - }, |
281 | | -}` |
282 | | - |
283 | | - var config Config |
284 | | - err := ParseJSON5([]byte(input), &config) |
285 | | - if err != nil { |
286 | | - t.Fatalf("ParseJSON5() error = %v", err) |
287 | | - } |
288 | | - |
289 | | - // Verify the parsed configuration |
290 | | - if config.Project.Name != "test-project" { |
291 | | - t.Errorf("Expected project name 'test-project', got '%s'", config.Project.Name) |
292 | | - } |
293 | | - |
294 | | - if config.Project.Description != "A test project" { |
295 | | - t.Errorf("Expected project description 'A test project', got '%s'", config.Project.Description) |
296 | | - } |
297 | | - |
298 | | - javaTool, exists := config.Tools["java"] |
299 | | - if !exists { |
300 | | - t.Errorf("Expected java tool to be configured") |
301 | | - } else { |
302 | | - if javaTool.Version != "21" { |
303 | | - t.Errorf("Expected Java version '21', got '%s'", javaTool.Version) |
304 | | - } |
305 | | - |
306 | | - if javaTool.Distribution != "temurin" { |
307 | | - t.Errorf("Expected Java distribution 'temurin', got '%s'", javaTool.Distribution) |
308 | | - } |
309 | | - } |
310 | | -} |
0 commit comments