jdk

Форк
0
/
test_os_windows.cpp 
738 строк · 28.1 Кб
1
/*
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.
4
 *
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.
8
 *
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).
14
 *
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.
18
 *
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
21
 * questions.
22
 */
23

24
#include "precompiled.hpp"
25

26
#ifdef _WINDOWS
27

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"
34

35
namespace {
36
  class MemoryReleaser {
37
    char* const _ptr;
38
    const size_t _size;
39
   public:
40
    MemoryReleaser(char* ptr, size_t size) : _ptr(ptr), _size(size) { }
41
    ~MemoryReleaser() {
42
      if (_ptr != nullptr) {
43
        os::release_memory_special(_ptr, _size);
44
      }
45
    }
46
  };
47
}
48

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
57
// be legitimate.
58
void TestReserveMemorySpecial_test() {
59
  if (!UseLargePages) {
60
    return;
61
  }
62

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);
68

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
73
      return;
74
  }
75
  MemoryReleaser m1(result, large_allocation_size);
76

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";
82

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());
89

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);
97
}
98

99
// The types of path modifications we randomly apply to a path. They should not change the file designated by the path.
100
enum ModsFilter {
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
106
};
107

108
// The mode in which to run.
109
enum Mode {
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.
113
};
114

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;
119

120

121
// Utility methods
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;
126
}
127

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))
133

134
static bool file_exists_w(const wchar_t* path) {
135
  WIN32_FILE_ATTRIBUTE_DATA file_data;
136
  return ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data);
137
}
138

139
static void create_rel_directory_w(const wchar_t* path) {
140
  WITH_ABS_PATH(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();
144
}
145

146
static void delete_empty_rel_directory_w(const wchar_t* path) {
147
  WITH_ABS_PATH(path);
148
  EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete directory: \"" << path << "\" does not exists";
149
  const int retry_count = 20;
150

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);
155

156
    if (!result && (i < retry_count)) {
157
      Sleep(1);
158
    } else {
159
      EXPECT_TRUE(result) << "Failed to delete directory \"" << path << "\": " << GetLastError();
160
      return;
161
    }
162
  }
163
}
164

165
static void create_rel_file_w(const wchar_t* path) {
166
  WITH_ABS_PATH(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();
170
  CloseHandle(h);
171
}
172

173
static void delete_rel_file_w(const wchar_t* path) {
174
  WITH_ABS_PATH(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();
178
}
179

180
static bool convert_to_cstring(char* c_str, size_t size, const wchar_t* w_str) {
181
  size_t converted;
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";
184

185
  return err == ERROR_SUCCESS;
186
}
187

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);
191

192
  if (already_used + len < size) {
193
    wcscpy_s(dest, size - already_used, to_copy);
194
  }
195

196
  return dest + wcslen(to_copy);
197
}
198

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"//\\/"
202
};
203

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;
209

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;
215
    } else {
216
      path_start = wcschr(src + 4, L'\\');
217
    }
218
  } else if (wcsncmp(src, L"\\\\", 2) == 0) {
219
    path_start = wcschr(src + 2, L'?');
220

221
    if (path_start == nullptr) {
222
      path_start = wcschr(src + 2, L'\\');
223
    } else {
224
      path_start = wcschr(path_start, L'\\');
225
    }
226
  } else {
227
    path_start = wcschr(src + 1, L'\\');
228
  }
229

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;
233

234
  while ((*src != L'\0') && (result + size > dest)) {
235
    wchar_t c = *src;
236
    *dest = c;
237
    ++src;
238
    ++dest;
239

240
    if (c == L'\\') {
241
      if (allow_sep_change && (os::random() & 3) == 3) {
242
        int i = os::random() % (sizeof(sep_replacements) / sizeof(sep_replacements[0]));
243

244
        if (i >= 0) {
245
          const wchar_t* replacement = sep_replacements[i];
246
          dest = my_wcscpy_s(dest - 1, size,  result, replacement);
247
        }
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;
251

252
          while (last_sep[0] != L'\\') {
253
            --last_sep;
254
          }
255

256
          if (last_sep > path_start) {
257
            dest = my_wcscpy_s(dest, size, result, L"../");
258
            src = last_sep + 1;
259
          }
260
        } else if (allow_dot_change && (src > path_start + 1) && ((os::random() & 7) == 7)) {
261
          dest = my_wcscpy_s(dest, size, result, L"./");
262
        }
263
      }
264
    }
