Add comprehensive test suite for manwhere: types, parser, display, search modules
This commit is contained in:
parent
34651156fb
commit
059c449ada
4 changed files with 758 additions and 47 deletions
236
tests/unittest/test_display.zig
Normal file
236
tests/unittest/test_display.zig
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
const std = @import("std");
|
||||
const types = @import("../../src/types.zig");
|
||||
const display = @import("../../src/display.zig");
|
||||
|
||||
test "displayManEntry - basic entry" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "ls",
|
||||
.section = "1",
|
||||
.description = "list directory contents",
|
||||
.path = null,
|
||||
};
|
||||
|
||||
// This test verifies the function doesn't panic
|
||||
// Actual output testing would require capturing stdout
|
||||
try display.displayManEntry(entry);
|
||||
}
|
||||
|
||||
test "displayManEntry - with path" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const entry = types.ManEntry{
|
||||
.name = "ls",
|
||||
.section = "1",
|
||||
.description = "list directory contents",
|
||||
.path = try allocator.dupe(u8, "/usr/share/man/man1/ls.1"),
|
||||
};
|
||||
defer if (entry.path) |path| allocator.free(path);
|
||||
|
||||
try display.displayManEntry(entry);
|
||||
}
|
||||
|
||||
test "displaySearchResults - non-verbose no sections" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
var entries = types.ManEntryList.init(allocator);
|
||||
defer {
|
||||
for (entries.items) |entry| {
|
||||
allocator.free(entry.name);
|
||||
allocator.free(entry.section);
|
||||
allocator.free(entry.description);
|
||||
}
|
||||
entries.deinit();
|
||||
}
|
||||
|
||||
try entries.append(types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "ls"),
|
||||
.section = try allocator.dupe(u8, "1"),
|
||||
.description = try allocator.dupe(u8, "list files"),
|
||||
.path = null,
|
||||
});
|
||||
|
||||
const config = types.SearchConfig{
|
||||
.keyword = "ls",
|
||||
.target_sections = null,
|
||||
.show_paths = false,
|
||||
.verbose = false,
|
||||
};
|
||||
|
||||
try display.displaySearchResults(entries, config, 100.0);
|
||||
}
|
||||
|
||||
test "displaySearchResults - non-verbose with sections" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
var entries = types.ManEntryList.init(allocator);
|
||||
defer {
|
||||
for (entries.items) |entry| {
|
||||
allocator.free(entry.name);
|
||||
allocator.free(entry.section);
|
||||
allocator.free(entry.description);
|
||||
}
|
||||
entries.deinit();
|
||||
}
|
||||
|
||||
const targets = &[_][]const u8{"1", "3"};
|
||||
|
||||
const config = types.SearchConfig{
|
||||
.keyword = "test",
|
||||
.target_sections = targets,
|
||||
.show_paths = false,
|
||||
.verbose = false,
|
||||
};
|
||||
|
||||
try display.displaySearchResults(entries, config, 50.0);
|
||||
}
|
||||
|
||||
test "displaySearchResults - verbose mode" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
var entries = types.ManEntryList.init(allocator);
|
||||
defer {
|
||||
for (entries.items) |entry| {
|
||||
allocator.free(entry.name);
|
||||
allocator.free(entry.section);
|
||||
allocator.free(entry.description);
|
||||
}
|
||||
entries.deinit();
|
||||
}
|
||||
|
||||
try entries.append(types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "cat"),
|
||||
.section = try allocator.dupe(u8, "1"),
|
||||
.description = try allocator.dupe(u8, "concatenate files"),
|
||||
.path = null,
|
||||
});
|
||||
|
||||
const config = types.SearchConfig{
|
||||
.keyword = "cat",
|
||||
.target_sections = null,
|
||||
.show_paths = false,
|
||||
.verbose = true,
|
||||
};
|
||||
|
||||
try display.displaySearchResults(entries, config, 250.5);
|
||||
}
|
||||
|
||||
test "displaySearchResults - multiple entries" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
var entries = types.ManEntryList.init(allocator);
|
||||
defer {
|
||||
for (entries.items) |entry| {
|
||||
allocator.free(entry.name);
|
||||
allocator.free(entry.section);
|
||||
allocator.free(entry.description);
|
||||
}
|
||||
entries.deinit();
|
||||
}
|
||||
|
||||
try entries.append(types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "ls"),
|
||||
.section = try allocator.dupe(u8, "1"),
|
||||
.description = try allocator.dupe(u8, "list files"),
|
||||
.path = null,
|
||||
});
|
||||
|
||||
try entries.append(types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "printf"),
|
||||
.section = try allocator.dupe(u8, "3"),
|
||||
.description = try allocator.dupe(u8, "format and print"),
|
||||
.path = null,
|
||||
});
|
||||
|
||||
try entries.append(types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "printf"),
|
||||
.section = try allocator.dupe(u8, "1"),
|
||||
.description = try allocator.dupe(u8, "format and print"),
|
||||
.path = null,
|
||||
});
|
||||
|
||||
const config = types.SearchConfig{
|
||||
.keyword = "printf",
|
||||
.target_sections = null,
|
||||
.show_paths = false,
|
||||
.verbose = false,
|
||||
};
|
||||
|
||||
try display.displaySearchResults(entries, config, 150.0);
|
||||
}
|
||||
|
||||
test "displaySearchStart - non-verbose" {
|
||||
const config = types.SearchConfig{
|
||||
.keyword = "test",
|
||||
.target_sections = null,
|
||||
.show_paths = false,
|
||||
.verbose = false,
|
||||
};
|
||||
|
||||
// Should not output anything in non-verbose mode
|
||||
try display.displaySearchStart(config);
|
||||
}
|
||||
|
||||
test "displaySearchStart - verbose no sections" {
|
||||
const config = types.SearchConfig{
|
||||
.keyword = "sleep",
|
||||
.target_sections = null,
|
||||
.show_paths = false,
|
||||
.verbose = true,
|
||||
};
|
||||
|
||||
try display.displaySearchStart(config);
|
||||
}
|
||||
|
||||
test "displaySearchStart - verbose with single section" {
|
||||
const targets = &[_][]const u8{"1"};
|
||||
|
||||
const config = types.SearchConfig{
|
||||
.keyword = "ls",
|
||||
.target_sections = targets,
|
||||
.show_paths = false,
|
||||
.verbose = true,
|
||||
};
|
||||
|
||||
try display.displaySearchStart(config);
|
||||
}
|
||||
|
||||
test "displaySearchStart - verbose with multiple sections" {
|
||||
const targets = &[_][]const u8{"1", "3", "8"};
|
||||
|
||||
const config = types.SearchConfig{
|
||||
.keyword = "admin",
|
||||
.target_sections = targets,
|
||||
.show_paths = false,
|
||||
.verbose = true,
|
||||
};
|
||||
|
||||
try display.displaySearchStart(config);
|
||||
}
|
||||
|
||||
test "displaySearchResults - empty results" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
var entries = types.ManEntryList.init(allocator);
|
||||
defer entries.deinit();
|
||||
|
||||
const config = types.SearchConfig{
|
||||
.keyword = "nonexistent12345",
|
||||
.target_sections = null,
|
||||
.show_paths = false,
|
||||
.verbose = true,
|
||||
};
|
||||
|
||||
try display.displaySearchResults(entries, config, 10.0);
|
||||
}
|
||||
196
tests/unittest/test_parser.zig
Normal file
196
tests/unittest/test_parser.zig
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
const std = @import("std");
|
||||
const parser = @import("../../src/parser.zig");
|
||||
const types = @import("../../src/types.zig");
|
||||
|
||||
test "parseArgs - basic keyword" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "sleep"};
|
||||
const config = try parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectEqualStrings("sleep", config.keyword);
|
||||
try std.testing.expect(config.target_sections == null);
|
||||
try std.testing.expect(!config.show_paths);
|
||||
try std.testing.expect(!config.verbose);
|
||||
}
|
||||
|
||||
test "parseArgs - with verbose flag" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "-v", "ls"};
|
||||
const config = try parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectEqualStrings("ls", config.keyword);
|
||||
try std.testing.expect(config.verbose);
|
||||
}
|
||||
|
||||
test "parseArgs - with long verbose flag" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "--verbose", "ls"};
|
||||
const config = try parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectEqualStrings("ls", config.keyword);
|
||||
try std.testing.expect(config.verbose);
|
||||
}
|
||||
|
||||
test "parseArgs - with paths flag" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "--paths", "printf"};
|
||||
const config = try parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectEqualStrings("printf", config.keyword);
|
||||
try std.testing.expect(config.show_paths);
|
||||
}
|
||||
|
||||
test "parseArgs - with section flag short" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "-s", "1", "ls"};
|
||||
const config = try parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectEqualStrings("ls", config.keyword);
|
||||
try std.testing.expect(config.target_sections != null);
|
||||
try std.testing.expectEqual(@as(usize, 1), config.target_sections.?.len);
|
||||
try std.testing.expectEqualStrings("1", config.target_sections.?[0]);
|
||||
}
|
||||
|
||||
test "parseArgs - with section flag long" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "--section", "3", "printf"};
|
||||
const config = try parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectEqualStrings("printf", config.keyword);
|
||||
try std.testing.expect(config.target_sections != null);
|
||||
try std.testing.expectEqualStrings("3", config.target_sections.?[0]);
|
||||
}
|
||||
|
||||
test "parseArgs - with multiple sections" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "-s", "1", "-s", "3", "test"};
|
||||
const config = try parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectEqualStrings("test", config.keyword);
|
||||
try std.testing.expect(config.target_sections != null);
|
||||
try std.testing.expectEqual(@as(usize, 2), config.target_sections.?.len);
|
||||
try std.testing.expectEqualStrings("1", config.target_sections.?[0]);
|
||||
try std.testing.expectEqualStrings("3", config.target_sections.?[1]);
|
||||
}
|
||||
|
||||
test "parseArgs - with section and verbose" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "-v", "-s", "3ssl", "ssl"};
|
||||
const config = try parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectEqualStrings("ssl", config.keyword);
|
||||
try std.testing.expect(config.verbose);
|
||||
try std.testing.expectEqualStrings("3ssl", config.target_sections.?[0]);
|
||||
}
|
||||
|
||||
test "parseArgs - error no keyword" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere"};
|
||||
const result = parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectError(error.NoKeyword, result);
|
||||
}
|
||||
|
||||
test "parseArgs - error invalid option" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "--invalid", "ls"};
|
||||
const result = parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectError(error.InvalidOption, result);
|
||||
}
|
||||
|
||||
test "parseArgs - error section without value" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "-s"};
|
||||
const result = parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectError(error.InvalidOption, result);
|
||||
}
|
||||
|
||||
test "parseArgs - error invalid section letter" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "-s", "abc", "ls"};
|
||||
const result = parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectError(error.InvalidSection, result);
|
||||
}
|
||||
|
||||
test "parseArgs - error section zero" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "-s", "0", "ls"};
|
||||
const result = parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectError(error.InvalidSection, result);
|
||||
}
|
||||
|
||||
test "parseArgs - error multiple keywords" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "ls", "cat"};
|
||||
const result = parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectError(error.MultipleKeywords, result);
|
||||
}
|
||||
|
||||
test "parseArgs - complex combination" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const args = &[_][:0]u8{"manwhere", "-v", "--paths", "-s", "1", "-s", "8", "admin"};
|
||||
const config = try parser.parseArgs(allocator, args);
|
||||
|
||||
try std.testing.expectEqualStrings("admin", config.keyword);
|
||||
try std.testing.expect(config.verbose);
|
||||
try std.testing.expect(config.show_paths);
|
||||
try std.testing.expectEqual(@as(usize, 2), config.target_sections.?.len);
|
||||
}
|
||||
|
||||
test "HELP_TEXT - contains usage info" {
|
||||
try std.testing.expect(std.mem.indexOf(u8, parser.HELP_TEXT, "Usage:") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, parser.HELP_TEXT, "OPTIONS:") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, parser.HELP_TEXT, "EXAMPLES:") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, parser.HELP_TEXT, "--verbose") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, parser.HELP_TEXT, "--section") != null);
|
||||
}
|
||||
|
|
@ -1,69 +1,108 @@
|
|||
const std = @import("std");
|
||||
const types = @import("../../src/types.zig"); // adjust path
|
||||
const ManSearcher = @import("../../src/searcher.zig").ManSearcher; // adjust path
|
||||
const types = @import("../../src/types.zig");
|
||||
|
||||
const error = error{
|
||||
FastFail,
|
||||
};
|
||||
const FastError = error{ FastFail, OutOfMemory };
|
||||
|
||||
test "searchManPagesFast returns dummy entries" {
|
||||
fn fakeFast() FastError!i32 {
|
||||
return error.FastFail;
|
||||
}
|
||||
|
||||
fn fakeOriginal() i32 {
|
||||
return 42;
|
||||
}
|
||||
|
||||
test "ManSearcher - basic initialization" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer gpa.deinit();
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
const stderr = std.io.getStdErr().writer();
|
||||
|
||||
// Fake ManSearcher with one dummy entry
|
||||
var searcher = ManSearcher.init(allocator);
|
||||
defer searcher.deinit();
|
||||
// ManSearcher would be tested here if exported from search module
|
||||
// For now, we test the types it uses
|
||||
var entries = types.ManEntryList.init(allocator);
|
||||
defer {
|
||||
for (entries.items) |entry| {
|
||||
allocator.free(entry.name);
|
||||
allocator.free(entry.section);
|
||||
allocator.free(entry.description);
|
||||
}
|
||||
entries.deinit();
|
||||
}
|
||||
|
||||
const dummy_entry = types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "printf"),
|
||||
try std.testing.expectEqual(@as(usize, 0), entries.items.len);
|
||||
}
|
||||
|
||||
test "ManEntry - full lifecycle" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const entry = types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "grep"),
|
||||
.section = try allocator.dupe(u8, "1"),
|
||||
.description = try allocator.dupe(u8, "format and print data"),
|
||||
.path = null,
|
||||
.description = try allocator.dupe(u8, "global regular expression print"),
|
||||
.path = try allocator.dupe(u8, "/usr/share/man/man1/grep.1.gz"),
|
||||
};
|
||||
try searcher.entries.append(dummy_entry);
|
||||
defer {
|
||||
allocator.free(entry.name);
|
||||
allocator.free(entry.section);
|
||||
allocator.free(entry.description);
|
||||
if (entry.path) |path| allocator.free(path);
|
||||
}
|
||||
|
||||
try std.testing.expect(searcher.entries.items.len == 1);
|
||||
try std.testing.expect(std.mem.eql(u8, searcher.entries.items[0].name, "printf"));
|
||||
try std.testing.expectEqualStrings("grep", entry.name);
|
||||
try std.testing.expectEqualStrings("1", entry.section);
|
||||
try std.testing.expectEqualStrings("global regular expression print", entry.description);
|
||||
try std.testing.expect(entry.path != null);
|
||||
try std.testing.expectEqualStrings("/usr/share/man/man1/grep.1.gz", entry.path.?);
|
||||
}
|
||||
|
||||
test "searchManPages fallback triggers on fast failure" {
|
||||
test "ManEntryList - append multiple" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer gpa.deinit();
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
const stderr = std.io.getStdErr().writer();
|
||||
|
||||
// Fake `searchManPagesFast` that always errors
|
||||
fn fakeFast(keyword: []const u8, target_section: ?[]const u8, show_paths: bool,
|
||||
verbose: bool, allocator: std.mem.Allocator, stderr: *std.io.Writer) !types.ManEntryList {
|
||||
return error.FastFail;
|
||||
var entries = types.ManEntryList.init(allocator);
|
||||
defer {
|
||||
for (entries.items) |entry| {
|
||||
allocator.free(entry.name);
|
||||
allocator.free(entry.section);
|
||||
allocator.free(entry.description);
|
||||
}
|
||||
entries.deinit();
|
||||
}
|
||||
|
||||
// Fake `searchManPagesOriginal` that returns a dummy entry
|
||||
fn fakeOriginal(keyword: []const u8, target_section: ?[]const u8, show_paths: bool,
|
||||
verbose: bool, allocator: std.mem.Allocator, stderr: *std.io.Writer) !types.ManEntryList {
|
||||
var list = types.ManEntryList.init(allocator);
|
||||
defer list.deinit();
|
||||
try entries.append(types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "ls"),
|
||||
.section = try allocator.dupe(u8, "1"),
|
||||
.description = try allocator.dupe(u8, "list"),
|
||||
.path = null,
|
||||
});
|
||||
|
||||
const dummy = types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "ls"),
|
||||
.section = try allocator.dupe(u8, "1"),
|
||||
.description = try allocator.dupe(u8, "list directory contents"),
|
||||
.path = null,
|
||||
};
|
||||
try list.append(dummy);
|
||||
try entries.append(types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "cat"),
|
||||
.section = try allocator.dupe(u8, "1"),
|
||||
.description = try allocator.dupe(u8, "concatenate"),
|
||||
.path = null,
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
try entries.append(types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "grep"),
|
||||
.section = try allocator.dupe(u8, "1"),
|
||||
.description = try allocator.dupe(u8, "search"),
|
||||
.path = null,
|
||||
});
|
||||
|
||||
// Mimic the fallback logic from your main function
|
||||
const result = fakeFast("ls", null, false, true, allocator, stderr) catch |err| {
|
||||
try std.testing.expect(err == error.FastFail);
|
||||
return fakeOriginal("ls", null, false, true, allocator, stderr);
|
||||
};
|
||||
|
||||
try std.testing.expect(result.items.len == 1);
|
||||
try std.testing.expect(std.mem.eql(u8, result.items[0].name, "ls"));
|
||||
try std.testing.expectEqual(@as(usize, 3), entries.items.len);
|
||||
try std.testing.expectEqualStrings("ls", entries.items[0].name);
|
||||
try std.testing.expectEqualStrings("cat", entries.items[1].name);
|
||||
try std.testing.expectEqualStrings("grep", entries.items[2].name);
|
||||
}
|
||||
|
||||
test "fallback error handling pattern" {
|
||||
const result = fakeFast() catch |err| {
|
||||
try std.testing.expect(err == error.FastFail);
|
||||
return fakeOriginal();
|
||||
};
|
||||
|
||||
try std.testing.expectEqual(@as(i32, 42), result);
|
||||
}
|
||||
|
|
|
|||
240
tests/unittest/test_types.zig
Normal file
240
tests/unittest/test_types.zig
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
const std = @import("std");
|
||||
const types = @import("../../src/types.zig");
|
||||
|
||||
test "ManEntry.getSectionMarker - commands" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "ls",
|
||||
.section = "1",
|
||||
.description = "list directory contents",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[*] Command", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - syscalls" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "open",
|
||||
.section = "2",
|
||||
.description = "open file",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[S] Syscall", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - C library" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "printf",
|
||||
.section = "3",
|
||||
.description = "format and print data",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[L] C Library", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - OpenSSL library" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "SSL_new",
|
||||
.section = "3ssl",
|
||||
.description = "create SSL structure",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[L] OpenSSL", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - POSIX library" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "pthread_create",
|
||||
.section = "3p",
|
||||
.description = "create thread",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[L] POSIX", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - device files" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "null",
|
||||
.section = "4",
|
||||
.description = "null device",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[D] Device", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - file formats" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "passwd",
|
||||
.section = "5",
|
||||
.description = "password file format",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[F] Format", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - games" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "tetris",
|
||||
.section = "6",
|
||||
.description = "Tetris game",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[G] Game", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - misc" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "ascii",
|
||||
.section = "7",
|
||||
.description = "ASCII table",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[M] Misc", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - admin" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "useradd",
|
||||
.section = "8",
|
||||
.description = "add user",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[A] Admin", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - kernel" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "kmalloc",
|
||||
.section = "9",
|
||||
.description = "kernel memory alloc",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[K] Kernel", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - unknown" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "unknown",
|
||||
.section = "99",
|
||||
.description = "unknown section",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[?] Unknown", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.getSectionMarker - empty section" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "test",
|
||||
.section = "",
|
||||
.description = "test",
|
||||
.path = null,
|
||||
};
|
||||
const marker = entry.getSectionMarker();
|
||||
try std.testing.expectEqualStrings("[?] Unknown", marker);
|
||||
}
|
||||
|
||||
test "ManEntry.matchesSection - no target sections" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "ls",
|
||||
.section = "1",
|
||||
.description = "list",
|
||||
.path = null,
|
||||
};
|
||||
try std.testing.expect(entry.matchesSection(null));
|
||||
}
|
||||
|
||||
test "ManEntry.matchesSection - exact match" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "ls",
|
||||
.section = "1",
|
||||
.description = "list",
|
||||
.path = null,
|
||||
};
|
||||
const targets = &[_][]const u8{"1"};
|
||||
try std.testing.expect(entry.matchesSection(targets));
|
||||
}
|
||||
|
||||
test "ManEntry.matchesSection - prefix match" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "SSL_new",
|
||||
.section = "3ssl",
|
||||
.description = "SSL",
|
||||
.path = null,
|
||||
};
|
||||
const targets = &[_][]const u8{"3"};
|
||||
try std.testing.expect(entry.matchesSection(targets));
|
||||
}
|
||||
|
||||
test "ManEntry.matchesSection - no match" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "ls",
|
||||
.section = "1",
|
||||
.description = "list",
|
||||
.path = null,
|
||||
};
|
||||
const targets = &[_][]const u8{"3"};
|
||||
try std.testing.expect(!entry.matchesSection(targets));
|
||||
}
|
||||
|
||||
test "ManEntry.matchesSection - multiple targets" {
|
||||
const entry = types.ManEntry{
|
||||
.name = "printf",
|
||||
.section = "3",
|
||||
.description = "print",
|
||||
.path = null,
|
||||
};
|
||||
const targets = &[_][]const u8{"1", "3", "8"};
|
||||
try std.testing.expect(entry.matchesSection(targets));
|
||||
}
|
||||
|
||||
test "ManEntryList - basic operations" {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
var list = types.ManEntryList.init(allocator);
|
||||
defer {
|
||||
for (list.items) |entry| {
|
||||
allocator.free(entry.name);
|
||||
allocator.free(entry.section);
|
||||
allocator.free(entry.description);
|
||||
if (entry.path) |path| allocator.free(path);
|
||||
}
|
||||
list.deinit();
|
||||
}
|
||||
|
||||
try list.append(types.ManEntry{
|
||||
.name = try allocator.dupe(u8, "ls"),
|
||||
.section = try allocator.dupe(u8, "1"),
|
||||
.description = try allocator.dupe(u8, "list"),
|
||||
.path = null,
|
||||
});
|
||||
|
||||
try std.testing.expectEqual(@as(usize, 1), list.items.len);
|
||||
try std.testing.expectEqualStrings("ls", list.items[0].name);
|
||||
}
|
||||
|
||||
test "SearchConfig - struct creation" {
|
||||
const config = types.SearchConfig{
|
||||
.keyword = "test",
|
||||
.target_sections = null,
|
||||
.show_paths = false,
|
||||
.verbose = true,
|
||||
};
|
||||
|
||||
try std.testing.expectEqualStrings("test", config.keyword);
|
||||
try std.testing.expect(config.target_sections == null);
|
||||
try std.testing.expect(!config.show_paths);
|
||||
try std.testing.expect(config.verbose);
|
||||
}
|
||||
Loading…
Reference in a new issue