Generated Documentation

This commit is contained in:
penify-dev[bot] 2025-04-26 20:13:18 +00:00
parent 3f96e9d97e
commit db21c59299
3 changed files with 309 additions and 13 deletions

View file

@ -20,6 +20,10 @@ import (
"testing"
)
// getCommand returns a Command object configured based on the provided PositionalArgs and a boolean indicating whether to include valid arguments.
// If withValid is true, the returned command will have ValidArgs set to ["one", "two", "three"].
// The Run field of the Command is initialized to emptyRun, which does nothing when called.
// Args determines what arguments are valid for this command.
func getCommand(args PositionalArgs, withValid bool) *Command {
c := &Command{
Use: "c",
@ -32,6 +36,12 @@ func getCommand(args PositionalArgs, withValid bool) *Command {
return c
}
// expectSuccess checks if the provided output and error are as expected. If output is not empty, it logs an error. If there is an error, it fails the test with a fatal error.
// Parameters:
// - output: The string output to check.
// - err: The error to check.
// - t: The testing.T instance used for logging errors and failing tests.
// Returns: no value.
func expectSuccess(output string, err error, t *testing.T) {
if output != "" {
t.Errorf("Unexpected output: %v", output)
@ -41,6 +51,9 @@ func expectSuccess(output string, err error, t *testing.T) {
}
}
// validOnlyWithInvalidArgs checks if the given error is not nil and has the expected error message.
// It takes an error and a testing.T instance as parameters. If the error is nil, it calls t.Fatal with a message indicating that an error was expected.
// It then compares the actual error message with the expected one and calls t.Errorf if they do not match.
func validOnlyWithInvalidArgs(err error, t *testing.T) {
if err == nil {
t.Fatal("Expected an error")
@ -52,6 +65,13 @@ func validOnlyWithInvalidArgs(err error, t *testing.T) {
}
}
// noArgsWithArgs checks if an error is returned when calling a function with no arguments and the specified argument.
// It asserts that the error message matches the expected value for the given command.
// If no error is returned, it calls t.Fatal with an appropriate message.
// Parameters:
// - err: The error to check.
// - t: A testing.T instance used for assertions.
// - arg: The argument passed to the function that triggered the error.
func noArgsWithArgs(err error, t *testing.T, arg string) {
if err == nil {
t.Fatal("Expected an error")
@ -63,6 +83,14 @@ func noArgsWithArgs(err error, t *testing.T, arg string) {
}
}
// minimumNArgsWithLessArgs checks if the provided error is due to a function requiring at least two arguments but receiving fewer.
//
// Parameters:
// - err: The error returned by the function.
// - t: A testing.T instance used for assertions.
//
// This function asserts that the error message matches the expected "requires at least 2 arg(s), only received 1".
// If the assertion fails, it calls t.Fatalf with a formatted error message.
func minimumNArgsWithLessArgs(err error, t *testing.T) {
if err == nil {
t.Fatal("Expected an error")
@ -74,6 +102,14 @@ func minimumNArgsWithLessArgs(err error, t *testing.T) {
}
}
// maximumNArgsWithMoreArgs checks if the error is related to accepting more arguments than allowed.
// It expects an error and a testing.T instance. If no error is received, it fails the test with a fatal error.
// It then compares the expected error message with the actual one; if they don't match, it fails the test with a fatal error.
// Parameters:
// - err: The error to be checked.
// - t: The testing.T instance used for assertions and logging.
// Returns:
// - No return value.
func maximumNArgsWithMoreArgs(err error, t *testing.T) {
if err == nil {
t.Fatal("Expected an error")
@ -85,6 +121,17 @@ func maximumNArgsWithMoreArgs(err error, t *testing.T) {
}
}
// exactArgsWithInvalidCount checks if the given error indicates that a function expects exactly two arguments but received three.
//
// Parameters:
// - err: The error to check.
// - t: The testing.T instance used for assertions.
//
// Returns:
// This function does not return any value.
//
// Errors:
// - If err is nil, this function calls t.Fatal with an "Expected an error" message.
func exactArgsWithInvalidCount(err error, t *testing.T) {
if err == nil {
t.Fatal("Expected an error")
@ -96,6 +143,9 @@ func exactArgsWithInvalidCount(err error, t *testing.T) {
}
}
// rangeArgsWithInvalidCount checks if the provided error is related to invalid argument count.
// It expects an error indicating that a function accepts between 2 and 4 arguments,
// but received only one. If the error does not match this expectation or if there is no error, it will call t.Fatal.
func rangeArgsWithInvalidCount(err error, t *testing.T) {
if err == nil {
t.Fatal("Expected an error")
@ -109,30 +159,40 @@ func rangeArgsWithInvalidCount(err error, t *testing.T) {
// NoArgs
// TestNoArgs tests the behavior of the command when no arguments are provided. It verifies that the command executes successfully without any errors.
func TestNoArgs(t *testing.T) {
c := getCommand(NoArgs, false)
output, err := executeCommand(c)
expectSuccess(output, err, t)
}
// TestNoArgs_WithArgs tests the command execution when it expects no arguments but receives one.
// It creates a command with NoArgs flag and executes it with an argument "one".
// The function checks if the error returned is as expected for a no-arguments command receiving an argument.
func TestNoArgs_WithArgs(t *testing.T) {
c := getCommand(NoArgs, false)
_, err := executeCommand(c, "one")
noArgsWithArgs(err, t, "one")
}
// TestNoArgs_WithValid_WithArgs tests the behavior of a command with no arguments when provided with valid and unexpected arguments.
// It checks if the command execution returns an error for an unexpected argument.
func TestNoArgs_WithValid_WithArgs(t *testing.T) {
c := getCommand(NoArgs, true)
_, err := executeCommand(c, "one")
noArgsWithArgs(err, t, "one")
}
// TestNoArgs_WithValid_WithInvalidArgs tests the NoArgs command with valid and invalid arguments.
func TestNoArgs_WithValid_WithInvalidArgs(t *testing.T) {
c := getCommand(NoArgs, true)
_, err := executeCommand(c, "a")
noArgsWithArgs(err, t, "a")
}
// TestNoArgs_WithValidOnly_WithInvalidArgs tests the execution of a command with both valid and invalid arguments when OnlyValidArgs and NoArgs matchers are used.
// It asserts that executing the command with an argument results in an error as expected.
// The test uses the getCommand function to create a command with specific matchers and then checks if the error returned by executeCommand is valid using validOnlyWithInvalidArgs.
func TestNoArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
c := getCommand(MatchAll(OnlyValidArgs, NoArgs), true)
_, err := executeCommand(c, "a")
@ -141,12 +201,15 @@ func TestNoArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
// OnlyValidArgs
// TestOnlyValidArgs tests the command with valid arguments.
func TestOnlyValidArgs(t *testing.T) {
c := getCommand(OnlyValidArgs, true)
output, err := executeCommand(c, "one", "two")
expectSuccess(output, err, t)
}
// TestOnlyValidArgs_WithInvalidArgs tests the behavior of the command when invalid arguments are provided.
// It verifies that an error is returned when executing the command with one invalid argument.
func TestOnlyValidArgs_WithInvalidArgs(t *testing.T) {
c := getCommand(OnlyValidArgs, true)
_, err := executeCommand(c, "a")
@ -155,24 +218,34 @@ func TestOnlyValidArgs_WithInvalidArgs(t *testing.T) {
// ArbitraryArgs
// TestArbitraryArgs tests the execution of a command with arbitrary arguments.
// It creates a command with the ArbitraryArgs flag set and executes it with two arguments "a" and "b".
// It then checks if the command executed successfully by expecting no errors and a successful output.
func TestArbitraryArgs(t *testing.T) {
c := getCommand(ArbitraryArgs, false)
output, err := executeCommand(c, "a", "b")
expectSuccess(output, err, t)
}
// TestArbitraryArgs_WithValid tests the execution of a command with arbitrary arguments when they are valid.
// It verifies that the command executes successfully and returns expected output without errors.
func TestArbitraryArgs_WithValid(t *testing.T) {
c := getCommand(ArbitraryArgs, true)
output, err := executeCommand(c, "one", "two")
expectSuccess(output, err, t)
}
// TestArbitraryArgs_WithValid_WithInvalidArgs tests the execution of a command with arbitrary arguments, including both valid and invalid cases.
// It verifies that the command executes successfully with valid arguments and handles errors for invalid arguments correctly.
// The function takes a testing.T instance to run assertions and checks the output and error of the executed command.
func TestArbitraryArgs_WithValid_WithInvalidArgs(t *testing.T) {
c := getCommand(ArbitraryArgs, true)
output, err := executeCommand(c, "a")
expectSuccess(output, err, t)
}
// TestArbitraryArgs_WithValidOnly_WithInvalidArgs tests the command execution when only valid arguments are provided along with arbitrary arguments.
// It expects an error when invalid arguments are present during execution.
func TestArbitraryArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
c := getCommand(MatchAll(OnlyValidArgs, ArbitraryArgs), true)
_, err := executeCommand(c, "a")
@ -181,48 +254,61 @@ func TestArbitraryArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
// MinimumNArgs
// TestMinimumNArgs tests the MinimumNArgs command with a minimum of 2 arguments.
func TestMinimumNArgs(t *testing.T) {
c := getCommand(MinimumNArgs(2), false)
output, err := executeCommand(c, "a", "b", "c")
expectSuccess(output, err, t)
}
// TestMinimumNArgs_WithValid tests the execution of a command with at least two arguments.
// It asserts that the command executes successfully when provided with valid arguments.
func TestMinimumNArgs_WithValid(t *testing.T) {
c := getCommand(MinimumNArgs(2), true)
output, err := executeCommand(c, "one", "three")
expectSuccess(output, err, t)
}
// TestMinimumNArgs_WithValid checks that the MinimumNArgs command works correctly with valid arguments.
// It tests both a successful execution and an error case when invalid arguments are provided.
func TestMinimumNArgs_WithValid__WithInvalidArgs(t *testing.T) {
c := getCommand(MinimumNArgs(2), true)
output, err := executeCommand(c, "a", "b")
expectSuccess(output, err, t)
}
// TestMinimumNArgs_WithValidOnly_WithInvalidArgs tests the behavior of the command when it expects a minimum number of arguments (2) and only valid args, but receives invalid ones.
// It validates that the command execution fails with an error indicating invalid arguments.
func TestMinimumNArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
c := getCommand(MatchAll(OnlyValidArgs, MinimumNArgs(2)), true)
_, err := executeCommand(c, "a", "b")
validOnlyWithInvalidArgs(err, t)
}
// TestMinimumNArgs_WithLessArgs tests the MinimumNArgs function when provided with fewer arguments than expected.
func TestMinimumNArgs_WithLessArgs(t *testing.T) {
c := getCommand(MinimumNArgs(2), false)
_, err := executeCommand(c, "a")
minimumNArgsWithLessArgs(err, t)
}
// TestMinimumNArgs_WithLessArgs_WithValid tests the MinimumNArgs function with fewer arguments than expected.
func TestMinimumNArgs_WithLessArgs_WithValid(t *testing.T) {
c := getCommand(MinimumNArgs(2), true)
_, err := executeCommand(c, "one")
minimumNArgsWithLessArgs(err, t)
}
// TestMinimumNArgs_WithLessArgs_WithValid_WithInvalidArgs tests the MinimumNArgs validator with fewer arguments than expected.
// It verifies both valid and invalid cases to ensure proper error handling.
func TestMinimumNArgs_WithLessArgs_WithValid_WithInvalidArgs(t *testing.T) {
c := getCommand(MinimumNArgs(2), true)
_, err := executeCommand(c, "a")
minimumNArgsWithLessArgs(err, t)
}
// TestMinimumNArgs_WithLessArgs_WithValidOnly_WithInvalidArgs tests the behavior of a command when executed with less than the minimum required arguments and only valid args are allowed.
// It verifies that the command returns an error indicating invalid argument count when called with insufficient arguments.
func TestMinimumNArgs_WithLessArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
c := getCommand(MatchAll(OnlyValidArgs, MinimumNArgs(2)), true)
_, err := executeCommand(c, "a")
@ -231,48 +317,76 @@ func TestMinimumNArgs_WithLessArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
// MaximumNArgs
// TestMaximumNArgs tests the execution of a command with a maximum number of arguments.
// It verifies that the command is executed successfully with up to 3 arguments and fails when more than 3 arguments are provided.
func TestMaximumNArgs(t *testing.T) {
c := getCommand(MaximumNArgs(3), false)
output, err := executeCommand(c, "a", "b")
expectSuccess(output, err, t)
}
// TestMaximumNArgs_WithValid tests the functionality of the MaximumNArgs function with valid arguments.
// It verifies that the command is executed successfully when provided with two arguments.
func TestMaximumNArgs_WithValid(t *testing.T) {
c := getCommand(MaximumNArgs(2), true)
output, err := executeCommand(c, "one", "three")
expectSuccess(output, err, t)
}
// TestMaximumNArgs_WithValid_WithInvalidArgs tests the behavior of the MaximumNArgs function with both valid and invalid arguments.
// It ensures that the function correctly handles different sets of input arguments.
func TestMaximumNArgs_WithValid_WithInvalidArgs(t *testing.T) {
c := getCommand(MaximumNArgs(2), true)
output, err := executeCommand(c, "a", "b")
expectSuccess(output, err, t)
}
// TestMaximumNArgs_WithValidOnly_WithInvalidArgs tests the behavior of a command with the MatchAll validator, OnlyValidArgs option, and MaximumNArgs set to 2 when provided with both valid and invalid arguments. It asserts that the command execution results in an error indicating the presence of invalid arguments.
// Parameters:
// - t: A pointer to a testing.T instance for running tests.
// Returns:
// None
// Errors:
// - An error if the command does not return an error when it should, or if the error message does not indicate the presence of invalid arguments.
func TestMaximumNArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
c := getCommand(MatchAll(OnlyValidArgs, MaximumNArgs(2)), true)
_, err := executeCommand(c, "a", "b")
validOnlyWithInvalidArgs(err, t)
}
// TestMaximumNArgs_WithMoreArgs tests the behavior of the MaximumNArgs constraint when provided with more arguments than allowed. It checks if the resulting command, when executed, returns an error indicating too many arguments.
// getCommand creates and returns a test command with the given argument constraint and allowStdin flag.
// executeCommand executes the given command with the specified arguments and returns the result and any error encountered.
// maximumNArgsWithMoreArgs asserts that the provided error indicates the use of more arguments than allowed for MaximumNArgs constraints.
func TestMaximumNArgs_WithMoreArgs(t *testing.T) {
c := getCommand(MaximumNArgs(2), false)
_, err := executeCommand(c, "a", "b", "c")
maximumNArgsWithMoreArgs(err, t)
}
// TestMaximumNArgs_WithMoreArgs_WithValid tests the execution of a command with more arguments than allowed by MaximumNArgs.
// It verifies that an error is returned when executing the command with three arguments when only two are permitted.
func TestMaximumNArgs_WithMoreArgs_WithValid(t *testing.T) {
c := getCommand(MaximumNArgs(2), true)
_, err := executeCommand(c, "one", "three", "two")
maximumNArgsWithMoreArgs(err, t)
}
// TestMaximumNArgs_WithMoreArgs_WithValid_WithInvalidArgs tests the behavior of the MaximumNArgs decorator when called with more arguments than expected.
// It checks both valid and invalid argument scenarios.
// It uses the getCommand function to create a command with the MaximumNArgs decorator applied.
// The executeCommand function is then used to run the command with "a", "b", and "c" as arguments.
// The maximumNArgsWithMoreArgs function asserts the expected error behavior based on the number of arguments.
func TestMaximumNArgs_WithMoreArgs_WithValid_WithInvalidArgs(t *testing.T) {
c := getCommand(MaximumNArgs(2), true)
_, err := executeCommand(c, "a", "b", "c")
maximumNArgsWithMoreArgs(err, t)
}
// TestMaximumNArgs_WithMoreArgs_WithValidOnly_WithInvalidArgs tests the behavior of a command with a maximum number of arguments and only valid arguments.
// It ensures that an error is returned when more than two arguments are provided.
// The test checks if the command correctly identifies invalid arguments when they are present.
func TestMaximumNArgs_WithMoreArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
c := getCommand(MatchAll(OnlyValidArgs, MaximumNArgs(2)), true)
_, err := executeCommand(c, "a", "b", "c")
@ -281,48 +395,68 @@ func TestMaximumNArgs_WithMoreArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
// ExactArgs
// TestExactArgs tests the functionality of a command that requires exactly three arguments.
// It sets up a command with ExactArgs set to 3 and executes it with three arguments.
// The output and error are then checked for success using expectSuccess.
func TestExactArgs(t *testing.T) {
c := getCommand(ExactArgs(3), false)
output, err := executeCommand(c, "a", "b", "c")
expectSuccess(output, err, t)
}
// TestExactArgs_WithValid tests the ExactArgs function with valid arguments.
// It verifies that the command is executed successfully when the correct number of arguments is provided.
func TestExactArgs_WithValid(t *testing.T) {
c := getCommand(ExactArgs(3), true)
output, err := executeCommand(c, "three", "one", "two")
expectSuccess(output, err, t)
}
// TestExactArgs_WithValid_WithInvalidArgs tests the ExactArgs validator with valid and invalid arguments.
// It creates a command with ExactArgs set to 3, executes it with various argument sets,
// and checks if the execution behaves as expected for both valid and invalid cases.
func TestExactArgs_WithValid_WithInvalidArgs(t *testing.T) {
c := getCommand(ExactArgs(3), true)
output, err := executeCommand(c, "three", "a", "two")
expectSuccess(output, err, t)
}
// TestExactArgs_WithValidOnly_WithInvalidArgs tests the behavior of a command that expects exactly 3 arguments and allows only valid args.
// It executes the command with invalid arguments and checks if the error returned is as expected when using OnlyValidArgs.
func TestExactArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
c := getCommand(MatchAll(OnlyValidArgs, ExactArgs(3)), true)
_, err := executeCommand(c, "three", "a", "two")
validOnlyWithInvalidArgs(err, t)
}
// TestExactArgs_WithInvalidCount tests the behavior of a command that expects exactly two arguments but receives an invalid count.
// It creates a command with ExactArgs(2) validator and executes it with three arguments, expecting an error due to the mismatched argument count.
func TestExactArgs_WithInvalidCount(t *testing.T) {
c := getCommand(ExactArgs(2), false)
_, err := executeCommand(c, "a", "b", "c")
exactArgsWithInvalidCount(err, t)
}
// TestExactArgs_WithInvalidCount_WithValid tests the execution of a command with an exact number of arguments when provided with an invalid count.
// It expects an error related to the argument count being incorrect.
// The test ensures that the command handling correctly identifies and reports errors for too many arguments.
func TestExactArgs_WithInvalidCount_WithValid(t *testing.T) {
c := getCommand(ExactArgs(2), true)
_, err := executeCommand(c, "three", "one", "two")
exactArgsWithInvalidCount(err, t)
}
// TestExactArgs_WithInvalidCount_WithValid_WithInvalidArgs tests the behavior of a command with exact arguments when executed with an invalid count and valid arguments.
// It checks if the command returns an error when provided with more than the expected number of arguments.
func TestExactArgs_WithInvalidCount_WithValid_WithInvalidArgs(t *testing.T) {
c := getCommand(ExactArgs(2), true)
_, err := executeCommand(c, "three", "a", "two")
exactArgsWithInvalidCount(err, t)
}
// TestExactArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs tests the behavior of a command with exact argument count and valid-only filter when provided with invalid arguments.
// It expects an error due to the mismatch in the number of arguments passed.
// The test ensures that the OnlyValidArgs filter is applied correctly, allowing only valid arguments through.
func TestExactArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs(t *testing.T) {
c := getCommand(MatchAll(OnlyValidArgs, ExactArgs(2)), true)
_, err := executeCommand(c, "three", "a", "two")
@ -331,48 +465,70 @@ func TestExactArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs(t *testing.T)
// RangeArgs
// TestRangeArgs tests the functionality of RangeArgs with provided arguments.
// It creates a command using RangeArgs and executes it with given input arguments.
// Finally, it checks if the command execution was successful.
func TestRangeArgs(t *testing.T) {
c := getCommand(RangeArgs(2, 4), false)
output, err := executeCommand(c, "a", "b", "c")
expectSuccess(output, err, t)
}
// TestRangeArgs_WithValid tests the RangeArgs function with valid arguments and ensures that the command execution is successful. It uses a test function to verify the output and error returned by the executeCommand function. The getCommand function is used to create a command based on the provided arguments and the debug flag.
func TestRangeArgs_WithValid(t *testing.T) {
c := getCommand(RangeArgs(2, 4), true)
output, err := executeCommand(c, "three", "one", "two")
expectSuccess(output, err, t)
}
// TestRangeArgs_WithValid_WithInvalidArgs tests the RangeArgs function with valid and invalid arguments.
// It verifies that the command execution behaves as expected when provided with a range of integers (2 to 4).
// It checks both valid and invalid arguments and ensures successful execution for valid inputs.
func TestRangeArgs_WithValid_WithInvalidArgs(t *testing.T) {
c := getCommand(RangeArgs(2, 4), true)
output, err := executeCommand(c, "three", "a", "two")
expectSuccess(output, err, t)
}
// TestRangeArgs_WithValidOnly_WithInvalidArgs tests the behavior of the command when it expects a range of arguments (2 to 4) and only valid arguments.
// It verifies that an error is returned when the provided arguments do not meet the specified criteria.
func TestRangeArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
c := getCommand(MatchAll(OnlyValidArgs, RangeArgs(2, 4)), true)
_, err := executeCommand(c, "three", "a", "two")
validOnlyWithInvalidArgs(err, t)
}
// TestRangeArgs_WithInvalidCount tests the behavior of the RangeArgs command when provided with an invalid number of arguments.
// It creates a command with an expected range and executes it with an incorrect argument count, expecting an error related to the number of arguments being out of range.
// The test uses a helper function `rangeArgsWithInvalidCount` to verify that the correct error is returned.
func TestRangeArgs_WithInvalidCount(t *testing.T) {
c := getCommand(RangeArgs(2, 4), false)
_, err := executeCommand(c, "a")
rangeArgsWithInvalidCount(err, t)
}
// TestRangeArgs_WithInvalidCount_WithValid tests the RangeArgs function with an invalid count but valid arguments.
// It creates a command using the getCommand function and executes it with a single argument "two".
// The function then checks if the error returned by executeCommand matches the expected error for invalid count.
func TestRangeArgs_WithInvalidCount_WithValid(t *testing.T) {
c := getCommand(RangeArgs(2, 4), true)
_, err := executeCommand(c, "two")
rangeArgsWithInvalidCount(err, t)
}
// TestRangeArgs_WithInvalidCount_WithValid_WithInvalidArgs tests the execution of a command with invalid count and valid arguments.
// It checks if the function handles errors correctly when provided with an invalid number of arguments.
// Parameters:
// - t: A pointer to a testing.T object used for test assertions.
// The function does not return any values but asserts on the behavior of the executeCommand function.
func TestRangeArgs_WithInvalidCount_WithValid_WithInvalidArgs(t *testing.T) {
c := getCommand(RangeArgs(2, 4), true)
_, err := executeCommand(c, "a")
rangeArgsWithInvalidCount(err, t)
}
// TestRangeArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs tests the behavior of a command with range arguments when given an invalid count and valid only option, expecting errors for invalid arguments.
// It uses a test function to verify that executing the command with "a" as an argument results in an error due to the mismatch between expected and actual arguments.
func TestRangeArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs(t *testing.T) {
c := getCommand(MatchAll(OnlyValidArgs, RangeArgs(2, 4)), true)
_, err := executeCommand(c, "a")
@ -381,6 +537,9 @@ func TestRangeArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs(t *testing.T)
// Takes(No)Args
// TestRootTakesNoArgs tests that calling the root command with illegal arguments returns an error.
// It creates a root command and a child command, adds the child to the root, and then attempts to execute
// the root command with invalid arguments. It expects an error indicating that the "illegal" command is unknown for "root".
func TestRootTakesNoArgs(t *testing.T) {
rootCmd := &Command{Use: "root", Run: emptyRun}
childCmd := &Command{Use: "child", Run: emptyRun}
@ -398,6 +557,7 @@ func TestRootTakesNoArgs(t *testing.T) {
}
}
// TestRootTakesArgs tests if the root command correctly handles arguments.
func TestRootTakesArgs(t *testing.T) {
rootCmd := &Command{Use: "root", Args: ArbitraryArgs, Run: emptyRun}
childCmd := &Command{Use: "child", Run: emptyRun}
@ -409,6 +569,9 @@ func TestRootTakesArgs(t *testing.T) {
}
}
// TestChildTakesNoArgs tests that the command handles unexpected arguments correctly when a subcommand does not accept any arguments.
//
// It verifies that calling "child" with additional arguments results in an error.
func TestChildTakesNoArgs(t *testing.T) {
rootCmd := &Command{Use: "root", Run: emptyRun}
childCmd := &Command{Use: "child", Args: NoArgs, Run: emptyRun}
@ -426,6 +589,9 @@ func TestChildTakesNoArgs(t *testing.T) {
}
}
// TestChildTakesArgs tests that a child command with arguments can be executed successfully.
// It creates a root command and adds a child command with arbitrary argument requirements.
// Then, it executes the child command with legal arguments and verifies there is no error.
func TestChildTakesArgs(t *testing.T) {
rootCmd := &Command{Use: "root", Run: emptyRun}
childCmd := &Command{Use: "child", Args: ArbitraryArgs, Run: emptyRun}
@ -437,6 +603,8 @@ func TestChildTakesArgs(t *testing.T) {
}
}
// TestMatchAll tests the MatchAll function with various test cases to ensure it correctly validates command arguments.
// It checks that the number of arguments is exactly 3 and each argument is exactly 2 bytes long.
func TestMatchAll(t *testing.T) {
// Somewhat contrived example check that ensures there are exactly 3
// arguments, and each argument is exactly 2 bytes long.
@ -487,34 +655,40 @@ func TestMatchAll(t *testing.T) {
// DEPRECATED
// TestExactValidArgs tests the behavior of a command when provided with exactly three valid arguments.
// It checks if the command executes successfully with the given arguments and validates the output.
func TestExactValidArgs(t *testing.T) {
c := getCommand(ExactValidArgs(3), true)
output, err := executeCommand(c, "three", "one", "two")
expectSuccess(output, err, t)
}
// TestExactValidArgs_WithInvalidCount tests the ExactValidArgs function with an invalid argument count.
// It asserts that an error is returned when the number of arguments does not match the expected count.
func TestExactValidArgs_WithInvalidCount(t *testing.T) {
c := getCommand(ExactValidArgs(2), false)
_, err := executeCommand(c, "three", "one", "two")
exactArgsWithInvalidCount(err, t)
}
// TestExactValidArgs_WithInvalidCount_WithInvalidArgs tests the behavior of the ExactValidArgs validator when provided with an invalid count and invalid arguments.
// It creates a command with the ExactValidArgs validator, executes it with three arguments (two valid and one invalid), and checks if the error returned is as expected for invalid argument counts.
func TestExactValidArgs_WithInvalidCount_WithInvalidArgs(t *testing.T) {
c := getCommand(ExactValidArgs(2), true)
_, err := executeCommand(c, "three", "a", "two")
exactArgsWithInvalidCount(err, t)
}
// TestExactValidArgs_WithInvalidArgs tests the behavior of ExactValidArgs when invoked with invalid arguments.
// It uses a test command and checks if the execution results in an error as expected.
func TestExactValidArgs_WithInvalidArgs(t *testing.T) {
c := getCommand(ExactValidArgs(2), true)
_, err := executeCommand(c, "three", "a")
validOnlyWithInvalidArgs(err, t)
}
// This test make sure we keep backwards-compatibility with respect
// to the legacyArgs() function.
// It makes sure the root command accepts arguments if it does not have
// sub-commands.
// TestLegacyArgsRootAcceptsArgs ensures that the root command accepts arguments if it does not have sub-commands.
// It verifies backwards-compatibility with respect to the legacyArgs() function.
func TestLegacyArgsRootAcceptsArgs(t *testing.T) {
rootCmd := &Command{Use: "root", Args: nil, Run: emptyRun}
@ -524,9 +698,7 @@ func TestLegacyArgsRootAcceptsArgs(t *testing.T) {
}
}
// This test make sure we keep backwards-compatibility with respect
// to the legacyArgs() function.
// It makes sure a sub-command accepts arguments and further sub-commands
// TestLegacyArgsSubcmdAcceptsArgs verifies that a sub-command accepts arguments and further sub-commands while maintaining backwards-compatibility with the legacyArgs() function. It ensures that executing commands like "root child somearg" does not result in errors.
func TestLegacyArgsSubcmdAcceptsArgs(t *testing.T) {
rootCmd := &Command{Use: "root", Args: nil, Run: emptyRun}
childCmd := &Command{Use: "child", Args: nil, Run: emptyRun}

View file

@ -401,6 +401,13 @@ __%[1]s_handle_word()
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name)))
}
// writePostscript writes postscript code to the provided buffer for a given command name.
//
// Parameters:
// - buf: io.StringWriter where the postscript code will be written.
// - name: The name of the command for which the postscript code is being generated.
//
// This function handles the generation of completion script postscript code for a Bash or similar shell. It replaces colons in the command name with double underscores, initializes completion variables and functions, and sets up the completion behavior using the 'complete' command.
func writePostscript(buf io.StringWriter, name string) {
name = strings.ReplaceAll(name, ":", "__")
WriteStringAndCheck(buf, fmt.Sprintf("__start_%s()\n", name))
@ -444,6 +451,16 @@ fi
WriteStringAndCheck(buf, "# ex: ts=4 sw=4 et filetype=sh\n")
}
// writeCommands writes the command definitions to a buffer.
//
// It takes an io.StringWriter and a *Command as parameters. The function iterates through
// the commands associated with the given Command instance. If a command is not available and
// is not the help command, it skips that command. For each valid command, it writes its name to the buffer
// in the format 'commands+=(<command_name>)' and calls writeCmdAliases to write any aliases for the command.
//
// The function includes a newline character at the end of the output.
//
// It returns nothing but may log errors through WriteStringAndCheck.
func writeCommands(buf io.StringWriter, cmd *Command) {
WriteStringAndCheck(buf, " commands=()\n")
for _, c := range cmd.Commands() {
@ -456,6 +473,16 @@ func writeCommands(buf io.StringWriter, cmd *Command) {
WriteStringAndCheck(buf, "\n")
}
// writeFlagHandler writes the flag completion handler for a given command and its annotations.
//
// Parameters:
// buf - an io.StringWriter where the completion handler will be written
// name - the name of the flag
// annotations - a map containing annotations for the flag, including types like BashCompFilenameExt, BashCompCustom, and BashCompSubdirsInDir
// cmd - the command associated with the flag
//
// Returns:
// This function does not return any value. It writes to the buffer provided.
func writeFlagHandler(buf io.StringWriter, name string, annotations map[string][]string, cmd *Command) {
for key, value := range annotations {
switch key {
@ -494,6 +521,15 @@ func writeFlagHandler(buf io.StringWriter, name string, annotations map[string][
const cbn = "\")\n"
// writeShortFlag writes a short flag to the provided buffer.
//
// Parameters:
// - buf: The io.StringWriter where the flag will be written.
// - flag: A pointer to the pflag.Flag representing the flag to write.
// - cmd: A pointer to the Command associated with the flag.
//
// It constructs a formatted string based on the flag's shorthand and annotations, then writes it to the buffer using WriteStringAndCheck.
// Additionally, it calls writeFlagHandler to handle any specific logic for the flag.
func writeShortFlag(buf io.StringWriter, flag *pflag.Flag, cmd *Command) {
name := flag.Shorthand
format := " "
@ -505,6 +541,17 @@ func writeShortFlag(buf io.StringWriter, flag *pflag.Flag, cmd *Command) {
writeFlagHandler(buf, "-"+name, flag.Annotations, cmd)
}
// writeFlag writes a flag definition to the buffer in a specific format.
//
// Parameters:
// - buf: The io.StringWriter where the flag definition will be written.
// - flag: The pflag.Flag object representing the flag being written.
// - cmd: The Command object associated with the flag.
//
// Returns:
// None
//
// This function handles the formatting and writing of a single flag, including handling cases for flags without default values and two-word flags. It also calls writeFlagHandler to process any additional annotations or handlers related to the flag.
func writeFlag(buf io.StringWriter, flag *pflag.Flag, cmd *Command) {
name := flag.Name
format := " flags+=(\"--%s"
@ -520,6 +567,14 @@ func writeFlag(buf io.StringWriter, flag *pflag.Flag, cmd *Command) {
writeFlagHandler(buf, "--"+name, flag.Annotations, cmd)
}
// writeLocalNonPersistentFlag writes the local non-persistent flags to the provided buffer.
//
// Parameters:
// - buf: The io.StringWriter where the flags will be written.
// - flag: A pointer to the pflag.Flag that contains the details of the flag.
//
// This function constructs a string representation of the flag and appends it to the buffer. If the flag has a shorthand,
// it also writes the shorthand version of the flag to the buffer.
func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) {
name := flag.Name
format := " local_nonpersistent_flags+=(\"--%[1]s" + cbn
@ -532,7 +587,9 @@ func writeLocalNonPersistentFlag(buf io.StringWriter, flag *pflag.Flag) {
}
}
// prepareCustomAnnotationsForFlags setup annotations for go completions for registered flags
// prepareCustomAnnotationsForFlags sets up custom annotations for go completions for registered flags.
//
// It takes a pointer to a Command and iterates over the flagCompletionFunctions map, adding custom annotations to each flag's Annotations field. The custom annotation is a Bash completion command that calls the __*_go_custom_completion function for the specified flag, ensuring that the root command name is correctly set for the prefix of the completion script.
func prepareCustomAnnotationsForFlags(cmd *Command) {
flagCompletionMutex.RLock()
defer flagCompletionMutex.RUnlock()
@ -548,6 +605,9 @@ func prepareCustomAnnotationsForFlags(cmd *Command) {
}
}
// writeFlags writes the flags for a command to the provided buffer.
// It handles both local and inherited flags, excluding non-completable ones.
// If flag parsing is disabled, it sets the corresponding variable in the buffer.
func writeFlags(buf io.StringWriter, cmd *Command) {
prepareCustomAnnotationsForFlags(cmd)
WriteStringAndCheck(buf, ` flags=()
@ -590,6 +650,12 @@ func writeFlags(buf io.StringWriter, cmd *Command) {
WriteStringAndCheck(buf, "\n")
}
// writeRequiredFlag appends to the buffer a line that specifies which flags are required for the command.
// It takes an io.StringWriter and a Command as parameters. The function checks each non-inherited flag of the command
// and adds it to the must_have_one_flag array if it is annotated with BashCompOneRequiredFlag. If the flag is not of type bool,
// it appends "=" after the flag name in the array.
// This function does not return any values, but it may write strings to the buffer and handle errors through WriteStringAndCheck.
// It also uses nonCompletableFlag to determine if a flag should be skipped.
func writeRequiredFlag(buf io.StringWriter, cmd *Command) {
WriteStringAndCheck(buf, " must_have_one_flag=()\n")
flags := cmd.NonInheritedFlags()
@ -612,6 +678,13 @@ func writeRequiredFlag(buf io.StringWriter, cmd *Command) {
})
}
// writeRequiredNouns writes the required nouns for a command to a buffer.
//
// It takes an io.StringWriter and a pointer to a Command as parameters. The Command should have valid arguments defined in ValidArgs or a function to provide them through ValidArgsFunction.
//
// This function sorts the valid arguments, removes any descriptions following a tab character (not supported by bash completion), and appends each noun to the buffer in the format required for command-line interface validation.
//
// If a ValidArgsFunction is provided, it also sets a flag indicating that a completion function is available.
func writeRequiredNouns(buf io.StringWriter, cmd *Command) {
WriteStringAndCheck(buf, " must_have_one_noun=()\n")
sort.Strings(cmd.ValidArgs)
@ -626,6 +699,14 @@ func writeRequiredNouns(buf io.StringWriter, cmd *Command) {
}
}
// writeCmdAliases writes the command aliases to the provided buffer.
//
// Parameters:
// - buf: An io.StringWriter where the aliases will be written.
// - cmd: A pointer to a Command struct containing the aliases to be written.
//
// Returns:
// - None
func writeCmdAliases(buf io.StringWriter, cmd *Command) {
if len(cmd.Aliases) == 0 {
return
@ -641,6 +722,15 @@ func writeCmdAliases(buf io.StringWriter, cmd *Command) {
WriteStringAndCheck(buf, ` fi`)
WriteStringAndCheck(buf, "\n")
}
// writeArgAliases writes argument aliases for a command to the buffer and checks for errors.
//
// Parameters:
// - buf: The string writer where the alias information will be written.
// - cmd: The command whose aliases are being written.
//
// This function formats and appends argument aliases of the given command to the buffer,
// ensuring they are sorted alphabetically. It also handles any errors that occur during
// the writing process using WriteStringAndCheck.
func writeArgAliases(buf io.StringWriter, cmd *Command) {
WriteStringAndCheck(buf, " noun_aliases=()\n")
sort.Strings(cmd.ArgAliases)
@ -649,6 +739,11 @@ func writeArgAliases(buf io.StringWriter, cmd *Command) {
}
}
// gen recursively generates a set of functions to call the provided command and its subcommands.
//
// Parameters:
// - buf: an io.StringWriter to write the generated functions to.
// - cmd: the current command to generate functions for.
func gen(buf io.StringWriter, cmd *Command) {
for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() && c != cmd.helpCommand {
@ -679,7 +774,13 @@ func gen(buf io.StringWriter, cmd *Command) {
WriteStringAndCheck(buf, "}\n\n")
}
// GenBashCompletion generates bash completion file and writes to the passed writer.
// GenBashCompletion generates a bash completion file and writes it to the provided writer.
//
// Parameters:
// - w: io.Writer - The writer to which the bash completion file will be written.
//
// Returns:
// - error: If an error occurs during the generation or writing process, it is returned.
func (c *Command) GenBashCompletion(w io.Writer) error {
buf := new(bytes.Buffer)
writePreamble(buf, c.Name())
@ -693,11 +794,18 @@ func (c *Command) GenBashCompletion(w io.Writer) error {
return err
}
// nonCompletableFlag checks if a flag is hidden or deprecated and returns true if it should not be completed.
func nonCompletableFlag(flag *pflag.Flag) bool {
return flag.Hidden || len(flag.Deprecated) > 0
}
// GenBashCompletionFile generates bash completion file.
// GenBashCompletionFile generates a bash completion file for the command.
//
// Parameters:
// filename - The path to the output bash completion file.
//
// Returns:
// error - An error if the file could not be created or written, nil otherwise.
func (c *Command) GenBashCompletionFile(filename string) error {
outFile, err := os.Create(filename)
if err != nil {

View file

@ -21,6 +21,9 @@ import (
"os"
)
// genBashCompletion generates Bash completion script for the command.
// It writes the completion script to the provided writer and includes descriptions if specified.
// Returns an error if the operation fails.
func (c *Command) genBashCompletion(w io.Writer, includeDesc bool) error {
buf := new(bytes.Buffer)
genBashComp(buf, c.Name(), includeDesc)
@ -466,7 +469,14 @@ fi
activeHelpMarker))
}
// GenBashCompletionFileV2 generates Bash completion version 2.
// GenBashCompletionFileV2 generates a Bash completion file for version 2.
//
// Parameters:
// - filename: The name of the file to be created.
// - includeDesc: A boolean indicating whether to include descriptions in the completion file.
//
// Returns:
// - error: An error if any occurs during file creation or generation.
func (c *Command) GenBashCompletionFileV2(filename string, includeDesc bool) error {
outFile, err := os.Create(filename)
if err != nil {
@ -477,8 +487,14 @@ func (c *Command) GenBashCompletionFileV2(filename string, includeDesc bool) err
return c.GenBashCompletionV2(outFile, includeDesc)
}
// GenBashCompletionV2 generates Bash completion file version 2
// and writes it to the passed writer.
// GenBashCompletionV2 generates Bash completion file version 2 and writes it to the provided writer. It includes a description of each command if includeDesc is true.
//
// Parameters:
// - w: The writer where the Bash completion file will be written.
// - includeDesc: A boolean indicating whether to include descriptions in the completion file.
//
// Returns:
// - An error if there was an issue generating or writing the completion file.
func (c *Command) GenBashCompletionV2(w io.Writer, includeDesc bool) error {
return c.genBashCompletion(w, includeDesc)
}