diff options
Diffstat (limited to 'test/web/native.zig')
| -rw-r--r-- | test/web/native.zig | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/test/web/native.zig b/test/web/native.zig new file mode 100644 index 0000000..ad11386 --- /dev/null +++ b/test/web/native.zig @@ -0,0 +1,66 @@ +//! Native use of the public HTTPS transport, exercised by the browser E2E runner. +const std = @import("std"); +const c9 = @import("cloud9"); +const Session = struct { + tunnel: *c9.http.Client, + client: c9.Client, + fn ask(s: *Session, request: c9.Client.Request) !c9.Client.Result { + const tag = try s.client.submit(request); + try s.tunnel.send(s.client.output()); + s.client.wrote(s.client.output().len); + var buffer: [65536]u8 = undefined; + const frame = try s.tunnel.receive(&buffer); + if (s.client.push(frame) != frame.len) return error.InputFull; + const done = s.client.take() orelse return error.MissingReply; + if (done.tag != tag or done.result == .fail) return error.UnexpectedReply; + return done.result; + } +}; +pub fn main(init: std.process.Init) !void { + const args = try init.minimal.args.toSlice(init.arena.allocator()); + if (args.len < 3 or args.len > 4) return error.Arguments; + var http: std.http.Client = .{ .allocator = init.gpa, .io = init.io }; + defer http.deinit(); + if (args.len == 4) { + http.now = std.Io.Clock.real.now(init.io); + try http.ca_bundle.addCertsFromFilePathAbsolute(init.gpa, init.io, http.now.?, args[3]); + } + var tunnel = try c9.http.Client.connect(&http, args[1], args[2]); + defer tunnel.deinit(); + var input: [65536]u8 = undefined; + var output: [65536]u8 = undefined; + var session: Session = .{ .tunnel = &tunnel, .client = .init(.{ .in = &input, .out = &output }) }; + _ = try session.ask(.{ .version = .{} }); + _ = try session.ask(.{ .attach = .{ .fid = 0, .uname = "user" } }); + _ = try session.ask(.{ .walk = .{ .fid = 0, .newfid = 1, .names = &.{"hello.txt"} } }); + _ = try session.ask(.{ .open = .{ .fid = 1, .mode = c9.oread } }); + const result = try session.ask(.{ .read = .{ .fid = 1, .offset = 0, .count = 1024 } }); + if (!std.mem.eql(u8, result.read, "Hello from 9P.\n")) return error.WrongContents; + // Two outstanding tags exercise the full-duplex bridge independently of + // the browser UI's serialized file-operation queue. + const read_tag = try session.client.submit(.{ .read = .{ .fid = 1, .offset = 0, .count = 1024 } }); + try tunnel.send(session.client.output()); + session.client.wrote(session.client.output().len); + const stat_tag = try session.client.submit(.{ .stat = .{ .fid = 0 } }); + try tunnel.send(session.client.output()); + session.client.wrote(session.client.output().len); + var seen_read = false; + var seen_stat = false; + var reply_buffer: [65536]u8 = undefined; + for (0..2) |_| { + const frame = try tunnel.receive(&reply_buffer); + if (session.client.push(frame) != frame.len) return error.InputFull; + const done = session.client.take() orelse return error.MissingReply; + if (done.tag == read_tag and !seen_read and done.result == .read) { + if (!std.mem.eql(u8, done.result.read, "Hello from 9P.\n")) return error.WrongContents; + seen_read = true; + } else if (done.tag == stat_tag and !seen_stat and done.result == .stat) { + if (done.result.stat.qid.type & c9.qtdir == 0) return error.WrongStat; + seen_stat = true; + } else return error.UnexpectedReply; + } + if (!seen_read or !seen_stat) return error.MissingReply; + _ = try session.ask(.{ .clunk = .{ .fid = 1 } }); + _ = try session.ask(.{ .clunk = .{ .fid = 0 } }); + std.debug.print("native HTTP transport passed\n", .{}); +} |
