add TLS integration test for sync client

This commit is contained in:
Karl Seguin
2025-03-20 11:39:50 +08:00
parent 2f362f2aa2
commit feb2046549
10 changed files with 504 additions and 143 deletions

View File

@@ -74,7 +74,7 @@ pub const Browser = struct {
.allocator = allocator,
.http_client = &app.http_client,
.session_pool = SessionPool.init(allocator),
.http_client = try http.Client.init(allocator, 5),
.http_client = try http.Client.init(allocator, 5, null),
.page_arena = std.heap.ArenaAllocator.init(allocator),
};
}

View File

@@ -1,3 +1,20 @@
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
//
// Francis Bouvier <francis@lightpanda.io>
// Pierre Tachoire <pierre@lightpanda.io>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
const std = @import("std");
const builtin = @import("builtin");
@@ -30,8 +47,9 @@ pub const Client = struct {
state_pool: StatePool,
root_ca: tls.config.CertBundle,
pub fn init(allocator: Allocator, max_concurrent: usize) !Client {
var root_ca = try tls.config.CertBundle.fromSystem(allocator);
// we only allow passing in a root_ca for testing
pub fn init(allocator: Allocator, max_concurrent: usize, root_ca_: ?tls.config.CertBundle) !Client {
var root_ca = root_ca_ orelse try tls.config.CertBundle.fromSystem(allocator);
errdefer root_ca.deinit(allocator);
const state_pool = try StatePool.init(allocator, max_concurrent);
@@ -1420,8 +1438,7 @@ pub const Response = struct {
fn processData(self: *Response) !?[]u8 {
const data = self._data orelse return null;
const result = try self._reader.process(data);
self._done = result
.done;
self._done = result.done;
self._data = result.unprocessed; // for the next call
return result.data;
}
@@ -1631,13 +1648,13 @@ test "HttpClient Reader: fuzz" {
}
test "HttpClient: invalid url" {
var client = try Client.init(testing.allocator, 1);
var client = try testClient();
defer client.deinit();
try testing.expectError(error.UriMissingHost, client.request(.GET, "http:///"));
}
test "HttpClient: sync connect error" {
var client = try Client.init(testing.allocator, 2);
var client = try testClient();
defer client.deinit();
var req = try client.request(.GET, "HTTP://127.0.0.1:9920");
@@ -1645,7 +1662,7 @@ test "HttpClient: sync connect error" {
}
test "HttpClient: sync no body" {
var client = try Client.init(testing.allocator, 2);
var client = try testClient();
defer client.deinit();
var req = try client.request(.GET, "http://127.0.0.1:9582/http_client/simple");
@@ -1658,8 +1675,24 @@ test "HttpClient: sync no body" {
try testing.expectEqual("0", res.header.get("content-length"));
}
test "HttpClient: sync tls no body" {
// https://github.com/ianic/tls.zig/issues/10
for (0..1) |_| {
var client = try testClient();
defer client.deinit();
var req = try client.request(.GET, "https://127.0.0.1:9581/http_client/simple");
var res = try req.sendSync(.{});
try testing.expectEqual(null, try res.next());
try testing.expectEqual(200, res.header.status);
try testing.expectEqual(1, res.header.count());
try testing.expectEqual("0", res.header.get("content-length"));
}
}
test "HttpClient: sync with body" {
var client = try Client.init(testing.allocator, 2);
var client = try testClient();
defer client.deinit();
var req = try client.request(.GET, "http://127.0.0.1:9582/http_client/echo");
@@ -1674,8 +1707,84 @@ test "HttpClient: sync with body" {
try testing.expectEqual("Close", res.header.get("_connection"));
}
test "HttpClient: sync tls with body" {
var arr: std.ArrayListUnmanaged(u8) = .{};
defer arr.deinit(testing.allocator);
try arr.ensureTotalCapacity(testing.allocator, 20);
// https://github.com/ianic/tls.zig/issues/10
for (0..1) |_| {
defer arr.clearRetainingCapacity();
var client = try testClient();
defer client.deinit();
var req = try client.request(.GET, "https://127.0.0.1:9581/http_client/body");
var res = try req.sendSync(.{});
while (try res.next()) |data| {
arr.appendSliceAssumeCapacity(data);
}
try testing.expectEqual("1234567890abcdefhijk", arr.items);
try testing.expectEqual(201, res.header.status);
try testing.expectEqual(2, res.header.count());
try testing.expectEqual("20", res.header.get("content-length"));
try testing.expectEqual("HEaDer", res.header.get("another"));
}
}
test "HttpClient: sync redirect from TLS to Plaintext" {
var arr: std.ArrayListUnmanaged(u8) = .{};
defer arr.deinit(testing.allocator);
try arr.ensureTotalCapacity(testing.allocator, 20);
// https://github.com/ianic/tls.zig/issues/10
for (0..1) |_| {
defer arr.clearRetainingCapacity();
var client = try testClient();
defer client.deinit();
var req = try client.request(.GET, "https://127.0.0.1:9581/http_client/redirect/insecure");
var res = try req.sendSync(.{});
while (try res.next()) |data| {
arr.appendSliceAssumeCapacity(data);
}
try testing.expectEqual(201, res.header.status);
try testing.expectEqual(4, res.header.count());
try testing.expectEqual("close", res.header.get("connection"));
try testing.expectEqual("10", res.header.get("content-length"));
try testing.expectEqual("127.0.0.1", res.header.get("_host"));
try testing.expectEqual("Close", res.header.get("_connection"));
}
}
test "HttpClient: sync redirect plaintext to TLS" {
var arr: std.ArrayListUnmanaged(u8) = .{};
defer arr.deinit(testing.allocator);
try arr.ensureTotalCapacity(testing.allocator, 20);
// https://github.com/ianic/tls.zig/issues/10
for (0..1) |_| {
defer arr.clearRetainingCapacity();
var client = try testClient();
defer client.deinit();
var req = try client.request(.GET, "http://127.0.0.1:9582/http_client/redirect/secure");
var res = try req.sendSync(.{});
while (try res.next()) |data| {
arr.appendSliceAssumeCapacity(data);
}
try testing.expectEqual(201, res.header.status);
try testing.expectEqual("1234567890abcdefhijk", arr.items);
try testing.expectEqual(2, res.header.count());
try testing.expectEqual("20", res.header.get("content-length"));
try testing.expectEqual("HEaDer", res.header.get("another"));
}
}
test "HttpClient: sync GET redirect" {
var client = try Client.init(testing.allocator, 2);
var client = try testClient();
defer client.deinit();
var req = try client.request(.GET, "http://127.0.0.1:9582/http_client/redirect");
@@ -1710,7 +1819,7 @@ test "HttpClient: async connect error" {
};
var reset: Thread.ResetEvent = .{};
var client = try Client.init(testing.allocator, 2);
var client = try testClient();
defer client.deinit();
var req = try client.request(.GET, "HTTP://127.0.0.1:9920");
@@ -1720,7 +1829,7 @@ test "HttpClient: async connect error" {
}
test "HttpClient: async no body" {
var client = try Client.init(testing.allocator, 2);
var client = try testClient();
defer client.deinit();
var handler = try CaptureHandler.init();
@@ -1731,8 +1840,7 @@ test "HttpClient: async no body" {
var req = try client.request(.GET, "HTTP://127.0.0.1:9582/http_client/simple");
try req.sendAsync(&handler.loop, &handler, .{});
try handler.loop.io.run_for_ns(std.time.ns_per_ms);
try handler.reset.timedWait(std.time.ns_per_s);
try handler.waitUntilDone();
const res = handler.response;
try testing.expectEqual("", res.body.items);
@@ -1740,8 +1848,28 @@ test "HttpClient: async no body" {
try res.assertHeaders(&.{ "connection", "close", "content-length", "0" });
}
// test "HttpClient: async tls no body" {
// var client = try testClient();
// defer client.deinit();
// var handler = try CaptureHandler.init();
// defer handler.deinit();
// var loop = try jsruntime.Loop.init(testing.allocator);
// defer loop.deinit();
// var req = try client.request(.GET, "HTTPs://127.0.0.1:9581/http_client/simple");
// try req.sendAsync(&handler.loop, &handler, .{});
// try handler.waitUntilDone();
// const res = handler.response;
// try testing.expectEqual("", res.body.items);
// try testing.expectEqual(200, res.status);
// try res.assertHeaders(&.{ "connection", "close", "content-length", "0" });
// }
test "HttpClient: async with body" {
var client = try Client.init(testing.allocator, 2);
var client = try testClient();
defer client.deinit();
var handler = try CaptureHandler.init();
@@ -1749,8 +1877,7 @@ test "HttpClient: async with body" {
var req = try client.request(.GET, "HTTP://127.0.0.1:9582/http_client/echo");
try req.sendAsync(&handler.loop, &handler, .{});
try handler.loop.io.run_for_ns(std.time.ns_per_ms);
try handler.reset.timedWait(std.time.ns_per_s);
try handler.waitUntilDone();
const res = handler.response;
try testing.expectEqual("over 9000!", res.body.items);
@@ -1764,7 +1891,7 @@ test "HttpClient: async with body" {
}
test "HttpClient: async redirect" {
var client = try Client.init(testing.allocator, 2);
var client = try testClient();
defer client.deinit();
var handler = try CaptureHandler.init();
@@ -1781,8 +1908,7 @@ test "HttpClient: async redirect" {
// start to requeue events (from the redirected request), so we need the
//loop to process those also.
try handler.loop.io.run_for_ns(std.time.ns_per_ms);
try handler.loop.io.run_for_ns(std.time.ns_per_ms);
try handler.reset.timedWait(std.time.ns_per_s);
try handler.waitUntilDone();
const res = handler.response;
try testing.expectEqual("over 9000!", res.body.items);
@@ -1885,6 +2011,11 @@ const CaptureHandler = struct {
self.reset.set();
}
}
fn waitUntilDone(self: *CaptureHandler) !void {
try self.loop.io.run_for_ns(std.time.ns_per_ms);
try self.reset.timedWait(std.time.ns_per_s);
}
};
fn testReader(state: *State, res: *TestResponse, data: []const u8) !void {
@@ -1928,3 +2059,9 @@ fn testReader(state: *State, res: *TestResponse, data: []const u8) !void {
}
return error.NeverDone;
}
fn testClient() !Client {
const test_dir = try std.fs.cwd().openDir("tests", .{});
const root_ca = try tls.config.CertBundle.fromFile(testing.allocator, test_dir, "test_cert.pem");
return try Client.init(testing.allocator, 1, root_ca);
}

View File

@@ -88,7 +88,7 @@ fn testExecFn(
std.debug.print("documentHTMLClose error: {s}\n", .{@errorName(err)});
};
var http_client = try @import("http/client.zig").Client.init(alloc, 5);
var http_client = try @import("http/client.zig").Client.init(alloc, 5, null);
defer http_client.deinit();
try js_env.setUserContext(.{

211
src/main_unit_tests.zig Normal file
View File

@@ -0,0 +1,211 @@
const std = @import("std");
const builtin = @import("builtin");
const parser = @import("netsurf");
const tls = @import("tls");
const Allocator = std.mem.Allocator;
test {
std.testing.refAllDecls(@import("url/query.zig"));
std.testing.refAllDecls(@import("browser/dump.zig"));
std.testing.refAllDecls(@import("browser/mime.zig"));
std.testing.refAllDecls(@import("css/css.zig"));
std.testing.refAllDecls(@import("css/libdom_test.zig"));
std.testing.refAllDecls(@import("css/match_test.zig"));
std.testing.refAllDecls(@import("css/parser.zig"));
std.testing.refAllDecls(@import("generate.zig"));
std.testing.refAllDecls(@import("http/client.zig"));
std.testing.refAllDecls(@import("storage/storage.zig"));
std.testing.refAllDecls(@import("storage/cookie.zig"));
std.testing.refAllDecls(@import("iterator/iterator.zig"));
std.testing.refAllDecls(@import("server.zig"));
std.testing.refAllDecls(@import("cdp/cdp.zig"));
std.testing.refAllDecls(@import("log.zig"));
std.testing.refAllDecls(@import("datetime.zig"));
std.testing.refAllDecls(@import("telemetry/telemetry.zig"));
std.testing.refAllDecls(@import("http/client.zig"));
}
var wg: std.Thread.WaitGroup = .{};
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
test "tests:beforeAll" {
try parser.init();
wg.startMany(3);
{
const address = try std.net.Address.parseIp("127.0.0.1", 9582);
const thread = try std.Thread.spawn(.{}, serveHTTP, .{ address });
thread.detach();
}
{
const address = try std.net.Address.parseIp("127.0.0.1", 9581);
const thread = try std.Thread.spawn(.{}, serveHTTPS, .{ address });
thread.detach();
}
{
const address = try std.net.Address.parseIp("127.0.0.1", 9583);
const thread = try std.Thread.spawn(.{}, serveCDP, .{address});
thread.detach();
}
// need to wait for the servers to be listening, else tests will fail because
// they aren't able to connect.
wg.wait();
}
test "tests:afterAll" {
parser.deinit();
}
fn serveHTTP(address: std.net.Address) !void {
const allocator = gpa.allocator();
var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit();
var listener = try address.listen(.{ .reuse_address = true });
defer listener.deinit();
wg.finish();
var read_buffer: [1024]u8 = undefined;
ACCEPT: while (true) {
defer _ = arena.reset(.{ .retain_with_limit = 1024 });
const aa = arena.allocator();
var conn = try listener.accept();
defer conn.stream.close();
var server = std.http.Server.init(conn, &read_buffer);
while (server.state == .ready) {
var request = server.receiveHead() catch |err| switch (err) {
error.HttpConnectionClosing => continue :ACCEPT,
else => {
std.debug.print("Test HTTP Server error: {}\n", .{err});
return err;
},
};
const path = request.head.target;
if (std.mem.eql(u8, path, "/loader")) {
try request.respond("Hello!", .{});
} else if (std.mem.eql(u8, path, "/http_client/simple")) {
try request.respond("", .{});
} else if (std.mem.eql(u8, path, "/http_client/redirect")) {
try request.respond("", .{
.status = .moved_permanently,
.extra_headers = &.{.{ .name = "LOCATION", .value = "../http_client/echo" }},
});
} else if (std.mem.eql(u8, path, "/http_client/redirect/secure")) {
try request.respond("", .{
.status = .moved_permanently,
.extra_headers = &.{.{ .name = "LOCATION", .value = "https://127.0.0.1:9581/http_client/body" }},
});
} else if (std.mem.eql(u8, path, "/http_client/echo")) {
var headers: std.ArrayListUnmanaged(std.http.Header) = .{};
var it = request.iterateHeaders();
while (it.next()) |hdr| {
try headers.append(aa, .{
.name = try std.fmt.allocPrint(aa, "_{s}", .{hdr.name}),
.value = hdr.value,
});
}
try request.respond("over 9000!", .{
.status = .created,
.extra_headers = headers.items,
});
}
}
}
}
// This is a lot of work for testing TLS, but the TLS (async) code is complicated
// This "server" is written specifically to test the client. It assumes the client
// isn't a jerk.
fn serveHTTPS(address: std.net.Address) !void {
const allocator = gpa.allocator();
const test_dir = try std.fs.cwd().openDir("tests", .{});
// openssl req -x509 -newkey rsa:4096 -keyout tests/test_key.pem -out tests/test_cert.pem -sha256 -days 3650 -nodes -subj "/CN=127.0.0.1"
var auth = try tls.config.CertKeyPair.load(allocator, test_dir, "test_cert.pem", "test_key.pem");
defer auth.deinit(allocator);
var listener = try address.listen(.{ .reuse_address = true });
defer listener.deinit();
var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit();
wg.finish();
var seed: u64 = undefined;
std.posix.getrandom(std.mem.asBytes(&seed)) catch unreachable;
var r = std.Random.DefaultPrng.init(seed);
const rand = r.random();
var read_buffer: [1024]u8 = undefined;
while (true) {
// defer _ = arena.reset(.{ .retain_with_limit = 1024 });
// const aa = arena.allocator();
const stream = blk: {
const conn = try listener.accept();
break :blk conn.stream;
};
defer stream.close();
var conn = try tls.server(stream, .{ .auth = &auth });
defer conn.close() catch {};
var pos: usize = 0;
while (true) {
const n = try conn.read(read_buffer[pos..]);
if (n == 0) {
break;
}
pos += n;
const header_end = std.mem.indexOf(u8, read_buffer[0..pos], "\r\n\r\n") orelse {
continue;
};
var it = std.mem.splitScalar(u8, read_buffer[0..header_end], ' ');
_ = it.next() orelse unreachable; // method
const path = it.next() orelse unreachable;
var response: []const u8 = undefined;
if (std.mem.eql(u8, path, "/http_client/simple")) {
response = "HTTP/1.1 200 \r\nContent-Length: 0\r\n\r\n";
} else if (std.mem.eql(u8, path, "/http_client/body")) {
response = "HTTP/1.1 201 CREATED\r\nContent-Length: 20\r\n Another : HEaDer \r\n\r\n1234567890abcdefhijk";
} else if (std.mem.eql(u8, path, "/http_client/redirect/insecure")) {
response = "HTTP/1.1 307 GOTO\r\nLocation: http://127.0.0.1:9582/http_client/redirect\r\n\r\n";
} else {
// should not have an unknown path
unreachable;
}
var unsent = response;
while (unsent.len > 0) {
const to_send = rand.intRangeAtMost(usize, 1, unsent.len);
const sent = try conn.write(unsent[0..to_send]);
unsent = unsent[sent..];
// std.time.sleep(std.time.ns_per_us * 5);
}
break;
}
}
}
fn serveCDP(address: std.net.Address) !void {
const App = @import("app.zig").App;
var app = try App.init(gpa.allocator(), .serve);
defer app.deinit();
const server = @import("server.zig");
wg.finish();
server.run(&app, address, std.time.ns_per_s * 2) catch |err| {
std.debug.print("CDP server error: {}", .{err});
return err;
};
}

View File

@@ -18,34 +18,31 @@
const std = @import("std");
const builtin = @import("builtin");
const parser = @import("netsurf");
const Allocator = std.mem.Allocator;
const App = @import("app.zig").App;
const jsruntime = @import("jsruntime");
pub const Types = jsruntime.reflect(@import("generate.zig").Tuple(.{}){});
pub const UserContext = @import("user_context.zig").UserContext;
pub const std_options = std.Options{
.log_level = .err,
.http_disable_tls = true,
};
const BORDER = "=" ** 80;
// use in custom panic handler
var current_test: ?[]const u8 = null;
const jsruntime = @import("jsruntime");
pub const Types = jsruntime.reflect(@import("generate.zig").Tuple(.{}){});
pub const UserContext = @import("user_context.zig").UserContext;
pub const std_options = std.Options{
.log_level = .warn,
// Crypto in Zig is generally slow, but it's particularly slow in debug mode
// this helps a lot (but it's still slow). Not safe to do this in non-test!
.side_channels_mitigations = .none,
};
pub fn main() !void {
try parser.init();
defer parser.deinit();
var mem: [8192]u8 = undefined;
var fba = std.heap.FixedBufferAllocator.init(&mem);
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var app = try App.init(allocator, .serve);
defer app.deinit();
const allocator = fba.allocator();
const env = Env.init(allocator);
defer env.deinit(allocator);
@@ -58,30 +55,20 @@ pub fn main() !void {
var skip: usize = 0;
var leak: usize = 0;
const http_thread = blk: {
const address = try std.net.Address.parseIp("127.0.0.1", 9582);
const thread = try std.Thread.spawn(.{}, serveHTTP, .{ allocator, address });
break :blk thread;
};
defer http_thread.join();
const cdp_thread = blk: {
const address = try std.net.Address.parseIp("127.0.0.1", 9583);
const thread = try std.Thread.spawn(.{}, serveCDP, .{
app,
address,
});
break :blk thread;
};
defer cdp_thread.join();
const printer = Printer.init();
printer.fmt("\r\x1b[0K", .{}); // beginning of line and clear to end of line
for (builtin.test_functions) |t| {
if (std.mem.eql(u8, t.name, "unit_tests.test_0")) {
// don't display anything for this test
try t.func();
if (isSetup(t)) {
t.func() catch |err| {
printer.status(.fail, "\nsetup \"{s}\" failed: {}\n", .{ t.name, err });
return err;
};
}
}
for (builtin.test_functions) |t| {
if (isSetup(t) or isTeardown(t)) {
continue;
}
@@ -151,6 +138,15 @@ pub fn main() !void {
}
}
for (builtin.test_functions) |t| {
if (isTeardown(t)) {
t.func() catch |err| {
printer.status(.fail, "\nteardown \"{s}\" failed: {}\n", .{ t.name, err });
return err;
};
}
}
const total_tests = pass + fail;
const status = if (fail == 0) Status.pass else Status.fail;
printer.status(status, "\n{d} of {d} test{s} passed\n", .{ pass, total_tests, if (total_tests != 1) "s" else "" });
@@ -315,6 +311,15 @@ const Env = struct {
}
};
pub const panic = std.debug.FullPanic(struct {
pub fn panicFn(msg: []const u8, first_trace_addr: ?usize) noreturn {
if (current_test) |ct| {
std.debug.print("\x1b[31m{s}\npanic running \"{s}\"\n{s}\x1b[0m\n", .{ BORDER, ct, BORDER });
}
std.debug.defaultPanic(msg, first_trace_addr);
}
}.panicFn);
fn isUnnamed(t: std.builtin.TestFn) bool {
const marker = ".test_";
const test_name = t.name;
@@ -323,86 +328,10 @@ fn isUnnamed(t: std.builtin.TestFn) bool {
return true;
}
fn serveHTTP(allocator: Allocator, address: std.net.Address) !void {
var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit();
var listener = try address.listen(.{ .reuse_address = true });
defer listener.deinit();
var read_buffer: [1024]u8 = undefined;
ACCEPT: while (true) {
defer _ = arena.reset(.{ .retain_with_limit = 1024 });
const aa = arena.allocator();
var conn = try listener.accept();
defer conn.stream.close();
var server = std.http.Server.init(conn, &read_buffer);
while (server.state == .ready) {
var request = server.receiveHead() catch |err| switch (err) {
error.HttpConnectionClosing => continue :ACCEPT,
else => {
std.debug.print("Test HTTP Server error: {}\n", .{err});
return err;
},
};
const path = request.head.target;
if (std.mem.eql(u8, path, "/loader")) {
try request.respond("Hello!", .{});
} else if (std.mem.eql(u8, path, "/http_client/simple")) {
try request.respond("", .{});
} else if (std.mem.eql(u8, path, "/http_client/redirect")) {
try request.respond("", .{
.status = .moved_permanently,
.extra_headers = &.{.{ .name = "LOCATION", .value = "../http_client/echo" }},
});
} else if (std.mem.eql(u8, path, "/http_client/echo")) {
var headers: std.ArrayListUnmanaged(std.http.Header) = .{};
var it = request.iterateHeaders();
while (it.next()) |hdr| {
try headers.append(aa, .{
.name = try std.fmt.allocPrint(aa, "_{s}", .{hdr.name}),
.value = hdr.value,
});
}
try request.respond("over 9000!", .{
.status = .created,
.extra_headers = headers.items,
});
}
}
}
fn isSetup(t: std.builtin.TestFn) bool {
return std.mem.endsWith(u8, t.name, "tests:beforeAll");
}
fn serveCDP(app: *App, address: std.net.Address) !void {
const server = @import("server.zig");
server.run(app, address, std.time.ns_per_s * 2) catch |err| {
std.debug.print("CDP server error: {}", .{err});
return err;
};
}
test {
std.testing.refAllDecls(@import("url/query.zig"));
std.testing.refAllDecls(@import("browser/dump.zig"));
std.testing.refAllDecls(@import("browser/mime.zig"));
std.testing.refAllDecls(@import("css/css.zig"));
std.testing.refAllDecls(@import("css/libdom_test.zig"));
std.testing.refAllDecls(@import("css/match_test.zig"));
std.testing.refAllDecls(@import("css/parser.zig"));
std.testing.refAllDecls(@import("generate.zig"));
std.testing.refAllDecls(@import("http/client.zig"));
std.testing.refAllDecls(@import("storage/storage.zig"));
std.testing.refAllDecls(@import("storage/cookie.zig"));
std.testing.refAllDecls(@import("iterator/iterator.zig"));
std.testing.refAllDecls(@import("server.zig"));
std.testing.refAllDecls(@import("cdp/cdp.zig"));
std.testing.refAllDecls(@import("log.zig"));
std.testing.refAllDecls(@import("datetime.zig"));
std.testing.refAllDecls(@import("telemetry/telemetry.zig"));
std.testing.refAllDecls(@import("http/client.zig"));
fn isTeardown(t: std.builtin.TestFn) bool {
return std.mem.endsWith(u8, t.name, "tests:afterAll");
}

View File

@@ -167,7 +167,7 @@ pub const Random = struct {
var seed: u64 = undefined;
std.posix.getrandom(std.mem.asBytes(&seed)) catch unreachable;
instance = std.Random.DefaultPrng.init(seed);
instance = std.Random.DefaultPrng.init(0);
// instance = std.Random.DefaultPrng.init(0);
}
return instance.?.random();
}