265
  }
266

267
  while (is_dir && ((os::random() & 15) == 1)) {
268
    dest = my_wcscpy_s(dest, size, result, L"/");
269
  }
270

271
  if (result + size > dest) {
272
    *dest = L'\0';
273
  }
274

275
  // Use this modification only if not too close to the max size.
276
  return result + size - 10 > dest;
277
}
278

279
static void check_dir_impl(wchar_t* path, bool should_be_empty) {
280
  char buf[JVM_MAXPATHLEN];
281

282
  if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
283
    struct stat st;
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);
288
    errno_t err = errno;
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;
292
  }
293
}
294

295
static void check_file_impl(wchar_t* path) {
296
  char buf[JVM_MAXPATHLEN];
297

298
  if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
299
    struct stat st;
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;
304
    if (fd >= 0) {
305
      ::close(fd);
306
    }
307
  }
308
}
309

310
static void check_file_not_present_impl(const wchar_t* path) {
311
  char buf[JVM_MAXPATHLEN];
312

313
  if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
314
    struct stat st;
315
    int stat_ret;
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 << "\"";
321
      if (fd >= 0) {
322
        ::close(fd);
323
      }
324
    }
325
  }
326
}
327

328
static void check_dir(wchar_t* path, bool should_be_empty) {
329
  check_dir_impl(path, should_be_empty);
330

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);
335
    }
336
  }
337
}
338

339
static void check_file(wchar_t* path) {
340
  check_file_impl(path);
341

342
  // Check os::same_files at least somewhat.
343
  char buf[JVM_MAXPATHLEN];
344

345
  if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
346
    wchar_t mod[JVM_MAXPATHLEN];
347

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 << "\"";
352
      }
353
    }
354
  }
355

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);
360
    }
361
  }
362
}
363

364
static void check_file_not_present(const wchar_t* path) {
365
  check_file_not_present_impl(path);
366

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);
371
    }
372
  }
373
}
374

375
static void record_path(char const* name, char const* len_name, wchar_t* path) {
376
  char buf[JVM_MAXPATHLEN];
377

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);
382
  }
383
}
384

385
static void bench_path(wchar_t* path) {
386
  char buf[JVM_MAXPATHLEN];
387
  int reps = 100000;
388

389
  if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
390
    jlong wtime[2];
391

392
    for (int t = 0; t < 2; ++t) {
393
      wtime[t] = os::javaTimeNanos();
394

395
      for (int i = 0; i < reps; ++i) {
396
        bool succ = false;
397
        size_t buf_len = strlen(buf);
398
        wchar_t* w_path = (wchar_t*) os::malloc(sizeof(wchar_t) * (buf_len + 1), mtInternal);
399

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) {
403
            if (t == 1) {
404
              wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * JVM_MAXPATHLEN, mtInternal);
405

406
              if (tmp) {
407
                if (_wfullpath(tmp, w_path, JVM_MAXPATHLEN)) {
408
                  succ = true;
409
                }
410

411
                // Note that we really don't use the full path name, but just add the cost of running _wfullpath.
412
                os::free(tmp);
413
              }
414
              if (!succ) {
415
                printf("Failed fullpathing \"%s\"\n", buf);
416
                return;
417
              }
418
              succ = false;
419
            }
420
            HANDLE h = ::CreateFileW(w_path, 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
421

422
            if (h != INVALID_HANDLE_VALUE) {
423
              ::CloseHandle(h);
424
              succ = true;
425
            }
426
          }
427
        }
428

429
        os::free(w_path);
430
        if (!succ) {
431
          printf("Failed getting W*attr. \"%s\"\n", buf);
432
          return;
433
        }
434
      }
435

436
      wtime[t] = os::javaTimeNanos() - wtime[t];
437
    }
438

439
    jlong ctime = os::javaTimeNanos();
440

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);
443

444
      if (h == INVALID_HANDLE_VALUE) {
445
        return;
446
      }
447

448
      ::CloseHandle(h);
