mirror of
https://github.com/oven-sh/bun
synced 2026-02-15 05:12:29 +00:00
upd
This commit is contained in:
@@ -240,6 +240,7 @@ src/bun.js/test/diff_format.zig
|
||||
src/bun.js/test/expect.zig
|
||||
src/bun.js/test/jest.zig
|
||||
src/bun.js/test/pretty_format.zig
|
||||
src/bun.js/test/printDiff.zig
|
||||
src/bun.js/test/snapshot.zig
|
||||
src/bun.js/test/test.zig
|
||||
src/bun.js/unbounded_queue.zig
|
||||
|
||||
@@ -107,40 +107,7 @@ fn printDiff(allocator: std.mem.Allocator, not: bool, received_slice: string, ex
|
||||
inline else => |enable_ansi_colors| try writer.print(Output.prettyFmt("Difference:\n\n<red>- Received<r>\n<green>+ Expected<r>\n\n", enable_ansi_colors), .{}),
|
||||
}
|
||||
|
||||
const equal_fmt = "<d> {s}<r>";
|
||||
const delete_fmt = "<red>- {s}<r>";
|
||||
const insert_fmt = "<green>+ {s}<r>";
|
||||
|
||||
for (diffs.items) |diff| {
|
||||
const text = diff.text;
|
||||
if (text.len == 0) continue;
|
||||
|
||||
switch (diff.operation) {
|
||||
inline else => |operation| {
|
||||
const fmt: []const u8 = comptime switch (operation) {
|
||||
.equal => equal_fmt,
|
||||
.insert => insert_fmt,
|
||||
.delete => delete_fmt,
|
||||
};
|
||||
|
||||
var rest = text;
|
||||
while (std.mem.indexOfScalar(u8, rest, '\n')) |i| {
|
||||
const line = rest[0..i];
|
||||
switch (Output.enable_ansi_colors) {
|
||||
inline else => |enable_ansi_colors| try writer.print(Output.prettyFmt(fmt, enable_ansi_colors), .{line}),
|
||||
}
|
||||
try writer.print("\n", .{});
|
||||
rest = rest[i + 1 ..];
|
||||
}
|
||||
|
||||
if (rest.len > 0) {
|
||||
switch (Output.enable_ansi_colors) {
|
||||
inline else => |enable_ansi_colors| try writer.print(Output.prettyFmt(fmt, enable_ansi_colors), .{rest}),
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
try @import("printDiff.zig").printDiff(allocator, writer, diffs.items, Output.enable_ansi_colors);
|
||||
}
|
||||
|
||||
// @sortImports
|
||||
|
||||
154
src/bun.js/test/printDiff.zig
Normal file
154
src/bun.js/test/printDiff.zig
Normal file
@@ -0,0 +1,154 @@
|
||||
const colors = struct {
|
||||
const red = "\x1b[31m";
|
||||
const green = "\x1b[32m";
|
||||
const red_bg = "\x1b[41m";
|
||||
const green_bg = "\x1b[42m";
|
||||
const dim = "\x1b[2m";
|
||||
const reset = "\x1b[0m";
|
||||
};
|
||||
|
||||
pub fn printDiff(arena: std.mem.Allocator, writer: anytype, segments: []const Diff, enable_ansi_colors: bool) !void {
|
||||
var line_buffer = std.ArrayList(Diff).init(arena);
|
||||
defer line_buffer.deinit();
|
||||
|
||||
var before_line_number: usize = 1;
|
||||
var after_line_number: usize = 1;
|
||||
|
||||
for (segments) |segment| {
|
||||
var text_iterator = std.mem.splitScalar(u8, segment.text, '\n');
|
||||
|
||||
// The first part of a split always belongs to the current line being built.
|
||||
// It's safe to call next() because even for an empty string, it returns one empty slice.
|
||||
const first_part = text_iterator.next().?;
|
||||
if (first_part.len > 0) {
|
||||
try line_buffer.append(.{ .operation = segment.operation, .text = first_part });
|
||||
}
|
||||
|
||||
// Any subsequent parts mean we've crossed a newline.
|
||||
// Each part (except the very last one in the stream) is a complete line.
|
||||
while (text_iterator.next()) |part| {
|
||||
switch (segment.operation) {
|
||||
.delete => before_line_number += 1,
|
||||
.insert => after_line_number += 1,
|
||||
.equal => {},
|
||||
}
|
||||
|
||||
// Process the completed line in the buffer.
|
||||
try printLine(writer, line_buffer.items, enable_ansi_colors);
|
||||
line_buffer.clearRetainingCapacity();
|
||||
|
||||
// The new part becomes the start of the next line.
|
||||
if (part.len > 0) {
|
||||
try line_buffer.append(.{ .operation = segment.operation, .text = part });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// After the loop, print the last line
|
||||
try printLine(writer, line_buffer.items, enable_ansi_colors);
|
||||
}
|
||||
|
||||
const ModifiedMode = enum {
|
||||
added,
|
||||
removed,
|
||||
modified,
|
||||
equal,
|
||||
};
|
||||
fn getMode(line_segments: []const Diff) ModifiedMode {
|
||||
var has_inserts = false;
|
||||
var has_deletes = false;
|
||||
var has_equal = false;
|
||||
for (line_segments) |segment| {
|
||||
switch (segment.operation) {
|
||||
.insert => has_inserts = true,
|
||||
.delete => has_deletes = true,
|
||||
.equal => has_equal = true,
|
||||
}
|
||||
}
|
||||
|
||||
if (has_inserts and !has_deletes and !has_equal) return .added;
|
||||
if (has_deletes and !has_inserts and !has_equal) return .removed;
|
||||
if (has_equal and !has_inserts and !has_deletes) return .equal;
|
||||
return .modified;
|
||||
}
|
||||
|
||||
// Helper function to format and print a single logical line.
|
||||
fn printLine(writer: anytype, line_segments: []const Diff, enable_ansi_colors: bool) !void {
|
||||
const mode = getMode(line_segments);
|
||||
const insert_line = switch (enable_ansi_colors) {
|
||||
true => colors.green ++ "+" ++ colors.reset ++ " ",
|
||||
false => "+ ",
|
||||
};
|
||||
const delete_line = switch (enable_ansi_colors) {
|
||||
true => colors.red ++ "-" ++ colors.reset ++ " ",
|
||||
false => "- ",
|
||||
};
|
||||
const red_bg = switch (enable_ansi_colors) {
|
||||
true => colors.red_bg,
|
||||
false => "",
|
||||
};
|
||||
const green_bg = switch (enable_ansi_colors) {
|
||||
true => colors.green_bg,
|
||||
false => "",
|
||||
};
|
||||
const dim = switch (enable_ansi_colors) {
|
||||
true => colors.dim,
|
||||
false => "",
|
||||
};
|
||||
const reset = switch (enable_ansi_colors) {
|
||||
true => colors.reset,
|
||||
false => "",
|
||||
};
|
||||
|
||||
switch (mode) {
|
||||
.modified => {
|
||||
// Modified line: print delete line, then insert line
|
||||
try writer.writeAll(delete_line);
|
||||
for (line_segments) |s| switch (s.operation) {
|
||||
.delete => try writer.print("{s}{s}{s}", .{ red_bg, s.text, reset }),
|
||||
.equal => try writer.print("{s}{s}{s}", .{ dim, s.text, reset }),
|
||||
.insert => {}, // Skip inserts on the delete line
|
||||
};
|
||||
try writer.writeAll("\n");
|
||||
|
||||
try writer.writeAll(insert_line);
|
||||
for (line_segments) |s| switch (s.operation) {
|
||||
.insert => try writer.print("{s}{s}{s}", .{ green_bg, s.text, reset }),
|
||||
.equal => try writer.print("{s}{s}{s}", .{ dim, s.text, reset }),
|
||||
.delete => {}, // Skip deletes on the insert line
|
||||
};
|
||||
try writer.writeAll("\n");
|
||||
},
|
||||
.added => {
|
||||
// Line added
|
||||
try writer.writeAll(insert_line);
|
||||
try writer.writeAll(green_bg);
|
||||
for (line_segments) |s| try writer.writeAll(s.text);
|
||||
try writer.writeAll(reset);
|
||||
try writer.writeAll("\n");
|
||||
},
|
||||
.removed => {
|
||||
// Line removed
|
||||
try writer.writeAll(delete_line);
|
||||
try writer.writeAll(red_bg);
|
||||
for (line_segments) |s| try writer.writeAll(s.text);
|
||||
try writer.writeAll(reset);
|
||||
try writer.writeAll("\n");
|
||||
},
|
||||
.equal => {
|
||||
// Equal-only line
|
||||
try writer.writeAll(" ");
|
||||
try writer.writeAll(dim);
|
||||
for (line_segments) |s| try writer.writeAll(s.text);
|
||||
try writer.writeAll(reset);
|
||||
try writer.writeAll("\n");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// @sortImports
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
const DiffMatchPatch = @import("../../deps/diffz/DiffMatchPatch.zig");
|
||||
const Diff = DiffMatchPatch.Diff;
|
||||
32
test/js/bun/test/printing/diffexample.fixture.ts
Normal file
32
test/js/bun/test/printing/diffexample.fixture.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { test, expect } from "bun:test";
|
||||
|
||||
test("example 1", () => {
|
||||
expect("a\nb\nc\n d\ne").toEqual("a\nd\nc\nd\ne");
|
||||
});
|
||||
test("example 2", () => {
|
||||
expect({
|
||||
object1: "a",
|
||||
object2: "b",
|
||||
object3: "c\nd\ne",
|
||||
}).toEqual({
|
||||
object1: "a",
|
||||
object2: " b",
|
||||
object3: "c\nd",
|
||||
});
|
||||
});
|
||||
|
||||
test("example 3 - very long string with few changes", () => {
|
||||
// Create a 1000 line string with only a few differences
|
||||
const lines = Array.from({ length: 1000 }, (_, i) => `line ${i + 1}`);
|
||||
const originalString = lines.join("\n");
|
||||
|
||||
// Create expected string with only a few changes
|
||||
const expectedLines = [...lines];
|
||||
expectedLines[499] = "line 500 - CHANGED"; // Change line 500
|
||||
expectedLines[750] = "line 751 - MODIFIED"; // Change line 751
|
||||
expectedLines[900] = "line 901 - DIFFERENT"; // Change line 901
|
||||
expectedLines.splice(100, 0, "line 101 - INSERTED");
|
||||
const expectedString = expectedLines.join("\n");
|
||||
|
||||
expect(originalString).toEqual(expectedString);
|
||||
});
|
||||
@@ -1,32 +1,32 @@
|
||||
import { test, expect } from "bun:test";
|
||||
import { bunEnv, bunExe } from "harness";
|
||||
|
||||
test("example 1", () => {
|
||||
expect("a\nb\nc\n d\ne").toEqual("a\nd\nc\nd\ne");
|
||||
});
|
||||
test("example 2", () => {
|
||||
expect({
|
||||
object1: "a",
|
||||
object2: "b",
|
||||
object3: "c\nd\ne",
|
||||
}).toEqual({
|
||||
object1: "a",
|
||||
object2: " b",
|
||||
object3: "c\nd",
|
||||
test("color", async () => {
|
||||
const spawn = Bun.spawn({
|
||||
cmd: [bunExe(), import.meta.resolve("diffexample.fixture.ts")],
|
||||
stdio: ["inherit", "pipe", "pipe"],
|
||||
env: {
|
||||
...bunEnv,
|
||||
FORCE_COLOR: "1",
|
||||
},
|
||||
});
|
||||
await spawn.exited;
|
||||
expect(await spawn.stderr.text()).toBe("");
|
||||
expect(spawn.exitCode).toBe(0);
|
||||
expect(await spawn.stdout.text()).toMatchInlineSnapshot();
|
||||
});
|
||||
|
||||
test("example 3 - very long string with few changes", () => {
|
||||
// Create a 1000 line string with only a few differences
|
||||
const lines = Array.from({ length: 1000 }, (_, i) => `line ${i + 1}`);
|
||||
const originalString = lines.join("\n");
|
||||
|
||||
// Create expected string with only a few changes
|
||||
const expectedLines = [...lines];
|
||||
expectedLines[499] = "line 500 - CHANGED"; // Change line 500
|
||||
expectedLines[750] = "line 751 - MODIFIED"; // Change line 751
|
||||
expectedLines[900] = "line 901 - DIFFERENT"; // Change line 901
|
||||
expectedLines.splice(100, 0, "line 101 - INSERTED");
|
||||
const expectedString = expectedLines.join("\n");
|
||||
|
||||
expect(originalString).toEqual(expectedString);
|
||||
test("no color", async () => {
|
||||
const spawn = Bun.spawn({
|
||||
cmd: [bunExe(), import.meta.resolve("diffexample.fixture.ts")],
|
||||
stdio: ["inherit", "pipe", "pipe"],
|
||||
env: {
|
||||
...bunEnv,
|
||||
FORCE_COLOR: "0",
|
||||
},
|
||||
});
|
||||
await spawn.exited;
|
||||
expect(await spawn.stderr.text()).toBe("");
|
||||
expect(spawn.exitCode).toBe(0);
|
||||
expect(await spawn.stdout.text()).toMatchInlineSnapshot();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user