From 6f8fbe1ccbac9f2f43272fb80cb4b1ba5961f015 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Wed, 27 May 2020 21:58:35 +0300 Subject: [PATCH] Added tests. --- .github/workflows/main.yml | 6 ++- build.zig | 10 +++- src/analysis.zig | 4 +- tests/unit_tests.zig | 102 +++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 tests/unit_tests.zig diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4523df0..e5515f0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,7 +28,11 @@ jobs: FILE=zig-cache/bin/zls if test -f "$FILE"; then - exit 0 + if zig test; then + exit 0 + else + exit 1 + fi else exit 1 fi diff --git a/build.zig b/build.zig index 21e64c9..4c40acf 100644 --- a/build.zig +++ b/build.zig @@ -131,7 +131,15 @@ pub fn build(b: *std.build.Builder) !void { const run_step = b.step("run", "Run the app"); run_step.dependOn(&run_cmd.step); - // const configure_step = std.build.Step.init("config", b.allocator, config); const configure_step = b.step("config", "Configure zls"); configure_step.makeFn = config; + + const test_step = b.step("test", "Run all the tests"); + test_step.dependOn(&exe.step); + + var unit_tests = b.addTest("tests/unit_tests.zig"); + unit_tests.addPackage(.{ .name = "analysis", .path = "src/analysis.zig" }); + unit_tests.addPackage(.{ .name = "types", .path = "src/types.zig" }); + unit_tests.setBuildMode(.Debug); + test_step.dependOn(&unit_tests.step); } diff --git a/src/analysis.zig b/src/analysis.zig index 73b1fc5..9199822 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -910,7 +910,7 @@ pub fn getImportStr(tree: *ast.Tree, source_index: usize) ?[]const u8 { const types = @import("types.zig"); pub const SourceRange = std.zig.Token.Loc; -const PositionContext = union(enum) { +pub const PositionContext = union(enum) { builtin: SourceRange, comment, string_literal: SourceRange, @@ -920,7 +920,7 @@ const PositionContext = union(enum) { other, empty, - fn range(self: PositionContext) ?SourceRange { + pub fn range(self: PositionContext) ?SourceRange { return switch (self) { .builtin => |r| r, .comment => null, diff --git a/tests/unit_tests.zig b/tests/unit_tests.zig new file mode 100644 index 0000000..86e62e9 --- /dev/null +++ b/tests/unit_tests.zig @@ -0,0 +1,102 @@ +const analysis = @import("analysis"); +const types = @import("types"); + +const std = @import("std"); + +const allocator = std.testing.allocator; + +fn makeDocument(uri: []const u8, text: []const u8) !types.TextDocument { + const mem = try allocator.alloc(u8, text.len); + std.mem.copy(u8, mem, text); + + return types.TextDocument{ + .uri = uri, + .mem = mem, + .text = mem[0..], + }; +} + +fn freeDocument(doc: types.TextDocument) void { + allocator.free(doc.text); +} + +fn makeUnnamedDocument(text: []const u8) !types.TextDocument { + return try makeDocument("test", text); +} + +fn testContext(comptime line: []const u8, comptime tag: var, comptime range: ?[]const u8) !void { + const cursor_idx = comptime std.mem.indexOf(u8, line, "").?; + const final_line = line[0..cursor_idx] ++ line[cursor_idx + "".len ..]; + + const doc = try makeUnnamedDocument(final_line); + defer freeDocument(doc); + + const ctx = try analysis.documentPositionContext(allocator, doc, types.Position{ + .line = 0, + .character = @intCast(i64, cursor_idx - 1), + }); + + if (std.meta.activeTag(ctx) != tag) { + std.debug.warn("Expected tag {}, got {}\n", .{ tag, std.meta.activeTag(ctx) }); + return error.DifferentTag; + } + + if (ctx.range()) |ctx_range| { + if (range == null) { + std.debug.warn("Expected null range, got `{}`\n", .{ + doc.text[ctx_range.start..ctx_range.end], + }); + } else { + const range_start = comptime std.mem.indexOf(u8, final_line, range.?).?; + const range_end = range_start + range.?.len; + + if (range_start != ctx_range.start or range_end != ctx_range.end) { + std.debug.warn("Expected range `{}` ({}..{}), got `{}` ({}..{})\n", .{ + doc.text[range_start..range_end], range_start, range_end, + doc.text[ctx_range.start..ctx_range.end], ctx_range.start, ctx_range.end, + }); + return error.DifferentRange; + } + } + } else if (range != null) { + std.debug.warn("Unexpected null range\n", .{}); + return error.DifferentRange; + } +} + +test "documentPositionContext" { + try testContext( + \\const this_var = identifier; + , + .var_access, + "id", + ); + + try testContext( + \\if (displ.*.?.c.*[0].@"a" == foo) { + , + .field_access, + "displ.*.?.c.*[0].", + ); + + try testContext( + \\const arr = std.ArrayList(SomeStruct(a, b, c, d)).init(allocator); + , + .field_access, + "std.ArrayList(SomeStruct(a, b, c, d)).in", + ); + + try testContext( + \\try erroringFn(the_first[arg], second[a..]); + , + .empty, + null, + ); + + try testContext( + \\ fn add(lhf: lself, rhs: rself) !Se { + , + .var_access, + "Se", + ); +}