Add test for dumpInput and fix memory leak

This commit is contained in:
Paul Campbell 2021-12-30 19:34:51 +00:00
parent 757508fb7e
commit a52156a686

View file

@ -22,15 +22,14 @@ pub fn main() anyerror!void {
var fba = heap.FixedBufferAllocator.init(&buffer); var fba = heap.FixedBufferAllocator.init(&buffer);
const allocator = fba.allocator(); const allocator = fba.allocator();
const config: Config = parseArgs(allocator) catch |err| switch (err) { const config: Config = parseArgs() catch |err| switch (err) {
error.EarlyExit => return, error.EarlyExit => return,
else => @panic("Unknown error"), else => @panic("Unknown error"),
}; };
defer config.deinit(); defer config.deinit();
const stdout = io.getStdOut(); const stdout = io.getStdOut();
if (config.file) |fileName| { if (config.file) |file| {
const file = try fs.cwd().openFile(fileName, .{ .read = true, .write = false });
try dumpInput(config, file, stdout, allocator); try dumpInput(config, file, stdout, allocator);
} else { } else {
const stdin = io.getStdIn(); const stdin = io.getStdIn();
@ -44,17 +43,16 @@ const errors = error {
const Config = struct { const Config = struct {
lines: u32, lines: u32,
file: ?[]const u8, file: ?fs.File,
allocator: mem.Allocator,
pub fn deinit(self: @This()) void { pub fn deinit(self: @This()) void {
if (self.file) |f| { if (self.file) |f| {
self.allocator.free(f); f.close();
} }
} }
}; };
fn parseArgs(allocator: mem.Allocator) !Config { fn parseArgs() !Config {
const params = comptime [_]clap.Param(clap.Help) { const params = comptime [_]clap.Param(clap.Help) {
clap.parseParam("<N> The number of lines to skip") catch unreachable, clap.parseParam("<N> The number of lines to skip") catch unreachable,
clap.parseParam("[<FILE>] The file to read or stdin if not given") catch unreachable, clap.parseParam("[<FILE>] The file to read or stdin if not given") catch unreachable,
@ -79,7 +77,7 @@ fn parseArgs(allocator: mem.Allocator) !Config {
} }
var n: u32 = 0; var n: u32 = 0;
var file: ?[]const u8 = null; var file: ?fs.File = null;
if (args.positionals().len == 0) { if (args.positionals().len == 0) {
std.debug.print("Number of lines to skip not given. Try skip --help\n", .{}); std.debug.print("Number of lines to skip not given. Try skip --help\n", .{});
return error.EarlyExit; return error.EarlyExit;
@ -88,12 +86,12 @@ fn parseArgs(allocator: mem.Allocator) !Config {
n = try fmt.parseInt(u32, args.positionals()[0], 10); n = try fmt.parseInt(u32, args.positionals()[0], 10);
} }
if (args.positionals().len >= 2) { if (args.positionals().len >= 2) {
file = try allocator.dupe(u8, args.positionals()[1]); const filename = args.positionals()[1];
file = try fs.cwd().openFile(filename, .{ .read = true, .write = false });
} }
return Config { return Config {
.lines = n, .lines = n,
.file = file, .file = file,
.allocator = allocator,
}; };
} }
@ -105,11 +103,43 @@ fn dumpInput(config: Config, in: fs.File, out: fs.File, allocator: mem.Allocator
var it: LineIterator = lineIterator(reader, allocator); var it: LineIterator = lineIterator(reader, allocator);
var c: u32 = 0; var c: u32 = 0;
while (c < config.lines) : (c += 1) { while (c < config.lines) : (c += 1) {
_ = it.next() orelse return; const line = it.next();
if (line) |memory| {
allocator.free(memory);
} else return;
} }
try pumpIterator(&it, writer, allocator); try pumpIterator(&it, writer, allocator);
} }
test "dumpInput" {
const file = try fs.cwd().openFile("src/test/two-lines.txt", .{ .read = true, .write = false });
defer file.close();
const tempFile = "zig-cache/test.txt";
const output = try fs.cwd().createFile(tempFile, .{});
defer output.close();
const config = Config{
.lines = 1,
.file = file,
};
try dumpInput(config, file, output, testing.allocator);
const result = try fs.cwd().openFile(tempFile, .{ .read = true });
defer result.close();
var rit = lineIterator(result.reader(), testing.allocator);
const line1 = rit.next().?;
defer testing.allocator.free(line1);
try testing.expectEqualStrings("line 2", line1);
const eof = rit.next();
try testing.expect(eof == null);
}
fn pumpIterator(it: *LineIterator, writer: fs.File.Writer, allocator: mem.Allocator) !void { fn pumpIterator(it: *LineIterator, writer: fs.File.Writer, allocator: mem.Allocator) !void {
while (it.next()) |line| { while (it.next()) |line| {
defer allocator.free(line); defer allocator.free(line);