1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 11 февр. 2019 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef TEST_MAIN_CONFIG_H_ 23 #define TEST_MAIN_CONFIG_H_ 24 25 #include <core/types.h> 26 #include <core/stdlib/stdio.h> 27 #include <core/io/charset.h> 28 #include <test/main/types.h> 29 #include <data/cvector.h> 30 #include <unistd.h> 31 #include <errno.h> 32 33 34 namespace lsp 35 { 36 enum test_mode_t 37 { 38 UNKNOWN, 39 PTEST, 40 UTEST, 41 MTEST 42 }; 43 44 typedef struct config_t 45 { 46 public: 47 mode_t mode; 48 bool fork; 49 bool verbose; 50 bool debug; 51 bool list_all; 52 bool mtrace; 53 bool ilist; 54 bool sysinfo; 55 bool is_child; 56 size_t threads; 57 const char *executable; 58 const char *outfile; 59 const char *tracepath; 60 cvector<char> list; 61 cvector<char> ignore; 62 cvector<char> args; 63 64 #ifdef PLATFORM_WINDOWS 65 size_t utf8_argc; 66 char **utf8_argv; 67 #endif /* PLATFORM_WINDOWS */ 68 69 public: 70 explicit config_t(); ~config_tconfig_t71 ~config_t() { clear(); } 72 73 status_t parse(FILE *out, int argc, const char **argv); 74 status_t print_usage(FILE *out, bool detailed=false); 75 void clear(); 76 77 } config_t; 78 print_usage(FILE * out,bool detailed)79 status_t config_t::print_usage(FILE *out, bool detailed) 80 { 81 fputs("USAGE: {utest|ptest|mtest} [args...] [test name...]\n", out); 82 if (!detailed) 83 return STATUS_INSUFFICIENT; 84 85 fputs(" First argument:\n", out); 86 fputs(" utest Unit testing subsystem\n", out); 87 fputs(" ptest Performance testing subsystem\n", out); 88 fputs(" mtest Manual testing subsystem\n", out); 89 fputs(" Additional arguments:\n", out); 90 fputs(" -a, --args [args...] Pass arguments to test\n", out); 91 fputs(" -d, --debug Disable time restrictions for unit tests\n", out); 92 fputs(" for debugging purposes\n", out); 93 fputs(" -e, --execute Launch tests specified after this switch\n", out); 94 fputs(" -f, --fork Fork child processes (opposite to --nofork)\n", out); 95 fputs(" -h, --help Display help\n", out); 96 fputs(" -i, --ignore Ignore tests specified after this switch\n", out); 97 fputs(" -j, --jobs Set number of job workers for unit tests\n", out); 98 fputs(" -l, --list List all available tests\n", out); 99 #ifdef PLATFORM_LINUX 100 fputs(" -mt, --mtrace Enable mtrace log\n", out); 101 #endif /* PLATFORM_LINUX */ 102 fputs(" -nf, --nofork Do not fork child processes (for better \n", out); 103 fputs(" debugging capabilities)\n", out); 104 #ifdef PLATFORM_LINUX 105 fputs(" -nt, --nomtrace Disable mtrace log\n", out); 106 #endif /* PLATFORM_LINUX */ 107 fputs(" -nsi, --nosysinfo Do not output system information\n", out); 108 fputs(" -o, --outfile file Output performance test statistics to specified file\n", out); 109 fputs(" -s, --silent Do not output additional information from tests\n", out); 110 fputs(" -si, --sysinfo Output system information\n", out); 111 fputs(" -t, --tracepath path Override default trace path with specified value\n", out); 112 fputs(" -v, --verbose Output additional information from tests\n", out); 113 114 return STATUS_INSUFFICIENT; 115 } 116 parse(FILE * out,int argc,const char ** argv)117 status_t config_t::parse(FILE *out, int argc, const char **argv) 118 { 119 clear(); 120 121 #if defined(PLATFORM_WINDOWS) 122 // Get number of processors for system 123 SYSTEM_INFO os_sysinfo; 124 GetSystemInfo(&os_sysinfo); 125 threads = os_sysinfo.dwNumberOfProcessors; 126 127 // Get command line 128 LPWSTR cmdline = GetCommandLineW(); 129 int nargs = 0; 130 LPWSTR *arglist = CommandLineToArgvW(cmdline, &nargs); 131 if ((arglist == NULL) || (nargs < 1)) 132 { 133 fprintf(stderr, "Error obtaining command-line arguments\n"); 134 fflush(stderr); 135 return STATUS_UNKNOWN_ERR; 136 } 137 138 // Convert UTF-16-encoded command line arguments to UTF-8-encoded 139 utf8_argc = nargs; 140 utf8_argv = reinterpret_cast<char **>(malloc(nargs * sizeof(char *))); 141 for (size_t i=0; i<utf8_argc; ++i) 142 utf8_argv[i] = NULL; 143 for (size_t i=0; i<utf8_argc; ++i) 144 { 145 utf8_argv[i] = lsp::utf16_to_utf8(arglist[i]); 146 if (utf8_argv[i] == NULL) 147 return STATUS_NO_MEM; 148 } 149 150 LocalFree(arglist); 151 152 // Patch arguments 153 argc = utf8_argc; 154 argv = const_cast<const char **>(utf8_argv); 155 #else 156 threads = sysconf(_SC_NPROCESSORS_ONLN); 157 #endif /* PLATFORM_WINDOWS */ 158 159 if (argc < 2) 160 return print_usage(out); 161 162 executable = argv[0]; 163 164 if (!strcmp(argv[1], "ptest")) 165 mode = PTEST; 166 else if (!strcmp(argv[1], "utest")) 167 mode = UTEST; 168 else if (!strcmp(argv[1], "mtest")) 169 mode = MTEST; 170 else if ((!strcmp(argv[1], "--help")) || ((!strcmp(argv[1], "-h")))) 171 return print_usage(out, true); 172 else 173 return print_usage(out); 174 175 for (int i=2; i<argc; ++i) 176 { 177 if ((!strcmp(argv[i], "--nofork")) || (!strcmp(argv[i], "-nf"))) 178 fork = false; 179 else if ((!strcmp(argv[i], "--fork")) || (!strcmp(argv[i], "-f"))) 180 fork = true; 181 else if ((!strcmp(argv[i], "--verbose")) || (!strcmp(argv[i], "-v"))) 182 verbose = true; 183 else if ((!strcmp(argv[i], "--silent")) || (!strcmp(argv[i], "-s"))) 184 verbose = false; 185 else if ((!strcmp(argv[i], "--sysinfo")) || (!strcmp(argv[i], "-si"))) 186 sysinfo = true; 187 else if ((!strcmp(argv[i], "--nosysinfo")) || (!strcmp(argv[i], "-nsi"))) 188 sysinfo = false; 189 else if ((!strcmp(argv[i], "--debug")) || (!strcmp(argv[i], "-d"))) 190 debug = true; 191 else if ((!strcmp(argv[i], "--list")) || (!strcmp(argv[i], "-l"))) 192 list_all = true; 193 #ifdef PLATFORM_LINUX 194 else if ((!strcmp(argv[i], "--mtrace")) || (!strcmp(argv[i], "-mt"))) 195 mtrace = true; 196 else if ((!strcmp(argv[i], "--nomtrace")) || (!strcmp(argv[i], "-nt"))) 197 mtrace = false; 198 #endif /* PLATFORM_LINUX */ 199 else if ((!strcmp(argv[i], "--tracepath")) || (!strcmp(argv[i], "-t"))) 200 { 201 if ((++i) >= argc) 202 { 203 fprintf(stderr, "Not specified trace path\n"); 204 return STATUS_INVALID_VALUE; 205 } 206 tracepath = argv[i]; 207 } 208 else if ((!strcmp(argv[i], "--outfile")) || (!strcmp(argv[i], "-o"))) 209 { 210 if ((++i) >= argc) 211 { 212 fprintf(stderr, "Not specified name of output file\n"); 213 return STATUS_INVALID_VALUE; 214 } 215 outfile = argv[i]; 216 } 217 else if ((!strcmp(argv[i], "--args")) || (!strcmp(argv[i], "-a"))) 218 { 219 while (++i < argc) 220 args.add(const_cast<char *>(argv[i])); 221 } 222 else if ((!strcmp(argv[i], "--jobs")) || (!strcmp(argv[i], "-j"))) 223 { 224 if ((++i) >= argc) 225 { 226 fprintf(stderr, "Not specified number of jobs for --jobs parameter\n"); 227 return STATUS_INVALID_VALUE; 228 } 229 230 errno = 0; 231 char *end = NULL; 232 long jobs = strtol(argv[i], &end, 10); 233 if ((errno != 0) || ((*end) != '\0') || (jobs <= 0)) 234 { 235 fprintf(stderr, "Invalid value for --jobs parameter: %s\n", argv[i]); 236 return STATUS_INVALID_VALUE; 237 } 238 threads = size_t(jobs); 239 } 240 else if ((!strcmp(argv[i], "--help")) || ((!strcmp(argv[i], "-h")))) 241 return print_usage(out, true); 242 else if ((!strcmp(argv[i], "--ignore")) || ((!strcmp(argv[i], "-i")))) 243 ilist = true; 244 else if ((!strcmp(argv[i], "--execute")) || ((!strcmp(argv[i], "-e")))) 245 ilist = false; 246 #ifdef PLATFORM_WINDOWS 247 else if (!strcmp(argv[i], "--run-as-nested-process")) 248 is_child = true; 249 #endif /* PLATFORM_WINDOWS */ 250 else 251 { 252 if (ilist) 253 ignore.add(const_cast<char *>(argv[i])); 254 else 255 list.add(const_cast<char *>(argv[i])); 256 } 257 } 258 259 return 0; 260 } 261 config_t()262 config_t::config_t() 263 { 264 mode = UNKNOWN; 265 fork = true; 266 verbose = false; 267 debug = false; 268 list_all = false; 269 mtrace = false; 270 ilist = false; 271 sysinfo = true; 272 is_child = false; 273 executable = NULL; 274 tracepath = "/tmp/lsp-plugins-trace"; 275 outfile = NULL; 276 threads = 1; 277 278 #if defined(PLATFORM_WINDOWS) 279 utf8_argc = 0; 280 utf8_argv = NULL; 281 #endif 282 } 283 clear()284 void config_t::clear() 285 { 286 #if defined(PLATFORM_WINDOWS) 287 if (utf8_argv != NULL) 288 { 289 for (size_t i=0; i<utf8_argc; ++i) 290 { 291 if (utf8_argv[i] != NULL) 292 free(utf8_argv[i]); 293 } 294 free(utf8_argv); 295 296 utf8_argv = NULL; 297 utf8_argc = 0; 298 } 299 #endif /* PLATFORM_WINDOWS */ 300 list.flush(); 301 ignore.flush(); 302 args.flush(); 303 } 304 } 305 306 #endif /* TEST_MAIN_CONFIG_H_ */ 307