449
    }
450

451
    ctime = os::javaTimeNanos() - ctime;
452

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);
455
  }
456
}
457

458
static void print_attr_result_for_path(const wchar_t* path) {
459
  WIN32_FILE_ATTRIBUTE_DATA file_data;
460
  struct stat st;
461
  char buf[JVM_MAXPATHLEN];
462
  wchar_t abs[JVM_MAXPATHLEN];
463

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");
469

470
  if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
471
    bret = ::GetFileAttributesExA(buf, GetFileExInfoStandard, &file_data);
472
    printf("GetFileAttributesExA() %s\n", bret ? "success" : "failed");
473

474
    bool succ = os::stat(buf, &st) != -1;
475
    printf("os::stat()             %s\n", succ ? "success" : "failed");
476
  }
477
}
478

479
static void print_attr_result(const wchar_t* format, ...) {
480
  va_list argptr;
481
  wchar_t buf[JVM_MAXPATHLEN];
482

483
  va_start(argptr, format);
484
  wvsprintfW(buf, format, argptr);
485
  print_attr_result_for_path(buf);
486
  va_end(argptr);
487
}
488

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
492

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];
515

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";
520
  wchar_t dir_letter;
521
  WIN32_FILE_ATTRIBUTE_DATA file_data;
522
  bool can_test_unc = false;
523

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);
529

530
  memcpy(nearly_long_rel_path, dir_prefix, sizeof(wchar_t) * dir_prefix_len);
531

532
  for (int i = dir_prefix_len; i < rel_path_len; ++i) {
533
    nearly_long_rel_path[i] = L'L';
534
  }
535

536
  nearly_long_rel_path[rel_path_len] = L'\0';
537

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);
555

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);
572

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);
579

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);
586
  } else {
587
    can_test_unc = true;
588
  }
589

590
  if (mode == BENCH) {
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);
597

598
    if (dir_letter) {
599
      static wchar_t top_buf[JVM_MAXPATHLEN];
600
      wchar_t* top_path = wcschr(cwd + 3, L'\\');
601

602
      if (top_path) {
603
        size_t top_len = (top_path - cwd) - 3;
604

605
        memcpy(top_buf, cwd + 3, top_len * 2);
606
        top_buf[top_len] = L'\0';
607
        top_path = top_buf;
608
      }
609

610
      print_attr_result(L"%lc:\\", dir_letter);
611
      print_attr_result(L"%lc:\\.\\", dir_letter);
612

613
      if (top_path) {
614
        print_attr_result(L"%lc:\\%ls\\..\\%ls\\", dir_letter, top_path, top_path);
615
      }
616

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);
634
    }
635

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);
642

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);
649
  } else {
650
    check_file_not_present(L"");
651

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);
659

660
    // Check absolute paths
661
    if (dir_letter) {
662
      check_dir(root_dir_path, false);
663
      check_dir(root_rel_dir_path, false);
664
    }
665

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);
672

673
    // Check UNC paths
674
    if (can_test_unc) {
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);
680
    }
681

682
    // Check handling of <DRIVE>:/../<OTHER_DRIVE>:/path/...
683
    // The other drive letter should not overwrite the original one.
684
    if (dir_letter) {
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);
691
    }
692
  }
693

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);
700
}
701

702
TEST_VM(os_windows, reserve_memory_special) {
703
  TestReserveMemorySpecial_test();
704
}
705

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";
709

710
  int processors = os::processor_count();
711
  EXPECT_GT(processors, 0) << "Expected at least 1 processor";
712

713
  int active_processors = os::active_processor_count();
714
  EXPECT_GT(active_processors, 0) << "Expected at least 1 active processor";
715

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";
719
  } else {
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";
722
  }
723
}
724

725
class ReserveMemorySpecialRunnable : public TestRunnable {
726
public:
727
  void runUnitTest() const {
728
    TestReserveMemorySpecial_test();
729
  }
730
};
731

732
TEST_VM(os_windows, reserve_memory_special_concurrent) {
733
  ReserveMemorySpecialRunnable runnable;
734
  ConcurrentTestRunner testRunner(&runnable, 30, 15000);
735
  testRunner.run();
736
}
737

738
#endif
739

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.