6ced8001ca2d535e1bf1fe21a06ebd2326d553ca
[platform/upstream/cmake.git] / Templates / TestDriver.cxx.in
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
30 typedef int (*MainFuncPointer)(int, char* []); /* NOLINT */
31 typedef struct /* NOLINT */
32 {
33   const char* name;
34   MainFuncPointer func;
35 } functionMapEntry;
36
37 static functionMapEntry cmakeGeneratedFunctionMapEntries[] = {
38   @CMAKE_FUNCTION_TABLE_ENTRIES@
39   { CM_NULL, CM_NULL } /* NOLINT */
40 };
41
42 static 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) */
47 static 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
66 int 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
77 int 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 = ((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 }