< prev index next >

test/hotspot/gtest/runtime/test_os_windows.cpp

Print this page




  68       // failed to allocate memory, skipping the test
  69       return;
  70   }
  71   MemoryReleaser mr(result, large_allocation_size);
  72 
  73   // allocate another page within the recently allocated memory area which seems to be a good location. At least
  74   // we managed to get it once.
  75   const size_t expected_allocation_size = os::large_page_size();
  76   char* expected_location = result + os::large_page_size();
  77   char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), expected_location, false);
  78   if (actual_location != NULL) {
  79       // failed to allocate memory, skipping the test
  80       return;
  81   }
  82   MemoryReleaser mr2(actual_location, expected_allocation_size);
  83 
  84   EXPECT_EQ(expected_location, actual_location)
  85         << "Failed to allocate memory at requested location " << expected_location << " of size " << expected_allocation_size;
  86 }
  87 
  88 
  89 // Test which tries to find out if the os::stat, os::open and os::dir_is_empty methods
  90 // can handle long path names correctly.
  91 enum ModsFilter {
  92   Allow_None = 0,
  93   Allow_Sep_Mods = 1,
  94   Allow_Dot_Path = 2,
  95   Allow_Dot_Dot_Path = 4,
  96   Allow_All = Allow_Sep_Mods | Allow_Dot_Path | Allow_Dot_Dot_Path
  97 };
  98 

  99 enum Mode {
 100   TEST,
 101   EXAMPLES,
 102   BENCH
 103 };
 104 

 105 static ModsFilter mods_filter = Allow_All;
 106 static int mods_per_path = 50;
 107 static Mode mode = TEST;
 108 


 109 static void get_current_dir_w(wchar_t* path, size_t size) {
 110   DWORD count = GetCurrentDirectoryW((DWORD) size, path);
 111   EXPECT_GT((int) count, 0) << "Failed to get current directory: " << GetLastError();
 112   EXPECT_LT((size_t) count, size) << "Buffer too small for current directory: " << size;
 113 }
 114 
 115 #define WITH_ABS_PATH(path) \
 116   wchar_t abs_path[JVM_MAXPATHLEN]; \
 117   wchar_t cwd[JVM_MAXPATHLEN]; \
 118   get_current_dir_w(cwd, JVM_MAXPATHLEN); \
 119   wsprintfW(abs_path, L"\\\\?\\%ls\\%ls", cwd, (path))
 120 
 121 static bool file_exists_w(const wchar_t* path) {
 122   WIN32_FILE_ATTRIBUTE_DATA file_data;
 123   return ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data);
 124 }
 125 
 126 static void create_rel_directory_w(const wchar_t* path) {
 127   WITH_ABS_PATH(path);
 128   EXPECT_FALSE(file_exists_w(abs_path)) <<  "Can't create directory: \"" << path << "\" already exists";


 143   HANDLE h = CreateFileW(abs_path, 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
 144   EXPECT_NE(h, INVALID_HANDLE_VALUE) << "Failed to create file \"" << path << "\": " << GetLastError();
 145   CloseHandle(h);
 146 }
 147 
 148 static void delete_rel_file_w(const wchar_t* path) {
 149   WITH_ABS_PATH(path);
 150   EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete file: \"" << path << "\" does not exists";
 151   BOOL result = DeleteFileW(abs_path);
 152   EXPECT_TRUE(result) << "Failed to delete file \"" << path << "\": " << GetLastError();
 153 }
 154 
 155 static bool convert_to_cstring(char* c_str, size_t size, wchar_t* w_str) {
 156   size_t converted;
 157   errno_t err = wcstombs_s(&converted, c_str, size, w_str, size - 1);
 158   EXPECT_EQ(err, ERROR_SUCCESS) << "Could not convert \"" << w_str << "\" to c-string";
 159 
 160   return err == ERROR_SUCCESS;
 161 }
 162 
 163 static const wchar_t* sep_replacements[] = {
 164   L"\\", L"\\/", L"/", L"//", L"\\\\/\\", L"//\\/"
 165 };
 166 
 167 static wchar_t* my_wcscpy_s(wchar_t* dest, size_t size, wchar_t* start, const wchar_t* to_copy) {
 168   size_t already_used = dest - start;
 169   size_t len = wcslen(to_copy);
 170 
 171   if (already_used + len < size) {
 172     wcscpy_s(dest, size - already_used, to_copy);
 173   }
 174 
 175   return dest + wcslen(to_copy);
 176 }
 177 






 178 static bool unnormalize_path(wchar_t* result, size_t size, bool is_dir, const wchar_t* path) {
 179   wchar_t* dest = result;
 180   const wchar_t* src = path;
 181   const wchar_t* path_start;
 182 
 183   if (wcsncmp(src, L"\\\\?\\UNC\\", 8) == 0) {
 184     path_start = src + 8;
 185   } else if (wcsncmp(src, L"\\\\?\\", 4) == 0) {
 186     if (src[5] == L':') {
 187       path_start = src + 6;
 188     } else {
 189       path_start = wcschr(src + 4, L'\\');
 190     }
 191   } else if (wcsncmp(src, L"\\\\", 2) == 0) {
 192     path_start = wcschr(src + 2, L'?');
 193 
 194     if (path_start == NULL) {
 195       path_start = wcschr(src + 2, L'\\');
 196     } else {
 197       path_start = wcschr(path_start, L'\\');


 295         ::close(fd);
 296       }
 297     }
 298   }
 299 }
 300 
 301 static void check_dir(wchar_t* path, bool should_be_empty) {
 302   check_dir_impl(path, should_be_empty);
 303 
 304   for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {
 305     wchar_t tmp[JVM_MAXPATHLEN];
 306     if (unnormalize_path(tmp, JVM_MAXPATHLEN, true, path)) {
 307       check_dir_impl(tmp, should_be_empty);
 308     }
 309   }
 310 }
 311 
 312 static void check_file(wchar_t* path) {
 313   check_file_impl(path);
 314 














 315   for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {
 316     wchar_t tmp[JVM_MAXPATHLEN];
 317     if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) {
 318       check_file_impl(tmp);
 319     }
 320   }
 321 }
 322 
 323 static void check_file_not_present(wchar_t* path) {
 324   check_file_not_present_impl(path);
 325 
 326   for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {
 327     wchar_t tmp[JVM_MAXPATHLEN];
 328     if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) {
 329       check_file_not_present_impl(tmp);
 330     }
 331   }
 332 }
 333 
 334 static void record_path(char const* name, char const* len_name, wchar_t* path) {


 350 
 351     for (int t = 0; t < 2; ++t) {
 352       wtime[t] = os::javaTimeNanos();
 353 
 354       for (int i = 0; i < reps; ++i) {
 355         bool succ = false;
 356         size_t buf_len = strlen(buf);
 357         wchar_t* w_path = (wchar_t*) os::malloc(sizeof(wchar_t) * (buf_len + 1), mtInternal);
 358 
 359         if (w_path != NULL) {
 360           size_t converted_chars;
 361           if (::mbstowcs_s(&converted_chars, w_path, buf_len + 1, buf, buf_len) == ERROR_SUCCESS) {
 362             if (t == 1) {
 363               wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * JVM_MAXPATHLEN, mtInternal);
 364 
 365               if (tmp) {
 366                 if (_wfullpath(tmp, w_path, JVM_MAXPATHLEN)) {
 367                   succ = true;
 368                 }
 369 

 370                 os::free(tmp);
 371               }
 372               if (!succ) {
 373                 printf("Failed fullpathing \"%s\"\n", buf);
 374                 return;
 375               }
 376               succ = false;
 377             }
 378             HANDLE h = ::CreateFileW(w_path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
 379 
 380             if (h != INVALID_HANDLE_VALUE) {
 381               ::CloseHandle(h);
 382               succ = true;
 383             }
 384           }
 385         }
 386 
 387         os::free(w_path);
 388         if (!succ) {
 389           printf("Failed getting W*attr. \"%s\"\n", buf);


 431 
 432     bool succ = os::stat(buf, &st) != -1;
 433     printf("os::stat()             %s\n", succ ? "success" : "failed");
 434   }
 435 }
 436 
 437 static void print_attr_result(wchar_t* format, ...) {
 438   va_list argptr;
 439   wchar_t buf[JVM_MAXPATHLEN];
 440 
 441   va_start(argptr, format);
 442   wvsprintfW(buf, format, argptr);
 443   print_attr_result_for_path(buf);
 444   va_end(argptr);
 445 }
 446 
 447 #define RECORD_PATH(name) record_path(#name, #name "Len", name)
 448 #define NAME_PART_50 L"01234567890123456789012345678901234567890123456789"
 449 #define NAME_PART_250 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50
 450 


 451 TEST_VM(os_windows, handle_long_paths) {
 452   static wchar_t cwd[JVM_MAXPATHLEN];
 453   static wchar_t nearly_long_rel_path[JVM_MAXPATHLEN];
 454   static wchar_t long_rel_path[JVM_MAXPATHLEN];
 455   static wchar_t empty_dir_rel_path[JVM_MAXPATHLEN];
 456   static wchar_t not_empty_dir_rel_path[JVM_MAXPATHLEN];
 457   static wchar_t file_rel_path[JVM_MAXPATHLEN];
 458   static wchar_t nearly_long_file_rel_path[JVM_MAXPATHLEN];
 459   static wchar_t nearly_long_path[JVM_MAXPATHLEN];
 460   static wchar_t empty_dir_path[JVM_MAXPATHLEN];
 461   static wchar_t not_empty_dir_path[JVM_MAXPATHLEN];
 462   static wchar_t nearly_long_file_path[JVM_MAXPATHLEN];
 463   static wchar_t file_path[JVM_MAXPATHLEN];
 464   static wchar_t nearly_long_unc_path[JVM_MAXPATHLEN];
 465   static wchar_t empty_dir_unc_path[JVM_MAXPATHLEN];
 466   static wchar_t not_empty_dir_unc_path[JVM_MAXPATHLEN];
 467   static wchar_t nearly_long_file_unc_path[JVM_MAXPATHLEN];
 468   static wchar_t file_unc_path[JVM_MAXPATHLEN];
 469   static wchar_t root_dir_path[JVM_MAXPATHLEN];
 470   static wchar_t root_rel_dir_path[JVM_MAXPATHLEN];




  68       // failed to allocate memory, skipping the test
  69       return;
  70   }
  71   MemoryReleaser mr(result, large_allocation_size);
  72 
  73   // allocate another page within the recently allocated memory area which seems to be a good location. At least
  74   // we managed to get it once.
  75   const size_t expected_allocation_size = os::large_page_size();
  76   char* expected_location = result + os::large_page_size();
  77   char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), expected_location, false);
  78   if (actual_location != NULL) {
  79       // failed to allocate memory, skipping the test
  80       return;
  81   }
  82   MemoryReleaser mr2(actual_location, expected_allocation_size);
  83 
  84   EXPECT_EQ(expected_location, actual_location)
  85         << "Failed to allocate memory at requested location " << expected_location << " of size " << expected_allocation_size;
  86 }
  87 
  88 // The types of path modifications we randomly apply to a path. They should not change the file designated by the path.


  89 enum ModsFilter {
  90   Allow_None = 0, // No modifications
  91   Allow_Sep_Mods = 1, // Replace '\\' by any sequence of '/' or '\\' or at least length 1.
  92   Allow_Dot_Path = 2, // Add /. segments at random positions
  93   Allow_Dot_Dot_Path = 4, // Add /../<correct-dir> segments at random positions.
  94   Allow_All = Allow_Sep_Mods | Allow_Dot_Path | Allow_Dot_Dot_Path
  95 };
  96 
  97 // The mode in which to run.
  98 enum Mode {
  99   TEST, // Runs the test. This is the normal modus.
 100   EXAMPLES, // Runs example which document the behaviour of the Windows system calls.
 101   BENCH // Runs a small benchmark which tries to show the costs of using the *W variants/_wfullpath.
 102 };
 103 
 104 // Parameters of the test.
 105 static ModsFilter mods_filter = Allow_All;
 106 static int mods_per_path = 50; // The number of variants of a path we try.
 107 static Mode mode = TEST;
 108 
 109 
 110 // Utility methods
 111 static void get_current_dir_w(wchar_t* path, size_t size) {
 112   DWORD count = GetCurrentDirectoryW((DWORD) size, path);
 113   EXPECT_GT((int) count, 0) << "Failed to get current directory: " << GetLastError();
 114   EXPECT_LT((size_t) count, size) << "Buffer too small for current directory: " << size;
 115 }
 116 
 117 #define WITH_ABS_PATH(path) \
 118   wchar_t abs_path[JVM_MAXPATHLEN]; \
 119   wchar_t cwd[JVM_MAXPATHLEN]; \
 120   get_current_dir_w(cwd, JVM_MAXPATHLEN); \
 121   wsprintfW(abs_path, L"\\\\?\\%ls\\%ls", cwd, (path))
 122 
 123 static bool file_exists_w(const wchar_t* path) {
 124   WIN32_FILE_ATTRIBUTE_DATA file_data;
 125   return ::GetFileAttributesExW(path, GetFileExInfoStandard, &file_data);
 126 }
 127 
 128 static void create_rel_directory_w(const wchar_t* path) {
 129   WITH_ABS_PATH(path);
 130   EXPECT_FALSE(file_exists_w(abs_path)) <<  "Can't create directory: \"" << path << "\" already exists";


 145   HANDLE h = CreateFileW(abs_path, 0, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
 146   EXPECT_NE(h, INVALID_HANDLE_VALUE) << "Failed to create file \"" << path << "\": " << GetLastError();
 147   CloseHandle(h);
 148 }
 149 
 150 static void delete_rel_file_w(const wchar_t* path) {
 151   WITH_ABS_PATH(path);
 152   EXPECT_TRUE(file_exists_w(abs_path)) << "Can't delete file: \"" << path << "\" does not exists";
 153   BOOL result = DeleteFileW(abs_path);
 154   EXPECT_TRUE(result) << "Failed to delete file \"" << path << "\": " << GetLastError();
 155 }
 156 
 157 static bool convert_to_cstring(char* c_str, size_t size, wchar_t* w_str) {
 158   size_t converted;
 159   errno_t err = wcstombs_s(&converted, c_str, size, w_str, size - 1);
 160   EXPECT_EQ(err, ERROR_SUCCESS) << "Could not convert \"" << w_str << "\" to c-string";
 161 
 162   return err == ERROR_SUCCESS;
 163 }
 164 




 165 static wchar_t* my_wcscpy_s(wchar_t* dest, size_t size, wchar_t* start, const wchar_t* to_copy) {
 166   size_t already_used = dest - start;
 167   size_t len = wcslen(to_copy);
 168 
 169   if (already_used + len < size) {
 170     wcscpy_s(dest, size - already_used, to_copy);
 171   }
 172 
 173   return dest + wcslen(to_copy);
 174 }
 175 
 176 // The currently finite list of seperator sequences we might use instead of '\\'.
 177 static const wchar_t* sep_replacements[] = {
 178   L"\\", L"\\/", L"/", L"//", L"\\\\/\\", L"//\\/"
 179 };
 180 
 181 // Takes a path and modifies it in a way that it should still designate the same file.
 182 static bool unnormalize_path(wchar_t* result, size_t size, bool is_dir, const wchar_t* path) {
 183   wchar_t* dest = result;
 184   const wchar_t* src = path;
 185   const wchar_t* path_start;
 186 
 187   if (wcsncmp(src, L"\\\\?\\UNC\\", 8) == 0) {
 188     path_start = src + 8;
 189   } else if (wcsncmp(src, L"\\\\?\\", 4) == 0) {
 190     if (src[5] == L':') {
 191       path_start = src + 6;
 192     } else {
 193       path_start = wcschr(src + 4, L'\\');
 194     }
 195   } else if (wcsncmp(src, L"\\\\", 2) == 0) {
 196     path_start = wcschr(src + 2, L'?');
 197 
 198     if (path_start == NULL) {
 199       path_start = wcschr(src + 2, L'\\');
 200     } else {
 201       path_start = wcschr(path_start, L'\\');


 299         ::close(fd);
 300       }
 301     }
 302   }
 303 }
 304 
 305 static void check_dir(wchar_t* path, bool should_be_empty) {
 306   check_dir_impl(path, should_be_empty);
 307 
 308   for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {
 309     wchar_t tmp[JVM_MAXPATHLEN];
 310     if (unnormalize_path(tmp, JVM_MAXPATHLEN, true, path)) {
 311       check_dir_impl(tmp, should_be_empty);
 312     }
 313   }
 314 }
 315 
 316 static void check_file(wchar_t* path) {
 317   check_file_impl(path);
 318 
 319   // Check os::same_files at least somewhat.
 320   char buf[JVM_MAXPATHLEN];
 321 
 322   if (convert_to_cstring(buf, JVM_MAXPATHLEN, path)) {
 323     wchar_t mod[JVM_MAXPATHLEN];
 324 
 325     if (unnormalize_path(mod, JVM_MAXPATHLEN, false, path)) {
 326       char mod_c[JVM_MAXPATHLEN];
 327       if (convert_to_cstring(mod_c, JVM_MAXPATHLEN, mod)) {
 328         EXPECT_EQ(os::same_files(buf, mod_c), true) << "os::same files failed for \\" << path << "\" and \"" << mod_c << "\"";
 329       }
 330     }
 331   }
 332 
 333   for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {
 334     wchar_t tmp[JVM_MAXPATHLEN];
 335     if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) {
 336       check_file_impl(tmp);
 337     }
 338   }
 339 }
 340 
 341 static void check_file_not_present(wchar_t* path) {
 342   check_file_not_present_impl(path);
 343 
 344   for (int i = 0; mods_filter != Allow_None && i < mods_per_path; ++i) {
 345     wchar_t tmp[JVM_MAXPATHLEN];
 346     if (unnormalize_path(tmp, JVM_MAXPATHLEN, false, path)) {
 347       check_file_not_present_impl(tmp);
 348     }
 349   }
 350 }
 351 
 352 static void record_path(char const* name, char const* len_name, wchar_t* path) {


 368 
 369     for (int t = 0; t < 2; ++t) {
 370       wtime[t] = os::javaTimeNanos();
 371 
 372       for (int i = 0; i < reps; ++i) {
 373         bool succ = false;
 374         size_t buf_len = strlen(buf);
 375         wchar_t* w_path = (wchar_t*) os::malloc(sizeof(wchar_t) * (buf_len + 1), mtInternal);
 376 
 377         if (w_path != NULL) {
 378           size_t converted_chars;
 379           if (::mbstowcs_s(&converted_chars, w_path, buf_len + 1, buf, buf_len) == ERROR_SUCCESS) {
 380             if (t == 1) {
 381               wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * JVM_MAXPATHLEN, mtInternal);
 382 
 383               if (tmp) {
 384                 if (_wfullpath(tmp, w_path, JVM_MAXPATHLEN)) {
 385                   succ = true;
 386                 }
 387 
 388                 // Note that we really don't use the full path name, but just add the cost of running _wfullpath.
 389                 os::free(tmp);
 390               }
 391               if (!succ) {
 392                 printf("Failed fullpathing \"%s\"\n", buf);
 393                 return;
 394               }
 395               succ = false;
 396             }
 397             HANDLE h = ::CreateFileW(w_path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
 398 
 399             if (h != INVALID_HANDLE_VALUE) {
 400               ::CloseHandle(h);
 401               succ = true;
 402             }
 403           }
 404         }
 405 
 406         os::free(w_path);
 407         if (!succ) {
 408           printf("Failed getting W*attr. \"%s\"\n", buf);


 450 
 451     bool succ = os::stat(buf, &st) != -1;
 452     printf("os::stat()             %s\n", succ ? "success" : "failed");
 453   }
 454 }
 455 
 456 static void print_attr_result(wchar_t* format, ...) {
 457   va_list argptr;
 458   wchar_t buf[JVM_MAXPATHLEN];
 459 
 460   va_start(argptr, format);
 461   wvsprintfW(buf, format, argptr);
 462   print_attr_result_for_path(buf);
 463   va_end(argptr);
 464 }
 465 
 466 #define RECORD_PATH(name) record_path(#name, #name "Len", name)
 467 #define NAME_PART_50 L"01234567890123456789012345678901234567890123456789"
 468 #define NAME_PART_250 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50 NAME_PART_50
 469 
 470 // Test which tries to find out if the os::stat, os::open and os::dir_is_empty methods
 471 // can handle long path names correctly.
 472 TEST_VM(os_windows, handle_long_paths) {
 473   static wchar_t cwd[JVM_MAXPATHLEN];
 474   static wchar_t nearly_long_rel_path[JVM_MAXPATHLEN];
 475   static wchar_t long_rel_path[JVM_MAXPATHLEN];
 476   static wchar_t empty_dir_rel_path[JVM_MAXPATHLEN];
 477   static wchar_t not_empty_dir_rel_path[JVM_MAXPATHLEN];
 478   static wchar_t file_rel_path[JVM_MAXPATHLEN];
 479   static wchar_t nearly_long_file_rel_path[JVM_MAXPATHLEN];
 480   static wchar_t nearly_long_path[JVM_MAXPATHLEN];
 481   static wchar_t empty_dir_path[JVM_MAXPATHLEN];
 482   static wchar_t not_empty_dir_path[JVM_MAXPATHLEN];
 483   static wchar_t nearly_long_file_path[JVM_MAXPATHLEN];
 484   static wchar_t file_path[JVM_MAXPATHLEN];
 485   static wchar_t nearly_long_unc_path[JVM_MAXPATHLEN];
 486   static wchar_t empty_dir_unc_path[JVM_MAXPATHLEN];
 487   static wchar_t not_empty_dir_unc_path[JVM_MAXPATHLEN];
 488   static wchar_t nearly_long_file_unc_path[JVM_MAXPATHLEN];
 489   static wchar_t file_unc_path[JVM_MAXPATHLEN];
 490   static wchar_t root_dir_path[JVM_MAXPATHLEN];
 491   static wchar_t root_rel_dir_path[JVM_MAXPATHLEN];


< prev index next >