1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/xre/test/win/TestXREMakeCommandLineWin.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,266 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include <stdio.h> 1.10 +#include <stdlib.h> 1.11 +#include <windows.h> 1.12 +// Support for _setmode 1.13 +#include <fcntl.h> 1.14 +#include <io.h> 1.15 + 1.16 +#include "nsWindowsRestart.cpp" 1.17 + 1.18 +// CommandLineToArgvW may return different values for argv[0] since it contains 1.19 +// the path to the binary that was executed so we prepend an argument that is 1.20 +// quoted with a space to prevent argv[1] being appended to argv[0]. 1.21 +#define DUMMY_ARG1 L"\"arg 1\" " 1.22 + 1.23 +#ifndef MAXPATHLEN 1.24 +# ifdef PATH_MAX 1.25 +# define MAXPATHLEN PATH_MAX 1.26 +# elif defined(MAX_PATH) 1.27 +# define MAXPATHLEN MAX_PATH 1.28 +# elif defined(_MAX_PATH) 1.29 +# define MAXPATHLEN _MAX_PATH 1.30 +# elif defined(CCHMAXPATH) 1.31 +# define MAXPATHLEN CCHMAXPATH 1.32 +# else 1.33 +# define MAXPATHLEN 1024 1.34 +# endif 1.35 +#endif 1.36 + 1.37 +#define TEST_NAME L"XRE MakeCommandLine" 1.38 +#define MAX_TESTS 100 1.39 + 1.40 +// Verbose output can be enabled by defining VERBOSE 1 1.41 +#define VERBOSE 0 1.42 + 1.43 +// Compares compareCmdLine with the output of MakeCommandLine. This is 1.44 +// accomplished by converting inCmdLine to an argument list with 1.45 +// CommandLineToArgvW and converting it back to a command line with 1.46 +// MakeCommandLine. 1.47 +static int 1.48 +verifyCmdLineCreation(wchar_t *inCmdLine, 1.49 + wchar_t *compareCmdLine, 1.50 + bool passes, int testNum) 1.51 +{ 1.52 + int rv = 0; 1.53 + int i; 1.54 + int inArgc; 1.55 + int outArgc; 1.56 + bool isEqual; 1.57 + 1.58 + // When debugging with command lines containing Unicode characters greater 1.59 + // than 255 you can set the mode for stdout to Unicode so the console will 1.60 + // receive the correct characters though it won't display them properly unless 1.61 + // the console's font has been set to one that can display the characters. You 1.62 + // can also redirect the console output to a file that has been saved as Unicode 1.63 + // to view the characters. 1.64 +// _setmode(_fileno(stdout), _O_WTEXT); 1.65 + 1.66 + // Prepend an additional argument to the command line. CommandLineToArgvW 1.67 + // handles argv[0] differently than other arguments since argv[0] is the path 1.68 + // to the binary being executed and MakeCommandLine only handles argv[1] and 1.69 + // larger. 1.70 + wchar_t *inCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(inCmdLine) + 1) * sizeof(wchar_t)); 1.71 + wcscpy(inCmdLineNew, DUMMY_ARG1); 1.72 + wcscat(inCmdLineNew, inCmdLine); 1.73 + LPWSTR *inArgv = CommandLineToArgvW(inCmdLineNew, &inArgc); 1.74 + 1.75 + wchar_t *outCmdLine = MakeCommandLine(inArgc - 1, inArgv + 1); 1.76 + wchar_t *outCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(outCmdLine) + 1) * sizeof(wchar_t)); 1.77 + wcscpy(outCmdLineNew, DUMMY_ARG1); 1.78 + wcscat(outCmdLineNew, outCmdLine); 1.79 + LPWSTR *outArgv = CommandLineToArgvW(outCmdLineNew, &outArgc); 1.80 + 1.81 + if (VERBOSE) { 1.82 + wprintf(L"\n"); 1.83 + wprintf(L"Verbose Output\n"); 1.84 + wprintf(L"--------------\n"); 1.85 + wprintf(L"Input command line : >%s<\n", inCmdLine); 1.86 + wprintf(L"MakeComandLine output: >%s<\n", outCmdLine); 1.87 + wprintf(L"Expected command line: >%s<\n", compareCmdLine); 1.88 + 1.89 + wprintf(L"input argc : %d\n", inArgc - 1); 1.90 + wprintf(L"output argc: %d\n", outArgc - 1); 1.91 + 1.92 + for (i = 1; i < inArgc; ++i) { 1.93 + wprintf(L"input argv[%d] : >%s<\n", i - 1, inArgv[i]); 1.94 + } 1.95 + 1.96 + for (i = 1; i < outArgc; ++i) { 1.97 + wprintf(L"output argv[%d]: >%s<\n", i - 1, outArgv[i]); 1.98 + } 1.99 + wprintf(L"\n"); 1.100 + } 1.101 + 1.102 + isEqual = (inArgc == outArgc); 1.103 + if (!isEqual) { 1.104 + wprintf(L"TEST-%s-FAIL | %s | ARGC Comparison (check %2d)\n", 1.105 + passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); 1.106 + if (passes) { 1.107 + rv = 1; 1.108 + } 1.109 + LocalFree(inArgv); 1.110 + LocalFree(outArgv); 1.111 + free(inCmdLineNew); 1.112 + free(outCmdLineNew); 1.113 + free(outCmdLine); 1.114 + return rv; 1.115 + } 1.116 + 1.117 + for (i = 1; i < inArgc; ++i) { 1.118 + isEqual = (wcscmp(inArgv[i], outArgv[i]) == 0); 1.119 + if (!isEqual) { 1.120 + wprintf(L"TEST-%s-FAIL | %s | ARGV Comparison (check %2d)\n", 1.121 + passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); 1.122 + if (passes) { 1.123 + rv = 1; 1.124 + } 1.125 + LocalFree(inArgv); 1.126 + LocalFree(outArgv); 1.127 + free(inCmdLineNew); 1.128 + free(outCmdLineNew); 1.129 + free(outCmdLine); 1.130 + return rv; 1.131 + } 1.132 + } 1.133 + 1.134 + isEqual = (wcscmp(outCmdLine, compareCmdLine) == 0); 1.135 + if (!isEqual) { 1.136 + wprintf(L"TEST-%s-FAIL | %s | Command Line Comparison (check %2d)\n", 1.137 + passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); 1.138 + if (passes) { 1.139 + rv = 1; 1.140 + } 1.141 + LocalFree(inArgv); 1.142 + LocalFree(outArgv); 1.143 + free(inCmdLineNew); 1.144 + free(outCmdLineNew); 1.145 + free(outCmdLine); 1.146 + return rv; 1.147 + } 1.148 + 1.149 + if (rv == 0) { 1.150 + if (passes) { 1.151 + wprintf(L"TEST-PASS | %s | check %2d\n", TEST_NAME, testNum); 1.152 + } else { 1.153 + wprintf(L"TEST-UNEXPECTED-PASS | %s | check %2d\n", TEST_NAME, testNum); 1.154 + rv = 1; 1.155 + } 1.156 + } 1.157 + 1.158 + LocalFree(inArgv); 1.159 + LocalFree(outArgv); 1.160 + free(inCmdLineNew); 1.161 + free(outCmdLineNew); 1.162 + free(outCmdLine); 1.163 + return rv; 1.164 +} 1.165 + 1.166 +int wmain(int argc, wchar_t *argv[]) 1.167 +{ 1.168 + int i; 1.169 + int rv = 0; 1.170 + 1.171 + if (argc > 1 && (_wcsicmp(argv[1], L"-check-one") != 0 || 1.172 + _wcsicmp(argv[1], L"-check-one") == 0 && argc != 3)) { 1.173 + fwprintf(stderr, L"Displays and validates output from MakeCommandLine.\n\n"); 1.174 + fwprintf(stderr, L"Usage: %s -check-one <test number>\n\n", argv[0]); 1.175 + fwprintf(stderr, L" <test number>\tSpecifies the test number to run from the\n"); 1.176 + fwprintf(stderr, L"\t\tTestXREMakeCommandLineWin.ini file.\n"); 1.177 + return 255; 1.178 + } 1.179 + 1.180 + wchar_t inifile[MAXPATHLEN]; 1.181 + if (!::GetModuleFileNameW(0, inifile, MAXPATHLEN)) { 1.182 + wprintf(L"TEST-UNEXPECTED-FAIL | %s | GetModuleFileNameW\n", TEST_NAME); 1.183 + return 2; 1.184 + } 1.185 + 1.186 + WCHAR *slash = wcsrchr(inifile, '\\'); 1.187 + if (!slash) { 1.188 + wprintf(L"TEST-UNEXPECTED-FAIL | %s | wcsrchr\n", TEST_NAME); 1.189 + return 3; 1.190 + } 1.191 + 1.192 + wcscpy(slash + 1, L"TestXREMakeCommandLineWin.ini\0"); 1.193 + 1.194 + for (i = 0; i < MAX_TESTS; ++i) { 1.195 + wchar_t sInputVal[MAXPATHLEN]; 1.196 + wchar_t sOutputVal[MAXPATHLEN]; 1.197 + wchar_t sPassesVal[MAXPATHLEN]; 1.198 + wchar_t sInputKey[MAXPATHLEN]; 1.199 + wchar_t sOutputKey[MAXPATHLEN]; 1.200 + wchar_t sPassesKey[MAXPATHLEN]; 1.201 + 1.202 + if (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0 && argc == 3) { 1.203 + i = _wtoi(argv[2]); 1.204 + } 1.205 + 1.206 + _snwprintf(sInputKey, MAXPATHLEN, L"input_%d", i); 1.207 + _snwprintf(sOutputKey, MAXPATHLEN, L"output_%d", i); 1.208 + _snwprintf(sPassesKey, MAXPATHLEN, L"passes_%d", i); 1.209 + 1.210 + if (!GetPrivateProfileStringW(L"MakeCommandLineTests", sInputKey, nullptr, 1.211 + sInputVal, MAXPATHLEN, inifile)) { 1.212 + if (i == 0 || argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0) { 1.213 + wprintf(L"TEST-UNEXPECTED-FAIL | %s | see following explanation:\n", TEST_NAME); 1.214 + wprintf(L"ERROR: Either the TestXREMakeCommandLineWin.ini file doesn't exist\n"); 1.215 + if (argc > 1 && _wcsicmp(argv[1], L"-check-one") == 0 && argc == 3) { 1.216 + wprintf(L"ERROR: or the test is not defined in the MakeCommandLineTests section.\n"); 1.217 + } else { 1.218 + wprintf(L"ERROR: or it has no tests defined in the MakeCommandLineTests section.\n"); 1.219 + } 1.220 + wprintf(L"ERROR: File: %s\n", inifile); 1.221 + return 4; 1.222 + } 1.223 + break; 1.224 + } 1.225 + 1.226 + GetPrivateProfileStringW(L"MakeCommandLineTests", sOutputKey, nullptr, 1.227 + sOutputVal, MAXPATHLEN, inifile); 1.228 + GetPrivateProfileStringW(L"MakeCommandLineTests", sPassesKey, nullptr, 1.229 + sPassesVal, MAXPATHLEN, inifile); 1.230 + 1.231 + rv |= verifyCmdLineCreation(sInputVal, sOutputVal, 1.232 + (_wcsicmp(sPassesVal, L"false") == 0) ? FALSE : TRUE, 1.233 + i); 1.234 + 1.235 + if (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0) { 1.236 + break; 1.237 + } 1.238 + } 1.239 + 1.240 + if (rv == 0) { 1.241 + wprintf(L"TEST-PASS | %s | all checks passed\n", TEST_NAME); 1.242 + } else { 1.243 + wprintf(L"TEST-UNEXPECTED-FAIL | %s | some checks failed\n", TEST_NAME); 1.244 + } 1.245 + 1.246 + return rv; 1.247 +} 1.248 + 1.249 +#ifdef __MINGW32__ 1.250 + 1.251 +/* MingW currently does not implement a wide version of the 1.252 + startup routines. Workaround is to implement something like 1.253 + it ourselves. See bug 411826 */ 1.254 + 1.255 +#include <shellapi.h> 1.256 + 1.257 +int main(int argc, char **argv) 1.258 +{ 1.259 + LPWSTR commandLine = GetCommandLineW(); 1.260 + int argcw = 0; 1.261 + LPWSTR *argvw = CommandLineToArgvW(commandLine, &argcw); 1.262 + if (!argvw) 1.263 + return 127; 1.264 + 1.265 + int result = wmain(argcw, argvw); 1.266 + LocalFree(argvw); 1.267 + return result; 1.268 +} 1.269 +#endif /* __MINGW32__ */