From 1c96e9bf021852dac68038e69bf02749d7da57de Mon Sep 17 00:00:00 2001 From: Rene Schallner Date: Sun, 16 Apr 2023 21:23:47 +0200 Subject: [PATCH] automated auth tests via http_client_testrunner --- build.zig | 16 +++- src/http_client_testrunner.zig | 44 +++++++++++ src/test_auth.zig | 132 +++++++++++++++++++++++++++++++-- 3 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 src/http_client_testrunner.zig diff --git a/build.zig b/build.zig index fd56d07..c228aa2 100644 --- a/build.zig +++ b/build.zig @@ -96,6 +96,20 @@ pub fn build(b: *std.build.Builder) !void { const http_client_build_step = b.addInstallArtifact(http_client_exe); http_client_step.dependOn(&http_client_build_step.step); + // http client for internal testing + var http_client_runner_exe = b.addExecutable(.{ + .name = "http_client_runner", + .root_source_file = .{ .path = "./src/http_client_testrunner.zig" }, + .target = target, + .optimize = optimize, + }); + var http_client_runner_step = b.step("http_client_runner", "Build the http_client test runner for internal testing"); + http_client_runner_exe.linkLibrary(facil_dep.artifact("facil.io")); + http_client_runner_exe.addModule("zap", zap_module); + const http_client_runner_build_step = b.addInstallArtifact(http_client_runner_exe); + http_client_runner_step.dependOn(&http_client_runner_build_step.step); + http_client_runner_exe.step.dependOn(&http_client_build_step.step); + // tests const exe_tests = b.addTest(.{ .root_source_file = .{ .path = "src/test_auth.zig" }, @@ -104,7 +118,7 @@ pub fn build(b: *std.build.Builder) !void { }); exe_tests.linkLibrary(facil_dep.artifact("facil.io")); exe_tests.addModule("zap", zap_module); - exe_tests.step.dependOn(&http_client_build_step.step); + exe_tests.step.dependOn(&http_client_runner_build_step.step); // Similar to creating the run step earlier, this exposes a `test` step to // the `zig build --help` menu, providing a way for the user to request diff --git a/src/http_client_testrunner.zig b/src/http_client_testrunner.zig new file mode 100644 index 0000000..c4d02b9 --- /dev/null +++ b/src/http_client_testrunner.zig @@ -0,0 +1,44 @@ +const std = @import("std"); + +pub fn main() !void { + const a = std.heap.page_allocator; + var p = std.ChildProcess.init(&.{ + "./zig-out/bin/http_client", + "http://127.0.0.1:3000/test", + "Bearer", + "ABCDEFG", + }, a); + _ = try p.spawnAndWait(); + + std.time.sleep(3 * std.time.ns_per_s); + + p = std.ChildProcess.init(&.{ + "./zig-out/bin/http_client", + "http://127.0.0.1:3000/test", + "Bearer", + "invalid", + }, a); + _ = try p.spawnAndWait(); + + std.time.sleep(3 * std.time.ns_per_s); + + p = std.ChildProcess.init(&.{ + "./zig-out/bin/http_client", + "http://127.0.0.1:3000/test", + "Basic", + "QWxhZGRpbjpvcGVuIHNlc2FtZQ==", + }, a); + _ = try p.spawnAndWait(); + + std.time.sleep(3 * std.time.ns_per_s); + + p = std.ChildProcess.init(&.{ + "./zig-out/bin/http_client", + "http://127.0.0.1:3000/test", + "Basic", + "invalid", + }, a); + _ = try p.spawnAndWait(); + + // std.time.sleep(3 * std.time.ns_per_s); +} diff --git a/src/test_auth.zig b/src/test_auth.zig index d8594c2..650b1d0 100644 --- a/src/test_auth.zig +++ b/src/test_auth.zig @@ -50,6 +50,15 @@ fn endpoint_http_get(e: *Endpoints.SimpleEndpoint, r: zap.SimpleRequest) void { zap.fio_stop(); } +fn endpoint_http_unauthorized(e: *Endpoints.SimpleEndpoint, r: zap.SimpleRequest) void { + _ = e; + r.setStatus(.unauthorized); + r.sendBody("UNAUTHORIZED ACCESS") catch return; + std.debug.print("\nunauthorized\n", .{}); + received_response = "UNAUTHORIZED"; + zap.fio_stop(); +} + // // http client code for in-process sending of http request // @@ -117,7 +126,7 @@ fn on_response(r: [*c]fio.http_s) callconv(.C) void { // end of http client code // -test "BearerAuthSingle authenticateRequest" { +test "BearerAuthSingle authenticateRequest OK" { const a = std.testing.allocator; const token = "ABCDEFG"; @@ -161,7 +170,62 @@ test "BearerAuthSingle authenticateRequest" { defer listener.deinit(); // create mini endpoint - var ep = Endpoints.SimpleEndpoint.init(.{ .path = "/test", .get = endpoint_http_get }); + var ep = Endpoints.SimpleEndpoint.init(.{ + .path = "/test", + .get = endpoint_http_get, + .unauthorized = endpoint_http_unauthorized, + }); + + // create authenticator + const Authenticator = Authenticators.BearerAuthSingle; + var authenticator = try Authenticator.init(a, token, null); + defer authenticator.deinit(); + + // create authenticating endpoint + const BearerAuthEndpoint = Endpoints.AuthenticatingEndpoint(Authenticator); + var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); + + try listener.addEndpoint(auth_ep.getEndpoint()); + + listener.listen() catch {}; + std.debug.print("Listening on 0.0.0.0:3000\n", .{}); + std.debug.print("\n\n*******************************************\n", .{}); + std.debug.print("\n\nPlease run the following:\n", .{}); + std.debug.print("./zig-out/bin/http_client_runner\n", .{}); + std.debug.print("\n\n*******************************************\n", .{}); + + // start worker threads + zap.start(.{ + .threads = 1, + .workers = 0, + }); + + try std.testing.expectEqualStrings(HTTP_RESPONSE, received_response); +} + +test "BearerAuthSingle authenticateRequest test-unauthorized" { + const a = std.testing.allocator; + const token = "ABCDEFG"; + + // setup listener + var listener = zap.SimpleEndpointListener.init( + a, + .{ + .port = 3000, + .on_request = null, + .log = false, + .max_clients = 10, + .max_body_size = 1 * 1024, + }, + ); + defer listener.deinit(); + + // create mini endpoint + var ep = Endpoints.SimpleEndpoint.init(.{ + .path = "/test", + .get = endpoint_http_get, + .unauthorized = endpoint_http_unauthorized, + }); // create authenticator const Authenticator = Authenticators.BearerAuthSingle; @@ -177,7 +241,7 @@ test "BearerAuthSingle authenticateRequest" { listener.listen() catch {}; std.debug.print("Listening on 0.0.0.0:3000\n", .{}); std.debug.print("Please run the following:\n", .{}); - std.debug.print("./zig-out/bin/http_client", .{}); + std.debug.print("./zig-out/bin/http_client http://127.0.0.1:3000/test Bearer invalid", .{}); // start worker threads zap.start(.{ @@ -185,7 +249,7 @@ test "BearerAuthSingle authenticateRequest" { .workers = 0, }); - try std.testing.expectEqualStrings(HTTP_RESPONSE, received_response); + try std.testing.expectEqualStrings("UNAUTHORIZED", received_response); } test "BasicAuth authenticateRequest" { @@ -206,7 +270,11 @@ test "BasicAuth authenticateRequest" { defer listener.deinit(); // create mini endpoint - var ep = Endpoints.SimpleEndpoint.init(.{ .path = "/test", .get = endpoint_http_get }); + var ep = Endpoints.SimpleEndpoint.init(.{ + .path = "/test", + .get = endpoint_http_get, + .unauthorized = endpoint_http_unauthorized, + }); // create a set of Token68 entries const Set = std.StringHashMap(void); var set = Set.init(a); // set @@ -237,3 +305,57 @@ test "BasicAuth authenticateRequest" { try std.testing.expectEqualStrings(HTTP_RESPONSE, received_response); } + +test "BasicAuth authenticateRequest test-unauthorized" { + const a = std.testing.allocator; + const token = "QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; + + // setup listener + var listener = zap.SimpleEndpointListener.init( + a, + .{ + .port = 3000, + .on_request = null, + .log = false, + .max_clients = 10, + .max_body_size = 1 * 1024, + }, + ); + defer listener.deinit(); + + // create mini endpoint + var ep = Endpoints.SimpleEndpoint.init(.{ + .path = "/test", + .get = endpoint_http_get, + .unauthorized = endpoint_http_unauthorized, + }); + // create a set of Token68 entries + const Set = std.StringHashMap(void); + var set = Set.init(a); // set + defer set.deinit(); + try set.put(token, {}); + + // create authenticator + const Authenticator = Authenticators.BasicAuth(Set, .Token68); + var authenticator = try Authenticator.init(a, &set, null); + defer authenticator.deinit(); + + // create authenticating endpoint + const BearerAuthEndpoint = Endpoints.AuthenticatingEndpoint(Authenticator); + var auth_ep = BearerAuthEndpoint.init(&ep, &authenticator); + + try listener.addEndpoint(auth_ep.getEndpoint()); + + listener.listen() catch {}; + std.debug.print("Listening on 0.0.0.0:3000\n", .{}); + std.debug.print("Please run the following:\n", .{}); + std.debug.print("./zig-out/bin/http_client http://127.0.0.1:3000/test Basic " ++ "invalid", .{}); + + // start worker threads + zap.start(.{ + .threads = 1, + .workers = 0, + }); + + try std.testing.expectEqualStrings("UNAUTHORIZED", received_response); +}