Path: blob/master/test/hotspot/gtest/runtime/test_os_windows.cpp
41144 views
/*1* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"2425#ifdef _WINDOWS2627#include "logging/log.hpp"28#include "runtime/os.hpp"29#include "runtime/flags/flagSetting.hpp"30#include "runtime/globals_extension.hpp"31#include "concurrentTestRunner.inline.hpp"32#include "unittest.hpp"3334namespace {35class MemoryReleaser {36char* const _ptr;37const size_t _size;38public:39MemoryReleaser(char* ptr, size_t size) : _ptr(ptr), _size(size) { }40~MemoryReleaser() {41if (_ptr != NULL) {42os::release_memory_special(_ptr, _size);43}44}45};46}4748// test tries to allocate memory in a single contiguous memory block at a particular address.49// The test first tries to find a good approximate address to allocate at by using the same50// method to allocate some memory at any address. The test then tries to allocate memory in51// the vicinity (not directly after it to avoid possible by-chance use of that location)52// This is of course only some dodgy assumption, there is no guarantee that the vicinity of53// the previously allocated memory is available for allocation. The only actual failure54// that is reported is when the test tries to allocate at a particular location but gets a55// different valid one. A NULL return value at this point is not considered an error but may56// be legitimate.57void TestReserveMemorySpecial_test() {58if (!UseLargePages) {59return;60}6162// set globals to make sure we hit the correct code path63AutoSaveRestore<bool> FLAG_GUARD(UseLargePagesIndividualAllocation);64AutoSaveRestore<bool> FLAG_GUARD(UseNUMAInterleaving);65FLAG_SET_CMDLINE(UseLargePagesIndividualAllocation, false);66FLAG_SET_CMDLINE(UseNUMAInterleaving, false);6768const size_t large_allocation_size = os::large_page_size() * 4;69char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), os::large_page_size(), NULL, false);70if (result == NULL) {71// failed to allocate memory, skipping the test72return;73}74MemoryReleaser m1(result, large_allocation_size);7576// Reserve another page within the recently allocated memory area. This should fail77const size_t expected_allocation_size = os::large_page_size();78char* expected_location = result + os::large_page_size();79char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, false);80EXPECT_TRUE(actual_location == NULL) << "Should not be allowed to reserve within present reservation";8182// Instead try reserving after the first reservation.83expected_location = result + large_allocation_size;84actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, false);85EXPECT_TRUE(actual_location != NULL) << "Unexpected reservation failure, can’t verify correct location";86EXPECT_TRUE(actual_location == expected_location) << "Reservation must be at requested location";87MemoryReleaser m2(actual_location, os::large_page_size());8889// Now try to do a reservation with a larger alignment.90const size_t alignment = os::large_page_size() * 2;91const size_t new_large_size = alignment * 4;92char* aligned_request = os::reserve_memory_special(new_large_size, alignment, os::large_page_size(), NULL, false);93EXPECT_TRUE(aligned_request != NULL) << "Unexpected reservation failure, can’t verify correct alignment";94EXPECT_TRUE(is_aligned(aligned_request, alignment)) << "Returned address must be aligned";95MemoryReleaser m3(aligned_request, new_large_size);96}9798// The types of path modifications we randomly apply to a path. They should not change the file designated by the path.99enum ModsFilter {100Allow_None = 0, // No modifications101Allow_Sep_Mods = 1, // Replace '\\' by any sequence of '/' or '\\' or at least length 1.102Allow_Dot_Path = 2, // Add /. segments at random positions103Allow_Dot_Dot_Path = 4, // Add /../<correct-dir> segments at random positions.104Allow_All = Allow_Sep_Mods | Allow_Dot_Path | Allow_Dot_Dot_Path105};106107// The mode in which to run.108enum Mode {109TEST, // Runs the test. This is the normal modus.110EXAMPLES, // Runs example which document the behaviour of the Windows system calls.111BENCH // Runs a small benchmark which tries to show the costs of using the *W variants/_wfullpath.112};113114// Parameters of the test.115static ModsFilter mods_filter = Allow_All;116static int mods_per_path = 50; // The number of variants of a path we try.117static Mode mode = TEST;118119120// Utility methods121static void get_current_dir_w(wchar_t* path, size_t size) {122DWORD count = GetCurrentDirectoryW((DWORD) size, path);123EXPECT_GT((int) count, 0) << "Failed to get current directory: " << GetLastError();124EXPECT_LT((size_t) count, size) << "Buffer too small for current directory: " << size;125}126127#define WITH_ABS_PATH(path) \128wchar_t abs_path[JVM_MAXPATHLEN]; \129wchar_t cwd[JVM_MAXPATHLEN]; \130get_current_dir_w(cwd, JVM_MAXPATHLEN); \131wsprintfW(abs_path, L"\\\\?\\%ls\\%ls", cwd, (path))132133static bool file_exists_w(const wchar_t* path) {134WIN32_FILE_ATTRIBUTE_DATA file_data;135return ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data);136}137138static void create_rel_directory_w(const wchar_t* path) {139WITH_ABS_PATH(path);140EXPECT_FALSE(file_exists_w(abs_path)) << "Can't create directory: \"" << path << "\" already exists";141BOOL result = CreateDirectoryW(abs_path, NULL);142EXPECT_TRUE(result) << "Failed to create directory \"" << path << "\" " << GetLastError();143}144145static void delete_empty_rel_directory_w(const wchar_t* path) {146WITH_ABS_PATH(path);147EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete directory: \"" << path << "\" does not exists";148const int retry_count = 20;149150// If the directory cannot be deleted directly, a file in it might be kept151// open by a virus scanner. Try a few times, since this should be temporary.152for (int i = 0; i <= retry_count; ++i) {153BOOL result = RemoveDirectoryW(abs_path);154155if (!result && (i < retry_count)) {156Sleep(1);157} else {158EXPECT_TRUE(result) << "Failed to delete directory \"" << path << "\": " << GetLastError();159return;160}161}162}163164static void create_rel_file_w(const wchar_t* path) {165WITH_ABS_PATH(path);166EXPECT_FALSE(file_exists_w(abs_path)) << "Can't create file: \"" << path << "\" already exists";167HANDLE h = CreateFileW(abs_path, 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);168EXPECT_NE(h, INVALID_HANDLE_VALUE) << "Failed to create file \"" << path << "\": " << GetLastError();169CloseHandle(h);170}171172static void delete_rel_file_w(const wchar_t* path) {173WITH_ABS_PATH(path);174EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete file: \"" << path << "\" does not exists";175BOOL result = DeleteFileW(abs_path);176EXPECT_TRUE(result) << "Failed to delete file \"" << path << "\": " << GetLastError();177}178179static bool convert_to_cstring(char* c_str, size_t size, wchar_t* w_str) {180size_t converted;181errno_t err = wcstombs_s(&converted, c_str, size, w_str, size - 1);182EXPECT_EQ(err, ERROR_SUCCESS) << "Could not convert \"" << w_str << "\" to c-string";183184return err == ERROR_SUCCESS;185}186187static wchar_t* my_wcscpy_s(wchar_t* dest, size_t size, wchar_t* start, const wchar_t* to_copy) {188size_t already_used = dest - start;189size_t len = wcslen(to_copy);190191if (already_used + len < size) {192wcscpy_s(dest, size - already_used, to_copy);193}194195return dest + wcslen(to_copy);196}197198// The currently finite list of seperator sequences we might use instead of '\\'.199static const wchar_t* sep_replacements[] = {200L"\\", L"\\/", L"/", L"//", L"\\\\/\\", L"//\\/"201};202203// Takes a path and modifies it in a way that it should still designate the same file.204static bool unnormalize_path(wchar_t* result, size_t size, bool is_dir, const wchar_t* path) {205wchar_t* dest = result;206const wchar_t* src = path;207const wchar_t* path_start;208209if (wcsncmp(src, L"\\\\?\\UNC\\", 8) == 0) {210path_start = src + 8;211} else if (wcsncmp(src, L"\\\\?\\", 4) == 0) {212if (src[5] == L':') {213path_start = src + 6;214} else {215path_start = wcschr(src + 4, L'\\');216}217} else if (wcsncmp(src, L"\\\\", 2) == 0) {218path_start = wcschr(src + 2, L'?');219220if (path_start == NULL) {221path_start = wcschr(src + 2, L'\\');222} else {223path_start = wcschr(path_start, L'\\');224}225} else {226path_start = wcschr(src + 1, L'\\');227}228229bool allow_sep_change = (mods_filter & Allow_Sep_Mods) && (os::random() & 1) == 0;230bool allow_dot_change = (mods_filter & Allow_Dot_Path) && (os::random() & 1) == 0;231bool allow_dotdot_change = (mods_filter & Allow_Dot_Dot_Path) && (os::random() & 1) == 0;232233while ((*src != L'\0') && (result + size > dest)) {234wchar_t c = *src;235*dest = c;236++src;237++dest;238239if (c == L'\\') {240if (allow_sep_change && (os::random() & 3) == 3) {241int i = os::random() % (sizeof(sep_replacements) / sizeof(sep_replacements[0]));242243if (i >= 0) {244const wchar_t* replacement = sep_replacements[i];245dest = my_wcscpy_s(dest - 1, size, result, replacement);246}247} else if (path_start != NULL) {248if (allow_dotdot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) {249wchar_t const* last_sep = src - 2;250251while (last_sep[0] != L'\\') {252--last_sep;253}254255if (last_sep > path_start) {256dest = my_wcscpy_s(dest, size, result, L"../");257src = last_sep + 1;258}259} else if (allow_dot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) {260dest = my_wcscpy_s(dest, size, result, L"./");261}262}263}264}265266while (is_dir && ((os::random() & 15) == 1)) {267dest = my_wcscpy_s(dest, size, result, L"/");268}269270if (result + size > dest) {271*dest = L'\0';272}273274// Use this modification only if not too close to the max size.275return result + size - 10 > dest;276}277278static void check_dir_impl(wchar_t* path, bool should_be_empty) {279char buf[JVM_MAXPATHLEN];280281if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {282struct stat st;283EXPECT_EQ(os::stat(buf, &st), 0) << "os::stat failed for \"" << path << "\"";284EXPECT_EQ(st.st_mode & S_IFMT, S_IFDIR) << "\"" << path << "\" is not a directory according to os::stat";285errno = ERROR_SUCCESS;286bool is_empty = os::dir_is_empty(buf);287errno_t err = errno;288EXPECT_EQ(is_empty, should_be_empty) << "os::dir_is_empty assumed \"" << path << "\" is "289<< (should_be_empty ? "not ": "") << "empty";290EXPECT_EQ(err, ERROR_SUCCESS) << "os::dir_is_empty failed for \"" << path << "\"with errno " << err;291}292}293294static void check_file_impl(wchar_t* path) {295char buf[JVM_MAXPATHLEN];296297if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {298struct stat st;299EXPECT_EQ(os::stat(buf, &st), 0) << "os::stat failed for \"" << path << "\"";300EXPECT_EQ(st.st_mode & S_IFMT, S_IFREG) << "\"" << path << "\" is not a regular file according to os::stat";301int fd = os::open(buf, O_RDONLY, 0);302EXPECT_NE(fd, -1) << "os::open failed for \"" << path << "\" with errno " << errno;303if (fd >= 0) {304::close(fd);305}306}307}308309static void check_file_not_present_impl(wchar_t* path) {310char buf[JVM_MAXPATHLEN];311312if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {313struct stat st;314int stat_ret;315EXPECT_EQ(stat_ret = os::stat(buf, &st), -1) << "os::stat did not fail for \"" << path << "\"";316if (stat_ret != -1) {317// Only check open if stat not already failed.318int fd = os::open(buf, O_RDONLY, 0);319EXPECT_EQ(fd, -1) << "os::open did not fail for \"" << path << "\"";320if (fd >= 0) {321::close(fd);322}323}324}325}326327static void check_dir(wchar_t* path, bool should_be_empty) {328check_dir_impl(path, should_be_empty);329330for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {331wchar_t tmp[JVM_MAXPATHLEN];332if (unnormalize_path(tmp, JVM_MAXPATHLEN, true, path)) {333check_dir_impl(tmp, should_be_empty);334}335}336}337338static void check_file(wchar_t* path) {339check_file_impl(path);340341// Check os::same_files at least somewhat.342char buf[JVM_MAXPATHLEN];343344if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {345wchar_t mod[JVM_MAXPATHLEN];346347if (unnormalize_path(mod, JVM_MAXPATHLEN, false, path)) {348char mod_c[JVM_MAXPATHLEN];349if (convert_to_cstring(mod_c, JVM_MAXPATHLEN, mod)) {350EXPECT_EQ(os::same_files(buf, mod_c), true) << "os::same files failed for \\" << path << "\" and \"" << mod_c << "\"";351}352}353}354355for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {356wchar_t tmp[JVM_MAXPATHLEN];357if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) {358check_file_impl(tmp);359}360}361}362363static void check_file_not_present(wchar_t* path) {364check_file_not_present_impl(path);365366for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {367wchar_t tmp[JVM_MAXPATHLEN];368if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) {369check_file_not_present_impl(tmp);370}371}372}373374static void record_path(char const* name, char const* len_name, wchar_t* path) {375char buf[JVM_MAXPATHLEN];376377if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {378::testing::Test::RecordProperty(name, buf);379os::snprintf(buf, JVM_MAXPATHLEN, "%d", (int) wcslen(path));380::testing::Test::RecordProperty(len_name, buf);381}382}383384static void bench_path(wchar_t* path) {385char buf[JVM_MAXPATHLEN];386int reps = 100000;387388if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {389jlong wtime[2];390391for (int t = 0; t < 2; ++t) {392wtime[t] = os::javaTimeNanos();393394for (int i = 0; i < reps; ++i) {395bool succ = false;396size_t buf_len = strlen(buf);397wchar_t* w_path = (wchar_t*) os::malloc(sizeof(wchar_t) * (buf_len + 1), mtInternal);398399if (w_path != NULL) {400size_t converted_chars;401if (::mbstowcs_s(&converted_chars, w_path, buf_len + 1, buf, buf_len) == ERROR_SUCCESS) {402if (t == 1) {403wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * JVM_MAXPATHLEN, mtInternal);404405if (tmp) {406if (_wfullpath(tmp, w_path, JVM_MAXPATHLEN)) {407succ = true;408}409410// Note that we really don't use the full path name, but just add the cost of running _wfullpath.411os::free(tmp);412}413if (!succ) {414printf("Failed fullpathing \"%s\"\n", buf);415return;416}417succ = false;418}419HANDLE h = ::CreateFileW(w_path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);420421if (h != INVALID_HANDLE_VALUE) {422::CloseHandle(h);423succ = true;424}425}426}427428os::free(w_path);429if (!succ) {430printf("Failed getting W*attr. \"%s\"\n", buf);431return;432}433}434435wtime[t] = os::javaTimeNanos() - wtime[t];436}437438jlong ctime = os::javaTimeNanos();439440for (int i = 0; i < reps; ++i) {441HANDLE h = ::CreateFileA(buf, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);442443if (h == INVALID_HANDLE_VALUE) {444return;445}446447::CloseHandle(h);448}449450ctime = os::javaTimeNanos() - ctime;451452printf("\"%s\" %f us for *A, %f us for *W, %f us for *W with fullpath\n", buf,4530.001 * ctime / reps, 0.001 * wtime[0] / reps, 0.001 * wtime[1] / reps);454}455}456457static void print_attr_result_for_path(wchar_t* path) {458WIN32_FILE_ATTRIBUTE_DATA file_data;459struct stat st;460char buf[JVM_MAXPATHLEN];461wchar_t abs[JVM_MAXPATHLEN];462463_wfullpath(abs, path, JVM_MAXPATHLEN);464printf("Checking \"%ls\" (%d chars):\n", path, (int) wcslen(path));465printf("_wfullpath %ls (%d chars)\n", abs, (int) wcslen(abs));466BOOL bret = ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data);467printf("GetFileAttributesExW() %s\n", bret ? "success" : "failed");468469if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {470bret = ::GetFileAttributesExA(buf, GetFileExInfoStandard, &file_data);471printf("GetFileAttributesExA() %s\n", bret ? "success" : "failed");472473bool succ = os::stat(buf, &st) != -1;474printf("os::stat() %s\n", succ ? "success" : "failed");475}476}477478static void print_attr_result(wchar_t* format, ...) {479va_list argptr;480wchar_t buf[JVM_MAXPATHLEN];481482va_start(argptr, format);483wvsprintfW(buf, format, argptr);484print_attr_result_for_path(buf);485va_end(argptr);486}487488#define RECORD_PATH(name) record_path(#name, #name "Len", name)489#define NAME_PART_50 L"01234567890123456789012345678901234567890123456789"490#define NAME_PART_250 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50491492// Test which tries to find out if the os::stat, os::open, os::same_files and os::dir_is_empty methods493// can handle long path names correctly.494TEST_VM(os_windows, handle_long_paths) {495static wchar_t cwd[JVM_MAXPATHLEN];496static wchar_t nearly_long_rel_path[JVM_MAXPATHLEN];497static wchar_t long_rel_path[JVM_MAXPATHLEN];498static wchar_t empty_dir_rel_path[JVM_MAXPATHLEN];499static wchar_t not_empty_dir_rel_path[JVM_MAXPATHLEN];500static wchar_t file_rel_path[JVM_MAXPATHLEN];501static wchar_t nearly_long_file_rel_path[JVM_MAXPATHLEN];502static wchar_t nearly_long_path[JVM_MAXPATHLEN];503static wchar_t empty_dir_path[JVM_MAXPATHLEN];504static wchar_t not_empty_dir_path[JVM_MAXPATHLEN];505static wchar_t nearly_long_file_path[JVM_MAXPATHLEN];506static wchar_t file_path[JVM_MAXPATHLEN];507static wchar_t nearly_long_unc_path[JVM_MAXPATHLEN];508static wchar_t empty_dir_unc_path[JVM_MAXPATHLEN];509static wchar_t not_empty_dir_unc_path[JVM_MAXPATHLEN];510static wchar_t nearly_long_file_unc_path[JVM_MAXPATHLEN];511static wchar_t file_unc_path[JVM_MAXPATHLEN];512static wchar_t root_dir_path[JVM_MAXPATHLEN];513static wchar_t root_rel_dir_path[JVM_MAXPATHLEN];514515wchar_t* dir_prefix = L"os_windows_long_paths_dir_";516wchar_t* empty_dir_name = L"empty_directory_with_long_path";517wchar_t* not_empty_dir_name = L"not_empty_directory_with_long_path";518wchar_t* file_name = L"file";519wchar_t dir_letter;520WIN32_FILE_ATTRIBUTE_DATA file_data;521bool can_test_unc = false;522523get_current_dir_w(cwd, sizeof(cwd) / sizeof(wchar_t));524dir_letter = (cwd[1] == L':' ? cwd[0] : L'\0');525int cwd_len = (int) wcslen(cwd);526int dir_prefix_len = (int) wcslen(dir_prefix);527int rel_path_len = MAX2(dir_prefix_len, 235 - cwd_len);528529memcpy(nearly_long_rel_path, dir_prefix, sizeof(wchar_t) * dir_prefix_len);530531for (int i = dir_prefix_len; i < rel_path_len; ++i) {532nearly_long_rel_path[i] = L'L';533}534535nearly_long_rel_path[rel_path_len] = L'\0';536537wsprintfW(long_rel_path, L"%ls\\%ls", nearly_long_rel_path, NAME_PART_250);538wsprintfW(empty_dir_rel_path, L"%ls\\%ls", nearly_long_rel_path, empty_dir_name);539wsprintfW(not_empty_dir_rel_path, L"%ls\\%ls", nearly_long_rel_path, not_empty_dir_name);540wsprintfW(nearly_long_file_rel_path, L"%ls\\%ls", nearly_long_rel_path, file_name);541wsprintfW(file_rel_path, L"%ls\\%ls\\%ls", nearly_long_rel_path, not_empty_dir_name, file_name);542wsprintfW(nearly_long_path, L"\\\\?\\%ls\\%ls", cwd, nearly_long_rel_path);543wsprintfW(empty_dir_path, L"%ls\\%ls", nearly_long_path, empty_dir_name);544wsprintfW(not_empty_dir_path, L"%ls\\%ls", nearly_long_path, not_empty_dir_name);545wsprintfW(nearly_long_file_path, L"%ls\\%ls", nearly_long_path, file_name);546wsprintfW(file_path, L"%ls\\%ls\\%ls", nearly_long_path, not_empty_dir_name, file_name);547wsprintfW(nearly_long_unc_path, L"\\\\localhost\\%lc$\\%s", dir_letter, nearly_long_path + 7);548wsprintfW(empty_dir_unc_path, L"%s\\%s", nearly_long_unc_path, empty_dir_name);549wsprintfW(not_empty_dir_unc_path, L"%s\\%s", nearly_long_unc_path, not_empty_dir_name);550wsprintfW(nearly_long_file_unc_path, L"%ls\\%ls", nearly_long_unc_path, file_name);551wsprintfW(file_unc_path, L"%s\\%s\\%s", nearly_long_unc_path, not_empty_dir_name, file_name);552wsprintfW(root_dir_path, L"%lc:\\", dir_letter);553wsprintfW(root_rel_dir_path, L"%lc:", dir_letter);554555RECORD_PATH(long_rel_path);556RECORD_PATH(nearly_long_rel_path);557RECORD_PATH(nearly_long_path);558RECORD_PATH(nearly_long_unc_path);559RECORD_PATH(empty_dir_rel_path);560RECORD_PATH(empty_dir_path);561RECORD_PATH(empty_dir_unc_path);562RECORD_PATH(not_empty_dir_rel_path);563RECORD_PATH(not_empty_dir_path);564RECORD_PATH(not_empty_dir_unc_path);565RECORD_PATH(nearly_long_file_rel_path);566RECORD_PATH(nearly_long_file_path);567RECORD_PATH(nearly_long_file_unc_path);568RECORD_PATH(file_rel_path);569RECORD_PATH(file_path);570RECORD_PATH(file_unc_path);571572create_rel_directory_w(nearly_long_rel_path);573create_rel_directory_w(long_rel_path);574create_rel_directory_w(empty_dir_rel_path);575create_rel_directory_w(not_empty_dir_rel_path);576create_rel_file_w(nearly_long_file_rel_path);577create_rel_file_w(file_rel_path);578579// For UNC path test we assume that the current DRIVE has a share580// called "<DRIVELETTER>$" (so for D: we expect \\localhost\D$ to be581// the same). Since this is only an assumption, we have to skip582// the UNC tests if the share is missing.583if (dir_letter && !::GetFileAttributesExW(nearly_long_unc_path, GetFileExInfoStandard, &file_data)) {584printf("Disabled UNC path test, since %lc: is not mapped as share %lc$.\n", dir_letter, dir_letter);585} else {586can_test_unc = true;587}588589if (mode == BENCH) {590bench_path(nearly_long_path + 4);591bench_path(nearly_long_rel_path);592bench_path(nearly_long_file_path + 4);593bench_path(nearly_long_file_rel_path);594} else if (mode == EXAMPLES) {595printf("Working directory: %ls", cwd);596597if (dir_letter) {598static wchar_t top_buf[JVM_MAXPATHLEN];599wchar_t* top_path = wcschr(cwd + 3, L'\\');600601if (top_path) {602size_t top_len = (top_path - cwd) - 3;603604memcpy(top_buf, cwd + 3, top_len * 2);605top_buf[top_len] = L'\0';606top_path = top_buf;607}608609print_attr_result(L"%lc:\\", dir_letter);610print_attr_result(L"%lc:\\.\\", dir_letter);611612if (top_path) {613print_attr_result(L"%lc:\\%ls\\..\\%ls\\", dir_letter, top_path, top_path);614}615616print_attr_result(L"%lc:", dir_letter);617print_attr_result(L"%lc:.", dir_letter);618print_attr_result(L"%lc:\\COM1", dir_letter);619print_attr_result(L"%lc:\\PRN", dir_letter);620print_attr_result(L"%lc:\\PRN\\COM1", dir_letter);621print_attr_result(L"\\\\?\\UNC\\localhost\\%lc$\\", dir_letter);622print_attr_result(L"\\\\?\\UNC\\\\localhost\\%lc$\\", dir_letter);623print_attr_result(nearly_long_unc_path);624print_attr_result(L"%ls\\.\\", nearly_long_unc_path);625print_attr_result(L"%ls\\..\\%ls", nearly_long_unc_path, nearly_long_rel_path);626print_attr_result(L"\\\\?\\UNC\\%ls", nearly_long_unc_path + 2);627print_attr_result(file_unc_path);628print_attr_result(L"%ls\\%ls\\..\\%ls\\%ls", nearly_long_unc_path, not_empty_dir_name, not_empty_dir_name, file_name);629print_attr_result(L"%ls\\%ls\\.\\%ls", nearly_long_unc_path, not_empty_dir_name, file_name);630print_attr_result(L"\\\\?\\UNC\\%ls", file_unc_path + 2);631print_attr_result(L"\\\\?\\UNC\\%ls\\%ls\\.\\%ls", nearly_long_unc_path + 2, not_empty_dir_name, file_name);632print_attr_result(L"\\\\?\\UNC\\%ls\\%ls\\..\\%ls\\%ls", nearly_long_unc_path + 2, not_empty_dir_name, not_empty_dir_name, file_name);633}634635print_attr_result(nearly_long_rel_path);636print_attr_result(L"%ls\\.\\", nearly_long_rel_path);637print_attr_result(L"%ls\\..\\%ls", nearly_long_rel_path, nearly_long_rel_path);638print_attr_result(L"%\\\\?\\%ls", nearly_long_rel_path);639print_attr_result(L"\\\\?\\%ls\\.\\", nearly_long_rel_path);640print_attr_result(L"\\\\?\\%ls\\..\\%ls", nearly_long_rel_path, nearly_long_rel_path);641642print_attr_result(nearly_long_path + 4);643print_attr_result(L"%ls\\.\\", nearly_long_path + 4);644print_attr_result(L"%ls\\..\\%ls", nearly_long_path + 4, nearly_long_rel_path);645print_attr_result(nearly_long_path);646print_attr_result(L"%ls\\.\\", nearly_long_path);647print_attr_result(L"%ls\\..\\%ls", nearly_long_path, nearly_long_rel_path);648} else {649check_file_not_present(L"");650651// Check relative paths652check_dir(nearly_long_rel_path, false);653check_dir(long_rel_path, true);654check_dir(empty_dir_rel_path, true);655check_dir(not_empty_dir_rel_path, false);656check_file(nearly_long_file_rel_path);657check_file(file_rel_path);658659// Check absolute paths660if (dir_letter) {661check_dir(root_dir_path, false);662check_dir(root_rel_dir_path, false);663}664665check_dir(cwd, false);666check_dir(nearly_long_path + 4, false);667check_dir(empty_dir_path + 4, true);668check_dir(not_empty_dir_path + 4, false);669check_file(nearly_long_file_path + 4);670check_file(file_path + 4);671672// Check UNC paths673if (can_test_unc) {674check_dir(nearly_long_unc_path, false);675check_dir(empty_dir_unc_path, true);676check_dir(not_empty_dir_unc_path, false);677check_file(nearly_long_file_unc_path);678check_file(file_unc_path);679}680681// Check handling of <DRIVE>:/../<OTHER_DRIVE>:/path/...682// The other drive letter should not overwrite the original one.683if (dir_letter) {684static wchar_t tmp[JVM_MAXPATHLEN];685wchar_t* other_letter = dir_letter == L'D' ? L"C" : L"D";686wsprintfW(tmp, L"%2ls\\..\\%ls:%ls", nearly_long_file_path, other_letter, nearly_long_file_path + 2);687check_file_not_present(tmp);688wsprintfW(tmp, L"%2ls\\..\\%ls:%ls", file_path, other_letter, file_path + 2);689check_file_not_present(tmp);690}691}692693delete_rel_file_w(file_rel_path);694delete_rel_file_w(nearly_long_file_rel_path);695delete_empty_rel_directory_w(not_empty_dir_rel_path);696delete_empty_rel_directory_w(empty_dir_rel_path);697delete_empty_rel_directory_w(long_rel_path);698delete_empty_rel_directory_w(nearly_long_rel_path);699}700701TEST_VM(os_windows, reserve_memory_special) {702TestReserveMemorySpecial_test();703}704705class ReserveMemorySpecialRunnable : public TestRunnable {706public:707void runUnitTest() const {708TestReserveMemorySpecial_test();709}710};711712TEST_VM(os_windows, reserve_memory_special_concurrent) {713ReserveMemorySpecialRunnable runnable;714ConcurrentTestRunner testRunner(&runnable, 30, 15000);715testRunner.run();716}717718#endif719720721