1const std = @import("std");
2const url = @import("url");
3const expect = @import("expect").expect;
4
5test {
6 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
7 defer arena.deinit();
8 const alloc = arena.allocator();
9
10 var x = try url.SearchParams.initFromString(alloc, "a=b&c=d");
11 try expect(x.get("a")).toEqualString("b");
12 try expect(x.get("c")).toEqualString("d");
13 try expect(x.get("e")).toBeNull();
14
15 try expect(try x.encode()).toEqualString("a=b&c=d");
16}
17
18test {
19 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
20 defer arena.deinit();
21 const alloc = arena.allocator();
22
23 var x = try url.SearchParams.initFromString(alloc, "e=f&g=h");
24 try expect(try x.encode()).toEqualString("e=f&g=h");
25
26 try x.set("i", " j ");
27 try expect(x.get("i")).toEqualString(" j ");
28 try expect(try x.encode()).toEqualString("e=f&g=h&i=+j+");
29
30 try x.set("e", "updated");
31 try expect(x.get("e")).toEqualString("updated");
32 try expect(try x.encode()).toEqualString("e=updated&g=h&i=+j+");
33}
34
35test {
36 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
37 defer arena.deinit();
38 const alloc = arena.allocator();
39
40 var x = url.SearchParams.init(alloc);
41 try x.append("a", "b");
42 try expect(try x.encode()).toEqualString("a=b");
43 try x.append("a", "b");
44 try expect(try x.encode()).toEqualString("a=b&a=b");
45 try x.append("a", "c");
46 try expect(try x.encode()).toEqualString("a=b&a=b&a=c");
47}
48
49test {
50 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
51 defer arena.deinit();
52 const alloc = arena.allocator();
53
54 var x = url.SearchParams.init(alloc);
55 try x.append("", "");
56 try expect(try x.encode()).toEqualString("=");
57 try x.append("", "");
58 try expect(try x.encode()).toEqualString("=&=");
59}
60
61test {
62 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
63 defer arena.deinit();
64 const alloc = arena.allocator();
65
66 var x = url.SearchParams.init(alloc);
67 try x.append("first", "1");
68 try x.append("second", "2");
69 try x.append("third", "");
70 try x.append("first", "10");
71 try expect(x.get("first")).not().toBeNull();
72 try expect(x.get("first")).toEqualString("1");
73 try expect(x.get("second")).toEqualString("2");
74 try expect(x.get("third")).toEqualString("");
75 try x.append("first", "10");
76 try expect(x.get("first")).toEqualString("1");
77}
78
79test {
80 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
81 defer arena.deinit();
82 const alloc = arena.allocator();
83
84 var x = url.SearchParams.init(alloc);
85 try expect(try x.encode()).toEqualString("");
86 try x.append("a", "b");
87 try expect(try x.encode()).toEqualString("a=b");
88 try x.append("a", "c");
89 try expect(try x.encode()).toEqualString("a=b&a=c");
90 try expect(x.take("a")).toEqualString("b");
91 try expect(try x.encode()).toEqualString("a=c");
92 try expect(x.take("a")).toEqualString("c");
93 try expect(try x.encode()).toEqualString("");
94}
95
96test {
97 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
98 defer arena.deinit();
99 const alloc = arena.allocator();
100
101 var x = try url.SearchParams.initFromString(alloc, "a=b&c=d");
102 x.delete("a", null);
103 try expect(try x.encode()).toEqualString("c=d");
104 x = try url.SearchParams.initFromString(alloc, "a=a&b=b&a=a&c=c");
105 x.delete("a", null);
106 try expect(try x.encode()).toEqualString("b=b&c=c");
107 x = try url.SearchParams.initFromString(alloc, "a=a&=&b=b&c=c");
108 x.delete("", null);
109 try expect(try x.encode()).toEqualString("a=a&b=b&c=c");
110 x = try url.SearchParams.initFromString(alloc, "a=a&null=null&b=b");
111 x.delete("null", null);
112 try expect(try x.encode()).toEqualString("a=a&b=b");
113 x = try url.SearchParams.initFromString(alloc, "a=a&undefined=undefined&b=b");
114 x.delete("undefined", null);
115 try expect(try x.encode()).toEqualString("a=a&b=b");
116}
117
118test {
119 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
120 defer arena.deinit();
121 const alloc = arena.allocator();
122
123 var x = url.SearchParams.init(alloc);
124 try x.append("first", "1");
125 try expect(x.has("first", null)).toEqual(true);
126 try expect(x.get("first")).toEqualSlice("1");
127 x.delete("first", null);
128 try expect(x.has("first", null)).toEqual(false);
129 try x.append("first", "1");
130 try x.append("first", "10");
131 x.delete("first", null);
132 try expect(x.has("first", null)).toEqual(false);
133}
134
135test {
136 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
137 defer arena.deinit();
138 const alloc = arena.allocator();
139
140 var x = url.SearchParams.init(alloc);
141 try x.append("a", "b");
142 try x.append("a", "c");
143 try x.append("a", "d");
144 x.delete("a", "c");
145 try expect(try x.encode()).toEqualString("a=b&a=d");
146}
147
148test {
149 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
150 defer arena.deinit();
151 const alloc = arena.allocator();
152
153 var x = url.SearchParams.init(alloc);
154 try x.append("a", "b");
155 try x.append("a", "c");
156 try x.append("b", "c");
157 try x.append("b", "d");
158 x.delete("b", "c");
159 x.delete("a", null);
160 try expect(try x.encode()).toEqualString("b=d");
161}
162
163test {
164 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
165 defer arena.deinit();
166 const alloc = arena.allocator();
167
168 var x = try url.SearchParams.initFromString(alloc, "a=b&c=d");
169 try expect(x.get("a")).toEqualString("b");
170 try expect(x.get("c")).toEqualString("d");
171 try expect(x.get("e")).toBeNull();
172 x = try url.SearchParams.initFromString(alloc, "a=b&c=d&a=e");
173 try expect(x.get("a")).toEqualString("b");
174 x = try url.SearchParams.initFromString(alloc, "=b&c=d");
175 try expect(x.get("")).toEqualString("b");
176 x = try url.SearchParams.initFromString(alloc, "a=&c=d&a=e");
177 try expect(x.get("a")).toEqualString("");
178}
179
180test {
181 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
182 defer arena.deinit();
183 const alloc = arena.allocator();
184
185 var x = try url.SearchParams.initFromString(alloc, "first=second&third&&");
186 try expect(x.has("first", null)).toEqual(true);
187 try expect(x.get("first")).toEqualString("second");
188 try expect(x.get("third")).toEqualString("");
189 try expect(x.get("fourth")).toBeNull();
190}
191
192test {
193 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
194 defer arena.deinit();
195 const alloc = arena.allocator();
196
197 var x = try url.SearchParams.initFromString(alloc, "a=b&c=d");
198 try expect(try x.getAll("a")).toEqualStringSlice(&.{"b"});
199 try expect(try x.getAll("c")).toEqualStringSlice(&.{"d"});
200 try expect(try x.getAll("e")).toEqualStringSlice(&.{});
201 x = try url.SearchParams.initFromString(alloc, "a=b&c=d&a=e");
202 try expect(try x.getAll("a")).toEqualStringSlice(&.{ "b", "e" });
203 x = try url.SearchParams.initFromString(alloc, "=b&c=d");
204 try expect(try x.getAll("")).toEqualStringSlice(&.{"b"});
205 x = try url.SearchParams.initFromString(alloc, "a=&c=d&a=e");
206 try expect(try x.getAll("a")).toEqualStringSlice(&.{ "", "e" });
207}
208
209test {
210 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
211 defer arena.deinit();
212 const alloc = arena.allocator();
213
214 var x = try url.SearchParams.initFromString(alloc, "a=1&a=2&a=3&a");
215 try expect(x.has("a", null)).toEqual(true);
216 var matches = try x.getAll("a");
217 try expect(matches).not().toBeNull();
218 try expect(matches.?.len).toEqual(4);
219 try expect(matches).toEqualStringSlice(&.{ "1", "2", "3", "" });
220 try x.set("a", "one");
221 try expect(x.get("a")).toEqualString("one");
222 try expect(try x.encode()).toEqualString("a=one");
223 matches = try x.getAll("a");
224 try expect(matches).not().toBeNull();
225 try expect(matches.?.len).toEqual(1);
226 try expect(matches).toEqualStringSlice(&.{"one"});
227}
228
229test {
230 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
231 defer arena.deinit();
232 const alloc = arena.allocator();
233
234 var x = try url.SearchParams.initFromString(alloc, "a=b&c=d");
235 try expect(x.has("a", null)).toEqual(true);
236 try expect(x.has("c", null)).toEqual(true);
237 try expect(x.has("e", null)).toEqual(false);
238 x = try url.SearchParams.initFromString(alloc, "a=b&c=d&a=e");
239 try expect(x.has("a", null)).toEqual(true);
240 x = try url.SearchParams.initFromString(alloc, "=b&c=d");
241 try expect(x.has("", null)).toEqual(true);
242 x = try url.SearchParams.initFromString(alloc, "null=a");
243 try expect(x.has("null", null)).toEqual(true);
244}
245
246test {
247 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
248 defer arena.deinit();
249 const alloc = arena.allocator();
250
251 var x = try url.SearchParams.initFromString(alloc, "a=b&c=d&&");
252 try x.append("first", "1");
253 try x.append("first", "2");
254 try expect(x.has("a", null)).toEqual(true);
255 try expect(x.has("c", null)).toEqual(true);
256 try expect(x.has("first", null)).toEqual(true);
257 try expect(x.has("d", null)).toEqual(false);
258 x.delete("first", null);
259 try expect(x.has("first", null)).toEqual(false);
260}
261
262test {
263 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
264 defer arena.deinit();
265 const alloc = arena.allocator();
266
267 var x = try url.SearchParams.initFromString(alloc, "a=b&a=d&c&e&");
268 try expect(x.has("a", "b")).toEqual(true);
269 try expect(x.has("a", "c")).toEqual(false);
270 try expect(x.has("a", "d")).toEqual(true);
271 try expect(x.has("e", "")).toEqual(true);
272 try x.append("first", "null");
273 try expect(x.has("first", "")).toEqual(false);
274 try expect(x.has("first", "null")).toEqual(true);
275 x.delete("a", "b");
276 try expect(x.has("a", "d")).toEqual(true);
277}
278
279test {
280 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
281 defer arena.deinit();
282 const alloc = arena.allocator();
283
284 var x = try url.SearchParams.initFromString(alloc, "a=b&a=d&c&e&");
285 try expect(x.has("a", "b")).toEqual(true);
286 try expect(x.has("a", "c")).toEqual(false);
287 try expect(x.has("a", "d")).toEqual(true);
288 try expect(x.has("a", null)).toEqual(true);
289}
290
291test {
292 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
293 defer arena.deinit();
294 const alloc = arena.allocator();
295
296 var x = try url.SearchParams.initFromString(alloc, "a=b&c=d");
297 try x.set("a", "B");
298 try expect(try x.encode()).toEqualString("a=B&c=d");
299 x = try url.SearchParams.initFromString(alloc, "a=b&c=d&a=e");
300 try x.set("a", "B");
301 try expect(try x.encode()).toEqualString("a=B&c=d");
302 try x.set("e", "f");
303 try expect(try x.encode()).toEqualString("a=B&c=d&e=f");
304}
305
306test {
307 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
308 defer arena.deinit();
309 const alloc = arena.allocator();
310
311 var x = try url.SearchParams.initFromString(alloc, "a=1&a=2&a=3");
312 try expect(x.has("a", null)).toEqual(true);
313 try expect(x.get("a")).toEqualString("1");
314 try x.set("first", "4");
315 try expect(x.has("a", null)).toEqual(true);
316 try expect(x.get("a")).toEqualString("1");
317 try x.set("a", "4");
318 try expect(x.has("a", null)).toEqual(true);
319 try expect(x.get("a")).toEqualString("4");
320}
321
322test {
323 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
324 defer arena.deinit();
325 const alloc = arena.allocator();
326
327 var x = try url.SearchParams.initFromString(alloc, "a=1&b=2&a=3");
328 try expect(x.size()).toEqual(3);
329 x.delete("a", null);
330 try expect(x.size()).toEqual(1);
331}
332
333test {
334 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
335 defer arena.deinit();
336 const alloc = arena.allocator();
337
338 var x = try url.SearchParams.initFromString(alloc, "a=1&b=2&a=3");
339 try expect(x.size()).toEqual(3);
340 try x.append("b", "4");
341 try expect(x.size()).toEqual(4);
342}
343
344test {
345 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
346 defer arena.deinit();
347 const alloc = arena.allocator();
348
349 var x = try url.SearchParams.initFromString(alloc, "a=1&b=2&a=3");
350 try expect(x.size()).toEqual(3);
351 x.delete("a", null);
352 try expect(x.size()).toEqual(1);
353 try x.append("b", "4");
354 try expect(x.size()).toEqual(2);
355}
356
357test {
358 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
359 defer arena.deinit();
360 const alloc = arena.allocator();
361
362 var x = url.SearchParams.init(alloc);
363 try x.append("a", "b c");
364 try expect(try x.encode()).toEqualString("a=b+c");
365 x.delete("a", null);
366 try x.append("a b", "c");
367 try expect(try x.encode()).toEqualString("a+b=c");
368}
369
370test {
371 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
372 defer arena.deinit();
373 const alloc = arena.allocator();
374
375 var x = url.SearchParams.init(alloc);
376 try x.append("a", "");
377 try expect(try x.encode()).toEqualString("a=");
378 try x.append("a", "");
379 try expect(try x.encode()).toEqualString("a=&a=");
380 try x.append("", "b");
381 try expect(try x.encode()).toEqualString("a=&a=&=b");
382 try x.append("", "");
383 try expect(try x.encode()).toEqualString("a=&a=&=b&=");
384 try x.append("", "");
385 try expect(try x.encode()).toEqualString("a=&a=&=b&=&=");
386}
387
388test {
389 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
390 defer arena.deinit();
391 const alloc = arena.allocator();
392
393 var x = url.SearchParams.init(alloc);
394 try x.append("", "b");
395 try expect(try x.encode()).toEqualString("=b");
396 try x.append("", "b");
397 try expect(try x.encode()).toEqualString("=b&=b");
398}
399
400test {
401 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
402 defer arena.deinit();
403 const alloc = arena.allocator();
404
405 var x = url.SearchParams.init(alloc);
406 try x.append("", "");
407 try expect(try x.encode()).toEqualString("=");
408 try x.append("", "");
409 try expect(try x.encode()).toEqualString("=&=");
410}
411
412test {
413 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
414 defer arena.deinit();
415 const alloc = arena.allocator();
416
417 var x = url.SearchParams.init(alloc);
418 try x.append("a", "b+c");
419 try expect(try x.encode()).toEqualString("a=b%2Bc");
420 x.delete("a", null);
421 try x.append("a+b", "c");
422 try expect(try x.encode()).toEqualString("a%2Bb=c");
423}
424
425test {
426 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
427 defer arena.deinit();
428 const alloc = arena.allocator();
429
430 var x = url.SearchParams.init(alloc);
431 try x.append("=", "a");
432 try expect(try x.encode()).toEqualString("%3D=a");
433 try x.append("b", "=");
434 try expect(try x.encode()).toEqualString("%3D=a&b=%3D");
435}
436
437test {
438 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
439 defer arena.deinit();
440 const alloc = arena.allocator();
441
442 var x = url.SearchParams.init(alloc);
443 try x.append("&", "a");
444 try expect(try x.encode()).toEqualString("%26=a");
445 try x.append("b", "&");
446 try expect(try x.encode()).toEqualString("%26=a&b=%26");
447}
448
449test {
450 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
451 defer arena.deinit();
452 const alloc = arena.allocator();
453
454 var x = url.SearchParams.init(alloc);
455 try x.append("a", "*-._");
456 try expect(try x.encode()).toEqualString("a=*-._");
457 x.delete("a", null);
458 try x.append("*-._", "c");
459 try expect(try x.encode()).toEqualString("*-._=c");
460}
461
462test {
463 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
464 defer arena.deinit();
465 const alloc = arena.allocator();
466
467 var x = url.SearchParams.init(alloc);
468 try x.append("a", "b%c");
469 try expect(try x.encode()).toEqualString("a=b%25c");
470 x.delete("a", null);
471 try x.append("a%b", "c");
472 try expect(try x.encode()).toEqualString("a%25b=c");
473 x = try url.SearchParams.initFromString(alloc, "id=0&value=%");
474 try expect(try x.encode()).toEqualString("id=0&value=%25");
475}
476
477test {
478 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
479 defer arena.deinit();
480 const alloc = arena.allocator();
481
482 var x = url.SearchParams.init(alloc);
483 try x.append("a", "b\x00c");
484 try expect(try x.encode()).toEqualString("a=b%00c");
485 x.delete("a", null);
486 try x.append("a\x00b", "c");
487 try expect(try x.encode()).toEqualString("a%00b=c");
488}
489
490test {
491 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
492 defer arena.deinit();
493 const alloc = arena.allocator();
494
495 var x = url.SearchParams.init(alloc);
496 // try x.append("a", "b\uD83D\uDCA9c");
497 try x.append("a", "b\xf0\x9f\x92\xa9c");
498 try expect(try x.encode()).toEqualString("a=b%F0%9F%92%A9c");
499 x.delete("a", null);
500 // try x.append("a\uD83D\uDCA9b", "c");
501 try x.append("a\xf0\x9f\x92\xa9b", "c");
502 try expect(try x.encode()).toEqualString("a%F0%9F%92%A9b=c");
503}
504
505test {
506 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
507 defer arena.deinit();
508 const alloc = arena.allocator();
509
510 var x = url.SearchParams.init(alloc);
511 x = try url.SearchParams.initFromString(alloc, "a=b&c=d&&e&&");
512 try expect(try x.encode()).toEqualString("a=b&c=d&e=");
513 x = try url.SearchParams.initFromString(alloc, "a = b &a=b&c=d%20");
514 try expect(try x.encode()).toEqualString("a+=+b+&a=b&c=d+");
515 // The lone "=" _does_ survive the roundtrip.
516 x = try url.SearchParams.initFromString(alloc, "a=&a=b");
517 try expect(try x.encode()).toEqualString("a=&a=b");
518 x = try url.SearchParams.initFromString(alloc, "b=%2sf%2a");
519 try expect(try x.encode()).toEqualString("b=%252sf*");
520 x = try url.SearchParams.initFromString(alloc, "b=%2%2af%2a");
521 try expect(try x.encode()).toEqualString("b=%252*f*");
522 x = try url.SearchParams.initFromString(alloc, "b=%%2a");
523 try expect(try x.encode()).toEqualString("b=%25*");
524}
525
526test {
527 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
528 defer arena.deinit();
529 const alloc = arena.allocator();
530
531 var x = try url.SearchParams.initFromString(alloc, "a=b,c");
532 try expect(try x.encode()).toEqualString("a=b%2Cc");
533 try x.append("x", "y");
534 try expect(try x.encode()).toEqualString("a=b%2Cc&x=y");
535}
536
537test {
538 var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
539 defer arena.deinit();
540 const alloc = arena.allocator();
541
542 var x = url.SearchParams.init(alloc);
543 try x.append("a\nb", "c\rd");
544 try x.append("e\n\rf", "g\r\nh");
545 try expect(try x.encode()).toEqualString("a%0Ab=c%0Dd&e%0A%0Df=g%0D%0Ah");
546}