diff options
Diffstat (limited to 'libs/cargs/test')
| -rwxr-xr-x | libs/cargs/test/definitions.h | 9 | ||||
| -rwxr-xr-x | libs/cargs/test/main.c | 105 | ||||
| -rwxr-xr-x | libs/cargs/test/option_test.c | 665 | 
3 files changed, 779 insertions, 0 deletions
| diff --git a/libs/cargs/test/definitions.h b/libs/cargs/test/definitions.h new file mode 100755 index 0000000..cdb820e --- /dev/null +++ b/libs/cargs/test/definitions.h @@ -0,0 +1,9 @@ +#pragma once
 +
 +#include "tests.h"
 +/**
 + * Creates prototypes for all test functions.
 + */
 +#define XX(u, t) int u##_##t(void);
 +UNIT_TESTS(XX)
 +#undef XX
 diff --git a/libs/cargs/test/main.c b/libs/cargs/test/main.c new file mode 100755 index 0000000..229cf80 --- /dev/null +++ b/libs/cargs/test/main.c @@ -0,0 +1,105 @@ +#include "definitions.h"
 +#include <cargs.h>
 +#include <memory.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +
 +struct cag_test
 +{
 +  const char *unit_name;
 +  const char *test_name;
 +  const char *full_name;
 +  int (*fn)(void);
 +};
 +
 +static struct cag_test tests[] = {
 +#define XX(u, t)                                                               \
 +  {.unit_name = #u, .test_name = #t, .full_name = #u "/" #t, .fn = u##_##t},
 +  UNIT_TESTS(XX)
 +#undef XX
 +};
 +
 +static int call_test(struct cag_test *test)
 +{
 +  size_t i;
 +
 +  printf(" Running '%s' ", test->full_name);
 +  for (i = strlen(test->full_name); i < 40; ++i) {
 +    fputs(".", stdout);
 +  }
 +
 +  if (test->fn() == EXIT_FAILURE) {
 +    fputs(" FAILURE\n", stdout);
 +    return EXIT_FAILURE;
 +  }
 +
 +  fputs(" SUCCESS\n", stdout);
 +  return EXIT_SUCCESS;
 +}
 +
 +int main(int argc, char *argv[])
 +{
 +  size_t i, count, failed, succeeded;
 +  const char *requested_unit_name, *requested_test_name;
 +  struct cag_test *test;
 +  double rate;
 +
 +  count = 0;
 +  failed = 0;
 +  if (argc < 2) {
 +    fputs("No unit specified. Running all tests.\n\n", stdout);
 +    for (i = 0; i < CAG_ARRAY_SIZE(tests); ++i) {
 +      test = &tests[i];
 +      ++count;
 +      if (call_test(test) == EXIT_FAILURE) {
 +        ++failed;
 +      }
 +    }
 +  } else if (argc < 3) {
 +    requested_unit_name = argv[1];
 +    printf("Running all unit tests of '%s'.\n\n", requested_unit_name);
 +    for (i = 0; i < CAG_ARRAY_SIZE(tests); ++i) {
 +      test = &tests[i];
 +      if (strcmp(test->unit_name, requested_unit_name) == 0) {
 +        ++count;
 +        if (call_test(test) == EXIT_FAILURE) {
 +          ++failed;
 +        }
 +      }
 +    }
 +  } else {
 +    requested_unit_name = argv[1];
 +    requested_test_name = argv[2];
 +    printf("Running a single test '%s/%s'.\n\n", requested_unit_name,
 +      requested_test_name);
 +    for (i = 0; i < CAG_ARRAY_SIZE(tests); ++i) {
 +      test = &tests[i];
 +      if (strcmp(test->unit_name, requested_unit_name) == 0 &&
 +          strcmp(test->test_name, requested_test_name) == 0) {
 +        ++count;
 +        if (call_test(test) == EXIT_FAILURE) {
 +          ++failed;
 +        }
 +      }
 +    }
 +  }
 +
 +  if (count == 1) {
 +    fputs("\nThe test has been executed.\n", stdout);
 +  } else if (count > 0) {
 +    succeeded = count - failed;
 +    rate = (double)succeeded / (double)count * 100;
 +    printf("\n%zu/%zu (%.2f%%) of those tests succeeded.\n", succeeded, count,
 +      rate);
 +  } else {
 +    printf("\nNo tests found.\n");
 +    return EXIT_FAILURE;
 +  }
 +
 +  if (failed > 0) {
 +    return EXIT_FAILURE;
 +  }
 +
 +  return EXIT_SUCCESS;
 +}
 diff --git a/libs/cargs/test/option_test.c b/libs/cargs/test/option_test.c new file mode 100755 index 0000000..c2dfff4 --- /dev/null +++ b/libs/cargs/test/option_test.c @@ -0,0 +1,665 @@ +#include "definitions.h"
 +#include <assert.h>
 +#include <cargs.h>
 +#include <limits.h>
 +#include <memory.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +
 +static struct cag_option options[] = {
 +
 +  {.identifier = 's',
 +    .access_letters = "s",
 +    .access_name = NULL,
 +    .value_name = NULL,
 +    .description = "Simple flag"},
 +
 +  {.identifier = 'a',
 +    .access_letters = "a",
 +    .access_name = NULL,
 +    .value_name = NULL,
 +    .description = "Another simple flag"},
 +
 +  {.identifier = 'm',
 +    .access_letters = "mMoO",
 +    .access_name = NULL,
 +    .value_name = NULL,
 +    .description = "Multiple access letters"},
 +
 +  {.identifier = 'l',
 +    .access_letters = NULL,
 +    .access_name = "long",
 +    .value_name = NULL,
 +    .description = "Long parameter name"},
 +
 +  {.identifier = 'k',
 +    .access_letters = "k",
 +    .access_name = "key",
 +    .value_name = "VALUE",
 +    .description = "Parameter value"}};
 +
 +struct cag_result
 +{
 +  bool simple;
 +  bool another;
 +  bool multi_access;
 +  bool long_parameter;
 +  bool value_parameter;
 +  bool unknown;
 +  bool def;
 +  const char *value;
 +};
 +
 +static struct cag_result result;
 +static char **argv;
 +static int argc;
 +
 +static int make_args(const char *str)
 +{
 +  const char *c;
 +  int argIndex, argStart, argLength;
 +
 +  argc = 0;
 +  c = str;
 +  do {
 +    if (*c == ' ' || *c == '\0') {
 +      ++argc;
 +    }
 +  } while (*(c++));
 +
 +  argv = malloc(sizeof(char *) * (argc + 1));
 +  if (argv == NULL) {
 +    return 1;
 +  }
 +
 +  c = str;
 +  argIndex = 0;
 +  argStart = 0;
 +  argLength = 0;
 +  do {
 +    if (*c == ' ' || *c == '\0') {
 +      argv[argIndex] = malloc(argLength + 1);
 +      memcpy(argv[argIndex], &str[argStart], argLength);
 +      argv[argIndex][argLength] = '\0';
 +      ++argIndex;
 +      argStart += argLength + 1;
 +      argLength = 0;
 +    } else {
 +      ++argLength;
 +    }
 +
 +  } while (*(c++));
 +
 +  argv[argc] = NULL;
 +
 +  return 0;
 +}
 +
 +static void destroy_args()
 +{
 +  int i;
 +
 +  for (i = 0; i < argc; ++i) {
 +    free(argv[i]);
 +  }
 +
 +  free(argv);
 +}
 +
 +static int option_test_run(int currentArgc, char *currentArgv[])
 +{
 +  int index;
 +  char identifier;
 +  cag_option_context context;
 +
 +  cag_option_prepare(&context, options, CAG_ARRAY_SIZE(options), currentArgc,
 +    currentArgv);
 +
 +  memset(&result, 0, sizeof(result));
 +
 +  while (cag_option_fetch(&context)) {
 +    identifier = cag_option_get(&context);
 +    switch (identifier) {
 +    case 's':
 +      result.simple = true;
 +      break;
 +    case 'a':
 +      result.another = true;
 +      break;
 +    case 'm':
 +      result.multi_access = true;
 +      break;
 +    case 'l':
 +      result.long_parameter = true;
 +      break;
 +    case 'k':
 +      result.value_parameter = true;
 +      result.value = cag_option_get_value(&context);
 +      break;
 +    case '?':
 +      result.unknown = true;
 +      break;
 +    default:
 +      result.def = true;
 +      break;
 +    }
 +  }
 +
 +  index = cag_option_get_index(&context);
 +  if (cag_option_fetch(&context) != false) {
 +    return -1;
 +  }
 +
 +  if (cag_option_get_index(&context) != index) {
 +    return -1;
 +  }
 +
 +  return cag_option_get_index(&context);
 +}
 +
 +int option_complex(void)
 +{
 +  int status;
 +
 +  status = make_args("test file1 -s -- -a -- a file");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (!result.simple || result.another || result.multi_access ||
 +      result.long_parameter || result.value_parameter || result.unknown ||
 +      result.def || result.value != NULL) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_mixed(void)
 +{
 +  int status, i;
 +
 +  const char *values[] = {"file1", "file2", "mixed", "file3", "--", "-m",
 +    "parameters", "file4"};
 +
 +  status = make_args(
 +    "test -s file1 -k=value file2 -a mixed file3 -- -m parameters file4");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0 || argc - status != 8) {
 +    goto err_wrong;
 +  }
 +
 +  for (i = 0; i < (int)CAG_ARRAY_SIZE(values); ++i) {
 +    if (strcmp(argv[status + i], values[i]) != 0) {
 +      goto err_wrong;
 +    }
 +  }
 +
 +  if (!result.simple || !result.another || result.multi_access ||
 +      result.long_parameter || !result.value_parameter || result.unknown ||
 +      result.def || result.value == NULL ||
 +      strcmp(result.value, "value") != 0) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_ending(void)
 +{
 +  int status;
 +
 +  status = make_args("test -s -- -a");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (!result.simple || result.another || result.multi_access ||
 +      result.long_parameter || result.value_parameter || result.unknown ||
 +      result.def || result.value != NULL) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_long_missing_value(void)
 +{
 +  int status;
 +
 +  status = make_args("test --key");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (result.simple || result.another || result.multi_access ||
 +      result.long_parameter || !result.value_parameter || result.unknown ||
 +      result.def || result.value != NULL) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_short_missing_value(void)
 +{
 +  int status;
 +
 +  status = make_args("test -k");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (result.simple || result.another || result.multi_access ||
 +      result.long_parameter || !result.value_parameter || result.unknown ||
 +      result.def || result.value != NULL) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_long_space_value(void)
 +{
 +  int status;
 +
 +  status = make_args("test --key super_value");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (result.simple || result.another || result.multi_access ||
 +      result.long_parameter || !result.value_parameter || result.unknown ||
 +      result.def || result.value == NULL ||
 +      strcmp(result.value, "super_value") != 0) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_short_space_value(void)
 +{
 +  int status;
 +
 +  status = make_args("test -k test_value");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (result.simple || result.another || result.multi_access ||
 +      result.long_parameter || !result.value_parameter || result.unknown ||
 +      result.def || result.value == NULL ||
 +      strcmp(result.value, "test_value") != 0) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_long_equal_value(void)
 +{
 +  int status;
 +
 +  status = make_args("test --key=super_value");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (result.simple || result.another || result.multi_access ||
 +      result.long_parameter || !result.value_parameter || result.unknown ||
 +      result.def || result.value == NULL ||
 +      strcmp(result.value, "super_value") != 0) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_short_equal_value(void)
 +{
 +  int status;
 +
 +  status = make_args("test -k=test_value");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (result.simple || result.another || result.multi_access ||
 +      result.long_parameter || !result.value_parameter || result.unknown ||
 +      result.def || result.value == NULL ||
 +      strcmp(result.value, "test_value") != 0) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_combined(void)
 +{
 +  int status;
 +
 +  status = make_args("test -sma");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (!result.simple || !result.another || !result.multi_access ||
 +      result.long_parameter || result.value_parameter || result.unknown ||
 +      result.def || result.value != NULL) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_unknown_long(void)
 +{
 +  int status;
 +
 +  status = make_args("test --unknown");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (result.simple || result.another || result.multi_access ||
 +      result.long_parameter || result.value_parameter || !result.unknown ||
 +      result.def || result.value != NULL) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_unknown_short(void)
 +{
 +  int status;
 +
 +  status = make_args("test -u");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (result.simple || result.another || result.multi_access ||
 +      result.long_parameter || result.value_parameter || !result.unknown ||
 +      result.def || result.value != NULL) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_alias(void)
 +{
 +  int status;
 +
 +  status = make_args("test -O");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (result.simple || result.another || !result.multi_access ||
 +      result.long_parameter || result.value_parameter || result.unknown ||
 +      result.def || result.value != NULL) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_simple_long(void)
 +{
 +  int status;
 +
 +  status = make_args("test --long");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (result.simple || result.another || result.multi_access ||
 +      !result.long_parameter || result.value_parameter || result.unknown ||
 +      result.def || result.value != NULL) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_simple(void)
 +{
 +  int status;
 +
 +  status = make_args("test -s");
 +  if (status != 0) {
 +    goto err_setup;
 +  }
 +
 +  status = option_test_run(argc, argv);
 +  if (status < 0) {
 +    goto err_wrong;
 +  }
 +
 +  if (!result.simple || result.another || result.multi_access ||
 +      result.long_parameter || result.value_parameter || result.unknown ||
 +      result.def || result.value != NULL) {
 +    goto err_wrong;
 +  }
 +
 +  destroy_args();
 +
 +  return EXIT_SUCCESS;
 +
 +err_wrong:
 +  destroy_args();
 +err_setup:
 +  return EXIT_FAILURE;
 +}
 +
 +int option_print(void)
 +{
 +  char buf[255];
 +  const char *expected;
 +  FILE *test_file;
 +
 +  expected = "  -s                   Simple flag\n"
 +             "  -a                   Another simple flag\n"
 +             "  -m, -M, -o, -O       Multiple access letters\n"
 +             "  --long               Long parameter name\n"
 +             "  -k, --key=VALUE      Parameter value\n";
 +
 +  test_file = tmpfile();
 +  if (test_file == NULL) {
 +    goto err_open;
 +  }
 +
 +  cag_option_print(options, CAG_ARRAY_SIZE(options), test_file);
 +  if (fseek(test_file, 0, SEEK_SET) != 0) {
 +    goto err_seek;
 +  }
 +
 +  if (fread(buf, sizeof(buf), 1, test_file) != 1 && feof(test_file) == 0) {
 +    goto err_read;
 +  }
 +
 +  if (memcmp(buf, expected, strlen(expected)) != 0) {
 +    goto err_test;
 +  }
 +
 +  fclose(test_file);
 +  return EXIT_SUCCESS;
 +
 +err_test:
 +err_read:
 +err_seek:
 +  fclose(test_file);
 +err_open:
 +  return EXIT_FAILURE;
 +}
 | 
