feat(args): args_handler error handling and print_usage
This commit is contained in:
parent
234713b6a0
commit
e3785dbd08
4 changed files with 183 additions and 6 deletions
15
src/main.c
15
src/main.c
|
|
@ -1,8 +1,19 @@
|
||||||
// all includes
|
// all includes
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "utils/args/args.h"
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
struct args_options options;
|
||||||
(void)argv;
|
int r = args_handler(argc, argv, &options);
|
||||||
|
if (r != 0)
|
||||||
|
{
|
||||||
|
print_usage(stderr, argv[0]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
args_print(&options);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,19 @@ int args_handler(int argc, char **argv, struct args_options *options)
|
||||||
{
|
{
|
||||||
options->verbose = true;
|
options->verbose = true;
|
||||||
}
|
}
|
||||||
else if (strcmp(argv[i], "-c") == 0 && i + 1 < argc)
|
else if (strcmp(argv[i], "-c") == 0)
|
||||||
{
|
{
|
||||||
if (options->type != INPUT_UNDEFINED)
|
if (options->type != INPUT_UNDEFINED)
|
||||||
return 1; // Error: multiple input types specified
|
{
|
||||||
|
fprintf(stderr, "Multiple input sources specified: %s\n",
|
||||||
|
argv[i + 1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (i + 1 >= argc)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "No command provided after -c\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
options->type = INPUT_CMD;
|
options->type = INPUT_CMD;
|
||||||
options->input_source = argv[i + 1];
|
options->input_source = argv[i + 1];
|
||||||
|
|
@ -32,12 +41,17 @@ int args_handler(int argc, char **argv, struct args_options *options)
|
||||||
}
|
}
|
||||||
else if (argv[i][0] == '-')
|
else if (argv[i][0] == '-')
|
||||||
{
|
{
|
||||||
return 1; // Error: unknown option
|
fprintf(stderr, "Unknown option: %s\n", argv[i]);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (options->type != INPUT_UNDEFINED)
|
if (options->type != INPUT_UNDEFINED)
|
||||||
return 1; // Error: multiple input types specified
|
{
|
||||||
|
fprintf(stderr, "Multiple input sources specified: %s\n",
|
||||||
|
argv[i]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
options->type = INPUT_FILE;
|
options->type = INPUT_FILE;
|
||||||
options->input_source = argv[i];
|
options->input_source = argv[i];
|
||||||
|
|
@ -62,3 +76,14 @@ void args_print(struct args_options *options)
|
||||||
printf("Pretty print: %s\n", options->pretty_print ? "true" : "false");
|
printf("Pretty print: %s\n", options->pretty_print ? "true" : "false");
|
||||||
printf("Verbose: %s\n", options->verbose ? "true" : "false");
|
printf("Verbose: %s\n", options->verbose ? "true" : "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_usage(FILE *std, const char *program_name)
|
||||||
|
{
|
||||||
|
fprintf(std, "Usage: %s [OPTIONS] [SCRIPT] [ARGUMENTS...]\n", program_name);
|
||||||
|
fprintf(std, "Options:\n");
|
||||||
|
fprintf(std, " -c [SCRIPT] Execute the given command string.\n");
|
||||||
|
fprintf(std, " --pretty-print Enable pretty printing of outputs.\n");
|
||||||
|
fprintf(std, " --verbose Enable verbose mode.\n");
|
||||||
|
fprintf(std,
|
||||||
|
"If no SCRIPT is provided, input is read from standard input.\n");
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define ARGS_H
|
#define ARGS_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
enum input_type
|
enum input_type
|
||||||
{
|
{
|
||||||
|
|
@ -38,4 +39,10 @@ int args_handler(int argc, char **argv, struct args_options *options);
|
||||||
*/
|
*/
|
||||||
void args_print(struct args_options *options);
|
void args_print(struct args_options *options);
|
||||||
|
|
||||||
|
/** Prints the usage information for the program.
|
||||||
|
* @param std The output stream to print to (e.g., stdout or stderr).
|
||||||
|
* @param program_name The name of the program.
|
||||||
|
*/
|
||||||
|
void print_usage(FILE *std, const char *program_name);
|
||||||
|
|
||||||
#endif /* ARGS_H */
|
#endif /* ARGS_H */
|
||||||
|
|
|
||||||
134
tests/unit/utils/args.c
Normal file
134
tests/unit/utils/args.c
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
#include "../../../src/utils/args/args.h"
|
||||||
|
|
||||||
|
#include <criterion/criterion.h>
|
||||||
|
#include <criterion/new/assert.h>
|
||||||
|
#include <criterion/redirect.h>
|
||||||
|
|
||||||
|
TestSuite(utils_args);
|
||||||
|
|
||||||
|
Test(utils_args, basic_command)
|
||||||
|
{
|
||||||
|
int argc = 3;
|
||||||
|
struct args_options options;
|
||||||
|
char *input[] = { "program", "-c", "echo Hello, World!" };
|
||||||
|
|
||||||
|
int r = args_handler(argc, input, &options);
|
||||||
|
|
||||||
|
cr_expect(r == 0);
|
||||||
|
cr_expect(options.pretty_print == false);
|
||||||
|
cr_expect(options.verbose == false);
|
||||||
|
cr_expect(options.type == INPUT_CMD);
|
||||||
|
cr_expect(eq(options.input_source, "echo Hello, World!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(utils_args, basic_command_with_flags)
|
||||||
|
{
|
||||||
|
int argc = 5;
|
||||||
|
struct args_options options;
|
||||||
|
char *input[] = { "program", "--pretty-print", "-c", "echo Hello, World!",
|
||||||
|
"--verbose" };
|
||||||
|
|
||||||
|
int r = args_handler(argc, input, &options);
|
||||||
|
|
||||||
|
cr_expect(r == 0);
|
||||||
|
cr_expect(options.pretty_print == true);
|
||||||
|
cr_expect(options.verbose == true);
|
||||||
|
cr_expect(options.type == INPUT_CMD);
|
||||||
|
cr_expect(eq(options.input_source, "echo Hello, World!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(utils_args, basic_file_input)
|
||||||
|
{
|
||||||
|
int argc = 2;
|
||||||
|
struct args_options options;
|
||||||
|
char *input[] = { "program", "input.txt" };
|
||||||
|
|
||||||
|
int r = args_handler(argc, input, &options);
|
||||||
|
|
||||||
|
cr_expect(r == 0);
|
||||||
|
cr_expect(options.pretty_print == false);
|
||||||
|
cr_expect(options.verbose == false);
|
||||||
|
cr_expect(options.type == INPUT_FILE);
|
||||||
|
cr_expect(eq(options.input_source, "input.txt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(utils_args, basic_file_input_with_flags)
|
||||||
|
{
|
||||||
|
int argc = 4;
|
||||||
|
struct args_options options;
|
||||||
|
char *input[] = { "program", "--verbose", "input.txt", "--pretty-print" };
|
||||||
|
|
||||||
|
int r = args_handler(argc, input, &options);
|
||||||
|
|
||||||
|
cr_expect(r == 0);
|
||||||
|
cr_expect(options.pretty_print == true);
|
||||||
|
cr_expect(options.verbose == true);
|
||||||
|
cr_expect(options.type == INPUT_FILE);
|
||||||
|
cr_expect(eq(options.input_source, "input.txt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(utils_args, basic_stdin_input)
|
||||||
|
{
|
||||||
|
int argc = 1;
|
||||||
|
struct args_options options;
|
||||||
|
char *input[] = { "program" };
|
||||||
|
|
||||||
|
int r = args_handler(argc, input, &options);
|
||||||
|
|
||||||
|
cr_expect(r == 0);
|
||||||
|
cr_expect(options.pretty_print == false);
|
||||||
|
cr_expect(options.verbose == false);
|
||||||
|
cr_expect(options.type == INPUT_STDIN);
|
||||||
|
cr_expect(options.input_source == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(utils_args, pretty_print_and_verbose_flags)
|
||||||
|
{
|
||||||
|
int argc = 3;
|
||||||
|
struct args_options options;
|
||||||
|
char *input[] = { "program", "--pretty-print", "--verbose" };
|
||||||
|
|
||||||
|
int r = args_handler(argc, input, &options);
|
||||||
|
|
||||||
|
cr_expect(r == 0);
|
||||||
|
cr_expect(options.pretty_print == true);
|
||||||
|
cr_expect(options.verbose == true);
|
||||||
|
cr_expect(options.type == INPUT_STDIN);
|
||||||
|
cr_expect(options.input_source == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(utils_args, missing_command_after_c, .init = cr_redirect_stderr)
|
||||||
|
{
|
||||||
|
int argc = 2;
|
||||||
|
struct args_options options;
|
||||||
|
char *input[] = { "program", "-c" };
|
||||||
|
|
||||||
|
int r = args_handler(argc, input, &options);
|
||||||
|
|
||||||
|
cr_expect(r != 0);
|
||||||
|
cr_assert_stderr_eq_str("No command provided after -c\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(utils_args, unknown_option, .init = cr_redirect_stderr)
|
||||||
|
{
|
||||||
|
int argc = 2;
|
||||||
|
struct args_options options;
|
||||||
|
char *input[] = { "program", "--unknown" };
|
||||||
|
|
||||||
|
int r = args_handler(argc, input, &options);
|
||||||
|
|
||||||
|
cr_expect(r != 0);
|
||||||
|
cr_assert_stderr_eq_str("Unknown option: --unknown\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(utils_args, conflicting_input_types, .init = cr_redirect_stderr)
|
||||||
|
{
|
||||||
|
int argc = 4;
|
||||||
|
struct args_options options;
|
||||||
|
char *input[] = { "program", "-c", "echo Hello", "input.txt" };
|
||||||
|
|
||||||
|
int r = args_handler(argc, input, &options);
|
||||||
|
|
||||||
|
cr_expect(r != 0);
|
||||||
|
cr_assert_stderr_eq_str("Multiple input sources specified: input.txt\n");
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue