From 9588f7b8db916998b0a5a645dedefc07be9da49d Mon Sep 17 00:00:00 2001 From: Ben Sinclair Date: Sun, 18 Feb 2024 01:17:47 +1100 Subject: [PATCH] Clean up tests and fix errdefer issue Added a test for an invalid obj file which causes the errdefer logic to be exercised, and added a test for sharing material info over two objects. --- examples/triangle_error.obj | 15 ++++ examples/triangle_two.obj | 17 ++++ src/obj.zig | 159 +++++++++++++++++++++++++----------- 3 files changed, 144 insertions(+), 47 deletions(-) create mode 100644 examples/triangle_error.obj create mode 100644 examples/triangle_two.obj diff --git a/examples/triangle_error.obj b/examples/triangle_error.obj new file mode 100644 index 0000000..882a2a7 --- /dev/null +++ b/examples/triangle_error.obj @@ -0,0 +1,15 @@ +# Blender v2.91.0 OBJ File: '' +# www.blender.org +mtllib triangle.mtl +o Plane +v -1.000000 0.000000 0.000000 +v 1.000000 0.000000 1.000000 +v 1.000000 0.000000 -1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vn 0.0000 1.0000 0.0000 +usemtl None +s off +f 1/1/1 2/2/1 3/3/1 +invalid diff --git a/examples/triangle_two.obj b/examples/triangle_two.obj new file mode 100644 index 0000000..2476580 --- /dev/null +++ b/examples/triangle_two.obj @@ -0,0 +1,17 @@ +# Blender v2.91.0 OBJ File: '' +# www.blender.org +mtllib triangle.mtl +o Plane +v -1.000000 0.000000 0.000000 +v 1.000000 0.000000 1.000000 +v 1.000000 0.000000 -1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vn 0.0000 1.0000 0.0000 +usemtl None +s off +f 1/1/1 2/2/1 3/3/1 + +o Plane2 +f 1/1/1 2/2/1 3/3/1 diff --git a/src/obj.zig b/src/obj.zig index 9f852cb..3d251d9 100644 --- a/src/obj.zig +++ b/src/obj.zig @@ -141,6 +141,7 @@ pub fn parse(allocator: Allocator, data: []const u8) !ObjData { // current mesh material var current_material: ?MeshMaterial = null; + errdefer if (current_material) |mat| allocator.free(mat.material); var mesh_materials = ArrayList(MeshMaterial).init(allocator); errdefer mesh_materials.deinit(); var num_processed_verts: usize = 0; @@ -297,6 +298,7 @@ const test_allocator = std.testing.allocator; const expect = std.testing.expect; const expectError = std.testing.expectError; +const expectEqual = std.testing.expectEqual; const expectEqualSlices = std.testing.expectEqualSlices; const expectEqualStrings = std.testing.expectEqualStrings; @@ -308,60 +310,60 @@ test "comment" { var result = try parse(test_allocator, "# this is a comment"); defer result.deinit(test_allocator); - try expect(result.vertices.len == 0); - try expect(result.tex_coords.len == 0); - try expect(result.normals.len == 0); - try expect(result.meshes.len == 0); + try expectEqual(0, result.vertices.len); + try expectEqual(0, result.tex_coords.len); + try expectEqual(0, result.normals.len); + try expectEqual(0, result.meshes.len); } test "single vertex def xyz" { var result = try parse(test_allocator, "v 0.123 0.234 0.345"); defer result.deinit(test_allocator); - try expect(std.mem.eql(f32, result.vertices, &[_]f32{ 0.123, 0.234, 0.345 })); - try expect(result.tex_coords.len == 0); - try expect(result.normals.len == 0); - try expect(result.meshes.len == 0); + try expectEqualSlices(f32, &.{ 0.123, 0.234, 0.345 }, result.vertices); + try expectEqual(0, result.tex_coords.len); + try expectEqual(0, result.normals.len); + try expectEqual(0, result.meshes.len); } test "single vertex def xyzw" { var result = try parse(test_allocator, "v 0.123 0.234 0.345 0.456"); defer result.deinit(test_allocator); - try expect(std.mem.eql(f32, result.vertices, &[_]f32{ 0.123, 0.234, 0.345 })); - try expect(result.tex_coords.len == 0); - try expect(result.normals.len == 0); - try expect(result.meshes.len == 0); + try expectEqualSlices(f32, &.{ 0.123, 0.234, 0.345 }, result.vertices); + try expectEqual(0, result.tex_coords.len); + try expectEqual(0, result.normals.len); + try expectEqual(0, result.meshes.len); } test "single tex coord def uv" { var result = try parse(test_allocator, "vt 0.123 0.234"); defer result.deinit(test_allocator); - try expect(std.mem.eql(f32, result.tex_coords, &[_]f32{ 0.123, 0.234 })); - try expect(result.vertices.len == 0); - try expect(result.normals.len == 0); - try expect(result.meshes.len == 0); + try expectEqualSlices(f32, &.{ 0.123, 0.234 }, result.tex_coords); + try expectEqual(0, result.vertices.len); + try expectEqual(0, result.normals.len); + try expectEqual(0, result.meshes.len); } test "single tex coord def uvw" { var result = try parse(test_allocator, "vt 0.123 0.234 0.345"); defer result.deinit(test_allocator); - try expect(std.mem.eql(f32, result.tex_coords, &[_]f32{ 0.123, 0.234 })); - try expect(result.vertices.len == 0); - try expect(result.normals.len == 0); - try expect(result.meshes.len == 0); + try expectEqualSlices(f32, &.{ 0.123, 0.234 }, result.tex_coords); + try expectEqual(0, result.vertices.len); + try expectEqual(0, result.normals.len); + try expectEqual(0, result.meshes.len); } test "single normal def xyz" { var result = try parse(test_allocator, "vn 0.123 0.234 0.345"); defer result.deinit(test_allocator); - try expect(std.mem.eql(f32, result.normals, &[_]f32{ 0.123, 0.234, 0.345 })); - try expect(result.vertices.len == 0); - try expect(result.tex_coords.len == 0); - try expect(result.meshes.len == 0); + try expectEqualSlices(f32, &.{ 0.123, 0.234, 0.345 }, result.normals); + try expectEqual(0, result.vertices.len); + try expectEqual(0, result.tex_coords.len); + try expectEqual(0, result.meshes.len); } test "single face def vertex only" { @@ -378,7 +380,7 @@ test "single face def vertex only" { }, .materials = &[_]MeshMaterial{}, }; - try expect(result.meshes.len == 1); + try expectEqual(1, result.meshes.len); try expect(result.meshes[0].eq(mesh)); } @@ -396,7 +398,7 @@ test "single face def vertex + tex coord" { }, .materials = &[_]MeshMaterial{}, }; - try expect(result.meshes.len == 1); + try expectEqual(1, result.meshes.len); try expect(result.meshes[0].eq(mesh)); } @@ -414,7 +416,7 @@ test "single face def vertex + tex coord + normal" { }, .materials = &[_]MeshMaterial{}, }; - try expect(result.meshes.len == 1); + try expectEqual(1, result.meshes.len); try expect(result.meshes[0].eq(mesh)); } @@ -432,7 +434,7 @@ test "single face def vertex + normal" { }, .materials = &[_]MeshMaterial{}, }; - try expect(result.meshes.len == 1); + try expectEqual(1, result.meshes.len); try expect(result.meshes[0].eq(expected)); } @@ -462,7 +464,7 @@ test "multiple materials in one mesh" { }, }; - try expect(result.meshes.len == 1); + try expectEqual(1, result.meshes.len); try expect(result.meshes[0].eq(expected)); } @@ -500,14 +502,14 @@ test "triangle obj exported from blender" { }, }, }; - try expect(result.material_libs.len == 1); - try expectEqualStrings(result.material_libs[0], expected.material_libs[0]); + try expectEqual(1, result.material_libs.len); + try expectEqualStrings(expected.material_libs[0], result.material_libs[0]); - try expectEqualSlices(f32, result.vertices, expected.vertices); - try expectEqualSlices(f32, result.tex_coords, expected.tex_coords); - try expectEqualSlices(f32, result.normals, expected.normals); + try expectEqualSlices(f32, expected.vertices, result.vertices); + try expectEqualSlices(f32, expected.tex_coords, result.tex_coords); + try expectEqualSlices(f32, expected.normals, result.normals); - try expect(result.meshes.len == 1); + try expectEqual(1, result.meshes.len); try expect(result.meshes[0].eq(expected.meshes[0])); } @@ -545,17 +547,80 @@ test "triangle obj exported from blender (windows line endings)" { }, }, }; - try expect(result.material_libs.len == 1); - try expectEqualStrings(result.material_libs[0], expected.material_libs[0]); + try expectEqual(1, result.material_libs.len); + try expectEqualStrings(expected.material_libs[0], result.material_libs[0]); - try expectEqualSlices(f32, result.vertices, expected.vertices); - try expectEqualSlices(f32, result.tex_coords, expected.tex_coords); - try expectEqualSlices(f32, result.normals, expected.normals); + try expectEqualSlices(f32, expected.vertices, result.vertices); + try expectEqualSlices(f32, expected.tex_coords, result.tex_coords); + try expectEqualSlices(f32, expected.normals, result.normals); - try expect(result.meshes.len == 1); + try expectEqual(1, result.meshes.len); try expect(result.meshes[0].eq(expected.meshes[0])); } +test "triangle obj exported from blender (two triangles)" { + const data = @embedFile("../examples/triangle_two.obj"); + + var result = try parse(test_allocator, data); + defer result.deinit(test_allocator); + + const expected = ObjData{ + .material_libs = &[_][]const u8{"triangle.mtl"}, + .vertices = &[_]f32{ + -1.0, 0.0, 0.0, + 1.0, 0.0, 1.0, + 1.0, 0.0, -1.0, + }, + .tex_coords = &[_]f32{ + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + }, + .normals = &[_]f32{ 0.0, 1.0, 0.0 }, + .meshes = &[_]Mesh{ + Mesh{ + .name = "Plane", + .num_vertices = &[_]u32{3}, + .indices = &[_]Mesh.Index{ + .{ .vertex = 0, .tex_coord = 0, .normal = 0 }, + .{ .vertex = 1, .tex_coord = 1, .normal = 0 }, + .{ .vertex = 2, .tex_coord = 2, .normal = 0 }, + }, + .materials = &[_]MeshMaterial{ + .{ .material = "None", .start_index = 0, .end_index = 3 }, + }, + }, + Mesh{ + .name = "Plane2", + .num_vertices = &[_]u32{3}, + .indices = &[_]Mesh.Index{ + .{ .vertex = 0, .tex_coord = 0, .normal = 0 }, + .{ .vertex = 1, .tex_coord = 1, .normal = 0 }, + .{ .vertex = 2, .tex_coord = 2, .normal = 0 }, + }, + .materials = &[_]MeshMaterial{ + .{ .material = "None", .start_index = 0, .end_index = 3 }, + }, + }, + }, + }; + try expectEqual(1, result.material_libs.len); + try expectEqualStrings(expected.material_libs[0], result.material_libs[0]); + + try expectEqualSlices(f32, expected.vertices, result.vertices); + try expectEqualSlices(f32, expected.tex_coords, result.tex_coords); + try expectEqualSlices(f32, expected.normals, result.normals); + + try expectEqual(2, result.meshes.len); + try expect(result.meshes[0].eq(expected.meshes[0])); + try expect(result.meshes[1].eq(expected.meshes[1])); +} + +test "triangle obj exported from blender (with error)" { + const data = @embedFile("../examples/triangle_error.obj"); + try expectError(error.UnknownDefType, parse(test_allocator, data)); +} + test "cube obj exported from blender" { const data = @embedFile("../examples/cube.obj"); @@ -633,14 +698,14 @@ test "cube obj exported from blender" { }, }; - try expect(result.material_libs.len == 1); - try expectEqualStrings(result.material_libs[0], expected.material_libs[0]); + try expectEqual(1, result.material_libs.len); + try expectEqualStrings(expected.material_libs[0], result.material_libs[0]); - try expectEqualSlices(f32, result.vertices, expected.vertices); - try expectEqualSlices(f32, result.tex_coords, expected.tex_coords); - try expectEqualSlices(f32, result.normals, expected.normals); + try expectEqualSlices(f32, expected.vertices, result.vertices); + try expectEqualSlices(f32, expected.tex_coords, result.tex_coords); + try expectEqualSlices(f32, expected.normals, result.normals); - try expect(result.meshes.len == 1); + try expectEqual(1, result.meshes.len); try expect(result.meshes[0].eq(expected.meshes[0])); }