diff --git a/.github/workflows/zig-tests.yml b/.github/workflows/zig-tests.yml new file mode 100644 index 0000000..dd1184d --- /dev/null +++ b/.github/workflows/zig-tests.yml @@ -0,0 +1,55 @@ +name: zig-tests + +on: + pull_request: + push: + +permissions: + contents: read + +env: + ZIG_VERSION: 0.15.2 + +jobs: + test: + name: test-${{ matrix.name }} + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - name: ubuntu + runner: ubuntu-24.04 + zig_archive: zig-x86_64-linux-0.15.2.tar.xz + zig_dir: zig-x86_64-linux-0.15.2 + - name: macos + runner: macos-14 + zig_archive: zig-aarch64-macos-0.15.2.tar.xz + zig_dir: zig-aarch64-macos-0.15.2 + - name: windows + runner: windows-2022 + zig_archive: zig-x86_64-windows-0.15.2.zip + zig_dir: zig-x86_64-windows-0.15.2 + + steps: + - uses: actions/checkout@v4 + + - name: Install Zig + if: runner.os != 'Windows' + shell: bash + run: | + set -euo pipefail + curl -L "https://ziglang.org/download/${ZIG_VERSION}/${{ matrix.zig_archive }}" -o zig.tar.xz + tar -xf zig.tar.xz + echo "$PWD/${{ matrix.zig_dir }}" >> "$GITHUB_PATH" + + - name: Install Zig + if: runner.os == 'Windows' + shell: pwsh + run: | + Invoke-WebRequest -Uri "https://ziglang.org/download/$env:ZIG_VERSION/${{ matrix.zig_archive }}" -OutFile zig.zip + Expand-Archive -Path zig.zip -DestinationPath . + Add-Content -Path $env:GITHUB_PATH -Value (Join-Path $PWD '${{ matrix.zig_dir }}') + + - name: Run tests + run: zig build test diff --git a/src/index.zig b/src/index.zig index 9ac0b15..7b132b0 100644 --- a/src/index.zig +++ b/src/index.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const std = @import("std"); const compat = @import("compat.zig"); @@ -968,6 +969,8 @@ pub const MmapTrigramIndex = struct { } fn initFromDiskInner(dir_path: []const u8, allocator: std.mem.Allocator) !?MmapTrigramIndex { + if (comptime builtin.os.tag == .windows) return null; + const postings_path = try std.fmt.allocPrint(allocator, "{s}/trigram.postings", .{dir_path}); defer allocator.free(postings_path); const lookup_path = try std.fmt.allocPrint(allocator, "{s}/trigram.lookup", .{dir_path}); @@ -1082,8 +1085,10 @@ pub const MmapTrigramIndex = struct { for (self.file_table) |p| self.allocator.free(p); self.allocator.free(self.file_table); self.file_set.deinit(); - std.posix.munmap(self.postings_data); - std.posix.munmap(self.lookup_data); + if (comptime builtin.os.tag != .windows) { + std.posix.munmap(self.postings_data); + std.posix.munmap(self.lookup_data); + } } pub fn fileCount(self: *const MmapTrigramIndex) u32 { @@ -2188,4 +2193,3 @@ pub const SparseNgramIndex = struct { return @intCast(self.file_ngrams.count()); } }; - diff --git a/src/tests.zig b/src/tests.zig index c5fccfc..95424c6 100644 --- a/src/tests.zig +++ b/src/tests.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const std = @import("std"); const testing = std.testing; @@ -1049,7 +1050,9 @@ test "explorer: removeFile frees owned map key" { try testing.expect(explorer.dep_graph.count() == 0); } test "watcher: queue overflow is explicit" { - var queue = watcher.EventQueue{}; + const queue = try testing.allocator.create(watcher.EventQueue); + defer testing.allocator.destroy(queue); + queue.* = .{}; var pushed: usize = 0; while (true) : (pushed += 1) { @@ -1068,7 +1071,9 @@ test "watcher: queue overflow is explicit" { } test "watcher: queue event copies path bytes" { - var queue = watcher.EventQueue{}; + const queue = try testing.allocator.create(watcher.EventQueue); + defer testing.allocator.destroy(queue); + queue.* = .{}; const original = try testing.allocator.dupe(u8, "tmp/deleted.zig"); try testing.expect(queue.push(watcher.FsEvent.init(original, .deleted, 99) orelse unreachable)); testing.allocator.free(original); @@ -1452,7 +1457,9 @@ test "regression: searchContent frees empty trigram candidate slice" { } test "regression: queue push stays non-blocking when full" { - var queue = watcher.EventQueue{}; + const queue = try testing.allocator.create(watcher.EventQueue); + defer testing.allocator.destroy(queue); + queue.* = .{}; var pushed: usize = 0; while (true) : (pushed += 1) { @@ -4530,8 +4537,9 @@ test "issue-151: Go block comments skipped" { try testing.expect(func_count == 1); // only realFunc } - test "issue-150: --help prints usage" { + if (comptime builtin.os.tag == .windows) return error.SkipZigTest; + const result = try std.process.Child.run(.{ .allocator = testing.allocator, .argv = &.{ "zig", "build", "run", "--", "--help" }, @@ -4545,6 +4553,8 @@ test "issue-150: --help prints usage" { } test "issue-150: -h prints usage" { + if (comptime builtin.os.tag == .windows) return error.SkipZigTest; + const result = try std.process.Child.run(.{ .allocator = testing.allocator, .argv = &.{ "zig", "build", "run", "--", "-h" }, @@ -4577,6 +4587,8 @@ test "issue-148: idle timeout is 10 minutes" { } test "issue-148: POLLHUP detects closed pipe" { + if (comptime builtin.os.tag == .windows) return error.SkipZigTest; + // Verify the polling infrastructure works for pipe-based transports const pipe = try std.posix.pipe(); defer std.posix.close(pipe[0]); @@ -4670,6 +4682,8 @@ const MmapTrigramIndex = @import("index.zig").MmapTrigramIndex; const AnyTrigramIndex = @import("index.zig").AnyTrigramIndex; test "issue-164: mmap trigram index returns same candidates as heap index" { + if (comptime builtin.os.tag == .windows) return error.SkipZigTest; + var arena = std.heap.ArenaAllocator.init(testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); @@ -4710,6 +4724,8 @@ test "issue-164: mmap trigram index returns same candidates as heap index" { } test "issue-164: mmap binary search on sorted lookup table" { + if (comptime builtin.os.tag == .windows) return error.SkipZigTest; + var arena = std.heap.ArenaAllocator.init(testing.allocator); defer arena.deinit(); const allocator = arena.allocator(); @@ -4745,11 +4761,15 @@ test "issue-164: mmap binary search on sorted lookup table" { } test "issue-164: mmap handles missing files gracefully" { + if (comptime builtin.os.tag == .windows) return error.SkipZigTest; + const result = MmapTrigramIndex.initFromDisk("/tmp/nonexistent-codedb-test-dir-164", testing.allocator); try testing.expect(result == null); } test "issue-164: AnyTrigramIndex dispatches to mmap variant" { + if (comptime builtin.os.tag == .windows) return error.SkipZigTest; + var arena = std.heap.ArenaAllocator.init(testing.allocator); defer arena.deinit(); const allocator = arena.allocator();