2
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
24
#include "precompiled.hpp"
28
#include "logging/log.hpp"
29
#include "runtime/flags/flagSetting.hpp"
30
#include "runtime/globals_extension.hpp"
31
#include "runtime/os.hpp"
32
#include "concurrentTestRunner.inline.hpp"
33
#include "unittest.hpp"
36
class MemoryReleaser {
40
MemoryReleaser(char* ptr, size_t size) : _ptr(ptr), _size(size) { }
42
if (_ptr != nullptr) {
43
os::release_memory_special(_ptr, _size);
49
// test tries to allocate memory in a single contiguous memory block at a particular address.
50
// The test first tries to find a good approximate address to allocate at by using the same
51
// method to allocate some memory at any address. The test then tries to allocate memory in
52
// the vicinity (not directly after it to avoid possible by-chance use of that location)
53
// This is of course only some dodgy assumption, there is no guarantee that the vicinity of
54
// the previously allocated memory is available for allocation. The only actual failure
55
// that is reported is when the test tries to allocate at a particular location but gets a
56
// different valid one. A nullptr return value at this point is not considered an error but may
58
void TestReserveMemorySpecial_test() {
63
// set globals to make sure we hit the correct code path
64
AutoSaveRestore<bool> FLAG_GUARD(UseLargePagesIndividualAllocation);
65
AutoSaveRestore<bool> FLAG_GUARD(UseNUMAInterleaving);
66
FLAG_SET_CMDLINE(UseLargePagesIndividualAllocation, false);
67
FLAG_SET_CMDLINE(UseNUMAInterleaving, false);
69
const size_t large_allocation_size = os::large_page_size() * 4;
70
char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), os::large_page_size(), nullptr, false);
71
if (result == nullptr) {
72
// failed to allocate memory, skipping the test
75
MemoryReleaser m1(result, large_allocation_size);
77
// Reserve another page within the recently allocated memory area. This should fail
78
const size_t expected_allocation_size = os::large_page_size();
79
char* expected_location = result + os::large_page_size();
80
char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, false);
81
EXPECT_TRUE(actual_location == nullptr) << "Should not be allowed to reserve within present reservation";
83
// Instead try reserving after the first reservation.
84
expected_location = result + large_allocation_size;
85
actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), os::large_page_size(), expected_location, false);
86
EXPECT_TRUE(actual_location != nullptr) << "Unexpected reservation failure, can’t verify correct location";
87
EXPECT_TRUE(actual_location == expected_location) << "Reservation must be at requested location";
88
MemoryReleaser m2(actual_location, os::large_page_size());
90
// Now try to do a reservation with a larger alignment.
91
const size_t alignment = os::large_page_size() * 2;
92
const size_t new_large_size = alignment * 4;
93
char* aligned_request = os::reserve_memory_special(new_large_size, alignment, os::large_page_size(), nullptr, false);
94
EXPECT_TRUE(aligned_request != nullptr) << "Unexpected reservation failure, can’t verify correct alignment";
95
EXPECT_TRUE(is_aligned(aligned_request, alignment)) << "Returned address must be aligned";
96
MemoryReleaser m3(aligned_request, new_large_size);
99
// The types of path modifications we randomly apply to a path. They should not change the file designated by the path.
101
Allow_None = 0, // No modifications
102
Allow_Sep_Mods = 1, // Replace '\\' by any sequence of '/' or '\\' or at least length 1.
103
Allow_Dot_Path = 2, // Add /. segments at random positions
104
Allow_Dot_Dot_Path = 4, // Add /../<correct-dir> segments at random positions.
105
Allow_All = Allow_Sep_Mods | Allow_Dot_Path | Allow_Dot_Dot_Path
108
// The mode in which to run.
110
TEST, // Runs the test. This is the normal modus.
111
EXAMPLES, // Runs example which document the behaviour of the Windows system calls.
112
BENCH // Runs a small benchmark which tries to show the costs of using the *W variants/_wfullpath.
115
// Parameters of the test.
116
static ModsFilter mods_filter = Allow_All;
117
static int mods_per_path = 50; // The number of variants of a path we try.
118
static Mode mode = TEST;
122
static void get_current_dir_w(wchar_t* path, size_t size) {
123
DWORD count = GetCurrentDirectoryW((DWORD) size, path);
124
EXPECT_GT((int) count, 0) << "Failed to get current directory: " << GetLastError();
125
EXPECT_LT((size_t) count, size) << "Buffer too small for current directory: " << size;
128
#define WITH_ABS_PATH(path) \
129
wchar_t abs_path[JVM_MAXPATHLEN]; \
130
wchar_t cwd[JVM_MAXPATHLEN]; \
131
get_current_dir_w(cwd, JVM_MAXPATHLEN); \
132
wsprintfW(abs_path, L"\\\\?\\%ls\\%ls", cwd, (path))
134
static bool file_exists_w(const wchar_t* path) {
135
WIN32_FILE_ATTRIBUTE_DATA file_data;
136
return ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data);
139
static void create_rel_directory_w(const wchar_t* path) {
141
EXPECT_FALSE(file_exists_w(abs_path)) << "Can't create directory: \"" << path << "\" already exists";
142
BOOL result = CreateDirectoryW(abs_path, nullptr);
143
EXPECT_TRUE(result) << "Failed to create directory \"" << path << "\" " << GetLastError();
146
static void delete_empty_rel_directory_w(const wchar_t* path) {
148
EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete directory: \"" << path << "\" does not exists";
149
const int retry_count = 20;
151
// If the directory cannot be deleted directly, a file in it might be kept
152
// open by a virus scanner. Try a few times, since this should be temporary.
153
for (int i = 0; i <= retry_count; ++i) {
154
BOOL result = RemoveDirectoryW(abs_path);
156
if (!result && (i < retry_count)) {
159
EXPECT_TRUE(result) << "Failed to delete directory \"" << path << "\": " << GetLastError();
165
static void create_rel_file_w(const wchar_t* path) {
167
EXPECT_FALSE(file_exists_w(abs_path)) << "Can't create file: \"" << path << "\" already exists";
168
HANDLE h = CreateFileW(abs_path, 0, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);
169
EXPECT_NE(h, INVALID_HANDLE_VALUE) << "Failed to create file \"" << path << "\": " << GetLastError();
173
static void delete_rel_file_w(const wchar_t* path) {
175
EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete file: \"" << path << "\" does not exists";
176
BOOL result = DeleteFileW(abs_path);
177
EXPECT_TRUE(result) << "Failed to delete file \"" << path << "\": " << GetLastError();
180
static bool convert_to_cstring(char* c_str, size_t size, const wchar_t* w_str) {
182
errno_t err = wcstombs_s(&converted, c_str, size, w_str, size - 1);
183
EXPECT_EQ(err, ERROR_SUCCESS) << "Could not convert \"" << w_str << "\" to c-string";
185
return err == ERROR_SUCCESS;
188
static wchar_t* my_wcscpy_s(wchar_t* dest, size_t size, wchar_t* start, const wchar_t* to_copy) {
189
size_t already_used = dest - start;
190
size_t len = wcslen(to_copy);
192
if (already_used + len < size) {
193
wcscpy_s(dest, size - already_used, to_copy);
196
return dest + wcslen(to_copy);
199
// The currently finite list of seperator sequences we might use instead of '\\'.
200
static const wchar_t* sep_replacements[] = {
201
L"\\", L"\\/", L"/", L"//", L"\\\\/\\", L"//\\/"
204
// Takes a path and modifies it in a way that it should still designate the same file.
205
static bool unnormalize_path(wchar_t* result, size_t size, bool is_dir, const wchar_t* path) {
206
wchar_t* dest = result;
207
const wchar_t* src = path;
208
const wchar_t* path_start;
210
if (wcsncmp(src, L"\\\\?\\UNC\\", 8) == 0) {
211
path_start = src + 8;
212
} else if (wcsncmp(src, L"\\\\?\\", 4) == 0) {
213
if (src[5] == L':') {
214
path_start = src + 6;
216
path_start = wcschr(src + 4, L'\\');
218
} else if (wcsncmp(src, L"\\\\", 2) == 0) {
219
path_start = wcschr(src + 2, L'?');
221
if (path_start == nullptr) {
222
path_start = wcschr(src + 2, L'\\');
224
path_start = wcschr(path_start, L'\\');
227
path_start = wcschr(src + 1, L'\\');
230
bool allow_sep_change = (mods_filter & Allow_Sep_Mods) && (os::random() & 1) == 0;
231
bool allow_dot_change = (mods_filter & Allow_Dot_Path) && (os::random() & 1) == 0;
232
bool allow_dotdot_change = (mods_filter & Allow_Dot_Dot_Path) && (os::random() & 1) == 0;
234
while ((*src != L'\0') && (result + size > dest)) {
241
if (allow_sep_change && (os::random() & 3) == 3) {
242
int i = os::random() % (sizeof(sep_replacements) / sizeof(sep_replacements[0]));
245
const wchar_t* replacement = sep_replacements[i];
246
dest = my_wcscpy_s(dest - 1, size, result, replacement);
248
} else if (path_start != nullptr) {
249
if (allow_dotdot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) {
250
wchar_t const* last_sep = src - 2;
252
while (last_sep[0] != L'\\') {
256
if (last_sep > path_start) {
257
dest = my_wcscpy_s(dest, size, result, L"../");
260
} else if (allow_dot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) {
261
dest = my_wcscpy_s(dest, size, result, L"./");
267
while (is_dir && ((os::random() & 15) == 1)) {
268
dest = my_wcscpy_s(dest, size, result, L"/");
271
if (result + size > dest) {
275
// Use this modification only if not too close to the max size.
276
return result + size - 10 > dest;
279
static void check_dir_impl(wchar_t* path, bool should_be_empty) {
280
char buf[JVM_MAXPATHLEN];
282
if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
284
EXPECT_EQ(os::stat(buf, &st), 0) << "os::stat failed for \"" << path << "\"";
285
EXPECT_EQ(st.st_mode & S_IFMT, S_IFDIR) << "\"" << path << "\" is not a directory according to os::stat";
286
errno = ERROR_SUCCESS;
287
bool is_empty = os::dir_is_empty(buf);
289
EXPECT_EQ(is_empty, should_be_empty) << "os::dir_is_empty assumed \"" << path << "\" is "
290
<< (should_be_empty ? "not ": "") << "empty";
291
EXPECT_EQ(err, ERROR_SUCCESS) << "os::dir_is_empty failed for \"" << path << "\"with errno " << err;
295
static void check_file_impl(wchar_t* path) {
296
char buf[JVM_MAXPATHLEN];
298
if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
300
EXPECT_EQ(os::stat(buf, &st), 0) << "os::stat failed for \"" << path << "\"";
301
EXPECT_EQ(st.st_mode & S_IFMT, S_IFREG) << "\"" << path << "\" is not a regular file according to os::stat";
302
int fd = os::open(buf, O_RDONLY, 0);
303
EXPECT_NE(fd, -1) << "os::open failed for \"" << path << "\" with errno " << errno;
310
static void check_file_not_present_impl(const wchar_t* path) {
311
char buf[JVM_MAXPATHLEN];
313
if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
316
EXPECT_EQ(stat_ret = os::stat(buf, &st), -1) << "os::stat did not fail for \"" << path << "\"";
317
if (stat_ret != -1) {
318
// Only check open if stat not already failed.
319
int fd = os::open(buf, O_RDONLY, 0);
320
EXPECT_EQ(fd, -1) << "os::open did not fail for \"" << path << "\"";
328
static void check_dir(wchar_t* path, bool should_be_empty) {
329
check_dir_impl(path, should_be_empty);
331
for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {
332
wchar_t tmp[JVM_MAXPATHLEN];
333
if (unnormalize_path(tmp, JVM_MAXPATHLEN, true, path)) {
334
check_dir_impl(tmp, should_be_empty);
339
static void check_file(wchar_t* path) {
340
check_file_impl(path);
342
// Check os::same_files at least somewhat.
343
char buf[JVM_MAXPATHLEN];
345
if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
346
wchar_t mod[JVM_MAXPATHLEN];
348
if (unnormalize_path(mod, JVM_MAXPATHLEN, false, path)) {
349
char mod_c[JVM_MAXPATHLEN];
350
if (convert_to_cstring(mod_c, JVM_MAXPATHLEN, mod)) {
351
EXPECT_EQ(os::same_files(buf, mod_c), true) << "os::same files failed for \\" << path << "\" and \"" << mod_c << "\"";
356
for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {
357
wchar_t tmp[JVM_MAXPATHLEN];
358
if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) {
359
check_file_impl(tmp);
364
static void check_file_not_present(const wchar_t* path) {
365
check_file_not_present_impl(path);
367
for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {
368
wchar_t tmp[JVM_MAXPATHLEN];
369
if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) {
370
check_file_not_present_impl(tmp);
375
static void record_path(char const* name, char const* len_name, wchar_t* path) {
376
char buf[JVM_MAXPATHLEN];
378
if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
379
::testing::Test::RecordProperty(name, buf);
380
os::snprintf(buf, JVM_MAXPATHLEN, "%d", (int) wcslen(path));
381
::testing::Test::RecordProperty(len_name, buf);
385
static void bench_path(wchar_t* path) {
386
char buf[JVM_MAXPATHLEN];
389
if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
392
for (int t = 0; t < 2; ++t) {
393
wtime[t] = os::javaTimeNanos();
395
for (int i = 0; i < reps; ++i) {
397
size_t buf_len = strlen(buf);
398
wchar_t* w_path = (wchar_t*) os::malloc(sizeof(wchar_t) * (buf_len + 1), mtInternal);
400
if (w_path != nullptr) {
401
size_t converted_chars;
402
if (::mbstowcs_s(&converted_chars, w_path, buf_len + 1, buf, buf_len) == ERROR_SUCCESS) {
404
wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * JVM_MAXPATHLEN, mtInternal);
407
if (_wfullpath(tmp, w_path, JVM_MAXPATHLEN)) {
411
// Note that we really don't use the full path name, but just add the cost of running _wfullpath.
415
printf("Failed fullpathing \"%s\"\n", buf);
420
HANDLE h = ::CreateFileW(w_path, 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
422
if (h != INVALID_HANDLE_VALUE) {
431
printf("Failed getting W*attr. \"%s\"\n", buf);
436
wtime[t] = os::javaTimeNanos() - wtime[t];
439
jlong ctime = os::javaTimeNanos();
441
for (int i = 0; i < reps; ++i) {
442
HANDLE h = ::CreateFileA(buf, 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
444
if (h == INVALID_HANDLE_VALUE) {
451
ctime = os::javaTimeNanos() - ctime;
453
printf("\"%s\" %f us for *A, %f us for *W, %f us for *W with fullpath\n", buf,
454
0.001 * ctime / reps, 0.001 * wtime[0] / reps, 0.001 * wtime[1] / reps);
458
static void print_attr_result_for_path(const wchar_t* path) {
459
WIN32_FILE_ATTRIBUTE_DATA file_data;
461
char buf[JVM_MAXPATHLEN];
462
wchar_t abs[JVM_MAXPATHLEN];
464
_wfullpath(abs, path, JVM_MAXPATHLEN);
465
printf("Checking \"%ls\" (%d chars):\n", path, (int) wcslen(path));
466
printf("_wfullpath %ls (%d chars)\n", abs, (int) wcslen(abs));
467
BOOL bret = ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data);
468
printf("GetFileAttributesExW() %s\n", bret ? "success" : "failed");
470
if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
471
bret = ::GetFileAttributesExA(buf, GetFileExInfoStandard, &file_data);
472
printf("GetFileAttributesExA() %s\n", bret ? "success" : "failed");
474
bool succ = os::stat(buf, &st) != -1;
475
printf("os::stat() %s\n", succ ? "success" : "failed");
479
static void print_attr_result(const wchar_t* format, ...) {
481
wchar_t buf[JVM_MAXPATHLEN];
483
va_start(argptr, format);
484
wvsprintfW(buf, format, argptr);
485
print_attr_result_for_path(buf);
489
#define RECORD_PATH(name) record_path(#name, #name "Len", name)
490
#define NAME_PART_50 L"01234567890123456789012345678901234567890123456789"
491
#define NAME_PART_250 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50
493
// Test which tries to find out if the os::stat, os::open, os::same_files and os::dir_is_empty methods
494
// can handle long path names correctly.
495
TEST_VM(os_windows, handle_long_paths) {
496
static wchar_t cwd[JVM_MAXPATHLEN];
497
static wchar_t nearly_long_rel_path[JVM_MAXPATHLEN];
498
static wchar_t long_rel_path[JVM_MAXPATHLEN];
499
static wchar_t empty_dir_rel_path[JVM_MAXPATHLEN];
500
static wchar_t not_empty_dir_rel_path[JVM_MAXPATHLEN];
501
static wchar_t file_rel_path[JVM_MAXPATHLEN];
502
static wchar_t nearly_long_file_rel_path[JVM_MAXPATHLEN];
503
static wchar_t nearly_long_path[JVM_MAXPATHLEN];
504
static wchar_t empty_dir_path[JVM_MAXPATHLEN];
505
static wchar_t not_empty_dir_path[JVM_MAXPATHLEN];
506
static wchar_t nearly_long_file_path[JVM_MAXPATHLEN];
507
static wchar_t file_path[JVM_MAXPATHLEN];
508
static wchar_t nearly_long_unc_path[JVM_MAXPATHLEN];
509
static wchar_t empty_dir_unc_path[JVM_MAXPATHLEN];
510
static wchar_t not_empty_dir_unc_path[JVM_MAXPATHLEN];
511
static wchar_t nearly_long_file_unc_path[JVM_MAXPATHLEN];
512
static wchar_t file_unc_path[JVM_MAXPATHLEN];
513
static wchar_t root_dir_path[JVM_MAXPATHLEN];
514
static wchar_t root_rel_dir_path[JVM_MAXPATHLEN];
516
const wchar_t* dir_prefix = L"os_windows_long_paths_dir_";
517
const wchar_t* empty_dir_name = L"empty_directory_with_long_path";
518
const wchar_t* not_empty_dir_name = L"not_empty_directory_with_long_path";
519
const wchar_t* file_name = L"file";
521
WIN32_FILE_ATTRIBUTE_DATA file_data;
522
bool can_test_unc = false;
524
get_current_dir_w(cwd, sizeof(cwd) / sizeof(wchar_t));
525
dir_letter = (cwd[1] == L':' ? cwd[0] : L'\0');
526
int cwd_len = (int) wcslen(cwd);
527
int dir_prefix_len = (int) wcslen(dir_prefix);
528
int rel_path_len = MAX2(dir_prefix_len, 235 - cwd_len);
530
memcpy(nearly_long_rel_path, dir_prefix, sizeof(wchar_t) * dir_prefix_len);
532
for (int i = dir_prefix_len; i < rel_path_len; ++i) {
533
nearly_long_rel_path[i] = L'L';
536
nearly_long_rel_path[rel_path_len] = L'\0';
538
wsprintfW(long_rel_path, L"%ls\\%ls", nearly_long_rel_path, NAME_PART_250);
539
wsprintfW(empty_dir_rel_path, L"%ls\\%ls", nearly_long_rel_path, empty_dir_name);
540
wsprintfW(not_empty_dir_rel_path, L"%ls\\%ls", nearly_long_rel_path, not_empty_dir_name);
541
wsprintfW(nearly_long_file_rel_path, L"%ls\\%ls", nearly_long_rel_path, file_name);
542
wsprintfW(file_rel_path, L"%ls\\%ls\\%ls", nearly_long_rel_path, not_empty_dir_name, file_name);
543
wsprintfW(nearly_long_path, L"\\\\?\\%ls\\%ls", cwd, nearly_long_rel_path);
544
wsprintfW(empty_dir_path, L"%ls\\%ls", nearly_long_path, empty_dir_name);
545
wsprintfW(not_empty_dir_path, L"%ls\\%ls", nearly_long_path, not_empty_dir_name);
546
wsprintfW(nearly_long_file_path, L"%ls\\%ls", nearly_long_path, file_name);
547
wsprintfW(file_path, L"%ls\\%ls\\%ls", nearly_long_path, not_empty_dir_name, file_name);
548
wsprintfW(nearly_long_unc_path, L"\\\\localhost\\%lc$\\%s", dir_letter, nearly_long_path + 7);
549
wsprintfW(empty_dir_unc_path, L"%s\\%s", nearly_long_unc_path, empty_dir_name);
550
wsprintfW(not_empty_dir_unc_path, L"%s\\%s", nearly_long_unc_path, not_empty_dir_name);
551
wsprintfW(nearly_long_file_unc_path, L"%ls\\%ls", nearly_long_unc_path, file_name);
552
wsprintfW(file_unc_path, L"%s\\%s\\%s", nearly_long_unc_path, not_empty_dir_name, file_name);
553
wsprintfW(root_dir_path, L"%lc:\\", dir_letter);
554
wsprintfW(root_rel_dir_path, L"%lc:", dir_letter);
556
RECORD_PATH(long_rel_path);
557
RECORD_PATH(nearly_long_rel_path);
558
RECORD_PATH(nearly_long_path);
559
RECORD_PATH(nearly_long_unc_path);
560
RECORD_PATH(empty_dir_rel_path);
561
RECORD_PATH(empty_dir_path);
562
RECORD_PATH(empty_dir_unc_path);
563
RECORD_PATH(not_empty_dir_rel_path);
564
RECORD_PATH(not_empty_dir_path);
565
RECORD_PATH(not_empty_dir_unc_path);
566
RECORD_PATH(nearly_long_file_rel_path);
567
RECORD_PATH(nearly_long_file_path);
568
RECORD_PATH(nearly_long_file_unc_path);
569
RECORD_PATH(file_rel_path);
570
RECORD_PATH(file_path);
571
RECORD_PATH(file_unc_path);
573
create_rel_directory_w(nearly_long_rel_path);
574
create_rel_directory_w(long_rel_path);
575
create_rel_directory_w(empty_dir_rel_path);
576
create_rel_directory_w(not_empty_dir_rel_path);
577
create_rel_file_w(nearly_long_file_rel_path);
578
create_rel_file_w(file_rel_path);
580
// For UNC path test we assume that the current DRIVE has a share
581
// called "<DRIVELETTER>$" (so for D: we expect \\localhost\D$ to be
582
// the same). Since this is only an assumption, we have to skip
583
// the UNC tests if the share is missing.
584
if (dir_letter && !::GetFileAttributesExW(nearly_long_unc_path, GetFileExInfoStandard, &file_data)) {
585
printf("Disabled UNC path test, since %lc: is not mapped as share %lc$.\n", dir_letter, dir_letter);
591
bench_path(nearly_long_path + 4);
592
bench_path(nearly_long_rel_path);
593
bench_path(nearly_long_file_path + 4);
594
bench_path(nearly_long_file_rel_path);
595
} else if (mode == EXAMPLES) {
596
printf("Working directory: %ls", cwd);
599
static wchar_t top_buf[JVM_MAXPATHLEN];
600
wchar_t* top_path = wcschr(cwd + 3, L'\\');
603
size_t top_len = (top_path - cwd) - 3;
605
memcpy(top_buf, cwd + 3, top_len * 2);
606
top_buf[top_len] = L'\0';
610
print_attr_result(L"%lc:\\", dir_letter);
611
print_attr_result(L"%lc:\\.\\", dir_letter);
614
print_attr_result(L"%lc:\\%ls\\..\\%ls\\", dir_letter, top_path, top_path);
617
print_attr_result(L"%lc:", dir_letter);
618
print_attr_result(L"%lc:.", dir_letter);
619
print_attr_result(L"%lc:\\COM1", dir_letter);
620
print_attr_result(L"%lc:\\PRN", dir_letter);
621
print_attr_result(L"%lc:\\PRN\\COM1", dir_letter);
622
print_attr_result(L"\\\\?\\UNC\\localhost\\%lc$\\", dir_letter);
623
print_attr_result(L"\\\\?\\UNC\\\\localhost\\%lc$\\", dir_letter);
624
print_attr_result(nearly_long_unc_path);
625
print_attr_result(L"%ls\\.\\", nearly_long_unc_path);
626
print_attr_result(L"%ls\\..\\%ls", nearly_long_unc_path, nearly_long_rel_path);
627
print_attr_result(L"\\\\?\\UNC\\%ls", nearly_long_unc_path + 2);
628
print_attr_result(file_unc_path);
629
print_attr_result(L"%ls\\%ls\\..\\%ls\\%ls", nearly_long_unc_path, not_empty_dir_name, not_empty_dir_name, file_name);
630
print_attr_result(L"%ls\\%ls\\.\\%ls", nearly_long_unc_path, not_empty_dir_name, file_name);
631
print_attr_result(L"\\\\?\\UNC\\%ls", file_unc_path + 2);
632
print_attr_result(L"\\\\?\\UNC\\%ls\\%ls\\.\\%ls", nearly_long_unc_path + 2, not_empty_dir_name, file_name);
633
print_attr_result(L"\\\\?\\UNC\\%ls\\%ls\\..\\%ls\\%ls", nearly_long_unc_path + 2, not_empty_dir_name, not_empty_dir_name, file_name);
636
print_attr_result(nearly_long_rel_path);
637
print_attr_result(L"%ls\\.\\", nearly_long_rel_path);
638
print_attr_result(L"%ls\\..\\%ls", nearly_long_rel_path, nearly_long_rel_path);
639
print_attr_result(L"%\\\\?\\%ls", nearly_long_rel_path);
640
print_attr_result(L"\\\\?\\%ls\\.\\", nearly_long_rel_path);
641
print_attr_result(L"\\\\?\\%ls\\..\\%ls", nearly_long_rel_path, nearly_long_rel_path);
643
print_attr_result(nearly_long_path + 4);
644
print_attr_result(L"%ls\\.\\", nearly_long_path + 4);
645
print_attr_result(L"%ls\\..\\%ls", nearly_long_path + 4, nearly_long_rel_path);
646
print_attr_result(nearly_long_path);
647
print_attr_result(L"%ls\\.\\", nearly_long_path);
648
print_attr_result(L"%ls\\..\\%ls", nearly_long_path, nearly_long_rel_path);
650
check_file_not_present(L"");
652
// Check relative paths
653
check_dir(nearly_long_rel_path, false);
654
check_dir(long_rel_path, true);
655
check_dir(empty_dir_rel_path, true);
656
check_dir(not_empty_dir_rel_path, false);
657
check_file(nearly_long_file_rel_path);
658
check_file(file_rel_path);
660
// Check absolute paths
662
check_dir(root_dir_path, false);
663
check_dir(root_rel_dir_path, false);
666
check_dir(cwd, false);
667
check_dir(nearly_long_path + 4, false);
668
check_dir(empty_dir_path + 4, true);
669
check_dir(not_empty_dir_path + 4, false);
670
check_file(nearly_long_file_path + 4);
671
check_file(file_path + 4);
675
check_dir(nearly_long_unc_path, false);
676
check_dir(empty_dir_unc_path, true);
677
check_dir(not_empty_dir_unc_path, false);
678
check_file(nearly_long_file_unc_path);
679
check_file(file_unc_path);
682
// Check handling of <DRIVE>:/../<OTHER_DRIVE>:/path/...
683
// The other drive letter should not overwrite the original one.
685
static wchar_t tmp[JVM_MAXPATHLEN];
686
const wchar_t* other_letter = dir_letter == L'D' ? L"C" : L"D";
687
wsprintfW(tmp, L"%2ls\\..\\%ls:%ls", nearly_long_file_path, other_letter, nearly_long_file_path + 2);
688
check_file_not_present(tmp);
689
wsprintfW(tmp, L"%2ls\\..\\%ls:%ls", file_path, other_letter, file_path + 2);
690
check_file_not_present(tmp);
694
delete_rel_file_w(file_rel_path);
695
delete_rel_file_w(nearly_long_file_rel_path);
696
delete_empty_rel_directory_w(not_empty_dir_rel_path);
697
delete_empty_rel_directory_w(empty_dir_rel_path);
698
delete_empty_rel_directory_w(long_rel_path);
699
delete_empty_rel_directory_w(nearly_long_rel_path);
702
TEST_VM(os_windows, reserve_memory_special) {
703
TestReserveMemorySpecial_test();
706
TEST_VM(os_windows, processor_count) {
707
JVMFlag* flag = JVMFlag::find_flag("UseAllWindowsProcessorGroups");
708
EXPECT_NE(flag, nullptr) << "Expected UseAllWindowsProcessorGroups product flag to be available";
710
int processors = os::processor_count();
711
EXPECT_GT(processors, 0) << "Expected at least 1 processor";
713
int active_processors = os::active_processor_count();
714
EXPECT_GT(active_processors, 0) << "Expected at least 1 active processor";
716
bool schedules_all_processor_groups = os::win32::is_windows_11_or_greater() || os::win32::is_windows_server_2022_or_greater();
717
if (schedules_all_processor_groups && UseAllWindowsProcessorGroups) {
718
EXPECT_EQ(active_processors, processors) << "Expected all processors to be active";
720
// active_processors should be at most the number of processors in 1 Windows processor group.
721
EXPECT_LE(active_processors, processors) << "Expected active processors to not exceed available processors";
725
class ReserveMemorySpecialRunnable : public TestRunnable {
727
void runUnitTest() const {
728
TestReserveMemorySpecial_test();
732
TEST_VM(os_windows, reserve_memory_special_concurrent) {
733
ReserveMemorySpecialRunnable runnable;
734
ConcurrentTestRunner testRunner(&runnable, 30, 15000);