fix most test compilation errors

This commit is contained in:
Emil Lerch 2025-08-23 08:48:32 -07:00
parent 8d399cb8a6
commit 1170ba99fc
Signed by: lobo
GPG key ID: A7B62D657EF764F8
3 changed files with 142 additions and 129 deletions

View file

@ -1412,14 +1412,14 @@ fn typeForField(comptime T: type, comptime field_name: []const u8) !type {
test "custom serialization for map objects" {
const allocator = std.testing.allocator;
var buffer = std.ArrayList(u8).init(allocator);
var buffer = std.Io.Writer.Allocating.init(allocator);
defer buffer.deinit();
var tags = try std.ArrayList(@typeInfo(try typeForField(services.lambda.tag_resource.Request, "tags")).pointer.child).initCapacity(allocator, 2);
defer tags.deinit();
defer tags.deinit(allocator);
tags.appendAssumeCapacity(.{ .key = "Foo", .value = "Bar" });
tags.appendAssumeCapacity(.{ .key = "Baz", .value = "Qux" });
const req = services.lambda.TagResourceRequest{ .resource = "hello", .tags = tags.items };
try std.json.stringify(req, .{ .whitespace = .indent_4 }, buffer.writer());
try buffer.writer.print("{f}", .{std.json.fmt(req, .{ .whitespace = .indent_4 })});
const parsed_body = try std.json.parseFromSlice(struct {
Resource: []const u8,
@ -1427,7 +1427,7 @@ test "custom serialization for map objects" {
Foo: []const u8,
Baz: []const u8,
},
}, testing.allocator, buffer.items, .{});
}, testing.allocator, buffer.written(), .{});
defer parsed_body.deinit();
try testing.expectEqualStrings("hello", parsed_body.value.Resource);
@ -1439,7 +1439,7 @@ test "proper serialization for kms" {
// Github issue #8
// https://github.com/elerch/aws-sdk-for-zig/issues/8
const allocator = std.testing.allocator;
var buffer = std.ArrayList(u8).init(allocator);
var buffer = std.Io.Writer.Allocating.init(allocator);
defer buffer.deinit();
const req = services.kms.encrypt.Request{
.encryption_algorithm = "SYMMETRIC_DEFAULT",
@ -1451,7 +1451,7 @@ test "proper serialization for kms" {
.dry_run = false,
.grant_tokens = &[_][]const u8{},
};
try std.json.stringify(req, .{ .whitespace = .indent_4 }, buffer.writer());
try buffer.writer.print("{f}", .{std.json.fmt(req, .{ .whitespace = .indent_4 })});
{
const parsed_body = try std.json.parseFromSlice(struct {
@ -1461,7 +1461,7 @@ test "proper serialization for kms" {
GrantTokens: [][]const u8,
EncryptionAlgorithm: []const u8,
DryRun: bool,
}, testing.allocator, buffer.items, .{});
}, testing.allocator, buffer.written(), .{});
defer parsed_body.deinit();
try testing.expectEqualStrings("42", parsed_body.value.KeyId);
@ -1471,7 +1471,7 @@ test "proper serialization for kms" {
try testing.expectEqual(false, parsed_body.value.DryRun);
}
var buffer_null = std.ArrayList(u8).init(allocator);
var buffer_null = std.Io.Writer.Allocating.init(allocator);
defer buffer_null.deinit();
const req_null = services.kms.encrypt.Request{
.encryption_algorithm = "SYMMETRIC_DEFAULT",
@ -1483,7 +1483,7 @@ test "proper serialization for kms" {
.grant_tokens = &[_][]const u8{},
};
try std.json.stringify(req_null, .{ .whitespace = .indent_4 }, buffer_null.writer());
try buffer_null.writer.print("{f}", .{std.json.fmt(req_null, .{ .whitespace = .indent_4 })});
{
const parsed_body = try std.json.parseFromSlice(struct {
@ -1493,7 +1493,7 @@ test "proper serialization for kms" {
GrantTokens: [][]const u8,
EncryptionAlgorithm: []const u8,
DryRun: bool,
}, testing.allocator, buffer_null.items, .{});
}, testing.allocator, buffer_null.written(), .{});
defer parsed_body.deinit();
try testing.expectEqualStrings("42", parsed_body.value.KeyId);
@ -1541,8 +1541,8 @@ test "REST Json v1 serializes lists in queries" {
}
test "REST Json v1 buildpath substitutes" {
const allocator = std.testing.allocator;
var al = std.ArrayList([]const u8).init(allocator);
defer al.deinit();
var al = std.ArrayList([]const u8){};
defer al.deinit(allocator);
const svs = Services(.{.lambda}){};
const request = svs.lambda.list_functions.Request{
.max_items = 1,
@ -1554,8 +1554,8 @@ test "REST Json v1 buildpath substitutes" {
}
test "REST Json v1 buildpath handles restricted characters" {
const allocator = std.testing.allocator;
var al = std.ArrayList([]const u8).init(allocator);
defer al.deinit();
var al = std.ArrayList([]const u8){};
defer al.deinit(allocator);
const svs = Services(.{.lambda}){};
const request = svs.lambda.list_functions.Request{
.marker = ":",
@ -1571,7 +1571,7 @@ test "basic json request serialization" {
const request = svs.dynamo_db.list_tables.Request{
.limit = 1,
};
var buffer = std.ArrayList(u8).init(allocator);
var buffer = std.Io.Writer.Allocating.init(allocator);
defer buffer.deinit();
// The transformer needs to allocate stuff out of band, but we
@ -1583,13 +1583,13 @@ test "basic json request serialization" {
// for a boxed member with no observable difference." But we're
// seeing a lot of differences here between spec and reality
//
try std.json.stringify(request, .{ .whitespace = .indent_4 }, buffer.writer());
try buffer.writer.print("{f}", .{std.json.fmt(request, .{ .whitespace = .indent_4 })});
try std.testing.expectEqualStrings(
\\{
\\ "ExclusiveStartTableName": null,
\\ "Limit": 1
\\}
, buffer.items);
, buffer.written());
}
test "layer object only" {
const TestResponse = struct {
@ -2291,7 +2291,7 @@ test "rest_json_1_work_with_lambda: lambda tagResource (only), to excercise zig
const options = try test_harness.start();
const lambda = (Services(.{.lambda}){}).lambda;
var tags = try std.ArrayList(@typeInfo(try typeForField(lambda.tag_resource.Request, "tags")).pointer.child).initCapacity(allocator, 1);
defer tags.deinit();
defer tags.deinit(allocator);
tags.appendAssumeCapacity(.{ .key = "Foo", .value = "Bar" });
const req = services.lambda.tag_resource.Request{ .resource = "arn:aws:lambda:us-west-2:550620852718:function:awsome-lambda-LambdaStackawsomeLambda", .tags = tags.items };
const call = try Request(lambda.tag_resource).call(req, options);
@ -2674,7 +2674,7 @@ test "jsonStringify: structure + enums" {
var arena = std.heap.ArenaAllocator.init(testing.allocator);
defer arena.deinit();
const request_json = try std.json.stringifyAlloc(std.testing.allocator, request, .{});
const request_json = try std.fmt.allocPrint(std.testing.allocator, "{f}", .{std.json.fmt(request, .{})});
defer std.testing.allocator.free(request_json);
const parsed = try std.json.parseFromSlice(struct {
@ -2699,7 +2699,7 @@ test "jsonStringify: strings" {
var arena = std.heap.ArenaAllocator.init(testing.allocator);
defer arena.deinit();
const request_json = try std.json.stringifyAlloc(std.testing.allocator, request, .{});
const request_json = try std.fmt.allocPrint(std.testing.allocator, "{f}", .{std.json.fmt(request, .{})});
defer std.testing.allocator.free(request_json);
try testing.expectEqualStrings("{\"arn\":\"1234\"}", request_json);
@ -2721,7 +2721,7 @@ test "jsonStringify" {
var arena = std.heap.ArenaAllocator.init(testing.allocator);
defer arena.deinit();
const request_json = try std.json.stringifyAlloc(std.testing.allocator, request, .{});
const request_json = try std.fmt.allocPrint(std.testing.allocator, "{f}", .{std.json.fmt(request, .{})});
defer std.testing.allocator.free(request_json);
const json_parsed = try std.json.parseFromSlice(struct {
@ -2748,7 +2748,7 @@ test "jsonStringify nullable object" {
},
};
const request_json = try std.json.stringifyAlloc(std.testing.allocator, request, .{});
const request_json = try std.fmt.allocPrint(std.testing.allocator, "{f}", .{std.json.fmt(request, .{})});
defer std.testing.allocator.free(request_json);
const json_parsed = try std.json.parseFromSlice(struct {
@ -2774,7 +2774,7 @@ test "jsonStringify nullable object" {
.ciphertext_blob = "bar",
};
const request_json = try std.json.stringifyAlloc(std.testing.allocator, request, .{});
const request_json = try std.fmt.allocPrint(std.testing.allocator, "{f}", .{std.json.fmt(request, .{})});
defer std.testing.allocator.free(request_json);
const json_parsed = try std.json.parseFromSlice(struct {

View file

@ -348,10 +348,10 @@ pub fn freeSignedRequest(allocator: std.mem.Allocator, request: *base.Request, c
pub const credentialsFn = *const fn ([]const u8) ?Credentials;
pub fn verifyServerRequest(allocator: std.mem.Allocator, request: *std.http.Server.Request, request_body_reader: anytype, credentials_fn: credentialsFn) !bool {
pub fn verifyServerRequest(allocator: std.mem.Allocator, request: *std.http.Server.Request, credentials_fn: credentialsFn) !bool {
var unverified_request = try UnverifiedRequest.init(allocator, request);
defer unverified_request.deinit();
return verify(allocator, unverified_request, request_body_reader, credentials_fn);
return verify(allocator, unverified_request, credentials_fn);
}
pub const UnverifiedRequest = struct {
@ -359,17 +359,19 @@ pub const UnverifiedRequest = struct {
target: []const u8,
method: std.http.Method,
allocator: std.mem.Allocator,
raw: *std.http.Server.Request,
pub fn init(allocator: std.mem.Allocator, request: *std.http.Server.Request) !UnverifiedRequest {
var al = std.ArrayList(std.http.Header).init(allocator);
defer al.deinit();
var al = std.ArrayList(std.http.Header){};
defer al.deinit(allocator);
var it = request.iterateHeaders();
while (it.next()) |h| try al.append(h);
while (it.next()) |h| try al.append(allocator, h);
return .{
.target = request.head.target,
.method = request.head.method,
.headers = try al.toOwnedSlice(),
.headers = try al.toOwnedSlice(allocator),
.allocator = allocator,
.raw = request,
};
}
@ -387,7 +389,7 @@ pub const UnverifiedRequest = struct {
}
};
pub fn verify(allocator: std.mem.Allocator, request: UnverifiedRequest, request_body_reader: anytype, credentials_fn: credentialsFn) !bool {
pub fn verify(allocator: std.mem.Allocator, request: UnverifiedRequest, credentials_fn: credentialsFn) !bool {
var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit();
const aa = arena.allocator();
@ -420,7 +422,6 @@ pub fn verify(allocator: std.mem.Allocator, request: UnverifiedRequest, request_
return verifyParsedAuthorization(
aa,
request,
request_body_reader,
credential.?,
signed_headers.?,
signature.?,
@ -431,7 +432,6 @@ pub fn verify(allocator: std.mem.Allocator, request: UnverifiedRequest, request_
fn verifyParsedAuthorization(
allocator: std.mem.Allocator,
request: UnverifiedRequest,
request_body_reader: anytype,
credential: []const u8,
signed_headers: []const u8,
signature: []const u8,
@ -494,7 +494,8 @@ fn verifyParsedAuthorization(
.content_type = request.getFirstHeaderValue("content-type").?,
};
signed_request.query = request.target[signed_request.path.len..]; // TODO: should this be +1? query here would include '?'
signed_request.body = try request_body_reader.readAllAlloc(allocator, std.math.maxInt(usize));
// TODO: This is almost certainly not what we want here long term, but will get tests working
signed_request.body = try request.raw.server.reader.in.allocRemaining(allocator, .unlimited);
defer allocator.free(signed_request.body);
signed_request = try signRequest(allocator, signed_request, config);
defer freeSignedRequest(allocator, &signed_request, config);
@ -1010,13 +1011,13 @@ test "canonical query" {
test "canonical headers" {
const allocator = std.testing.allocator;
var headers = try std.ArrayList(std.http.Header).initCapacity(allocator, 5);
defer headers.deinit();
try headers.append(.{ .name = "Host", .value = "iam.amazonaws.com" });
try headers.append(.{ .name = "Content-Type", .value = "application/x-www-form-urlencoded; charset=utf-8" });
try headers.append(.{ .name = "User-Agent", .value = "This header should be skipped" });
try headers.append(.{ .name = "My-header1", .value = " a b c " });
try headers.append(.{ .name = "X-Amz-Date", .value = "20150830T123600Z" });
try headers.append(.{ .name = "My-header2", .value = " \"a b c\" " });
defer headers.deinit(allocator);
try headers.append(allocator, .{ .name = "Host", .value = "iam.amazonaws.com" });
try headers.append(allocator, .{ .name = "Content-Type", .value = "application/x-www-form-urlencoded; charset=utf-8" });
try headers.append(allocator, .{ .name = "User-Agent", .value = "This header should be skipped" });
try headers.append(allocator, .{ .name = "My-header1", .value = " a b c " });
try headers.append(allocator, .{ .name = "X-Amz-Date", .value = "20150830T123600Z" });
try headers.append(allocator, .{ .name = "My-header2", .value = " \"a b c\" " });
const expected =
\\content-type:application/x-www-form-urlencoded; charset=utf-8
\\host:iam.amazonaws.com
@ -1035,12 +1036,12 @@ test "canonical headers" {
test "canonical request" {
const allocator = std.testing.allocator;
var headers = try std.ArrayList(std.http.Header).initCapacity(allocator, 5);
defer headers.deinit();
try headers.append(.{ .name = "User-agent", .value = "c sdk v1.0" });
defer headers.deinit(allocator);
try headers.append(allocator, .{ .name = "User-agent", .value = "c sdk v1.0" });
// In contrast to AWS CRT (aws-c-auth), we add the date as part of the
// signing operation. They add it as part of the canonicalization
try headers.append(.{ .name = "X-Amz-Date", .value = "20150830T123600Z" });
try headers.append(.{ .name = "Host", .value = "example.amazonaws.com" });
try headers.append(allocator, .{ .name = "X-Amz-Date", .value = "20150830T123600Z" });
try headers.append(allocator, .{ .name = "Host", .value = "example.amazonaws.com" });
const req = base.Request{
.path = "/",
.method = "GET",
@ -1095,10 +1096,10 @@ test "can sign" {
const allocator = std.testing.allocator;
var headers = try std.ArrayList(std.http.Header).initCapacity(allocator, 5);
defer headers.deinit();
try headers.append(.{ .name = "Content-Type", .value = "application/x-www-form-urlencoded; charset=utf-8" });
try headers.append(.{ .name = "Content-Length", .value = "13" });
try headers.append(.{ .name = "Host", .value = "example.amazonaws.com" });
defer headers.deinit(allocator);
try headers.append(allocator, .{ .name = "Content-Type", .value = "application/x-www-form-urlencoded; charset=utf-8" });
try headers.append(allocator, .{ .name = "Content-Length", .value = "13" });
try headers.append(allocator, .{ .name = "Host", .value = "example.amazonaws.com" });
const req = base.Request{
.path = "/",
.query = "",
@ -1165,25 +1166,25 @@ test "can verify server request" {
"X-Amz-Date: 20230908T170252Z\r\n" ++
"x-amz-content-sha256: fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9\r\n" ++
"Authorization: AWS4-HMAC-SHA256 Credential=ACCESS/20230908/us-west-2/s3/aws4_request, SignedHeaders=accept;content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class, Signature=fcc43ce73a34c9bd1ddf17e8a435f46a859812822f944f9eeb2aabcd64b03523\r\n\r\nbar";
var read_buffer: [1024]u8 = undefined;
@memcpy(read_buffer[0..req.len], req);
var reader = std.Io.Reader.fixed(req);
var server: std.http.Server = .{
.connection = undefined,
.out = undefined, // We're not sending a response here
.reader = .{
.in = &reader,
.interface = undefined,
.state = .ready,
.read_buffer = &read_buffer,
.read_buffer_len = req.len,
.next_request_start = 0,
.max_head_len = req.len,
},
};
var request: std.http.Server.Request = .{
.server = &server,
.head_end = req.len - 3,
.head = try std.http.Server.Request.Head.parse(read_buffer[0 .. req.len - 3]),
.reader_state = undefined,
.head = undefined,
.head_buffer = &.{},
};
// I think we need a request.receiveHead() call here
// std.testing.log_level = .debug;
var fbs = std.io.fixedBufferStream("bar");
try std.testing.expect(try verifyServerRequest(allocator, &request, fbs.reader(), struct {
try std.testing.expect(try verifyServerRequest(allocator, &request, struct {
cred: Credentials,
const Self = @This();
@ -1221,22 +1222,24 @@ test "can verify server request without x-amz-content-sha256" {
const req_data = head ++ body;
var read_buffer: [2048]u8 = undefined;
@memcpy(read_buffer[0..req_data.len], req_data);
var reader = std.Io.Reader.fixed(&read_buffer);
var server: std.http.Server = .{
.connection = undefined,
.out = undefined, // We're not sending a response here
.reader = .{
.interface = undefined,
.in = &reader,
.state = .ready,
.read_buffer = &read_buffer,
.read_buffer_len = req_data.len,
.next_request_start = 0,
.max_head_len = 1024,
},
};
var request: std.http.Server.Request = .{
.server = &server,
.head_end = head.len,
.head = try std.http.Server.Request.Head.parse(read_buffer[0..head.len]),
.reader_state = undefined,
.head = undefined,
.head_buffer = &.{},
};
{
var h = std.ArrayList(std.http.Header).init(allocator);
defer h.deinit();
var h = try std.ArrayList(std.http.Header).initCapacity(allocator, 4);
defer h.deinit(allocator);
const signed_headers = &[_][]const u8{ "content-type", "host", "x-amz-date", "x-amz-target" };
var it = request.iterateHeaders();
while (it.next()) |source| {
@ -1245,7 +1248,7 @@ test "can verify server request without x-amz-content-sha256" {
match = std.ascii.eqlIgnoreCase(s, source.name);
if (match) break;
}
if (match) try h.append(.{ .name = source.name, .value = source.value });
if (match) try h.append(allocator, .{ .name = source.name, .value = source.value });
}
const req = base.Request{
.path = "/",
@ -1282,9 +1285,7 @@ test "can verify server request without x-amz-content-sha256" {
}
{ // verification
var fis = std.io.fixedBufferStream(body[0..]);
try std.testing.expect(try verifyServerRequest(allocator, &request, fis.reader(), struct {
try std.testing.expect(try verifyServerRequest(allocator, &request, struct {
cred: Credentials,
const Self = @This();

View file

@ -103,7 +103,6 @@ pub fn encodeInternal(
return rc;
}
fn testencode(allocator: std.mem.Allocator, expected: []const u8, value: anytype, comptime options: EncodingOptions) !void {
const ValidationWriter = struct {
const Self = @This();
pub const Writer = std.io.Writer(*Self, Error, write);
@ -113,17 +112,30 @@ fn testencode(allocator: std.mem.Allocator, expected: []const u8, value: anytype
};
expected_remaining: []const u8,
writer: std.Io.Writer,
fn init(exp: []const u8) Self {
return .{ .expected_remaining = exp };
return .{
.expected_remaining = exp,
.writer = .{
.buffer = &.{},
.vtable = &.{
.drain = drain,
},
},
};
}
pub fn writer(self: *Self) Writer {
return .{ .context = self };
fn drain(w: *std.Io.Writer, data: []const []const u8, splat: usize) std.Io.Writer.Error!usize {
if (splat > 0) @panic("No splat");
const self: *ValidationWriter = @fieldParentPtr("writer", w);
var bytes: usize = 0;
for (data) |d| bytes += try self.write(d);
return bytes;
}
fn write(self: *Self, bytes: []const u8) Error!usize {
// std.debug.print("{s}\n", .{bytes});
fn write(self: *Self, bytes: []const u8) std.Io.Writer.Error!usize {
if (self.expected_remaining.len < bytes.len) {
std.log.warn(
\\====== expected this output: =========
@ -135,7 +147,7 @@ fn testencode(allocator: std.mem.Allocator, expected: []const u8, value: anytype
self.expected_remaining,
bytes,
});
return error.TooMuchData;
return error.WriteFailed;
}
if (!std.mem.eql(u8, self.expected_remaining[0..bytes.len], bytes)) {
std.log.warn(
@ -148,15 +160,15 @@ fn testencode(allocator: std.mem.Allocator, expected: []const u8, value: anytype
self.expected_remaining[0..bytes.len],
bytes,
});
return error.DifferentData;
return error.WriteFailed;
}
self.expected_remaining = self.expected_remaining[bytes.len..];
return bytes.len;
}
};
fn testencode(allocator: std.mem.Allocator, expected: []const u8, value: anytype, comptime options: EncodingOptions) !void {
var vos = ValidationWriter.init(expected);
try encode(allocator, value, vos.writer(), options);
try encode(allocator, value, &vos.writer, options);
if (vos.expected_remaining.len > 0) return error.NotEnoughData;
}
@ -238,17 +250,17 @@ test "can urlencode an EC2 Filter" {
},
.{},
) catch |err| {
var al = std.ArrayList(u8).init(std.testing.allocator);
defer al.deinit();
var aw = std.Io.Writer.Allocating.init(std.testing.allocator);
defer aw.deinit();
try encode(
std.testing.allocator,
Request{
.filters = @constCast(&[_]Filter{.{ .name = "foo", .values = @constCast(&[_][]const u8{"bar"}) }}),
},
al.writer(),
&aw.writer,
.{},
);
std.log.warn("Error found. Full encoding is '{s}'", .{al.items});
std.log.warn("Error found. Full encoding is '{s}'", .{aw.written()});
return err;
};
}