flow/test/tests_buffer.zig

424 lines
15 KiB
Zig

const std = @import("std");
const Buffer = @import("Buffer");
const ArrayList = std.ArrayList;
const a = std.testing.allocator;
fn metrics() Buffer.Metrics {
return .{
.ctx = undefined,
.egc_length = struct {
fn f(_: Buffer.Metrics, _: []const u8, colcount: *c_int, _: usize) usize {
colcount.* = 1;
return 1;
}
}.f,
.egc_chunk_width = struct {
fn f(_: Buffer.Metrics, chunk_: []const u8, _: usize) usize {
return chunk_.len;
}
}.f,
.egc_last = struct {
fn f(_: Buffer.Metrics, _: []const u8) []const u8 {
@panic("not implemented");
}
}.f,
.tab_width = 8,
};
}
fn get_big_doc(eol_mode: *Buffer.EolMode) !*Buffer {
const nl_lines = 10000;
var doc: std.Io.Writer.Allocating = .init(a);
defer doc.deinit();
for (0..nl_lines) |line_num| {
try doc.writer.print("this is line {d}\n", .{line_num});
}
var buf = try Buffer.create(a);
var sanitized: bool = false;
buf.update(try buf.load_from_string(doc.written(), eol_mode, &sanitized));
return buf;
}
test "buffer" {
const doc: []const u8 =
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
;
var eol_mode: Buffer.EolMode = .lf;
var sanitized: bool = false;
const buffer = try Buffer.create(a);
defer buffer.deinit();
const root = try buffer.load_from_string(doc, &eol_mode, &sanitized);
try std.testing.expect(root.is_balanced());
buffer.update(root);
const result: []const u8 = try buffer.store_to_string(a, eol_mode);
defer a.free(result);
try std.testing.expectEqualDeep(result, doc);
try std.testing.expectEqual(doc.len, result.len);
try std.testing.expectEqual(doc.len, buffer.root.length());
}
fn get_line(buf: *const Buffer, line: usize) ![]const u8 {
var result: std.Io.Writer.Allocating = .init(a);
try buf.root.get_line(line, &result.writer, metrics());
return result.toOwnedSlice();
}
test "walk_from_line" {
var eol_mode: Buffer.EolMode = .lf;
const buffer = try get_big_doc(&eol_mode);
defer buffer.deinit();
const lines = buffer.root.lines();
try std.testing.expectEqual(lines, 10001);
const line0 = try get_line(buffer, 0);
defer a.free(line0);
try std.testing.expect(std.mem.eql(u8, line0, "this is line 0"));
const line1 = try get_line(buffer, 1);
defer a.free(line1);
try std.testing.expect(std.mem.eql(u8, line1, "this is line 1"));
const line100 = try get_line(buffer, 100);
defer a.free(line100);
try std.testing.expect(std.mem.eql(u8, line100, "this is line 100"));
const line9999 = try get_line(buffer, 9999);
defer a.free(line9999);
try std.testing.expectEqualDeep("this is line 9999", line9999);
}
test "line_len" {
const doc: []const u8 =
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
;
var eol_mode: Buffer.EolMode = .lf;
var sanitized: bool = false;
const buffer = try Buffer.create(a);
defer buffer.deinit();
buffer.update(try buffer.load_from_string(doc, &eol_mode, &sanitized));
try std.testing.expectEqual(try buffer.root.line_width(0, metrics()), 8);
try std.testing.expectEqual(try buffer.root.line_width(1, metrics()), 5);
}
test "get_byte_pos" {
const doc: []const u8 =
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
;
var eol_mode: Buffer.EolMode = .lf;
var sanitized: bool = false;
const buffer = try Buffer.create(a);
defer buffer.deinit();
buffer.update(try buffer.load_from_string(doc, &eol_mode, &sanitized));
try std.testing.expectEqual(0, try buffer.root.get_byte_pos(.{ .row = 0, .col = 0 }, metrics(), eol_mode));
try std.testing.expectEqual(9, try buffer.root.get_byte_pos(.{ .row = 1, .col = 0 }, metrics(), eol_mode));
try std.testing.expectEqual(11, try buffer.root.get_byte_pos(.{ .row = 1, .col = 2 }, metrics(), eol_mode));
try std.testing.expectEqual(33, try buffer.root.get_byte_pos(.{ .row = 4, .col = 0 }, metrics(), eol_mode));
try std.testing.expectEqual(66, try buffer.root.get_byte_pos(.{ .row = 8, .col = 0 }, metrics(), eol_mode));
try std.testing.expectEqual(97, try buffer.root.get_byte_pos(.{ .row = 11, .col = 2 }, metrics(), eol_mode));
eol_mode = .crlf;
try std.testing.expectEqual(0, try buffer.root.get_byte_pos(.{ .row = 0, .col = 0 }, metrics(), eol_mode));
try std.testing.expectEqual(10, try buffer.root.get_byte_pos(.{ .row = 1, .col = 0 }, metrics(), eol_mode));
try std.testing.expectEqual(12, try buffer.root.get_byte_pos(.{ .row = 1, .col = 2 }, metrics(), eol_mode));
try std.testing.expectEqual(37, try buffer.root.get_byte_pos(.{ .row = 4, .col = 0 }, metrics(), eol_mode));
try std.testing.expectEqual(74, try buffer.root.get_byte_pos(.{ .row = 8, .col = 0 }, metrics(), eol_mode));
try std.testing.expectEqual(108, try buffer.root.get_byte_pos(.{ .row = 11, .col = 2 }, metrics(), eol_mode));
}
test "delete_bytes" {
const doc: []const u8 =
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
;
var eol_mode: Buffer.EolMode = .lf;
var sanitized: bool = false;
const buffer = try Buffer.create(a);
defer buffer.deinit();
buffer.update(try buffer.load_from_string(doc, &eol_mode, &sanitized));
buffer.update(try buffer.root.delete_bytes(3, try buffer.root.line_width(3, metrics()) - 1, 1, buffer.allocator, metrics()));
const line3 = try get_line(buffer, 3);
defer a.free(line3);
try std.testing.expect(std.mem.eql(u8, line3, "us"));
buffer.update(try buffer.root.delete_bytes(3, 0, 7, buffer.allocator, metrics()));
const line3_1 = try get_line(buffer, 3);
defer a.free(line3_1);
try std.testing.expect(std.mem.eql(u8, line3_1, "your"));
try std.testing.expect(buffer.root.is_balanced());
buffer.update(try buffer.root.rebalance(buffer.allocator, buffer.allocator));
try std.testing.expect(buffer.root.is_balanced());
buffer.update(try buffer.root.delete_bytes(0, try buffer.root.line_width(0, metrics()) - 1, 2, buffer.allocator, metrics()));
const line0 = try get_line(buffer, 0);
defer a.free(line0);
try std.testing.expect(std.mem.eql(u8, line0, "All youropes"));
}
fn check_line(buffer: *const Buffer, line_no: usize, expect: []const u8) !void {
const line = try get_line(buffer, line_no);
defer a.free(line);
try std.testing.expect(std.mem.eql(u8, line, expect));
}
test "delete_bytes2" {
const doc: []const u8 =
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
;
var eol_mode: Buffer.EolMode = .lf;
var sanitized: bool = false;
const buffer = try Buffer.create(a);
defer buffer.deinit();
buffer.update(try buffer.load_from_string(doc, &eol_mode, &sanitized));
buffer.update(try buffer.root.delete_bytes(2, try buffer.root.line_width(2, metrics()) - 3, 6, buffer.allocator, metrics()));
try check_line(buffer, 2, "are belong!");
try check_line(buffer, 3, "All your");
try check_line(buffer, 4, "ropes");
}
test "delete_bytes_with_tab_issue83" {
const doc: []const u8 =
\\All your
\\ropes
\\are belong to
\\\t
\\All your
\\ropes
\\are belong to
\\us!
;
var eol_mode: Buffer.EolMode = .lf;
var sanitized: bool = false;
const buffer = try Buffer.create(a);
defer buffer.deinit();
buffer.update(try buffer.load_from_string(doc, &eol_mode, &sanitized));
const len = blk: {
const line2 = try get_line(buffer, 2);
const line3 = try get_line(buffer, 3);
const line4 = try get_line(buffer, 4);
defer a.free(line2);
defer a.free(line3);
defer a.free(line4);
break :blk line2.len + 1 +
line3.len + 1 +
line4.len + 1;
};
buffer.update(try buffer.root.delete_bytes(2, 0, len, buffer.allocator, metrics()));
const result: []const u8 = try buffer.store_to_string(a, eol_mode);
defer a.free(result);
// std.debug.print("{s}", .{result});
try check_line(buffer, 2, "ropes");
}
test "insert_chars" {
const doc: []const u8 =
\\B
;
var eol_mode: Buffer.EolMode = .lf;
var sanitized: bool = false;
const buffer = try Buffer.create(a);
defer buffer.deinit();
buffer.update(try buffer.load_from_string(doc, &eol_mode, &sanitized));
const line0 = try get_line(buffer, 0);
defer a.free(line0);
try std.testing.expect(std.mem.eql(u8, line0, "B"));
_, _, var root = try buffer.root.insert_chars(0, 0, "1", buffer.allocator, metrics());
buffer.update(root);
const line1 = try get_line(buffer, 0);
defer a.free(line1);
try std.testing.expect(std.mem.eql(u8, line1, "1B"));
_, _, root = try root.insert_chars(0, 1, "2", buffer.allocator, metrics());
buffer.update(root);
const line2 = try get_line(buffer, 0);
defer a.free(line2);
try std.testing.expect(std.mem.eql(u8, line2, "12B"));
_, _, root = try root.insert_chars(0, 2, "3", buffer.allocator, metrics());
buffer.update(root);
const line3 = try get_line(buffer, 0);
defer a.free(line3);
try std.testing.expect(std.mem.eql(u8, line3, "123B"));
_, _, root = try root.insert_chars(0, 3, "4", buffer.allocator, metrics());
buffer.update(root);
const line4 = try get_line(buffer, 0);
defer a.free(line4);
try std.testing.expect(std.mem.eql(u8, line4, "1234B"));
_, _, root = try root.insert_chars(0, 4, "5", buffer.allocator, metrics());
buffer.update(root);
const line5 = try get_line(buffer, 0);
defer a.free(line5);
try std.testing.expect(std.mem.eql(u8, line5, "12345B"));
_, _, root = try root.insert_chars(0, 5, "6", buffer.allocator, metrics());
buffer.update(root);
const line6 = try get_line(buffer, 0);
defer a.free(line6);
try std.testing.expect(std.mem.eql(u8, line6, "123456B"));
_, _, root = try root.insert_chars(0, 6, "7", buffer.allocator, metrics());
buffer.update(root);
const line7 = try get_line(buffer, 0);
defer a.free(line7);
try std.testing.expect(std.mem.eql(u8, line7, "1234567B"));
const line, const col, root = try buffer.root.insert_chars(0, 7, "8\n9", buffer.allocator, metrics());
buffer.update(root);
const line8 = try get_line(buffer, 0);
defer a.free(line8);
const line9 = try get_line(buffer, 1);
defer a.free(line9);
try std.testing.expect(std.mem.eql(u8, line8, "12345678"));
try std.testing.expect(std.mem.eql(u8, line9, "9B"));
try std.testing.expectEqual(line, 1);
try std.testing.expectEqual(col, 1);
}
test "get_from_pos" {
var eol_mode: Buffer.EolMode = .lf;
const buffer = try get_big_doc(&eol_mode);
defer buffer.deinit();
const lines = buffer.root.lines();
try std.testing.expectEqual(lines, 10001);
const line0 = try get_line(buffer, 0);
defer a.free(line0);
const line1 = try get_line(buffer, 1);
defer a.free(line1);
var result_buf: [1024]u8 = undefined;
const result1 = buffer.root.get_from_pos(.{ .row = 0, .col = 0 }, &result_buf, metrics());
try std.testing.expectEqualDeep(result1[0..line0.len], line0);
const result2 = buffer.root.get_from_pos(.{ .row = 1, .col = 5 }, &result_buf, metrics());
try std.testing.expectEqualDeep(result2[0 .. line1.len - 5], line1[5..]);
_, _, const root = try buffer.root.insert_chars(1, 3, " ", buffer.allocator, metrics());
buffer.update(root);
const result3 = buffer.root.get_from_pos(.{ .row = 1, .col = 5 }, &result_buf, metrics());
try std.testing.expectEqualDeep(result3[0 .. line1.len - 4], line1[4..]);
}
test "byte_offset_to_line_and_col" {
const doc: []const u8 =
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
\\All your
\\ropes
\\are belong to
\\us!
;
var eol_mode: Buffer.EolMode = .lf;
var sanitized: bool = false;
const buffer = try Buffer.create(a);
defer buffer.deinit();
buffer.update(try buffer.load_from_string(doc, &eol_mode, &sanitized));
try std.testing.expectEqual(Buffer.Cursor{ .row = 0, .col = 0 }, buffer.root.byte_offset_to_line_and_col(0, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 0, .col = 8 }, buffer.root.byte_offset_to_line_and_col(8, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 1, .col = 0 }, buffer.root.byte_offset_to_line_and_col(9, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 1, .col = 2 }, buffer.root.byte_offset_to_line_and_col(11, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 4, .col = 0 }, buffer.root.byte_offset_to_line_and_col(33, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 8, .col = 0 }, buffer.root.byte_offset_to_line_and_col(66, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 11, .col = 2 }, buffer.root.byte_offset_to_line_and_col(97, metrics(), eol_mode));
eol_mode = .crlf;
try std.testing.expectEqual(Buffer.Cursor{ .row = 0, .col = 0 }, buffer.root.byte_offset_to_line_and_col(0, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 0, .col = 8 }, buffer.root.byte_offset_to_line_and_col(8, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 0, .col = 8 }, buffer.root.byte_offset_to_line_and_col(9, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 1, .col = 0 }, buffer.root.byte_offset_to_line_and_col(10, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 1, .col = 2 }, buffer.root.byte_offset_to_line_and_col(12, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 4, .col = 0 }, buffer.root.byte_offset_to_line_and_col(37, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 8, .col = 0 }, buffer.root.byte_offset_to_line_and_col(74, metrics(), eol_mode));
try std.testing.expectEqual(Buffer.Cursor{ .row = 11, .col = 2 }, buffer.root.byte_offset_to_line_and_col(108, metrics(), eol_mode));
}