| ... | @@ -10,7 +10,8 @@ const expectError = std.testing.expectError; | ... | @@ -10,7 +10,8 @@ const expectError = std.testing.expectError; |
| 10 | | 10 | |
| 11 | test "trailers" { | 11 | test "trailers" { |
| 12 | const test_server = try createTestServer(struct { | 12 | const test_server = try createTestServer(struct { |
| 13 | fn run(net_server: *std.net.Server) anyerror!void { | 13 | fn run(test_server: *TestServer) anyerror!void { |
| | 14 | const net_server = &test_server.net_server; |
| 14 | var recv_buffer: [1024]u8 = undefined; | 15 | var recv_buffer: [1024]u8 = undefined; |
| 15 | var send_buffer: [1024]u8 = undefined; | 16 | var send_buffer: [1024]u8 = undefined; |
| 16 | var remaining: usize = 1; | 17 | var remaining: usize = 1; |
| ... | @@ -96,7 +97,8 @@ test "trailers" { | ... | @@ -96,7 +97,8 @@ test "trailers" { |
| 96 | | 97 | |
| 97 | test "HTTP server handles a chunked transfer coding request" { | 98 | test "HTTP server handles a chunked transfer coding request" { |
| 98 | const test_server = try createTestServer(struct { | 99 | const test_server = try createTestServer(struct { |
| 99 | fn run(net_server: *std.net.Server) !void { | 100 | fn run(test_server: *TestServer) anyerror!void { |
| | 101 | const net_server = &test_server.net_server; |
| 100 | var recv_buffer: [8192]u8 = undefined; | 102 | var recv_buffer: [8192]u8 = undefined; |
| 101 | var send_buffer: [500]u8 = undefined; | 103 | var send_buffer: [500]u8 = undefined; |
| 102 | const connection = try net_server.accept(); | 104 | const connection = try net_server.accept(); |
| ... | @@ -162,11 +164,12 @@ test "HTTP server handles a chunked transfer coding request" { | ... | @@ -162,11 +164,12 @@ test "HTTP server handles a chunked transfer coding request" { |
| 162 | | 164 | |
| 163 | test "echo content server" { | 165 | test "echo content server" { |
| 164 | const test_server = try createTestServer(struct { | 166 | const test_server = try createTestServer(struct { |
| 165 | fn run(net_server: *std.net.Server) anyerror!void { | 167 | fn run(test_server: *TestServer) anyerror!void { |
| | 168 | const net_server = &test_server.net_server; |
| 166 | var recv_buffer: [1024]u8 = undefined; | 169 | var recv_buffer: [1024]u8 = undefined; |
| 167 | var send_buffer: [100]u8 = undefined; | 170 | var send_buffer: [100]u8 = undefined; |
| 168 | | 171 | |
| 169 | accept: while (true) { | 172 | accept: while (!test_server.shutting_down) { |
| 170 | const connection = try net_server.accept(); | 173 | const connection = try net_server.accept(); |
| 171 | defer connection.stream.close(); | 174 | defer connection.stream.close(); |
| 172 | | 175 | |
| ... | @@ -251,7 +254,8 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { | ... | @@ -251,7 +254,8 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { |
| 251 | // In this case, the response is expected to stream until the connection is | 254 | // In this case, the response is expected to stream until the connection is |
| 252 | // closed, indicating the end of the body. | 255 | // closed, indicating the end of the body. |
| 253 | const test_server = try createTestServer(struct { | 256 | const test_server = try createTestServer(struct { |
| 254 | fn run(net_server: *std.net.Server) anyerror!void { | 257 | fn run(test_server: *TestServer) anyerror!void { |
| | 258 | const net_server = &test_server.net_server; |
| 255 | var recv_buffer: [1000]u8 = undefined; | 259 | var recv_buffer: [1000]u8 = undefined; |
| 256 | var send_buffer: [500]u8 = undefined; | 260 | var send_buffer: [500]u8 = undefined; |
| 257 | var remaining: usize = 1; | 261 | var remaining: usize = 1; |
| ... | @@ -279,6 +283,7 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { | ... | @@ -279,6 +283,7 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { |
| 279 | try bw.print("{d}, ah ha ha!\n", .{i}); | 283 | try bw.print("{d}, ah ha ha!\n", .{i}); |
| 280 | } | 284 | } |
| 281 | try expectEqual(7390, bw.count); | 285 | try expectEqual(7390, bw.count); |
| | 286 | try bw.flush(); |
| 282 | try response.end(); | 287 | try response.end(); |
| 283 | try expectEqual(.closing, server.reader.state); | 288 | try expectEqual(.closing, server.reader.state); |
| 284 | } | 289 | } |
| ... | @@ -319,7 +324,8 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { | ... | @@ -319,7 +324,8 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { |
| 319 | | 324 | |
| 320 | test "receiving arbitrary http headers from the client" { | 325 | test "receiving arbitrary http headers from the client" { |
| 321 | const test_server = try createTestServer(struct { | 326 | const test_server = try createTestServer(struct { |
| 322 | fn run(net_server: *std.net.Server) anyerror!void { | 327 | fn run(test_server: *TestServer) anyerror!void { |
| | 328 | const net_server = &test_server.net_server; |
| 323 | var recv_buffer: [666]u8 = undefined; | 329 | var recv_buffer: [666]u8 = undefined; |
| 324 | var send_buffer: [777]u8 = undefined; | 330 | var send_buffer: [777]u8 = undefined; |
| 325 | var remaining: usize = 1; | 331 | var remaining: usize = 1; |
| ... | @@ -385,15 +391,13 @@ test "general client/server API coverage" { | ... | @@ -385,15 +391,13 @@ test "general client/server API coverage" { |
| 385 | return error.SkipZigTest; | 391 | return error.SkipZigTest; |
| 386 | } | 392 | } |
| 387 | | 393 | |
| 388 | const global = struct { | | |
| 389 | var handle_new_requests = true; | | |
| 390 | }; | | |
| 391 | const test_server = try createTestServer(struct { | 394 | const test_server = try createTestServer(struct { |
| 392 | fn run(net_server: *std.net.Server) anyerror!void { | 395 | fn run(test_server: *TestServer) anyerror!void { |
| | 396 | const net_server = &test_server.net_server; |
| 393 | var recv_buffer: [1024]u8 = undefined; | 397 | var recv_buffer: [1024]u8 = undefined; |
| 394 | var send_buffer: [100]u8 = undefined; | 398 | var send_buffer: [100]u8 = undefined; |
| 395 | | 399 | |
| 396 | outer: while (global.handle_new_requests) { | 400 | outer: while (!test_server.shutting_down) { |
| 397 | var connection = try net_server.accept(); | 401 | var connection = try net_server.accept(); |
| 398 | defer connection.stream.close(); | 402 | defer connection.stream.close(); |
| 399 | | 403 | |
| ... | @@ -544,17 +548,13 @@ test "general client/server API coverage" { | ... | @@ -544,17 +548,13 @@ test "general client/server API coverage" { |
| 544 | return s.listen_address.in.getPort(); | 548 | return s.listen_address.in.getPort(); |
| 545 | } | 549 | } |
| 546 | }); | 550 | }); |
| 547 | defer { | 551 | defer test_server.destroy(); |
| 548 | global.handle_new_requests = false; | | |
| 549 | test_server.destroy(); | | |
| 550 | } | | |
| 551 | | 552 | |
| 552 | const log = std.log.scoped(.client); | 553 | const log = std.log.scoped(.client); |
| 553 | | 554 | |
| 554 | const gpa = std.testing.allocator; | 555 | const gpa = std.testing.allocator; |
| 555 | var client: http.Client = .{ .allocator = gpa }; | 556 | var client: http.Client = .{ .allocator = gpa }; |
| 556 | errdefer client.deinit(); | 557 | defer client.deinit(); |
| 557 | // defer client.deinit(); handled below | | |
| 558 | | 558 | |
| 559 | const port = test_server.port(); | 559 | const port = test_server.port(); |
| 560 | | 560 | |
| ... | @@ -870,20 +870,12 @@ test "general client/server API coverage" { | ... | @@ -870,20 +870,12 @@ test "general client/server API coverage" { |
| 870 | | 870 | |
| 871 | // connection has been kept alive | 871 | // connection has been kept alive |
| 872 | try expect(client.http_proxy != null or client.connection_pool.free_len == 1); | 872 | try expect(client.http_proxy != null or client.connection_pool.free_len == 1); |
| 873 | | | |
| 874 | client.deinit(); | | |
| 875 | | | |
| 876 | { | | |
| 877 | global.handle_new_requests = false; | | |
| 878 | | | |
| 879 | const conn = try std.net.tcpConnectToAddress(test_server.net_server.listen_address); | | |
| 880 | conn.close(); | | |
| 881 | } | | |
| 882 | } | 873 | } |
| 883 | | 874 | |
| 884 | test "Server streams both reading and writing" { | 875 | test "Server streams both reading and writing" { |
| 885 | const test_server = try createTestServer(struct { | 876 | const test_server = try createTestServer(struct { |
| 886 | fn run(net_server: *std.net.Server) anyerror!void { | 877 | fn run(test_server: *TestServer) anyerror!void { |
| | 878 | const net_server = &test_server.net_server; |
| 887 | var recv_buffer: [1024]u8 = undefined; | 879 | var recv_buffer: [1024]u8 = undefined; |
| 888 | var send_buffer: [777]u8 = undefined; | 880 | var send_buffer: [777]u8 = undefined; |
| 889 | | 881 | |
| ... | @@ -1091,19 +1083,18 @@ fn echoTests(client: *http.Client, port: u16) !void { | ... | @@ -1091,19 +1083,18 @@ fn echoTests(client: *http.Client, port: u16) !void { |
| 1091 | try expectEqual(.expectation_failed, response.head.status); | 1083 | try expectEqual(.expectation_failed, response.head.status); |
| 1092 | _ = try response.reader().discardRemaining(); | 1084 | _ = try response.reader().discardRemaining(); |
| 1093 | } | 1085 | } |
| 1094 | | | |
| 1095 | _ = try client.fetch(.{ | | |
| 1096 | .location = .{ | | |
| 1097 | .url = try std.fmt.bufPrint(&location_buffer, "http://127.0.0.1:{d}/end", .{port}), | | |
| 1098 | }, | | |
| 1099 | }); | | |
| 1100 | } | 1086 | } |
| 1101 | | 1087 | |
| 1102 | const TestServer = struct { | 1088 | const TestServer = struct { |
| | 1089 | shutting_down: bool, |
| 1103 | server_thread: std.Thread, | 1090 | server_thread: std.Thread, |
| 1104 | net_server: std.net.Server, | 1091 | net_server: std.net.Server, |
| 1105 | | 1092 | |
| 1106 | fn destroy(self: *@This()) void { | 1093 | fn destroy(self: *@This()) void { |
| | 1094 | self.shutting_down = true; |
| | 1095 | const conn = std.net.tcpConnectToAddress(self.net_server.listen_address) catch @panic("shutdown failure"); |
| | 1096 | conn.close(); |
| | 1097 | |
| 1107 | self.server_thread.join(); | 1098 | self.server_thread.join(); |
| 1108 | self.net_server.deinit(); | 1099 | self.net_server.deinit(); |
| 1109 | std.testing.allocator.destroy(self); | 1100 | std.testing.allocator.destroy(self); |
| ... | @@ -1123,14 +1114,18 @@ fn createTestServer(S: type) !*TestServer { | ... | @@ -1123,14 +1114,18 @@ fn createTestServer(S: type) !*TestServer { |
| 1123 | | 1114 | |
| 1124 | const address = try std.net.Address.parseIp("127.0.0.1", 0); | 1115 | const address = try std.net.Address.parseIp("127.0.0.1", 0); |
| 1125 | const test_server = try std.testing.allocator.create(TestServer); | 1116 | const test_server = try std.testing.allocator.create(TestServer); |
| 1126 | test_server.net_server = try address.listen(.{ .reuse_address = true }); | 1117 | test_server.* = .{ |
| 1127 | test_server.server_thread = try std.Thread.spawn(.{}, S.run, .{&test_server.net_server}); | 1118 | .net_server = try address.listen(.{ .reuse_address = true }), |
| | 1119 | .server_thread = try std.Thread.spawn(.{}, S.run, .{test_server}), |
| | 1120 | .shutting_down = false, |
| | 1121 | }; |
| 1128 | return test_server; | 1122 | return test_server; |
| 1129 | } | 1123 | } |
| 1130 | | 1124 | |
| 1131 | test "redirect to different connection" { | 1125 | test "redirect to different connection" { |
| 1132 | const test_server_new = try createTestServer(struct { | 1126 | const test_server_new = try createTestServer(struct { |
| 1133 | fn run(net_server: *std.net.Server) anyerror!void { | 1127 | fn run(test_server: *TestServer) anyerror!void { |
| | 1128 | const net_server = &test_server.net_server; |
| 1134 | var recv_buffer: [888]u8 = undefined; | 1129 | var recv_buffer: [888]u8 = undefined; |
| 1135 | var send_buffer: [777]u8 = undefined; | 1130 | var send_buffer: [777]u8 = undefined; |
| 1136 | | 1131 | |
| ... | @@ -1155,7 +1150,8 @@ test "redirect to different connection" { | ... | @@ -1155,7 +1150,8 @@ test "redirect to different connection" { |
| 1155 | global.other_port = test_server_new.port(); | 1150 | global.other_port = test_server_new.port(); |
| 1156 | | 1151 | |
| 1157 | const test_server_orig = try createTestServer(struct { | 1152 | const test_server_orig = try createTestServer(struct { |
| 1158 | fn run(net_server: *std.net.Server) anyerror!void { | 1153 | fn run(test_server: *TestServer) anyerror!void { |
| | 1154 | const net_server = &test_server.net_server; |
| 1159 | var recv_buffer: [999]u8 = undefined; | 1155 | var recv_buffer: [999]u8 = undefined; |
| 1160 | var send_buffer: [100]u8 = undefined; | 1156 | var send_buffer: [100]u8 = undefined; |
| 1161 | | 1157 | |