michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: // Support for _setmode michael@0: #include michael@0: #include michael@0: michael@0: #include "nsWindowsRestart.cpp" michael@0: michael@0: // CommandLineToArgvW may return different values for argv[0] since it contains michael@0: // the path to the binary that was executed so we prepend an argument that is michael@0: // quoted with a space to prevent argv[1] being appended to argv[0]. michael@0: #define DUMMY_ARG1 L"\"arg 1\" " michael@0: michael@0: #ifndef MAXPATHLEN michael@0: # ifdef PATH_MAX michael@0: # define MAXPATHLEN PATH_MAX michael@0: # elif defined(MAX_PATH) michael@0: # define MAXPATHLEN MAX_PATH michael@0: # elif defined(_MAX_PATH) michael@0: # define MAXPATHLEN _MAX_PATH michael@0: # elif defined(CCHMAXPATH) michael@0: # define MAXPATHLEN CCHMAXPATH michael@0: # else michael@0: # define MAXPATHLEN 1024 michael@0: # endif michael@0: #endif michael@0: michael@0: #define TEST_NAME L"XRE MakeCommandLine" michael@0: #define MAX_TESTS 100 michael@0: michael@0: // Verbose output can be enabled by defining VERBOSE 1 michael@0: #define VERBOSE 0 michael@0: michael@0: // Compares compareCmdLine with the output of MakeCommandLine. This is michael@0: // accomplished by converting inCmdLine to an argument list with michael@0: // CommandLineToArgvW and converting it back to a command line with michael@0: // MakeCommandLine. michael@0: static int michael@0: verifyCmdLineCreation(wchar_t *inCmdLine, michael@0: wchar_t *compareCmdLine, michael@0: bool passes, int testNum) michael@0: { michael@0: int rv = 0; michael@0: int i; michael@0: int inArgc; michael@0: int outArgc; michael@0: bool isEqual; michael@0: michael@0: // When debugging with command lines containing Unicode characters greater michael@0: // than 255 you can set the mode for stdout to Unicode so the console will michael@0: // receive the correct characters though it won't display them properly unless michael@0: // the console's font has been set to one that can display the characters. You michael@0: // can also redirect the console output to a file that has been saved as Unicode michael@0: // to view the characters. michael@0: // _setmode(_fileno(stdout), _O_WTEXT); michael@0: michael@0: // Prepend an additional argument to the command line. CommandLineToArgvW michael@0: // handles argv[0] differently than other arguments since argv[0] is the path michael@0: // to the binary being executed and MakeCommandLine only handles argv[1] and michael@0: // larger. michael@0: wchar_t *inCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(inCmdLine) + 1) * sizeof(wchar_t)); michael@0: wcscpy(inCmdLineNew, DUMMY_ARG1); michael@0: wcscat(inCmdLineNew, inCmdLine); michael@0: LPWSTR *inArgv = CommandLineToArgvW(inCmdLineNew, &inArgc); michael@0: michael@0: wchar_t *outCmdLine = MakeCommandLine(inArgc - 1, inArgv + 1); michael@0: wchar_t *outCmdLineNew = (wchar_t *) malloc((wcslen(DUMMY_ARG1) + wcslen(outCmdLine) + 1) * sizeof(wchar_t)); michael@0: wcscpy(outCmdLineNew, DUMMY_ARG1); michael@0: wcscat(outCmdLineNew, outCmdLine); michael@0: LPWSTR *outArgv = CommandLineToArgvW(outCmdLineNew, &outArgc); michael@0: michael@0: if (VERBOSE) { michael@0: wprintf(L"\n"); michael@0: wprintf(L"Verbose Output\n"); michael@0: wprintf(L"--------------\n"); michael@0: wprintf(L"Input command line : >%s<\n", inCmdLine); michael@0: wprintf(L"MakeComandLine output: >%s<\n", outCmdLine); michael@0: wprintf(L"Expected command line: >%s<\n", compareCmdLine); michael@0: michael@0: wprintf(L"input argc : %d\n", inArgc - 1); michael@0: wprintf(L"output argc: %d\n", outArgc - 1); michael@0: michael@0: for (i = 1; i < inArgc; ++i) { michael@0: wprintf(L"input argv[%d] : >%s<\n", i - 1, inArgv[i]); michael@0: } michael@0: michael@0: for (i = 1; i < outArgc; ++i) { michael@0: wprintf(L"output argv[%d]: >%s<\n", i - 1, outArgv[i]); michael@0: } michael@0: wprintf(L"\n"); michael@0: } michael@0: michael@0: isEqual = (inArgc == outArgc); michael@0: if (!isEqual) { michael@0: wprintf(L"TEST-%s-FAIL | %s | ARGC Comparison (check %2d)\n", michael@0: passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); michael@0: if (passes) { michael@0: rv = 1; michael@0: } michael@0: LocalFree(inArgv); michael@0: LocalFree(outArgv); michael@0: free(inCmdLineNew); michael@0: free(outCmdLineNew); michael@0: free(outCmdLine); michael@0: return rv; michael@0: } michael@0: michael@0: for (i = 1; i < inArgc; ++i) { michael@0: isEqual = (wcscmp(inArgv[i], outArgv[i]) == 0); michael@0: if (!isEqual) { michael@0: wprintf(L"TEST-%s-FAIL | %s | ARGV Comparison (check %2d)\n", michael@0: passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); michael@0: if (passes) { michael@0: rv = 1; michael@0: } michael@0: LocalFree(inArgv); michael@0: LocalFree(outArgv); michael@0: free(inCmdLineNew); michael@0: free(outCmdLineNew); michael@0: free(outCmdLine); michael@0: return rv; michael@0: } michael@0: } michael@0: michael@0: isEqual = (wcscmp(outCmdLine, compareCmdLine) == 0); michael@0: if (!isEqual) { michael@0: wprintf(L"TEST-%s-FAIL | %s | Command Line Comparison (check %2d)\n", michael@0: passes ? L"UNEXPECTED" : L"KNOWN", TEST_NAME, testNum); michael@0: if (passes) { michael@0: rv = 1; michael@0: } michael@0: LocalFree(inArgv); michael@0: LocalFree(outArgv); michael@0: free(inCmdLineNew); michael@0: free(outCmdLineNew); michael@0: free(outCmdLine); michael@0: return rv; michael@0: } michael@0: michael@0: if (rv == 0) { michael@0: if (passes) { michael@0: wprintf(L"TEST-PASS | %s | check %2d\n", TEST_NAME, testNum); michael@0: } else { michael@0: wprintf(L"TEST-UNEXPECTED-PASS | %s | check %2d\n", TEST_NAME, testNum); michael@0: rv = 1; michael@0: } michael@0: } michael@0: michael@0: LocalFree(inArgv); michael@0: LocalFree(outArgv); michael@0: free(inCmdLineNew); michael@0: free(outCmdLineNew); michael@0: free(outCmdLine); michael@0: return rv; michael@0: } michael@0: michael@0: int wmain(int argc, wchar_t *argv[]) michael@0: { michael@0: int i; michael@0: int rv = 0; michael@0: michael@0: if (argc > 1 && (_wcsicmp(argv[1], L"-check-one") != 0 || michael@0: _wcsicmp(argv[1], L"-check-one") == 0 && argc != 3)) { michael@0: fwprintf(stderr, L"Displays and validates output from MakeCommandLine.\n\n"); michael@0: fwprintf(stderr, L"Usage: %s -check-one \n\n", argv[0]); michael@0: fwprintf(stderr, L" \tSpecifies the test number to run from the\n"); michael@0: fwprintf(stderr, L"\t\tTestXREMakeCommandLineWin.ini file.\n"); michael@0: return 255; michael@0: } michael@0: michael@0: wchar_t inifile[MAXPATHLEN]; michael@0: if (!::GetModuleFileNameW(0, inifile, MAXPATHLEN)) { michael@0: wprintf(L"TEST-UNEXPECTED-FAIL | %s | GetModuleFileNameW\n", TEST_NAME); michael@0: return 2; michael@0: } michael@0: michael@0: WCHAR *slash = wcsrchr(inifile, '\\'); michael@0: if (!slash) { michael@0: wprintf(L"TEST-UNEXPECTED-FAIL | %s | wcsrchr\n", TEST_NAME); michael@0: return 3; michael@0: } michael@0: michael@0: wcscpy(slash + 1, L"TestXREMakeCommandLineWin.ini\0"); michael@0: michael@0: for (i = 0; i < MAX_TESTS; ++i) { michael@0: wchar_t sInputVal[MAXPATHLEN]; michael@0: wchar_t sOutputVal[MAXPATHLEN]; michael@0: wchar_t sPassesVal[MAXPATHLEN]; michael@0: wchar_t sInputKey[MAXPATHLEN]; michael@0: wchar_t sOutputKey[MAXPATHLEN]; michael@0: wchar_t sPassesKey[MAXPATHLEN]; michael@0: michael@0: if (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0 && argc == 3) { michael@0: i = _wtoi(argv[2]); michael@0: } michael@0: michael@0: _snwprintf(sInputKey, MAXPATHLEN, L"input_%d", i); michael@0: _snwprintf(sOutputKey, MAXPATHLEN, L"output_%d", i); michael@0: _snwprintf(sPassesKey, MAXPATHLEN, L"passes_%d", i); michael@0: michael@0: if (!GetPrivateProfileStringW(L"MakeCommandLineTests", sInputKey, nullptr, michael@0: sInputVal, MAXPATHLEN, inifile)) { michael@0: if (i == 0 || argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0) { michael@0: wprintf(L"TEST-UNEXPECTED-FAIL | %s | see following explanation:\n", TEST_NAME); michael@0: wprintf(L"ERROR: Either the TestXREMakeCommandLineWin.ini file doesn't exist\n"); michael@0: if (argc > 1 && _wcsicmp(argv[1], L"-check-one") == 0 && argc == 3) { michael@0: wprintf(L"ERROR: or the test is not defined in the MakeCommandLineTests section.\n"); michael@0: } else { michael@0: wprintf(L"ERROR: or it has no tests defined in the MakeCommandLineTests section.\n"); michael@0: } michael@0: wprintf(L"ERROR: File: %s\n", inifile); michael@0: return 4; michael@0: } michael@0: break; michael@0: } michael@0: michael@0: GetPrivateProfileStringW(L"MakeCommandLineTests", sOutputKey, nullptr, michael@0: sOutputVal, MAXPATHLEN, inifile); michael@0: GetPrivateProfileStringW(L"MakeCommandLineTests", sPassesKey, nullptr, michael@0: sPassesVal, MAXPATHLEN, inifile); michael@0: michael@0: rv |= verifyCmdLineCreation(sInputVal, sOutputVal, michael@0: (_wcsicmp(sPassesVal, L"false") == 0) ? FALSE : TRUE, michael@0: i); michael@0: michael@0: if (argc > 2 && _wcsicmp(argv[1], L"-check-one") == 0) { michael@0: break; michael@0: } michael@0: } michael@0: michael@0: if (rv == 0) { michael@0: wprintf(L"TEST-PASS | %s | all checks passed\n", TEST_NAME); michael@0: } else { michael@0: wprintf(L"TEST-UNEXPECTED-FAIL | %s | some checks failed\n", TEST_NAME); michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: #ifdef __MINGW32__ michael@0: michael@0: /* MingW currently does not implement a wide version of the michael@0: startup routines. Workaround is to implement something like michael@0: it ourselves. See bug 411826 */ michael@0: michael@0: #include michael@0: michael@0: int main(int argc, char **argv) michael@0: { michael@0: LPWSTR commandLine = GetCommandLineW(); michael@0: int argcw = 0; michael@0: LPWSTR *argvw = CommandLineToArgvW(commandLine, &argcw); michael@0: if (!argvw) michael@0: return 127; michael@0: michael@0: int result = wmain(argcw, argvw); michael@0: LocalFree(argvw); michael@0: return result; michael@0: } michael@0: #endif /* __MINGW32__ */