1#include <ctype.h>  /* NOLINT */
2#include <stdio.h>  /* NOLINT */
3#include <stdlib.h> /* NOLINT */
4#include <string.h> /* NOLINT */
5#include <time.h>   /* NOLINT */
6
7#if defined(_MSC_VER)
8#pragma warning(disable : 4996) /* deprecation */
9#endif
10
11@CMAKE_TESTDRIVER_EXTRA_INCLUDES@
12
13/* Forward declare test functions. */
14@CMAKE_FORWARD_DECLARE_TESTS@
15
16#ifdef __cplusplus
17#  define CM_CAST(TYPE, EXPR) static_cast<TYPE>(EXPR)
18#  if __cplusplus >= 201103L
19#    define CM_NULL nullptr
20#  else
21#    define CM_NULL NULL
22#  endif
23#else
24#  define CM_CAST(TYPE, EXPR) (TYPE)(EXPR)
25#  define CM_NULL NULL
26#endif
27
28/* Create map.  */
29
30typedef int (*MainFuncPointer)(int, char* []); /* NOLINT */
31typedef struct /* NOLINT */
32{
33  const char* name;
34  MainFuncPointer func;
35} functionMapEntry;
36
37static functionMapEntry cmakeGeneratedFunctionMapEntries[] = {
38  @CMAKE_FUNCTION_TABLE_ENTRIES@
39  { CM_NULL, CM_NULL } /* NOLINT */
40};
41
42static const int NumTests = CM_CAST(int,
43  sizeof(cmakeGeneratedFunctionMapEntries) / sizeof(functionMapEntry)) - 1;
44
45/* Allocate and create a lowercased copy of string
46   (note that it has to be free'd manually) */
47static char* lowercase(const char* string)
48{
49  char *new_string;
50  char *p;
51  size_t stringSize;
52
53  stringSize = CM_CAST(size_t, strlen(string) + 1);
54  new_string = CM_CAST(char*, malloc(sizeof(char) * stringSize));
55
56  if (new_string == CM_NULL) { /* NOLINT */
57    return CM_NULL;            /* NOLINT */
58  }
59  strcpy(new_string, string);  /* NOLINT */
60  for (p = new_string; *p != 0; ++p) {
61    *p = CM_CAST(char, tolower(*p));
62  }
63  return new_string;
64}
65
66int isTestSkipped(const char *name, int n_skipped_tests, char *skipped_tests[]) {
67  int i;
68  for (i = 0; i < n_skipped_tests; i++) {
69    if (strcmp(name, skipped_tests[i]) == 0) {
70      return 1;
71    }
72  }
73
74  return 0;
75}
76
77int main(int ac, char* av[])
78{
79  int i;
80  int testNum = 0;
81  int partial_match;
82  int run_all;
83  char *arg;
84  int testToRun = -1;
85
86  @CMAKE_TESTDRIVER_ARGVC_FUNCTION@
87
88  /* If no test name was given */
89  /* process command line with user function.  */
90  if (ac < 2) {
91    /* Ask for a test.  */
92    printf("Available tests:\n");
93    for (i = 0; i < NumTests; ++i) {
94      printf("%3d. %s\n", i, cmakeGeneratedFunctionMapEntries[i].name);
95    }
96    printf("To run a test, enter the test number: ");
97    fflush(stdout);
98    if (scanf("%d", &testNum) != 1) {
99      printf("Couldn't parse that input as a number\n");
100      return -1;
101    }
102    if (testNum >= NumTests) {
103      printf("%3d is an invalid test number.\n", testNum);
104      return -1;
105    }
106    testToRun = testNum;
107    ac--;
108    av++;
109  }
110  partial_match = 0;
111  run_all = 0;
112  arg = CM_NULL; /* NOLINT */
113  /* If partial match or running all tests are requested.  */
114  if (testToRun == -1 && ac > 1) {
115    partial_match = (strcmp(av[1], "-R") == 0) ? 1 : 0;
116    run_all = (strcmp(av[1], "-A") == 0) ? 1 : 0;
117  }
118  if (partial_match != 0 && ac < 3) {
119    printf("-R needs an additional parameter.\n");
120    return -1;
121  }
122  if (run_all == 1) {
123    clock_t t;
124    int status = 0;
125    const char* status_message = CM_NULL;
126    printf("TAP version 13\n");
127    printf("1..%d\n", NumTests);
128    for (i = 0; i < NumTests; ++i) {
129      const char *name = cmakeGeneratedFunctionMapEntries[i].name;
130      if (ac > 2) {
131        if (isTestSkipped(name, ac - 2, av + 2) == 1) {
132          printf("ok %d %s # SKIP\n", i + 1, name);
133          continue;
134        }
135      }
136      t = clock();
137      status = (*cmakeGeneratedFunctionMapEntries[i].func)(ac, av);
138      t = clock() - t;
139      status_message = (status == -1) ? "not ok" : "ok";
140      {
141        double time_taken = CM_CAST(double, t) / CLOCKS_PER_SEC;
142        printf("%s %d %s # %f\n", status_message, i + 1, name, time_taken);
143      }
144    }
145    printf("All tests finished.\n");
146
147    return 0;
148  }
149
150  if (testToRun == -1) {
151    arg = lowercase(av[1 + partial_match]);
152  }
153  for (i = 0; i < NumTests && testToRun == -1; ++i) {
154    char *test_name = lowercase(cmakeGeneratedFunctionMapEntries[i].name);
155    if (partial_match != 0 && strstr(test_name, arg) != CM_NULL) { /* NOLINT */
156      testToRun = i;
157      ac -= 2;
158      av += 2;
159    } else if (partial_match == 0 && strcmp(test_name, arg) == 0) {
160      testToRun = i;
161      ac--;
162      av++;
163    }
164    free(test_name);
165  }
166  free(arg);
167  if (testToRun != -1) {
168    int result;
169@CMAKE_TESTDRIVER_BEFORE_TESTMAIN@
170    if (testToRun < 0 || testToRun >= NumTests) {
171      printf("testToRun was modified by TestDriver code to an invalid value: "
172             "%3d.\n",
173             testNum);
174      return -1;
175    }
176    result = (*cmakeGeneratedFunctionMapEntries[testToRun].func)(ac, av);
177@CMAKE_TESTDRIVER_AFTER_TESTMAIN@
178    return result;
179  }
180
181  /* Nothing was run, display the test names.  */
182  printf("Available tests:\n");
183  for (i = 0; i < NumTests; ++i) {
184    printf("%3d. %s\n", i, cmakeGeneratedFunctionMapEntries[i].name);
185  }
186  printf("Failed: %s is an invalid test name.\n", av[1]);
187
188  return -1;
189}
190