const std = @import("std"); const parsing = @import("parsing"); const ArgumentRegistry = @import("ArgumentRegistry").ArgumentRegistry; const metadata = @import("metadata"); const ArgumentType = @import("ArgumentType").ArgumentType; // Test struct for parsing const SimpleConfig = struct { verbose: bool = false, output: []const u8 = "default.txt", count: u32 = 10, pub const meta = .{ .verbose = .{ .short = 'v', .help = "Verbose output" }, .output = .{ .short = 'o', .help = "Output file" }, .count = .{ .short = 'c', .help = "Item count" }, }; }; test "parse long boolean flag" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "--verbose" }; try parsing.parseArgv(®istry, argv); const value = registry.getParsedValue("verbose"); try std.testing.expect(value != null); try std.testing.expectEqual(true, value.?.bool); } test "parse short boolean flag" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "-v" }; try parsing.parseArgv(®istry, argv); const value = registry.getParsedValue("verbose"); try std.testing.expect(value != null); try std.testing.expectEqual(true, value.?.bool); } test "parse long flag with equals value" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "--output=myfile.txt" }; try parsing.parseArgv(®istry, argv); const value = registry.getParsedValue("output"); try std.testing.expect(value != null); try std.testing.expectEqualStrings("myfile.txt", value.?.string); } test "parse long flag with space-separated value" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "--output", "myfile.txt" }; try parsing.parseArgv(®istry, argv); const value = registry.getParsedValue("output"); try std.testing.expect(value != null); try std.testing.expectEqualStrings("myfile.txt", value.?.string); } test "parse short flag with value" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "-o", "myfile.txt" }; try parsing.parseArgv(®istry, argv); const value = registry.getParsedValue("output"); try std.testing.expect(value != null); try std.testing.expectEqualStrings("myfile.txt", value.?.string); } test "parse integer value" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "--count=42" }; try parsing.parseArgv(®istry, argv); const value = registry.getParsedValue("count"); try std.testing.expect(value != null); try std.testing.expectEqual(@as(u32, 42), value.?.u32); } test "parse multiple arguments" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "-v", "--output", "test.txt", "--count=99" }; try parsing.parseArgv(®istry, argv); const verbose = registry.getParsedValue("verbose"); const output = registry.getParsedValue("output"); const count = registry.getParsedValue("count"); try std.testing.expect(verbose != null); try std.testing.expectEqual(true, verbose.?.bool); try std.testing.expect(output != null); try std.testing.expectEqualStrings("test.txt", output.?.string); try std.testing.expect(count != null); try std.testing.expectEqual(@as(u32, 99), count.?.u32); } test "parse multi-flag short form" { const MultiFlag = struct { verbose: bool = false, debug: bool = false, quiet: bool = false, pub const meta = .{ .verbose = .{ .short = 'v' }, .debug = .{ .short = 'd' }, .quiet = .{ .short = 'q' }, }; }; var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(MultiFlag, "test"); const argv = &[_][:0]const u8{ "program", "-vdq" }; try parsing.parseArgv(®istry, argv); const verbose = registry.getParsedValue("verbose"); const debug = registry.getParsedValue("debug"); const quiet = registry.getParsedValue("quiet"); try std.testing.expect(verbose != null); try std.testing.expectEqual(true, verbose.?.bool); try std.testing.expect(debug != null); try std.testing.expectEqual(true, debug.?.bool); try std.testing.expect(quiet != null); try std.testing.expectEqual(true, quiet.?.bool); } test "parse help flag" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "--help" }; try parsing.parseArgv(®istry, argv); try std.testing.expect(registry.isHelpRequested()); } test "parse short help flag" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "-h" }; try parsing.parseArgv(®istry, argv); try std.testing.expect(registry.isHelpRequested()); } test "unknown argument error" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "--unknown" }; const result = parsing.parseArgv(®istry, argv); try std.testing.expectError(error.UnknownArgument, result); } test "missing value error" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "--output" }; const result = parsing.parseArgv(®istry, argv); try std.testing.expectError(error.MissingArgumentValue, result); } test "populate struct with defaults" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{"program"}; try parsing.parseArgv(®istry, argv); const config = try parsing.populateStruct(SimpleConfig, ®istry, std.testing.allocator); try std.testing.expectEqual(false, config.verbose); try std.testing.expectEqualStrings("default.txt", config.output); try std.testing.expectEqual(@as(u32, 10), config.count); } test "populate struct with parsed values" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "-v", "--output=result.txt", "--count=5" }; try parsing.parseArgv(®istry, argv); const config = try parsing.populateStruct(SimpleConfig, ®istry, std.testing.allocator); try std.testing.expectEqual(true, config.verbose); try std.testing.expectEqualStrings("result.txt", config.output); try std.testing.expectEqual(@as(u32, 5), config.count); } test "populate struct with mixed defaults and values" { var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(SimpleConfig, "test"); const argv = &[_][:0]const u8{ "program", "-v" }; try parsing.parseArgv(®istry, argv); const config = try parsing.populateStruct(SimpleConfig, ®istry, std.testing.allocator); try std.testing.expectEqual(true, config.verbose); try std.testing.expectEqualStrings("default.txt", config.output); try std.testing.expectEqual(@as(u32, 10), config.count); } test "parse enum values" { const Mode = enum { fast, slow, medium }; const EnumConfig = struct { mode: Mode = .medium, pub const meta = .{ .mode = .{ .help = "Processing mode" }, }; }; var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(EnumConfig, "test"); const argv = &[_][:0]const u8{ "program", "--mode=fast" }; try parsing.parseArgv(®istry, argv); const config = try parsing.populateStruct(EnumConfig, ®istry, std.testing.allocator); try std.testing.expectEqual(Mode.fast, config.mode); } test "parse optional types" { const OptionalConfig = struct { name: ?[]const u8 = null, age: ?u32 = null, pub const meta = .{ .name = .{ .help = "Optional name" }, .age = .{ .help = "Optional age" }, }; }; var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(OptionalConfig, "test"); // Test with values { const argv = &[_][:0]const u8{ "program", "--name=Alice", "--age=30" }; try parsing.parseArgv(®istry, argv); const config = try parsing.populateStruct(OptionalConfig, ®istry, std.testing.allocator); try std.testing.expect(config.name != null); try std.testing.expectEqualStrings("Alice", config.name.?); try std.testing.expect(config.age != null); try std.testing.expectEqual(@as(u32, 30), config.age.?); } } test "parse string list with comma separation" { const ListConfig = struct { files: []const []const u8 = &[_][]const u8{}, pub const meta = .{ .files = .{ .help = "List of files" }, }; }; var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(ListConfig, "test"); const argv = &[_][:0]const u8{ "program", "--files=a.txt,b.txt,c.txt" }; try parsing.parseArgv(®istry, argv); const value = registry.getParsedValue("files"); try std.testing.expect(value != null); try std.testing.expectEqual(@as(usize, 3), value.?.string_list.len); try std.testing.expectEqualStrings("a.txt", value.?.string_list[0]); try std.testing.expectEqualStrings("b.txt", value.?.string_list[1]); try std.testing.expectEqualStrings("c.txt", value.?.string_list[2]); } test "parse string list with repeated arguments" { const ListConfig = struct { files: []const []const u8 = &[_][]const u8{}, pub const meta = .{ .files = .{ .help = "List of files" }, }; }; var registry = ArgumentRegistry.init(std.testing.allocator); defer registry.deinit(); try registry.registerMetadata(ListConfig, "test"); const argv = &[_][:0]const u8{ "program", "--files=a.txt", "--files=b.txt", "--files=c.txt" }; try parsing.parseArgv(®istry, argv); const value = registry.getParsedValue("files"); try std.testing.expect(value != null); try std.testing.expectEqual(@as(usize, 3), value.?.string_list.len); try std.testing.expectEqualStrings("a.txt", value.?.string_list[0]); try std.testing.expectEqualStrings("b.txt", value.?.string_list[1]); try std.testing.expectEqualStrings("c.txt", value.?.string_list[2]); }