Skip to content

Commit ba12945

Browse files
Move read input from Cmd callback to allow unit tests
Signed-off-by: Francis Bouvier <[email protected]>
1 parent 96906df commit ba12945

File tree

1 file changed

+71
-52
lines changed

1 file changed

+71
-52
lines changed

src/server.zig

Lines changed: 71 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub const Cmd = struct {
4545
}
4646

4747
// input
48-
var input = self.buf[0..size];
48+
const input = self.buf[0..size];
4949
if (std.log.defaultLogEnabled(.debug)) {
5050
std.debug.print("\ninput size: {d}, content: {s}\n", .{ size, input });
5151
}
@@ -56,57 +56,8 @@ pub const Cmd = struct {
5656
return;
5757
}
5858

59-
// cmds
60-
while (true) {
61-
62-
// parse json msg size
63-
const size_pos = std.mem.indexOfScalar(u8, input, ':').?;
64-
std.log.debug("msg size pos: {d}", .{size_pos});
65-
const size_str = input[0..size_pos];
66-
input = input[size_pos + 1 ..];
67-
const size_msg = std.fmt.parseInt(u32, size_str, 10) catch |err| {
68-
self.err = err;
69-
return;
70-
};
71-
std.log.debug("msg size: {d}", .{size_msg});
72-
73-
// part
74-
const is_part = input.len < size_msg;
75-
std.log.debug("is_part: {any}", .{is_part});
76-
if (is_part) {
77-
std.log.debug("size_msg {d}, input {d}", .{ size_msg, input.len });
78-
@panic("part msg"); // TODO: implement part
79-
}
80-
81-
// handle several JSON msg in 1 read
82-
const is_multi = input.len > size_msg;
83-
std.log.debug("is_multi: {any}", .{is_multi});
84-
const cmd = input[0..size_msg];
85-
std.log.debug("cmd: {s}", .{cmd});
86-
if (is_multi) {
87-
input = input[size_msg..];
88-
std.log.debug("rest: {s}", .{input});
89-
}
90-
91-
// cdp
92-
const res = cdp.do(self.alloc(), cmd, self) catch |err| {
93-
if (cdp.isCdpError(err)) |e| {
94-
self.err = e;
95-
return;
96-
}
97-
@panic(@errorName(err));
98-
};
99-
100-
// send result
101-
if (!std.mem.eql(u8, res, "")) {
102-
std.log.debug("res {s}", .{res});
103-
sendAsync(self, res) catch unreachable;
104-
}
105-
106-
if (!is_multi) break;
107-
108-
// TODO: handle 1 read smaller than a complete JSON msg
109-
}
59+
// read and execute input
60+
readInput(input, Cmd.do, self) catch unreachable;
11061

11162
// continue receving incomming messages asynchronously
11263
self.loop().io.recv(*Cmd, self, cbk, completion, self.socket, self.buf);
@@ -122,8 +73,76 @@ pub const Cmd = struct {
12273
// TODO: pointer instead?
12374
return self.browser.currentSession().loop;
12475
}
76+
77+
fn do(self: *Cmd, cmd: []const u8) !void {
78+
const res = try cdp.do(self.alloc(), cmd, self);
79+
80+
// send result
81+
if (!std.mem.eql(u8, res, "")) {
82+
std.log.debug("res {s}", .{res});
83+
return sendAsync(self, res);
84+
}
85+
}
12586
};
12687

88+
fn readInput(buf: []const u8, func: anytype, data: anytype) !void {
89+
var input = buf;
90+
91+
while (true) {
92+
var cmd: []const u8 = undefined;
93+
94+
// size msg
95+
var size_msg: usize = undefined;
96+
97+
// parse json msg size
98+
const size_pos = std.mem.indexOfScalar(u8, input, ':').?;
99+
std.log.debug("msg size pos: {d}", .{size_pos});
100+
const size_str = input[0..size_pos];
101+
input = input[size_pos + 1 ..];
102+
size_msg = try std.fmt.parseInt(u32, size_str, 10);
103+
// }
104+
std.log.debug("msg size: {d}", .{size_msg});
105+
106+
// handle several JSON msg in 1 read
107+
const is_multi = input.len > size_msg;
108+
std.log.debug("is_multi: {any}", .{is_multi});
109+
cmd = input[0..size_msg];
110+
std.log.debug("cmd: {s}", .{cmd[0..@min(BufReadSize, size_msg)]});
111+
if (is_multi) {
112+
input = input[size_msg..];
113+
std.log.debug("rest: {s}", .{input});
114+
}
115+
116+
try @call(.auto, func, .{ data, cmd });
117+
118+
if (!is_multi) break;
119+
120+
// TODO: handle 1 read smaller than a complete JSON msg
121+
}
122+
}
123+
124+
fn doTest(nb: *u8, _: []const u8) anyerror!void {
125+
nb.* += 1;
126+
}
127+
128+
test {
129+
const Case = struct {
130+
input: []const u8,
131+
nb: u8,
132+
};
133+
const cases = [_]Case{
134+
// simple
135+
.{ .input = "2:ok", .nb = 1 },
136+
// multi
137+
.{ .input = "2:ok3:foo7:bar2:ok", .nb = 3 }, // "bar2:ok" is a message, no need to escape "2:" here
138+
};
139+
for (cases) |case| {
140+
var nb: u8 = 0;
141+
try readInput(case.input, doTest, &nb);
142+
try std.testing.expect(nb == case.nb);
143+
}
144+
}
145+
127146
// I/O Send
128147
// --------
129148

0 commit comments

Comments
 (0)