Skip to content

Commit 95332e9

Browse files
committed
Adding tests
1 parent 5a5f27c commit 95332e9

File tree

6 files changed

+97
-23
lines changed

6 files changed

+97
-23
lines changed

build.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub fn build(b: *std.Build) void {
1111
});
1212

1313
const unit_tests = b.addTest(.{
14-
.root_source_file = b.path("src/url_test.zig"),
14+
.root_source_file = b.path("src/test.zig"),
1515
.target = target,
1616
.optimize = optimize,
1717
});

src/test.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
test {
2+
_ = @import("url_test.zig");
3+
_ = @import("values_test.zig");
4+
}

src/url.zig

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ const Uri = std.Uri;
55
const ParseError = std.Uri.ParseError;
66
const StringHashMap = @import("std").StringHashMap;
77

8+
const Values = @import("values.zig").Values;
9+
810
pub const URL = @This();
911

1012
allocator: std.mem.Allocator = std.heap.page_allocator,
@@ -14,14 +16,15 @@ host: ?[]const u8 = undefined,
1416
path: []const u8 = "/",
1517
fragment: ?[]const u8 = undefined,
1618
query: ?[]const u8 = undefined,
17-
querymap: ?StringHashMap([]const u8) = StringHashMap([]const u8).init(std.heap.page_allocator),
19+
20+
// querymap: ?StringHashMap(std.ArrayList([]const u8)) = StringHashMap(std.ArrayList([]const u8)).init(std.heap.page_allocator),
21+
values: ?std.StringHashMap(std.ArrayList([]const u8)) = std.StringHashMap(std.ArrayList([]const u8)).init(std.heap.page_allocator),
1822

1923
// https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL
2024

