mirror of
https://git.mirrors.martin98.com/https://github.com/gulrak/filesystem
synced 2025-06-04 11:13:58 +08:00
Squashed commit of the following:
commit 742d51b24cce19915e10f0d1f97cf49ff408b66d Author: Steffen Schuemann <s.schuemann@pobox.com> Date: Sat Apr 27 10:17:15 2019 +0200 Fixed ctest call. commit f96b65562d42cc6801ba3855dc603117e4ce864a Author: Steffen Schümann <s.schuemann@pobox.com> Date: Sat Apr 27 09:42:20 2019 +0200 Fix in canonical root path handling. commit 1cd346d23e87b274d32b9d56a8b6327e36be4147 Author: gulrak <s.schuemann@pobox.com> Date: Sat Apr 27 06:22:13 2019 +0200 Work on MingW issues and additional tests.
This commit is contained in:
parent
55cf5307c6
commit
c75a663ec9
@ -56,5 +56,5 @@ before_script:
|
||||
script:
|
||||
- export VERBOSE=1
|
||||
- cmake --build . --config Release
|
||||
- ctest
|
||||
- ctest -C Release -E Windows
|
||||
|
||||
|
@ -75,7 +75,7 @@
|
||||
#elif defined(GHC_FILESYSTEM_FWD)
|
||||
#define GHC_INLINE
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
#define GHC_FS_API extern
|
||||
#define GHC_FS_API extern
|
||||
#define GHC_FS_API_CLASS
|
||||
#else
|
||||
#define GHC_FS_API extern
|
||||
@ -1259,8 +1259,7 @@ namespace detail {
|
||||
|
||||
GHC_INLINE bool startsWith(const std::string& what, const std::string& with)
|
||||
{
|
||||
return with.length() <= what.length()
|
||||
&& equal(with.begin(), with.end(), what.begin());
|
||||
return with.length() <= what.length() && equal(with.begin(), with.end(), what.begin());
|
||||
}
|
||||
|
||||
GHC_INLINE void postprocess_path_with_format(path::string_type& p, path::format fmt)
|
||||
@ -1277,11 +1276,11 @@ GHC_INLINE void postprocess_path_with_format(path::string_type& p, path::format
|
||||
case path::auto_format:
|
||||
case path::native_format:
|
||||
#endif
|
||||
if(startsWith(p, std::string("\\\\?\\"))) {
|
||||
if (startsWith(p, std::string("\\\\?\\"))) {
|
||||
// remove Windows long filename marker
|
||||
p.erase(0, 4);
|
||||
if(startsWith(p, std::string("UNC\\"))) {
|
||||
p.erase(0,2);
|
||||
if (startsWith(p, std::string("UNC\\"))) {
|
||||
p.erase(0, 2);
|
||||
p[0] = '\\';
|
||||
}
|
||||
}
|
||||
@ -1356,7 +1355,15 @@ namespace detail {
|
||||
GHC_INLINE bool compare_no_case(const char* str1, const char* str2)
|
||||
{
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
# ifdef __GNUC__
|
||||
while (::tolower((unsigned char)*str1) == ::tolower((unsigned char)*str2++)) {
|
||||
if (*str1++ == 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
# else
|
||||
return ::_stricmp(str1, str2);
|
||||
# endif
|
||||
#else
|
||||
return ::strcasecmp(str1, str2);
|
||||
#endif
|
||||
@ -1530,10 +1537,8 @@ GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec)
|
||||
char buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE] = {0};
|
||||
REPARSE_DATA_BUFFER& reparseData = *(REPARSE_DATA_BUFFER*)buffer;
|
||||
ULONG bufferUsed;
|
||||
ULONG dwError;
|
||||
path result;
|
||||
if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, &reparseData, sizeof(buffer), &bufferUsed, 0)) {
|
||||
dwError = NOERROR;
|
||||
if (IsReparseTagMicrosoft(reparseData.ReparseTag)) {
|
||||
switch (reparseData.ReparseTag) {
|
||||
case IO_REPARSE_TAG_SYMLINK:
|
||||
@ -2080,9 +2085,9 @@ GHC_INLINE void path::swap(path& rhs) noexcept
|
||||
GHC_INLINE const path::string_type& path::native() const
|
||||
{
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
if(is_absolute() && _path.length() >= MAX_PATH) {
|
||||
if (is_absolute() && _path.length() > MAX_PATH - 10) {
|
||||
// expand long Windows filenames with marker
|
||||
if(has_root_name() && _path[0] == '/') {
|
||||
if (has_root_name() && _path[0] == '/') {
|
||||
_native_cache = "\\\\?\\UNC" + _path.substr(1);
|
||||
}
|
||||
else {
|
||||
@ -2850,7 +2855,10 @@ GHC_INLINE path canonical(const path& p, std::error_code& ec)
|
||||
result = result.parent_path();
|
||||
continue;
|
||||
}
|
||||
|
||||
else if ((result/pe).string().length() <= root.string().length()) {
|
||||
result /= pe;
|
||||
continue;
|
||||
}
|
||||
auto sls = symlink_status(result / pe, ec);
|
||||
if (ec) {
|
||||
return path();
|
||||
@ -3700,6 +3708,16 @@ GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::e
|
||||
}
|
||||
}
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
# ifdef __GNUC__
|
||||
auto oldAttr = GetFileAttributesW(p.wstring().c_str());
|
||||
if (oldAttr != INVALID_FILE_ATTRIBUTES) {
|
||||
DWORD newAttr = ((prms & perms::owner_write) == perms::owner_write) ? oldAttr & ~FILE_ATTRIBUTE_READONLY : oldAttr | FILE_ATTRIBUTE_READONLY;
|
||||
if (oldAttr == newAttr || SetFileAttributesW(p.wstring().c_str(), newAttr)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ec = std::error_code(::GetLastError(), std::system_category());
|
||||
# else
|
||||
int mode = 0;
|
||||
if ((prms & perms::owner_read) == perms::owner_read) {
|
||||
mode |= _S_IREAD;
|
||||
@ -3710,6 +3728,7 @@ GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::e
|
||||
if (::_wchmod(p.wstring().c_str(), mode) != 0) {
|
||||
ec = std::error_code(::GetLastError(), std::system_category());
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
if ((opts & perm_options::nofollow) != perm_options::nofollow) {
|
||||
if (::chmod(p.c_str(), static_cast<mode_t>(prms)) != 0) {
|
||||
|
@ -1,4 +1,8 @@
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
set(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS ON)
|
||||
include(ParseAndAddCatchTests)
|
||||
|
||||
add_executable(filesystem_test filesystem_test.cpp catch.hpp)
|
||||
target_link_libraries(filesystem_test ghc_filesystem)
|
||||
target_compile_options(filesystem_test PRIVATE
|
||||
@ -13,7 +17,7 @@ if(CMAKE_GENERATOR STREQUAL Xcode)
|
||||
target_compile_options(filesystem_test_cov PRIVATE "$<$<CONFIG:DEBUG>:--coverage>")
|
||||
target_link_libraries(filesystem_test_cov PUBLIC ghc_filesystem PRIVATE --coverage)
|
||||
endif()
|
||||
add_test(filesystem_test filesystem_test)
|
||||
ParseAndAddCatchTests(filesystem_test filesystem_test)
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
|
||||
if(APPLE)
|
||||
|
225
test/cmake/ParseAndAddCatchTests.cmake
Normal file
225
test/cmake/ParseAndAddCatchTests.cmake
Normal file
@ -0,0 +1,225 @@
|
||||
#==================================================================================================#
|
||||
# supported macros #
|
||||
# - TEST_CASE, #
|
||||
# - SCENARIO, #
|
||||
# - TEST_CASE_METHOD, #
|
||||
# - CATCH_TEST_CASE, #
|
||||
# - CATCH_SCENARIO, #
|
||||
# - CATCH_TEST_CASE_METHOD. #
|
||||
# #
|
||||
# Usage #
|
||||
# 1. make sure this module is in the path or add this otherwise: #
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
|
||||
# 2. make sure that you've enabled testing option for the project by the call: #
|
||||
# enable_testing() #
|
||||
# 3. add the lines to the script for testing target (sample CMakeLists.txt): #
|
||||
# project(testing_target) #
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
|
||||
# enable_testing() #
|
||||
# #
|
||||
# find_path(CATCH_INCLUDE_DIR "catch.hpp") #
|
||||
# include_directories(${INCLUDE_DIRECTORIES} ${CATCH_INCLUDE_DIR}) #
|
||||
# #
|
||||
# file(GLOB SOURCE_FILES "*.cpp") #
|
||||
# add_executable(${PROJECT_NAME} ${SOURCE_FILES}) #
|
||||
# #
|
||||
# include(ParseAndAddCatchTests) #
|
||||
# ParseAndAddCatchTests(${PROJECT_NAME}) #
|
||||
# #
|
||||
# The following variables affect the behavior of the script: #
|
||||
# #
|
||||
# PARSE_CATCH_TESTS_VERBOSE (Default OFF) #
|
||||
# -- enables debug messages #
|
||||
# PARSE_CATCH_TESTS_NO_HIDDEN_TESTS (Default OFF) #
|
||||
# -- excludes tests marked with [!hide], [.] or [.foo] tags #
|
||||
# PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME (Default ON) #
|
||||
# -- adds fixture class name to the test name #
|
||||
# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) #
|
||||
# -- adds cmake target name to the test name #
|
||||
# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) #
|
||||
# -- causes CMake to rerun when file with tests changes so that new tests will be discovered #
|
||||
# #
|
||||
# One can also set (locally) the optional variable OptionalCatchTestLauncher to precise the way #
|
||||
# a test should be run. For instance to use test MPI, one can write #
|
||||
# set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC}) #
|
||||
# just before calling this ParseAndAddCatchTests function #
|
||||
# #
|
||||
# The AdditionalCatchParameters optional variable can be used to pass extra argument to the test #
|
||||
# command. For example, to include successful tests in the output, one can write #
|
||||
# set(AdditionalCatchParameters --success) #
|
||||
# #
|
||||
# After the script, the ParseAndAddCatchTests_TESTS property for the target, and for each source #
|
||||
# file in the target is set, and contains the list of the tests extracted from that target, or #
|
||||
# from that file. This is useful, for example to add further labels or properties to the tests. #
|
||||
# #
|
||||
#==================================================================================================#
|
||||
|
||||
if (CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.8)
|
||||
message(FATAL_ERROR "ParseAndAddCatchTests requires CMake 2.8.8 or newer")
|
||||
endif()
|
||||
|
||||
option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF)
|
||||
option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF)
|
||||
option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON)
|
||||
option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON)
|
||||
option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF)
|
||||
|
||||
function(ParseAndAddCatchTests_PrintDebugMessage)
|
||||
if(PARSE_CATCH_TESTS_VERBOSE)
|
||||
message(STATUS "ParseAndAddCatchTests: ${ARGV}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# This removes the contents between
|
||||
# - block comments (i.e. /* ... */)
|
||||
# - full line comments (i.e. // ... )
|
||||
# contents have been read into '${CppCode}'.
|
||||
# !keep partial line comments
|
||||
function(ParseAndAddCatchTests_RemoveComments CppCode)
|
||||
string(ASCII 2 CMakeBeginBlockComment)
|
||||
string(ASCII 3 CMakeEndBlockComment)
|
||||
string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "\\*/" "${CMakeEndBlockComment}" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "${CMakeBeginBlockComment}[^${CMakeEndBlockComment}]*${CMakeEndBlockComment}" "" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "\n[ \t]*//+[^\n]+" "\n" ${CppCode} "${${CppCode}}")
|
||||
|
||||
set(${CppCode} "${${CppCode}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Worker function
|
||||
function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
|
||||
# If SourceFile is an object library, do not scan it (as it is not a file). Exit without giving a warning about a missing file.
|
||||
if(SourceFile MATCHES "\\\$<TARGET_OBJECTS:.+>")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Detected OBJECT library: ${SourceFile} this will not be scanned for tests.")
|
||||
return()
|
||||
endif()
|
||||
# According to CMake docs EXISTS behavior is well-defined only for full paths.
|
||||
get_filename_component(SourceFile ${SourceFile} ABSOLUTE)
|
||||
if(NOT EXISTS ${SourceFile})
|
||||
message(WARNING "Cannot find source file: ${SourceFile}")
|
||||
return()
|
||||
endif()
|
||||
ParseAndAddCatchTests_PrintDebugMessage("parsing ${SourceFile}")
|
||||
file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME)
|
||||
|
||||
# Remove block and fullline comments
|
||||
ParseAndAddCatchTests_RemoveComments(Contents)
|
||||
|
||||
# Find definition of test names
|
||||
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
|
||||
|
||||
if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
|
||||
set_property(
|
||||
DIRECTORY
|
||||
APPEND
|
||||
PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile}
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(TestName ${Tests})
|
||||
# Strip newlines
|
||||
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")
|
||||
|
||||
# Get test type and fixture if applicable
|
||||
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
|
||||
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
|
||||
string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}")
|
||||
|
||||
# Get string parts of test definition
|
||||
string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
|
||||
|
||||
# Strip wrapping quotation marks
|
||||
string(REGEX REPLACE "^\"(.*)\"$" "\\1" TestStrings "${TestStrings}")
|
||||
string(REPLACE "\";\"" ";" TestStrings "${TestStrings}")
|
||||
|
||||
# Validate that a test name and tags have been provided
|
||||
list(LENGTH TestStrings TestStringsLength)
|
||||
if(TestStringsLength GREATER 2 OR TestStringsLength LESS 1)
|
||||
message(FATAL_ERROR "You must provide a valid test name and tags for all tests in ${SourceFile}")
|
||||
endif()
|
||||
|
||||
# Assign name and tags
|
||||
list(GET TestStrings 0 Name)
|
||||
if("${TestType}" STREQUAL "SCENARIO")
|
||||
set(Name "Scenario: ${Name}")
|
||||
endif()
|
||||
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND TestFixture)
|
||||
set(CTestName "${TestFixture}:${Name}")
|
||||
else()
|
||||
set(CTestName "${Name}")
|
||||
endif()
|
||||
if(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME)
|
||||
set(CTestName "${TestTarget}:${CTestName}")
|
||||
endif()
|
||||
# add target to labels to enable running all tests added from this target
|
||||
set(Labels ${TestTarget})
|
||||
if(TestStringsLength EQUAL 2)
|
||||
list(GET TestStrings 1 Tags)
|
||||
string(TOLOWER "${Tags}" Tags)
|
||||
# remove target from labels if the test is hidden
|
||||
if("${Tags}" MATCHES ".*\\[!?(hide|\\.)\\].*")
|
||||
list(REMOVE_ITEM Labels ${TestTarget})
|
||||
endif()
|
||||
string(REPLACE "]" ";" Tags "${Tags}")
|
||||
string(REPLACE "[" "" Tags "${Tags}")
|
||||
else()
|
||||
# unset tags variable from previous loop
|
||||
unset(Tags)
|
||||
endif()
|
||||
|
||||
list(APPEND Labels ${Tags})
|
||||
|
||||
set(HiddenTagFound OFF)
|
||||
foreach(label ${Labels})
|
||||
string(REGEX MATCH "^!hide|^\\." result ${label})
|
||||
if(result)
|
||||
set(HiddenTagFound ON)
|
||||
break()
|
||||
endif(result)
|
||||
endforeach(label)
|
||||
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
|
||||
else()
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Adding test \"${CTestName}\"")
|
||||
if(Labels)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Setting labels to ${Labels}")
|
||||
endif()
|
||||
|
||||
# Escape commas in the test spec
|
||||
string(REPLACE "," "\\," Name ${Name})
|
||||
|
||||
# Add the test and set its properties
|
||||
add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters})
|
||||
# Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
|
||||
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property")
|
||||
set_tests_properties("\"${CTestName}\"" PROPERTIES DISABLED ON)
|
||||
else()
|
||||
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||
LABELS "${Labels}")
|
||||
endif()
|
||||
set_property(
|
||||
TARGET ${TestTarget}
|
||||
APPEND
|
||||
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"")
|
||||
set_property(
|
||||
SOURCE ${SourceFile}
|
||||
APPEND
|
||||
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"")
|
||||
endif()
|
||||
|
||||
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# entry point
|
||||
function(ParseAndAddCatchTests TestTarget)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}")
|
||||
get_target_property(SourceFiles ${TestTarget} SOURCES)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}")
|
||||
foreach(SourceFile ${SourceFiles})
|
||||
ParseAndAddCatchTests_ParseFile(${SourceFile} ${TestTarget})
|
||||
endforeach()
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Finished parsing ${TestTarget}")
|
||||
endfunction()
|
@ -39,8 +39,10 @@
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#ifdef WIN32
|
||||
#define NOMINMAX
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#ifndef __GNUC__
|
||||
#define NOMINMAX 1
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
@ -70,7 +72,6 @@ using fstream = std::fstream;
|
||||
#ifdef GHC_FILESYSTEM_FWD_TEST
|
||||
#include <ghc/fs_fwd.hpp>
|
||||
#else
|
||||
#define NOMINMAX
|
||||
#include <ghc/filesystem.hpp>
|
||||
#endif
|
||||
namespace fs {
|
||||
@ -174,32 +175,57 @@ static void generateFile(const fs::path& pathname, int withSize = -1)
|
||||
}
|
||||
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
inline bool isWow64Proc()
|
||||
{
|
||||
typedef BOOL(WINAPI * IsWow64Process_t)(HANDLE, PBOOL);
|
||||
BOOL bIsWow64 = FALSE;
|
||||
auto fnIsWow64Process = (IsWow64Process_t)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
|
||||
if (NULL != fnIsWow64Process) {
|
||||
if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) {
|
||||
bIsWow64 = FALSE;
|
||||
}
|
||||
}
|
||||
return bIsWow64;
|
||||
}
|
||||
|
||||
static bool is_symlink_creation_supported()
|
||||
{
|
||||
bool result = true;
|
||||
HKEY key;
|
||||
REGSAM flags = KEY_READ;
|
||||
#ifdef _WIN64
|
||||
flags |= KEY_WOW64_64KEY;
|
||||
#else
|
||||
BOOL f64 = FALSE;
|
||||
if (IsWow64Process(GetCurrentProcess(), &f64) && f64) {
|
||||
#elif defined(KEY_WOW64_64KEY)
|
||||
if (isWow64Proc()) {
|
||||
flags |= KEY_WOW64_64KEY;
|
||||
}
|
||||
else {
|
||||
flags |= KEY_WOW64_32KEY;
|
||||
}
|
||||
#else
|
||||
result = false;
|
||||
#endif
|
||||
auto err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock", 0, flags, &key);
|
||||
if (err != ERROR_SUCCESS) {
|
||||
return false;
|
||||
if (result) {
|
||||
auto err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock", 0, flags, &key);
|
||||
if (err == ERROR_SUCCESS) {
|
||||
DWORD val = 0, size = sizeof(DWORD);
|
||||
err = RegQueryValueExW(key, L"AllowDevelopmentWithoutDevLicense", 0, NULL, reinterpret_cast<LPBYTE>(&val), &size);
|
||||
RegCloseKey(key);
|
||||
if (err != ERROR_SUCCESS) {
|
||||
result = false;
|
||||
}
|
||||
else {
|
||||
result = (val != 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
DWORD val = 0, size = sizeof(DWORD);
|
||||
err = RegQueryValueExW(key, L"AllowDevelopmentWithoutDevLicense", 0, NULL, reinterpret_cast<LPBYTE>(&val), &size);
|
||||
RegCloseKey(key);
|
||||
if (err != ERROR_SUCCESS) {
|
||||
return false;
|
||||
if (!result) {
|
||||
std::clog << "Warning: Symlink creation not supported." << std::endl;
|
||||
}
|
||||
return val != 0;
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
static bool is_symlink_creation_supported()
|
||||
@ -1058,7 +1084,7 @@ TEST_CASE("30.10.12 class directory_entry", "[filesystem][directory_entry][fs.di
|
||||
CHECK(de.hard_link_count() == 1);
|
||||
}
|
||||
|
||||
TEST_CASE("30.10.13 class directory_iterator", "[filesystem][directory_iterator]")
|
||||
TEST_CASE("30.10.13 class directory_iterator", "[filesystem][directory_iterator][fs.class.directory_iterator]")
|
||||
{
|
||||
{
|
||||
TemporaryDirectory t;
|
||||
@ -1107,7 +1133,7 @@ TEST_CASE("30.10.13 class directory_iterator", "[filesystem][directory_iterator]
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("30.10.14 class recursive_directory_iterator", "[filesystem][recursive_directory_iterator]")
|
||||
TEST_CASE("30.10.14 class recursive_directory_iterator", "[filesystem][recursive_directory_iterator][fs.class.rec.dir.itr]")
|
||||
{
|
||||
{
|
||||
TemporaryDirectory t;
|
||||
@ -1246,7 +1272,7 @@ TEST_CASE("30.10.15.3 copy", "[filesystem][operations][fs.op.copy]")
|
||||
CHECK(fs::exists("dir4/file2"));
|
||||
CHECK(fs::exists("dir4/dir2/file3"));
|
||||
}
|
||||
if(is_symlink_creation_supported()) {
|
||||
if (is_symlink_creation_supported()) {
|
||||
TemporaryDirectory t(TempOpt::change_path);
|
||||
std::error_code ec;
|
||||
fs::create_directory("dir1");
|
||||
@ -1427,7 +1453,7 @@ TEST_CASE("30.10.15.7 create_directory", "[filesystem][operations][fs.op.create_
|
||||
|
||||
TEST_CASE("30.10.15.8 create_directory_symlink", "[filesystem][operations][fs.op.create_directory_symlink]")
|
||||
{
|
||||
if(is_symlink_creation_supported()) {
|
||||
if (is_symlink_creation_supported()) {
|
||||
TemporaryDirectory t;
|
||||
fs::create_directory(t.path() / "dir1");
|
||||
generateFile(t.path() / "dir1/test1");
|
||||
@ -1463,7 +1489,7 @@ TEST_CASE("30.10.15.9 create_hard_link", "[filesystem][operations][fs.op.create_
|
||||
|
||||
TEST_CASE("30.10.15.10 create_symlink", "[filesystem][operations][fs.op.create_symlink]")
|
||||
{
|
||||
if(is_symlink_creation_supported()) {
|
||||
if (is_symlink_creation_supported()) {
|
||||
TemporaryDirectory t;
|
||||
fs::create_directory(t.path() / "dir1");
|
||||
generateFile(t.path() / "dir1/test1");
|
||||
@ -1770,7 +1796,7 @@ TEST_CASE_METHOD(FileTypeMixFixture, "30.10.15.18 is_directory", "[filesystem][o
|
||||
CHECK(!fs::is_directory(fs::file_status(fs::file_type::unknown)));
|
||||
}
|
||||
|
||||
TEST_CASE("30.10.15.19 is_empty", "[filesystem][options][fs.op.is_empty]")
|
||||
TEST_CASE("30.10.15.19 is_empty", "[filesystem][operations][fs.op.is_empty]")
|
||||
{
|
||||
TemporaryDirectory t(TempOpt::change_path);
|
||||
std::error_code ec;
|
||||
@ -2038,7 +2064,7 @@ TEST_CASE("30.10.15.27 proximate", "[filesystem][operations][fs.op.proximate]")
|
||||
|
||||
TEST_CASE("30.10.15.28 read_symlink", "[filesystem][operations][fs.op.read_symlink]")
|
||||
{
|
||||
if(is_symlink_creation_supported()) {
|
||||
if (is_symlink_creation_supported()) {
|
||||
TemporaryDirectory t(TempOpt::change_path);
|
||||
std::error_code ec;
|
||||
generateFile("foo");
|
||||
@ -2272,3 +2298,36 @@ TEST_CASE("30.10.15.39 weakly_canonical", "[filesystem][operations][fs.op.weakly
|
||||
CHECK(fs::weakly_canonical(rel / "d1/../f1/../f2") == dir / "f2");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GHC_OS_WINDOWS
|
||||
TEST_CASE("Windows: Long filename support", "[filesystem][path][fs.path.win.long]")
|
||||
{
|
||||
TemporaryDirectory t(TempOpt::change_path);
|
||||
char c = 'A';
|
||||
fs::path dir = fs::current_path();
|
||||
for (; c <= 'Z'; ++c) {
|
||||
std::string part = std::string(16, c);
|
||||
dir /= part;
|
||||
CHECK_NOTHROW(fs::create_directory(dir));
|
||||
CHECK(fs::exists(dir));
|
||||
generateFile(dir / "f0");
|
||||
CHECK(fs::exists(dir / "f0"));
|
||||
std::string native = dir.u8string();
|
||||
if (native.substr(0, 4) == "\\\\?\\") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK(c <= 'Z');
|
||||
}
|
||||
|
||||
TEST_CASE("Windows: UNC path support", "[filesystem][path][fs.path.win.unc]")
|
||||
{
|
||||
std::error_code ec;
|
||||
fs::path p(R"(\\localhost\c$\Windows)");
|
||||
auto symstat = fs::symlink_status(p, ec);
|
||||
CHECK(!ec);
|
||||
auto p2 = fs::canonical(p, ec);
|
||||
CHECK(!ec);
|
||||
CHECK(p2 == p);
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user