2125
pub fn init(self: URL) URL {
2226
return .{
2327
.allocator = self.allocator,
24-
// .uri = self.uri,
2528
// .querymap = self.querymap,
2629
};
2730
}
@@ -67,7 +70,7 @@ pub fn parseUrl(self: *URL, text: []const u8) ParseError!*URL {
6770
if ((reader.peek() orelse 0) == '?') { // query part
6871
std.debug.assert(reader.get().? == '?');
6972
self.query = reader.readUntil(isQuerySeparator);
70-
self.querymap = parseQuery(self.query.?);
73+
try parseQuery(&self.values.?, self.query.?);
7174
}
7275

7376
if ((reader.peek() orelse 0) == '#') { // fragment part
@@ -90,7 +93,7 @@ fn uriToUrl(self: *URL, uri: Uri) void {
9093

9194
if (uri.query != null) {
9295
self.query = @constCast(uri.query.?.percent_encoded);
93-
self.querymap = parseQuery(@constCast(uri.query.?.percent_encoded));
96+
try parseQuery(&self.values.?, @constCast(uri.query.?.percent_encoded));
9497
}
9598
if (uri.fragment != null) {
9699
self.fragment = @constCast(uri.fragment.?.percent_encoded);
@@ -104,8 +107,7 @@ pub fn parseUri(self: *URL, text: []const u8) ParseError!*URL {
104107
return self;
105108
}
106109

107-
pub fn parseQuery(uri_query: []const u8) StringHashMap([]const u8) {
108-
var querymap = StringHashMap([]const u8).init(std.heap.page_allocator);
110+
pub fn parseQuery(map: *std.StringHashMap(std.ArrayList([]const u8)), uri_query: []const u8) !void {
109111
var queryitmes = std.mem.splitSequence(u8, uri_query, "&");
110112
while (true) {
111113
const pair = queryitmes.next();
@@ -114,19 +116,31 @@ pub fn parseQuery(uri_query: []const u8) StringHashMap([]const u8) {
114116
}
115117
var kv = std.mem.splitSequence(u8, pair.?, "=");
116118
if (kv.buffer.len == 0) {
117-
break;
119+
continue;
118120
}
119121
const key = kv.next();
120122
if (key == null) {
121-
break;
123+
continue;
122124
}
125+
123126
const value = kv.next();
124127
if (value == null) {
125-
break;
128+
continue;
129+
}
130+
131+
var al: std.ArrayList([]const u8) = undefined;
132+
const v = map.get(key.?);
133+
if (v == null) {
134+
al = std.ArrayList([]const u8).init(std.heap.page_allocator);
135+
al.append(value.?) catch continue;
136+
map.put(key.?, al) catch continue;
137+
continue;
126138
}
127-
querymap.put(key.?, value.?) catch break;
139+
140+
al = v.?;
141+
al.append(value.?) catch continue;
142+
map.put(key.?, al) catch continue;
128143
}
129-
return querymap;
130144
}
131145

132146
fn isAuthoritySeparator(c: u8) bool {

src/url_test.zig

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,23 @@ test "parseUri 1" {
2121
);
2222
try testing.expectEqualStrings("query=1&query2=2", result.query.?);
2323

24-
var querymap = result.querymap.?;
24+
var querymap = result.values.?;
2525
defer querymap.deinit();
26-
try testing.expectEqualStrings("1", querymap.get("query").?);
27-
try testing.expectEqualStrings("2", querymap.get("query2").?);
26+
try testing.expectEqualStrings("1", querymap.get("query").?.items[0]);
27+
try testing.expectEqualStrings("2", querymap.get("query2").?.items[0]);
2828

2929
if (querymap.get("query3") != null) {
3030
try testing.expect(false);
3131
}
3232

3333
// query=1&query2=2
3434

35-
var qm = URL.parseQuery(result.query.?);
35+
var qm = std.StringHashMap(std.ArrayList([]const u8)).init(std.testing.allocator);
36+
URL.parseQuery(&qm, result.query.?) catch return;
3637
defer qm.deinit();
37-
try testing.expectEqualStrings("1", qm.get("query").?);
38-
try testing.expectEqualStrings("2", qm.get("query2").?);
38+
39+
try testing.expectEqualStrings("1", qm.get("query").?.items[0]);
40+
try testing.expectEqualStrings("2", qm.get("query2").?.items[0]);
3941

4042
if (qm.get("query3") != null) {
4143
try testing.expect(false);
@@ -55,9 +57,10 @@ test "parseUri 2" {
5557
result.path,
5658
);
5759
try testing.expectEqualStrings("name=ferret", result.query.?);
58-
var qm = url.querymap.?;
60+
var qm = url.values.?;
5961
defer qm.deinit();
60-
try testing.expectEqualStrings("ferret", qm.get("name").?);
62+
const vm = qm.get("name").?;
63+
try testing.expectEqualStrings("ferret", vm.items[0]);
6164
try testing.expectEqualStrings("nose", result.fragment.?);
6265
}
6366

@@ -83,8 +86,9 @@ test "RFC example 1" {
8386
try testing.expectEqualStrings("/over/there", result.path);
8487
try testing.expectEqualStrings("name=ferret", @constCast(result.query.?));
8588
try testing.expectEqualStrings("nose", result.fragment.?);
86-
87-
var qm = url.querymap.?;
89+
90+
var qm = url.values.?;
8891
defer qm.deinit();
89-
try testing.expectEqualStrings("ferret", qm.get("name").?);
92+
const vm = qm.get("name").?;
93+
try testing.expectEqualStrings("ferret", vm.items[0]);
9094
}

src/values.zig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// const std = @import("std");
2+
// const StringArrayHashMap = std.StringArrayHashMap;
3+
// const ArrayList = std.ArrayList;
4+
// const allocator = std.heap.page_allocator;
5+
6+
// pub fn has(list: ArrayList([]const u8), value: []const u8) bool {
7+
// for (list.items) |item| {
8+
// if (std.mem.eql(u8, item, value)) {
9+
// return true;
10+
// }
11+
// }
12+
// return false;
13+
// }

src/values_test.zig

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const std = @import("std");
2+
const url = @import("url.zig");
3+
test "sample1" {
4+
var values: std.StringHashMap(std.ArrayList([]const u8)) = std.StringHashMap(std.ArrayList([]const u8)).init(std.heap.page_allocator);
5+
defer values.deinit();
6+
7+
var name = std.ArrayList([]const u8).init(std.heap.page_allocator);
8+
try name.append("Ava");
9+
10+
var friend = std.ArrayList([]const u8).init(std.heap.page_allocator);
11+
try friend.append("Jess");
12+
try friend.append("Sarah");
13+
try friend.append("Zoe");
14+
15+
try values.put("name", name);
16+
try values.put("friend", friend);
17+
18+
try std.testing.expectEqualStrings("Ava", name.getLast());
19+
20+
const friend1 = values.get("friend").?.items[0];
21+
const friend2 = values.get("friend").?.items[1];
22+
const friend3 = values.get("friend").?.items[2];
23+
try std.testing.expectEqualStrings("Jess", friend1);
24+
try std.testing.expectEqualStrings("Sarah", friend2);
25+
try std.testing.expectEqualStrings("Zoe", friend3);
26+
27+
values.clearAndFree();
28+
}
29+
30+
test "sample2" {
31+
const text = "name=Ava&friend=Jess&friend=Sarah&friend=Zoe";
32+
var values: std.StringHashMap(std.ArrayList([]const u8)) = std.StringHashMap(std.ArrayList([]const u8)).init(std.heap.page_allocator);
33+
defer values.deinit();
34+
try url.parseQuery(&values, text);
35+
try std.testing.expectEqualStrings("Ava", values.get("name").?.items[0]);
36+
try std.testing.expectEqualStrings("Jess", values.get("friend").?.items[0]);
37+
try std.testing.expectEqualStrings("Sarah", values.get("friend").?.items[1]);
38+
try std.testing.expectEqualStrings("Zoe", values.get("friend").?.items[2]);
39+
}

0 commit comments

Comments
 (0)