forked from OSchip/llvm-project
Revert "[libc++] Build <filesystem> support as part of the dylib"
When I applied r356500 (https://reviews.llvm.org/D59152), I somehow deleted all of filesystem's tests. I will revert r356500 and re-apply it properly. llvm-svn: 356505
This commit is contained in:
parent
d81df259b3
commit
f7b43230b8
|
@ -73,6 +73,12 @@ option(LIBCXX_ENABLE_ASSERTIONS "Enable assertions independent of build mode." O
|
|||
option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON)
|
||||
option(LIBCXX_ENABLE_STATIC "Build libc++ as a static library." ON)
|
||||
option(LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY "Build libc++experimental.a" ON)
|
||||
set(ENABLE_FILESYSTEM_DEFAULT ${LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY})
|
||||
if (WIN32)
|
||||
set(ENABLE_FILESYSTEM_DEFAULT OFF)
|
||||
endif()
|
||||
option(LIBCXX_ENABLE_FILESYSTEM "Build filesystem as part of libc++fs.a"
|
||||
${ENABLE_FILESYSTEM_DEFAULT})
|
||||
option(LIBCXX_INCLUDE_TESTS "Build the libc++ tests." ${LLVM_INCLUDE_TESTS})
|
||||
|
||||
# Benchmark options -----------------------------------------------------------
|
||||
|
@ -111,6 +117,9 @@ option(LIBCXX_INSTALL_SUPPORT_HEADERS "Install libc++ support headers." ON)
|
|||
cmake_dependent_option(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY
|
||||
"Install libc++experimental.a" ON
|
||||
"LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY;LIBCXX_INSTALL_LIBRARY" OFF)
|
||||
cmake_dependent_option(LIBCXX_INSTALL_FILESYSTEM_LIBRARY
|
||||
"Install libc++fs.a" ON
|
||||
"LIBCXX_ENABLE_FILESYSTEM;LIBCXX_INSTALL_LIBRARY" OFF)
|
||||
|
||||
set(LIBCXX_ABI_VERSION "1" CACHE STRING "ABI version of libc++. Can be either 1 or 2, where 2 is currently not stable. Defaults to 1.")
|
||||
set(LIBCXX_ABI_NAMESPACE "" CACHE STRING "The inline ABI namespace used by libc++. It defaults to __n where `n` is the current ABI version.")
|
||||
|
@ -282,6 +291,11 @@ option(LIBCXX_HERMETIC_STATIC_LIBRARY
|
|||
# Check option configurations
|
||||
#===============================================================================
|
||||
|
||||
if (LIBCXX_ENABLE_FILESYSTEM AND NOT LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY)
|
||||
message(FATAL_ERROR
|
||||
"LIBCXX_ENABLE_FILESYSTEM cannot be turned on when LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF")
|
||||
endif()
|
||||
|
||||
# Ensure LIBCXX_ENABLE_MONOTONIC_CLOCK is set to ON only when
|
||||
# LIBCXX_ENABLE_THREADS is on.
|
||||
if(LIBCXX_ENABLE_THREADS AND NOT LIBCXX_ENABLE_MONOTONIC_CLOCK)
|
||||
|
@ -777,6 +791,9 @@ set(LIBCXX_TEST_DEPS "")
|
|||
if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY)
|
||||
list(APPEND LIBCXX_TEST_DEPS cxx_experimental)
|
||||
endif()
|
||||
if (LIBCXX_ENABLE_FILESYSTEM)
|
||||
list(APPEND LIBCXX_TEST_DEPS cxx_filesystem)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY)
|
||||
list(APPEND LIBCXX_TEST_DEPS cxx_external_threads)
|
||||
|
|
|
@ -146,6 +146,9 @@ function(add_benchmark_test name source_file)
|
|||
if (TARGET cxx_experimental)
|
||||
target_link_libraries(${libcxx_target} cxx_experimental)
|
||||
endif()
|
||||
if (TARGET cxx_filesystem)
|
||||
target_link_libraries(${libcxx_target} cxx_filesystem)
|
||||
endif()
|
||||
target_link_libraries(${libcxx_target} -lbenchmark)
|
||||
if (LLVM_USE_SANITIZER)
|
||||
target_link_libraries(${libcxx_target} -ldl)
|
||||
|
|
|
@ -224,6 +224,18 @@ libc++experimental Specific Options
|
|||
Install libc++experimental.a alongside libc++.
|
||||
|
||||
|
||||
.. option:: LIBCXX_ENABLE_FILESYSTEM:BOOL
|
||||
|
||||
**Default**: ``ON``
|
||||
|
||||
Build filesystem as a standalone library libc++fs.a.
|
||||
|
||||
.. option:: LIBCXX_INSTALL_FILESYSTEM_LIBRARY:BOOL
|
||||
|
||||
**Default**: ``LIBCXX_ENABLE_FILESYSTEM AND LIBCXX_INSTALL_LIBRARY``
|
||||
|
||||
Install libc++fs.a alongside libc++.
|
||||
|
||||
.. _ABI Library Specific Options:
|
||||
|
||||
ABI Library Specific Options
|
||||
|
|
|
@ -50,6 +50,23 @@ An example of using ``LD_LIBRARY_PATH``:
|
|||
$ ./a.out # Searches for libc++ along LD_LIBRARY_PATH
|
||||
|
||||
|
||||
Using ``<filesystem>`` and libc++fs
|
||||
====================================
|
||||
|
||||
Libc++ provides the implementation of the filesystem library in a separate
|
||||
library. Users of ``<filesystem>`` and ``<experimental/filesystem>`` are
|
||||
required to link ``-lc++fs``.
|
||||
|
||||
.. note::
|
||||
Prior to libc++ 7.0, users of ``<experimental/filesystem>`` were required
|
||||
to link libc++experimental.
|
||||
|
||||
.. warning::
|
||||
The Filesystem library is still experimental in nature. As such normal
|
||||
guarantees about ABI stability and backwards compatibility do not yet apply
|
||||
to it. In the future, this restriction will be removed.
|
||||
|
||||
|
||||
Using libc++experimental and ``<experimental/...>``
|
||||
=====================================================
|
||||
|
||||
|
@ -66,6 +83,9 @@ installed. For information on building libc++experimental from source see
|
|||
:ref:`Building Libc++ <build instructions>` and
|
||||
:ref:`libc++experimental CMake Options <libc++experimental options>`.
|
||||
|
||||
Note that as of libc++ 7.0 using the ``<experimental/filesystem>`` requires linking
|
||||
libc++fs instead of libc++experimental.
|
||||
|
||||
Also see the `Experimental Library Implementation Status <http://libcxx.llvm.org/ts1z_status.html>`__
|
||||
page.
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@ set(LIBCXX_LIB_CMAKEFILES_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTOR
|
|||
# Get sources
|
||||
# FIXME: Don't use glob here
|
||||
file(GLOB LIBCXX_SOURCES ../src/*.cpp)
|
||||
list(APPEND LIBCXX_SOURCES ../src/filesystem/operations.cpp
|
||||
../src/filesystem/directory_iterator.cpp)
|
||||
if(WIN32)
|
||||
file(GLOB LIBCXX_WIN32_SOURCES ../src/support/win32/*.cpp)
|
||||
list(APPEND LIBCXX_SOURCES ${LIBCXX_WIN32_SOURCES})
|
||||
|
@ -13,14 +11,6 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
|
|||
list(APPEND LIBCXX_SOURCES ${LIBCXX_SOLARIS_SOURCES})
|
||||
endif()
|
||||
|
||||
# Filesystem uses __int128_t, which requires a definition of __muloi4 when
|
||||
# compiled with UBSAN. This definition is not provided by libgcc_s, but is
|
||||
# provided by compiler-rt. So we need to disable it to avoid having multiple
|
||||
# definitions. See filesystem/int128_builtins.cpp.
|
||||
if (NOT LIBCXX_USE_COMPILER_RT)
|
||||
list(APPEND LIBCXX_SOURCES ../src/filesystem/int128_builtins.cpp)
|
||||
endif()
|
||||
|
||||
# Add all the headers to the project for IDEs.
|
||||
if (LIBCXX_CONFIGURE_IDE)
|
||||
file(GLOB_RECURSE LIBCXX_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/*)
|
||||
|
@ -288,6 +278,39 @@ endif()
|
|||
# Add a meta-target for both libraries.
|
||||
add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_BUILD_TARGETS})
|
||||
|
||||
if (LIBCXX_ENABLE_FILESYSTEM)
|
||||
set(LIBCXX_FILESYSTEM_SOURCES
|
||||
../src/filesystem/operations.cpp
|
||||
../src/filesystem/directory_iterator.cpp)
|
||||
|
||||
# Filesystem uses __int128_t, which requires a definition of __muloi4 when
|
||||
# compiled with UBSAN. This definition is not provided by libgcc_s, but is
|
||||
# provided by compiler-rt. So we need to disable it to avoid having multiple
|
||||
# definitions. See filesystem/int128_builtins.cpp.
|
||||
if (NOT LIBCXX_USE_COMPILER_RT)
|
||||
list(APPEND LIBCXX_FILESYSTEM_SOURCES ../src/filesystem/int128_builtins.cpp)
|
||||
endif()
|
||||
|
||||
add_library(cxx_filesystem STATIC ${LIBCXX_FILESYSTEM_SOURCES})
|
||||
if (LIBCXX_ENABLE_SHARED)
|
||||
target_link_libraries(cxx_filesystem cxx_shared)
|
||||
else()
|
||||
target_link_libraries(cxx_filesystem cxx_static)
|
||||
endif()
|
||||
|
||||
set(filesystem_flags "${LIBCXX_COMPILE_FLAGS}")
|
||||
check_flag_supported(-std=c++14)
|
||||
if (NOT MSVC AND LIBCXX_SUPPORTS_STD_EQ_CXX14_FLAG AND LIBCXX_STANDARD_VER STREQUAL "c++11")
|
||||
string(REPLACE "-std=c++11" "-std=c++14" filesystem_flags "${LIBCXX_COMPILE_FLAGS}")
|
||||
endif()
|
||||
set_target_properties(cxx_filesystem
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "${filesystem_flags}"
|
||||
OUTPUT_NAME "c++fs"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY)
|
||||
file(GLOB LIBCXX_EXPERIMENTAL_SOURCES ../src/experimental/*.cpp)
|
||||
add_library(cxx_experimental STATIC ${LIBCXX_EXPERIMENTAL_SOURCES})
|
||||
|
@ -356,10 +379,13 @@ if (LIBCXX_ENABLE_SHARED AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
|
|||
endif()
|
||||
|
||||
if (LIBCXX_INSTALL_LIBRARY)
|
||||
if (LIBCXX_INSTALL_FILESYSTEM_LIBRARY)
|
||||
set(filesystem_lib cxx_filesystem)
|
||||
endif()
|
||||
if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY)
|
||||
set(experimental_lib cxx_experimental)
|
||||
endif()
|
||||
install(TARGETS ${LIBCXX_INSTALL_TARGETS} ${experimental_lib}
|
||||
install(TARGETS ${LIBCXX_INSTALL_TARGETS} ${filesystem_lib} ${experimental_lib}
|
||||
LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx
|
||||
ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx
|
||||
)
|
||||
|
@ -379,6 +405,9 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR
|
|||
if(LIBCXX_INSTALL_LIBRARY)
|
||||
set(lib_install_target cxx)
|
||||
endif()
|
||||
if (LIBCXX_INSTALL_FILESYSTEM_LIBRARY)
|
||||
set(filesystem_lib_install_target cxx_filesystem)
|
||||
endif()
|
||||
if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY)
|
||||
set(experimental_lib_install_target cxx_experimental)
|
||||
endif()
|
||||
|
@ -388,6 +417,7 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR
|
|||
add_custom_target(install-cxx
|
||||
DEPENDS ${lib_install_target}
|
||||
${experimental_lib_install_target}
|
||||
${filesystem_lib_install_target}
|
||||
${header_install_target}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=cxx
|
||||
|
@ -395,6 +425,7 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR
|
|||
add_custom_target(install-cxx-stripped
|
||||
DEPENDS ${lib_install_target}
|
||||
${experimental_lib_install_target}
|
||||
${filesystem_lib_install_target}
|
||||
${header_install_target}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=cxx
|
||||
|
|
|
@ -16,130 +16,6 @@ New entries should be added directly below the "Version" header.
|
|||
Version 9.0
|
||||
-----------
|
||||
|
||||
* rXXXXXX - Integrate <filesystem> support into the shared library
|
||||
|
||||
This patch introduces support for <filesystem> into the shared library,
|
||||
instead of requiring users to manually link against a static archive. As
|
||||
such, new symbols required to implement <filesystem> are exported from
|
||||
the shared library.
|
||||
|
||||
x86_64-unknown-linux-gnu
|
||||
------------------------
|
||||
TODO
|
||||
|
||||
x86_64-apple-apple-darwin
|
||||
-------------------------
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem18directory_iterator13__dereferenceEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem28recursive_directory_iterator13__dereferenceEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem28recursive_directory_iterator5depthEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem28recursive_directory_iterator7optionsEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path10__filenameEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path11__extensionEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path11__root_nameEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path13__parent_pathEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path15__relative_pathEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path15__root_path_rawEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path16__root_directoryEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path16lexically_normalEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path18lexically_relativeERKS2_
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path3endEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path5beginEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path6__stemEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path9__compareENS_17basic_string_viewIcNS_11char_traitsIcEEEE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem10__absoluteERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem10hash_valueERKNS1_4pathE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem11__canonicalERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem11__copy_fileERKNS1_4pathES4_NS1_12copy_optionsEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem11__file_sizeERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem12__equivalentERKNS1_4pathES4_PNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem12__remove_allERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem13__fs_is_emptyERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem13__permissionsERKNS1_4pathENS1_5permsENS1_12perm_optionsEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem13__resize_fileERKNS1_4pathEmPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem14__copy_symlinkERKNS1_4pathES4_PNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem14__current_pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem14__current_pathERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem14__read_symlinkERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem15directory_entry12__do_refreshEv
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16__create_symlinkERKNS1_4pathES4_PNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16__symlink_statusERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16_FilesystemClock3nowEv
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16filesystem_error13__create_whatEi
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16filesystem_errorD0Ev
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16filesystem_errorD1Ev
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16filesystem_errorD2Ev
|
||||
Symbol added: __ZNSt3__14__fs10filesystem17__hard_link_countERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem17__last_write_timeERKNS1_4pathENS_6chrono10time_pointINS1_16_FilesystemClockENS5_8durationInNS_5ratioILl1ELl1000000000EEEEEEEPNS_10error_codeE
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem28recursive_directory_iterator5depthEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem28recursive_directory_iterator7optionsEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path10__filenameEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path11__extensionEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path11__root_nameEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path13__parent_pathEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path15__relative_pathEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path15__root_path_rawEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path16__root_directoryEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path16lexically_normalEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path18lexically_relativeERKS2_
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path3endEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path5beginEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path6__stemEv
|
||||
Symbol added: __ZNKSt3__14__fs10filesystem4path9__compareENS_17basic_string_viewIcNS_11char_traitsIcEEEE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem10__absoluteERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem10hash_valueERKNS1_4pathE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem11__canonicalERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem11__copy_fileERKNS1_4pathES4_NS1_12copy_optionsEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem11__file_sizeERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem12__equivalentERKNS1_4pathES4_PNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem12__remove_allERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem13__fs_is_emptyERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem13__permissionsERKNS1_4pathENS1_5permsENS1_12perm_optionsEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem13__resize_fileERKNS1_4pathEmPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem14__copy_symlinkERKNS1_4pathES4_PNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem14__current_pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem14__current_pathERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem14__read_symlinkERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem15directory_entry12__do_refreshEv
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16__create_symlinkERKNS1_4pathES4_PNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16__symlink_statusERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16_FilesystemClock3nowEv
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16filesystem_error13__create_whatEi
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16filesystem_errorD0Ev
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16filesystem_errorD1Ev
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16filesystem_errorD2Ev
|
||||
Symbol added: __ZNSt3__14__fs10filesystem17__hard_link_countERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem17__last_write_timeERKNS1_4pathENS_6chrono10time_pointINS1_16_FilesystemClockENS5_8durationInNS_5ratioILl1ELl1000000000EEEEEEEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem17__last_write_timeERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem18__create_directoryERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem18__create_directoryERKNS1_4pathES4_PNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem18__create_hard_linkERKNS1_4pathES4_PNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem18__weakly_canonicalERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem18directory_iterator11__incrementEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem18directory_iteratorC1ERKNS1_4pathEPNS_10error_codeENS1_17directory_optionsE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem18directory_iteratorC2ERKNS1_4pathEPNS_10error_codeENS1_17directory_optionsE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem20__create_directoriesERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem21__temp_directory_pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem26__create_directory_symlinkERKNS1_4pathES4_PNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem28recursive_directory_iterator11__incrementEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem28recursive_directory_iterator15__try_recursionEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem28recursive_directory_iterator5__popEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem28recursive_directory_iterator9__advanceEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem28recursive_directory_iteratorC1ERKNS1_4pathENS1_17directory_optionsEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem28recursive_directory_iteratorC2ERKNS1_4pathENS1_17directory_optionsEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem4path17replace_extensionERKS2_
|
||||
Symbol added: __ZNSt3__14__fs10filesystem4path8iterator11__decrementEv
|
||||
Symbol added: __ZNSt3__14__fs10filesystem4path8iterator11__incrementEv
|
||||
Symbol added: __ZNSt3__14__fs10filesystem6__copyERKNS1_4pathES4_NS1_12copy_optionsEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem7__spaceERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem8__removeERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem8__renameERKNS1_4pathES4_PNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem8__statusERKNS1_4pathEPNS_10error_codeE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem16_FilesystemClock9is_steadyE
|
||||
Symbol added: __ZNSt3__14__fs10filesystem4path19preferred_separatorE
|
||||
Symbol added: __ZTINSt3__14__fs10filesystem16filesystem_errorE
|
||||
Symbol added: __ZTSNSt3__14__fs10filesystem16filesystem_errorE
|
||||
Symbol added: __ZTVNSt3__14__fs10filesystem16filesystem_errorE
|
||||
|
||||
* rTBD - Remove exception throwing debug mode handler support.
|
||||
|
||||
The reason libc++ implemented a throwing debug mode handler was for ease of testing. Specifically,
|
||||
|
|
|
@ -2346,74 +2346,3 @@
|
|||
{'is_defined': True, 'name': '___dynamic_cast', 'type': 'I'}
|
||||
{'is_defined': False, 'name': '___gxx_personality_v0', 'type': 'U'}
|
||||
{'is_defined': True, 'name': '___gxx_personality_v0', 'type': 'I'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem18directory_iterator13__dereferenceEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem28recursive_directory_iterator13__dereferenceEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem28recursive_directory_iterator5depthEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem28recursive_directory_iterator7optionsEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path10__filenameEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path11__extensionEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path11__root_nameEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path13__parent_pathEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path15__relative_pathEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path15__root_path_rawEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path16__root_directoryEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path16lexically_normalEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path18lexically_relativeERKS2_'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path3endEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path5beginEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path6__stemEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__14__fs10filesystem4path9__compareENS_17basic_string_viewIcNS_11char_traitsIcEEEE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem10__absoluteERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem10hash_valueERKNS1_4pathE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem11__canonicalERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem11__copy_fileERKNS1_4pathES4_NS1_12copy_optionsEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem11__file_sizeERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem12__equivalentERKNS1_4pathES4_PNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem12__remove_allERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem13__fs_is_emptyERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem13__permissionsERKNS1_4pathENS1_5permsENS1_12perm_optionsEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem13__resize_fileERKNS1_4pathEmPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem14__copy_symlinkERKNS1_4pathES4_PNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem14__current_pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem14__current_pathERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem14__read_symlinkERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem15directory_entry12__do_refreshEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16__create_symlinkERKNS1_4pathES4_PNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16__symlink_statusERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16_FilesystemClock3nowEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16filesystem_error13__create_whatEi'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16filesystem_errorD0Ev'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16filesystem_errorD1Ev'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16filesystem_errorD2Ev'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem17__hard_link_countERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem17__last_write_timeERKNS1_4pathENS_6chrono10time_pointINS1_16_FilesystemClockENS5_8durationInNS_5ratioILl1ELl1000000000EEEEEEEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem17__last_write_timeERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18__create_directoryERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18__create_directoryERKNS1_4pathES4_PNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18__create_hard_linkERKNS1_4pathES4_PNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18__weakly_canonicalERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18directory_iterator11__incrementEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18directory_iteratorC1ERKNS1_4pathEPNS_10error_codeENS1_17directory_optionsE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem18directory_iteratorC2ERKNS1_4pathEPNS_10error_codeENS1_17directory_optionsE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem20__create_directoriesERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem21__temp_directory_pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem26__create_directory_symlinkERKNS1_4pathES4_PNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iterator11__incrementEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iterator15__try_recursionEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iterator5__popEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iterator9__advanceEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iteratorC1ERKNS1_4pathENS1_17directory_optionsEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem28recursive_directory_iteratorC2ERKNS1_4pathENS1_17directory_optionsEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem4path17replace_extensionERKS2_'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem4path8iterator11__decrementEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem4path8iterator11__incrementEv'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem6__copyERKNS1_4pathES4_NS1_12copy_optionsEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem7__spaceERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem8__removeERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem8__renameERKNS1_4pathES4_PNS_10error_codeE'}
|
||||
{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem8__statusERKNS1_4pathEPNS_10error_codeE'}
|
||||
{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem16_FilesystemClock9is_steadyE', 'size': 0}
|
||||
{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__14__fs10filesystem4path19preferred_separatorE', 'size': 0}
|
||||
{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__14__fs10filesystem16filesystem_errorE', 'size': 0}
|
||||
{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__14__fs10filesystem16filesystem_errorE', 'size': 0}
|
||||
{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__14__fs10filesystem16filesystem_errorE', 'size': 0}
|
||||
|
|
|
@ -28,6 +28,7 @@ endif()
|
|||
|
||||
pythonize_bool(LIBCXX_ENABLE_EXCEPTIONS)
|
||||
pythonize_bool(LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY)
|
||||
pythonize_bool(LIBCXX_ENABLE_FILESYSTEM)
|
||||
pythonize_bool(LIBCXX_ENABLE_RTTI)
|
||||
pythonize_bool(LIBCXX_ENABLE_SHARED)
|
||||
pythonize_bool(LIBCXX_BUILD_32_BITS)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# Disable all of the filesystem tests if the correct feature is not available.
|
||||
if 'c++filesystem' not in config.available_features:
|
||||
config.unsupported = True
|
|
@ -6,6 +6,7 @@ config.libcxx_obj_root = "@LIBCXX_BINARY_DIR@"
|
|||
config.cxx_library_root = "@LIBCXX_LIBRARY_DIR@"
|
||||
config.enable_exceptions = @LIBCXX_ENABLE_EXCEPTIONS@
|
||||
config.enable_experimental = @LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY@
|
||||
config.enable_filesystem = @LIBCXX_ENABLE_FILESYSTEM@
|
||||
config.enable_rtti = @LIBCXX_ENABLE_RTTI@
|
||||
config.enable_shared = @LIBCXX_ENABLE_SHARED@
|
||||
config.enable_32bit = @LIBCXX_BUILD_32_BITS@
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
dne
|
|
@ -0,0 +1 @@
|
|||
dir3
|
|
@ -0,0 +1 @@
|
|||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
@ -0,0 +1 @@
|
|||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
|
@ -0,0 +1 @@
|
|||
dir1
|
|
@ -0,0 +1 @@
|
|||
empty_file
|
|
@ -0,0 +1,73 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// directory_entry(const directory_entry&) = default;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "test_convertible.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_path_ctor_suite)
|
||||
|
||||
TEST_CASE(copy_ctor) {
|
||||
using namespace fs;
|
||||
// Copy
|
||||
{
|
||||
static_assert(std::is_copy_constructible<directory_entry>::value,
|
||||
"directory_entry must be copy constructible");
|
||||
static_assert(!std::is_nothrow_copy_constructible<directory_entry>::value,
|
||||
"directory_entry's copy constructor cannot be noexcept");
|
||||
const path p("foo/bar/baz");
|
||||
const directory_entry e(p);
|
||||
assert(e.path() == p);
|
||||
directory_entry e2(e);
|
||||
assert(e.path() == p);
|
||||
assert(e2.path() == p);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(copy_ctor_copies_cache) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path sym = env.create_symlink("dir/file", "sym");
|
||||
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
|
||||
fs::remove(sym);
|
||||
|
||||
directory_entry ent_cp(ent);
|
||||
TEST_CHECK(ent_cp.path() == sym);
|
||||
TEST_CHECK(ent_cp.is_symlink());
|
||||
}
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
|
||||
fs::remove(file);
|
||||
|
||||
directory_entry ent_cp(ent);
|
||||
TEST_CHECK(ent_cp.path() == file);
|
||||
TEST_CHECK(ent_cp.is_regular_file());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,81 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// directory_entry& operator=(directory_entry const&) = default;
|
||||
// directory_entry& operator=(directory_entry&&) noexcept = default;
|
||||
// void assign(path const&);
|
||||
// void replace_filename(path const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_ctor_suite)
|
||||
|
||||
TEST_CASE(test_copy_assign_operator) {
|
||||
using namespace fs;
|
||||
// Copy
|
||||
{
|
||||
static_assert(std::is_copy_assignable<directory_entry>::value,
|
||||
"directory_entry must be copy assignable");
|
||||
static_assert(!std::is_nothrow_copy_assignable<directory_entry>::value,
|
||||
"directory_entry's copy assignment cannot be noexcept");
|
||||
const path p("foo/bar/baz");
|
||||
const path p2("abc");
|
||||
const directory_entry e(p);
|
||||
directory_entry e2;
|
||||
assert(e.path() == p && e2.path() == path());
|
||||
e2 = e;
|
||||
assert(e.path() == p && e2.path() == p);
|
||||
directory_entry e3(p2);
|
||||
e2 = e3;
|
||||
assert(e2.path() == p2 && e3.path() == p2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(copy_assign_copies_cache) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path sym = env.create_symlink("dir/file", "sym");
|
||||
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
|
||||
fs::remove(sym);
|
||||
|
||||
directory_entry ent_cp;
|
||||
ent_cp = ent;
|
||||
TEST_CHECK(ent_cp.path() == sym);
|
||||
TEST_CHECK(ent_cp.is_symlink());
|
||||
}
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
|
||||
fs::remove(file);
|
||||
|
||||
directory_entry ent_cp;
|
||||
ent_cp = ent;
|
||||
TEST_CHECK(ent_cp.path() == file);
|
||||
TEST_CHECK(ent_cp.is_regular_file());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,32 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// directory_entry() noexcept = default;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
// Default
|
||||
{
|
||||
static_assert(std::is_nothrow_default_constructible<directory_entry>::value,
|
||||
"directory_entry must have a nothrow default constructor");
|
||||
directory_entry e;
|
||||
assert(e.path() == path());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
// XFAIL: apple-clang-7, clang-3.7, clang-3.8
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// directory_entry() noexcept = default;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
// Default
|
||||
{
|
||||
static_assert(std::is_nothrow_default_constructible<directory_entry>::value,
|
||||
"directory_entry must have a nothrow default constructor");
|
||||
const directory_entry e;
|
||||
assert(e.path() == path());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// directory_entry(directory_entry&&) noexcept = default;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "test_convertible.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_path_ctor_suite)
|
||||
|
||||
TEST_CASE(move_ctor) {
|
||||
using namespace fs;
|
||||
// Move
|
||||
{
|
||||
static_assert(std::is_nothrow_move_constructible<directory_entry>::value,
|
||||
"directory_entry must be nothrow move constructible");
|
||||
const path p("foo/bar/baz");
|
||||
directory_entry e(p);
|
||||
assert(e.path() == p);
|
||||
directory_entry e2(std::move(e));
|
||||
assert(e2.path() == p);
|
||||
assert(e.path() != p); // Testing moved from state.
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(move_ctor_copies_cache) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path sym = env.create_symlink("dir/file", "sym");
|
||||
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
|
||||
fs::remove(sym);
|
||||
|
||||
directory_entry ent_cp(std::move(ent));
|
||||
TEST_CHECK(ent_cp.path() == sym);
|
||||
TEST_CHECK(ent_cp.is_symlink());
|
||||
}
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
|
||||
fs::remove(file);
|
||||
|
||||
directory_entry ent_cp(std::move(ent));
|
||||
TEST_CHECK(ent_cp.path() == file);
|
||||
TEST_CHECK(ent_cp.is_regular_file());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,77 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// directory_entry& operator=(directory_entry const&) = default;
|
||||
// directory_entry& operator=(directory_entry&&) noexcept = default;
|
||||
// void assign(path const&);
|
||||
// void replace_filename(path const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_ctor_suite)
|
||||
|
||||
TEST_CASE(test_move_assign_operator) {
|
||||
using namespace fs;
|
||||
// Copy
|
||||
{
|
||||
static_assert(std::is_nothrow_move_assignable<directory_entry>::value,
|
||||
"directory_entry is noexcept move assignable");
|
||||
const path p("foo/bar/baz");
|
||||
const path p2("abc");
|
||||
directory_entry e(p);
|
||||
directory_entry e2(p2);
|
||||
assert(e.path() == p && e2.path() == p2);
|
||||
e2 = std::move(e);
|
||||
assert(e2.path() == p);
|
||||
assert(e.path() != p); // testing moved from state
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(move_assign_copies_cache) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path sym = env.create_symlink("dir/file", "sym");
|
||||
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
|
||||
fs::remove(sym);
|
||||
|
||||
directory_entry ent_cp;
|
||||
ent_cp = std::move(ent);
|
||||
TEST_CHECK(ent_cp.path() == sym);
|
||||
TEST_CHECK(ent_cp.is_symlink());
|
||||
}
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
|
||||
fs::remove(file);
|
||||
|
||||
directory_entry ent_cp;
|
||||
ent_cp = std::move(ent);
|
||||
TEST_CHECK(ent_cp.path() == file);
|
||||
TEST_CHECK(ent_cp.is_regular_file());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,181 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// explicit directory_entry(const path);
|
||||
// directory_entry(const path&, error_code& ec);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "test_convertible.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_path_ctor_suite)
|
||||
|
||||
TEST_CASE(path_ctor) {
|
||||
using namespace fs;
|
||||
{
|
||||
static_assert(std::is_constructible<directory_entry, const path&>::value,
|
||||
"directory_entry must be constructible from path");
|
||||
static_assert(
|
||||
!std::is_nothrow_constructible<directory_entry, const path&>::value,
|
||||
"directory_entry constructor should not be noexcept");
|
||||
static_assert(!std::is_convertible<path const&, directory_entry>::value,
|
||||
"directory_entry constructor should be explicit");
|
||||
}
|
||||
{
|
||||
const path p("foo/bar/baz");
|
||||
const directory_entry e(p);
|
||||
TEST_CHECK(e.path() == p);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(path_ec_ctor) {
|
||||
using namespace fs;
|
||||
{
|
||||
static_assert(
|
||||
std::is_constructible<directory_entry, const path&,
|
||||
std::error_code&>::value,
|
||||
"directory_entry must be constructible from path and error_code");
|
||||
static_assert(!std::is_nothrow_constructible<directory_entry, const path&,
|
||||
std::error_code&>::value,
|
||||
"directory_entry constructor should not be noexcept");
|
||||
static_assert(
|
||||
test_convertible<directory_entry, const path&, std::error_code&>(),
|
||||
"directory_entry constructor should not be explicit");
|
||||
}
|
||||
{
|
||||
std::error_code ec = GetTestEC();
|
||||
const directory_entry e(StaticEnv::File, ec);
|
||||
TEST_CHECK(e.path() == StaticEnv::File);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
{
|
||||
const path p("foo/bar/baz");
|
||||
std::error_code ec = GetTestEC();
|
||||
const directory_entry e(p, ec);
|
||||
TEST_CHECK(e.path() == p);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(path_ctor_calls_refresh) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path sym = env.create_symlink("dir/file", "sym");
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
std::error_code ec = GetTestEC();
|
||||
directory_entry ent_ec(file, ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
LIBCPP_ONLY(remove(file));
|
||||
|
||||
TEST_CHECK(ent.exists());
|
||||
TEST_CHECK(ent_ec.exists());
|
||||
|
||||
TEST_CHECK(ent.file_size() == 42);
|
||||
TEST_CHECK(ent_ec.file_size() == 42);
|
||||
}
|
||||
|
||||
env.create_file("dir/file", 101);
|
||||
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
std::error_code ec = GetTestEC();
|
||||
directory_entry ent_ec(sym, ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
LIBCPP_ONLY(remove(file));
|
||||
LIBCPP_ONLY(remove(sym));
|
||||
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
TEST_CHECK(ent_ec.is_symlink());
|
||||
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
TEST_CHECK(ent_ec.is_regular_file());
|
||||
|
||||
TEST_CHECK(ent.file_size() == 101);
|
||||
TEST_CHECK(ent_ec.file_size() == 101);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(path_ctor_dne) {
|
||||
using namespace fs;
|
||||
|
||||
{
|
||||
std::error_code ec = GetTestEC();
|
||||
directory_entry ent(StaticEnv::DNE, ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
TEST_CHECK(ent.path() == StaticEnv::DNE);
|
||||
}
|
||||
// don't report dead symlinks as an error.
|
||||
{
|
||||
std::error_code ec = GetTestEC();
|
||||
directory_entry ent(StaticEnv::BadSymlink, ec);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK(ent.path() == StaticEnv::BadSymlink);
|
||||
}
|
||||
// DNE does not cause the constructor to throw
|
||||
{
|
||||
directory_entry ent(StaticEnv::DNE);
|
||||
TEST_CHECK(ent.path() == StaticEnv::DNE);
|
||||
|
||||
directory_entry ent_two(StaticEnv::BadSymlink);
|
||||
TEST_CHECK(ent_two.path() == StaticEnv::BadSymlink);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(path_ctor_cannot_resolve) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path file_out_of_dir = env.create_file("file1", 101);
|
||||
const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
|
||||
const path sym_in_dir = env.create_symlink("dir/file1", "dir/sym2");
|
||||
permissions(dir, perms::none);
|
||||
|
||||
{
|
||||
std::error_code ec = GetTestEC();
|
||||
directory_entry ent(file, ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
TEST_CHECK(ent.path() == file);
|
||||
}
|
||||
{
|
||||
std::error_code ec = GetTestEC();
|
||||
directory_entry ent(sym_in_dir, ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
TEST_CHECK(ent.path() == sym_in_dir);
|
||||
}
|
||||
{
|
||||
std::error_code ec = GetTestEC();
|
||||
directory_entry ent(sym_out_of_dir, ec);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK(ent.path() == sym_out_of_dir);
|
||||
}
|
||||
{
|
||||
TEST_CHECK_NO_THROW(directory_entry(file));
|
||||
TEST_CHECK_NO_THROW(directory_entry(sym_in_dir));
|
||||
TEST_CHECK_NO_THROW(directory_entry(sym_out_of_dir));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,131 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// directory_entry& operator=(directory_entry const&) = default;
|
||||
// directory_entry& operator=(directory_entry&&) noexcept = default;
|
||||
// void assign(path const&);
|
||||
// void replace_filename(path const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_mods_suite)
|
||||
|
||||
TEST_CASE(test_path_assign_method) {
|
||||
using namespace fs;
|
||||
const path p("foo/bar/baz");
|
||||
const path p2("abc");
|
||||
directory_entry e(p);
|
||||
{
|
||||
static_assert(std::is_same<decltype(e.assign(p)), void>::value,
|
||||
"return type should be void");
|
||||
static_assert(noexcept(e.assign(p)) == false,
|
||||
"operation must not be noexcept");
|
||||
}
|
||||
{
|
||||
TEST_CHECK(e.path() == p);
|
||||
e.assign(p2);
|
||||
TEST_CHECK(e.path() == p2 && e.path() != p);
|
||||
e.assign(p);
|
||||
TEST_CHECK(e.path() == p && e.path() != p2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_path_assign_ec_method) {
|
||||
using namespace fs;
|
||||
const path p("foo/bar/baz");
|
||||
const path p2("abc");
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_entry e(p);
|
||||
static_assert(std::is_same<decltype(e.assign(p, ec)), void>::value,
|
||||
"return type should be void");
|
||||
static_assert(noexcept(e.assign(p, ec)) == false,
|
||||
"operation must not be noexcept");
|
||||
}
|
||||
{
|
||||
directory_entry ent(p);
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(p2, ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
TEST_CHECK(ent.path() == p2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_assign_calls_refresh) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path sym = env.create_symlink("dir/file", "sym");
|
||||
|
||||
{
|
||||
directory_entry ent;
|
||||
ent.assign(file);
|
||||
|
||||
// removing the file demonstrates that the values where cached previously.
|
||||
LIBCPP_ONLY(remove(file));
|
||||
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
}
|
||||
env.create_file("dir/file", 101);
|
||||
{
|
||||
directory_entry ent;
|
||||
ent.assign(sym);
|
||||
|
||||
LIBCPP_ONLY(remove(file));
|
||||
LIBCPP_ONLY(remove(sym));
|
||||
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_assign_propagates_error) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
|
||||
const path file_out_of_dir = env.create_file("file1");
|
||||
const path sym_in_dir = env.create_symlink("file1", "dir/sym1");
|
||||
|
||||
permissions(dir, perms::none);
|
||||
|
||||
{
|
||||
directory_entry ent;
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(file, ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
}
|
||||
{
|
||||
directory_entry ent;
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(sym_in_dir, ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
}
|
||||
{
|
||||
directory_entry ent;
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(sym_out_of_dir, ec);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,340 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// directory_entry& operator=(directory_entry const&) = default;
|
||||
// directory_entry& operator=(directory_entry&&) noexcept = default;
|
||||
// void assign(path const&);
|
||||
// void replace_filename(path const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_mods_suite)
|
||||
|
||||
TEST_CASE(test_refresh_method) {
|
||||
using namespace fs;
|
||||
{
|
||||
directory_entry e;
|
||||
static_assert(noexcept(e.refresh()) == false,
|
||||
"operation cannot be noexcept");
|
||||
static_assert(std::is_same<decltype(e.refresh()), void>::value,
|
||||
"operation must return void");
|
||||
}
|
||||
{
|
||||
directory_entry e;
|
||||
e.refresh();
|
||||
TEST_CHECK(!e.exists());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_refresh_ec_method) {
|
||||
using namespace fs;
|
||||
{
|
||||
directory_entry e;
|
||||
std::error_code ec;
|
||||
static_assert(noexcept(e.refresh(ec)), "operation should be noexcept");
|
||||
static_assert(std::is_same<decltype(e.refresh(ec)), void>::value,
|
||||
"operation must return void");
|
||||
}
|
||||
{
|
||||
directory_entry e;
|
||||
std::error_code ec = GetTestEC();
|
||||
e.refresh(ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(refresh_on_file_dne) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
|
||||
const perms old_perms = status(dir).permissions();
|
||||
|
||||
// test file doesn't exist
|
||||
{
|
||||
directory_entry ent(file);
|
||||
remove(file);
|
||||
TEST_CHECK(ent.exists());
|
||||
|
||||
ent.refresh();
|
||||
|
||||
permissions(dir, perms::none);
|
||||
TEST_CHECK(!ent.exists());
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
env.create_file("dir/file", 101);
|
||||
{
|
||||
directory_entry ent(file);
|
||||
remove(file);
|
||||
TEST_CHECK(ent.exists());
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.refresh(ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
permissions(dir, perms::none);
|
||||
TEST_CHECK(!ent.exists());
|
||||
}
|
||||
}
|
||||
|
||||
void remove_if_exists(const fs::path& p) {
|
||||
std::error_code ec;
|
||||
remove(p, ec);
|
||||
}
|
||||
|
||||
TEST_CASE(refresh_on_bad_symlink) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path sym = env.create_symlink("dir/file", "sym");
|
||||
|
||||
const perms old_perms = status(dir).permissions();
|
||||
|
||||
// test file doesn't exist
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
LIBCPP_ONLY(remove(file));
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
TEST_CHECK(ent.exists());
|
||||
|
||||
remove_if_exists(file);
|
||||
ent.refresh();
|
||||
|
||||
LIBCPP_ONLY(permissions(dir, perms::none));
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
TEST_CHECK(!ent.is_regular_file());
|
||||
TEST_CHECK(!ent.exists());
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
env.create_file("dir/file", 101);
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
LIBCPP_ONLY(remove(file));
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
TEST_CHECK(ent.exists());
|
||||
|
||||
remove_if_exists(file);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.refresh(ec);
|
||||
TEST_CHECK(!ec); // we don't report bad symlinks as an error.
|
||||
|
||||
LIBCPP_ONLY(permissions(dir, perms::none));
|
||||
TEST_CHECK(!ent.exists());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(refresh_cannot_resolve) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path file_out_of_dir = env.create_file("file1", 99);
|
||||
const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
|
||||
const path sym_in_dir = env.create_symlink("file1", "dir/sym1");
|
||||
perms old_perms = status(dir).permissions();
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
permissions(dir, perms::none);
|
||||
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.refresh(ec);
|
||||
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
TEST_CHECK(ent.path() == file);
|
||||
|
||||
ExceptionChecker Checker(file, std::errc::permission_denied,
|
||||
"directory_entry::refresh");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.refresh());
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
{
|
||||
directory_entry ent(sym_in_dir);
|
||||
permissions(dir, perms::none);
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.refresh(ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
TEST_CHECK(ent.path() == sym_in_dir);
|
||||
|
||||
ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
|
||||
"directory_entry::refresh");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.refresh());
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
{
|
||||
directory_entry ent(sym_out_of_dir);
|
||||
permissions(dir, perms::none);
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
|
||||
// Failure to resolve the linked entity due to permissions is not
|
||||
// reported as an error.
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.refresh(ec);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.exists(ec) == false);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
TEST_CHECK(ent.path() == sym_out_of_dir);
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
{
|
||||
directory_entry ent_file(file);
|
||||
directory_entry ent_sym(sym_in_dir);
|
||||
directory_entry ent_sym2(sym_out_of_dir);
|
||||
permissions(dir, perms::none);
|
||||
((void)ent_file);
|
||||
((void)ent_sym);
|
||||
|
||||
TEST_CHECK_THROW(filesystem_error, ent_file.refresh());
|
||||
TEST_CHECK_THROW(filesystem_error, ent_sym.refresh());
|
||||
TEST_CHECK_NO_THROW(ent_sym2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(refresh_doesnt_throw_on_dne_but_reports_it) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
|
||||
const path file = env.create_file("file1", 42);
|
||||
const path sym = env.create_symlink("file1", "sym");
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
TEST_CHECK(ent.file_size() == 42);
|
||||
|
||||
remove(file);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.refresh(ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
TEST_CHECK_NO_THROW(ent.refresh());
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
// doesn't throw!
|
||||
TEST_CHECK_THROW(filesystem_error, ent.file_size());
|
||||
}
|
||||
env.create_file("file1", 99);
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
TEST_CHECK(ent.file_size() == 99);
|
||||
|
||||
remove(file);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.refresh(ec);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
TEST_CHECK_THROW(filesystem_error, ent.file_size());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(access_cache_after_refresh_fails) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path file_out_of_dir = env.create_file("file1", 101);
|
||||
const path sym = env.create_symlink("dir/file", "sym");
|
||||
const path sym_in_dir = env.create_symlink("dir/file", "dir/sym2");
|
||||
|
||||
const perms old_perms = status(dir).permissions();
|
||||
|
||||
#define CHECK_ACCESS(func, expect) \
|
||||
ec = GetTestEC(); \
|
||||
TEST_CHECK(ent.func(ec) == expect); \
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied))
|
||||
|
||||
// test file doesn't exist
|
||||
{
|
||||
directory_entry ent(file);
|
||||
|
||||
TEST_CHECK(!ent.is_symlink());
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
TEST_CHECK(ent.exists());
|
||||
|
||||
permissions(dir, perms::none);
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.refresh(ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
CHECK_ACCESS(exists, false);
|
||||
CHECK_ACCESS(is_symlink, false);
|
||||
CHECK_ACCESS(last_write_time, file_time_type::min());
|
||||
CHECK_ACCESS(hard_link_count, uintmax_t(-1));
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
{
|
||||
directory_entry ent(sym_in_dir);
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
TEST_CHECK(ent.exists());
|
||||
|
||||
permissions(dir, perms::none);
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.refresh(ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
CHECK_ACCESS(exists, false);
|
||||
CHECK_ACCESS(is_symlink, false);
|
||||
CHECK_ACCESS(last_write_time, file_time_type::min());
|
||||
CHECK_ACCESS(hard_link_count, uintmax_t(-1));
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
TEST_CHECK(ent.exists());
|
||||
|
||||
permissions(dir, perms::none);
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.refresh(ec);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
|
||||
CHECK_ACCESS(exists, false);
|
||||
CHECK_ACCESS(is_regular_file, false);
|
||||
CHECK_ACCESS(last_write_time, file_time_type::min());
|
||||
CHECK_ACCESS(hard_link_count, uintmax_t(-1));
|
||||
}
|
||||
#undef CHECK_ACCESS
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,168 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// directory_entry& operator=(directory_entry const&) = default;
|
||||
// directory_entry& operator=(directory_entry&&) noexcept = default;
|
||||
// void assign(path const&);
|
||||
// void replace_filename(path const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_mods_suite)
|
||||
|
||||
TEST_CASE(test_replace_filename_method) {
|
||||
using namespace fs;
|
||||
|
||||
{
|
||||
directory_entry e;
|
||||
path replace;
|
||||
static_assert(noexcept(e.replace_filename(replace)) == false,
|
||||
"operation cannot be noexcept");
|
||||
static_assert(
|
||||
std::is_same<decltype(e.replace_filename(replace)), void>::value,
|
||||
"operation must return void");
|
||||
}
|
||||
{
|
||||
const path p("/path/to/foo.exe");
|
||||
const path replace("bar.out");
|
||||
const path expect("/path/to/bar.out");
|
||||
directory_entry e(p);
|
||||
TEST_CHECK(e.path() == p);
|
||||
e.replace_filename(replace);
|
||||
TEST_CHECK(e.path() == expect);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_replace_filename_ec_method) {
|
||||
using namespace fs;
|
||||
|
||||
{
|
||||
directory_entry e;
|
||||
path replace;
|
||||
std::error_code ec;
|
||||
static_assert(noexcept(e.replace_filename(replace, ec)) == false,
|
||||
"operation cannot be noexcept");
|
||||
static_assert(
|
||||
std::is_same<decltype(e.replace_filename(replace, ec)), void>::value,
|
||||
"operation must return void");
|
||||
}
|
||||
{
|
||||
const path p("/path/to/foo.exe");
|
||||
const path replace("bar.out");
|
||||
const path expect("/path/to/bar.out");
|
||||
directory_entry e(p);
|
||||
TEST_CHECK(e.path() == p);
|
||||
std::error_code ec = GetTestEC();
|
||||
e.replace_filename(replace, ec);
|
||||
TEST_CHECK(e.path() == expect);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
}
|
||||
{
|
||||
const path p = StaticEnv::EmptyFile;
|
||||
const path expect = StaticEnv::NonEmptyFile;
|
||||
const path replace = StaticEnv::NonEmptyFile.filename();
|
||||
TEST_REQUIRE(expect.parent_path() == p.parent_path());
|
||||
directory_entry e(p);
|
||||
TEST_CHECK(e.path() == p);
|
||||
std::error_code ec = GetTestEC();
|
||||
e.replace_filename(replace, ec);
|
||||
TEST_CHECK(e.path() == expect);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_replace_filename_calls_refresh) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path file_two = env.create_file("dir/file_two", 101);
|
||||
const path sym = env.create_symlink("dir/file", "sym");
|
||||
const path sym_two = env.create_symlink("dir/file_two", "sym_two");
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
ent.replace_filename(file_two.filename());
|
||||
TEST_REQUIRE(ent.path() == file_two);
|
||||
|
||||
// removing the file demonstrates that the values where cached previously.
|
||||
LIBCPP_ONLY(remove(file_two));
|
||||
|
||||
TEST_CHECK(ent.file_size() == 101);
|
||||
}
|
||||
env.create_file("dir/file_two", 99);
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
ent.replace_filename(sym_two.filename());
|
||||
TEST_REQUIRE(ent.path() == sym_two);
|
||||
|
||||
LIBCPP_ONLY(remove(file_two));
|
||||
LIBCPP_ONLY(remove(sym_two));
|
||||
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
TEST_CHECK(ent.is_regular_file());
|
||||
TEST_CHECK(ent.file_size() == 99);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_replace_filename_propagates_error) {
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path file_two = env.create_file("dir/file_two", 99);
|
||||
const path file_out_of_dir = env.create_file("file_three", 101);
|
||||
const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
|
||||
const path sym_out_of_dir_two = env.create_symlink("dir/file", "sym_two");
|
||||
const path sym_in_dir = env.create_symlink("file_two", "dir/sym_three");
|
||||
const path sym_in_dir_two = env.create_symlink("file_two", "dir/sym_four");
|
||||
|
||||
const perms old_perms = status(dir).permissions();
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
permissions(dir, perms::none);
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.replace_filename(file_two.filename(), ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
{
|
||||
directory_entry ent(sym_in_dir);
|
||||
permissions(dir, perms::none);
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.replace_filename(sym_in_dir_two.filename(), ec);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
{
|
||||
directory_entry ent(sym_out_of_dir);
|
||||
permissions(dir, perms::none);
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.replace_filename(sym_out_of_dir_two.filename(), ec);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK(ent.is_symlink());
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(!ent.exists(ec));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,82 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// bool operator==(directory_entry const&) const noexcept;
|
||||
// bool operator!=(directory_entry const&) const noexcept;
|
||||
// bool operator< (directory_entry const&) const noexcept;
|
||||
// bool operator<=(directory_entry const&) const noexcept;
|
||||
// bool operator> (directory_entry const&) const noexcept;
|
||||
// bool operator>=(directory_entry const&) const noexcept;
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
#define CHECK_OP(Op) \
|
||||
static_assert(std::is_same<decltype(ce. operator Op (ce)), bool>::value, ""); \
|
||||
static_assert(noexcept(ce.operator Op (ce)), "Operation must be noexcept" )
|
||||
|
||||
void test_comparison_signatures() {
|
||||
using namespace fs;
|
||||
path const p("foo/bar/baz");
|
||||
// Check that the operators are member functions with the correct signatures.
|
||||
{
|
||||
directory_entry const ce(p);
|
||||
CHECK_OP(==);
|
||||
CHECK_OP(!=);
|
||||
CHECK_OP(< );
|
||||
CHECK_OP(<=);
|
||||
CHECK_OP(> );
|
||||
CHECK_OP(>=);
|
||||
}
|
||||
}
|
||||
#undef CHECK_OP
|
||||
|
||||
// The actual semantics of the comparisons are testing via paths operators.
|
||||
void test_comparisons_simple() {
|
||||
using namespace fs;
|
||||
typedef std::pair<path, path> TestType;
|
||||
TestType TestCases[] =
|
||||
{
|
||||
{"", ""},
|
||||
{"", "a"},
|
||||
{"a", "a"},
|
||||
{"a", "b"},
|
||||
{"foo/bar/baz", "foo/bar/baz/"}
|
||||
};
|
||||
auto TestFn = [](path const& LHS, const directory_entry& LHSE,
|
||||
path const& RHS, const directory_entry& RHSE) {
|
||||
assert((LHS == RHS) == (LHSE == RHSE));
|
||||
assert((LHS != RHS) == (LHSE != RHSE));
|
||||
assert((LHS < RHS) == (LHSE < RHSE));
|
||||
assert((LHS <= RHS) == (LHSE <= RHSE));
|
||||
assert((LHS > RHS) == (LHSE > RHSE));
|
||||
assert((LHS >= RHS) == (LHSE >= RHSE));
|
||||
};
|
||||
for (auto const& TC : TestCases) {
|
||||
const directory_entry L(TC.first);
|
||||
const directory_entry R(TC.second);
|
||||
TestFn(TC.first, L, TC.second, R);
|
||||
TestFn(TC.second, R, TC.first, L);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test_comparison_signatures();
|
||||
test_comparisons_simple();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// uintmax_t file_size() const;
|
||||
// uintmax_t file_size(error_code const&) const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
TEST_SUITE(directory_entry_obs_testsuite)
|
||||
|
||||
TEST_CASE(signatures) {
|
||||
using namespace fs;
|
||||
{
|
||||
const fs::directory_entry e = {};
|
||||
std::error_code ec;
|
||||
static_assert(std::is_same<decltype(e.file_size()), uintmax_t>::value, "");
|
||||
static_assert(std::is_same<decltype(e.file_size(ec)), uintmax_t>::value,
|
||||
"");
|
||||
static_assert(noexcept(e.file_size()) == false, "");
|
||||
static_assert(noexcept(e.file_size(ec)) == true, "");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(basic) {
|
||||
using namespace fs;
|
||||
|
||||
scoped_test_env env;
|
||||
const path file = env.create_file("file", 42);
|
||||
const path dir = env.create_dir("dir");
|
||||
const path sym = env.create_symlink("file", "sym");
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
uintmax_t expect = file_size(ent);
|
||||
TEST_CHECK(expect == 42);
|
||||
|
||||
// Remove the file to show that the results were already in the cache.
|
||||
LIBCPP_ONLY(remove(file));
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == expect);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
env.create_file("file", 99);
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
|
||||
uintmax_t expect = file_size(ent);
|
||||
TEST_CHECK(expect == 99);
|
||||
|
||||
LIBCPP_ONLY(remove(ent));
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == 99);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(not_regular_file) {
|
||||
using namespace fs;
|
||||
|
||||
scoped_test_env env;
|
||||
struct {
|
||||
const path p;
|
||||
std::errc expected_err;
|
||||
} TestCases[] = {
|
||||
{env.create_dir("dir"), std::errc::is_a_directory},
|
||||
{env.create_fifo("fifo"), std::errc::not_supported},
|
||||
{env.create_symlink("dir", "sym"), std::errc::is_a_directory}};
|
||||
|
||||
for (auto const& TC : TestCases) {
|
||||
const path& p = TC.p;
|
||||
directory_entry ent(p);
|
||||
TEST_CHECK(ent.path() == p);
|
||||
std::error_code ec = GetTestEC(0);
|
||||
|
||||
std::error_code other_ec = GetTestEC(1);
|
||||
uintmax_t expect = file_size(p, other_ec);
|
||||
|
||||
uintmax_t got = ent.file_size(ec);
|
||||
TEST_CHECK(got == expect);
|
||||
TEST_CHECK(got == uintmax_t(-1));
|
||||
TEST_CHECK(ec == other_ec);
|
||||
TEST_CHECK(ErrorIs(ec, TC.expected_err));
|
||||
|
||||
ExceptionChecker Checker(p, TC.expected_err, "directory_entry::file_size");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(error_reporting) {
|
||||
using namespace fs;
|
||||
|
||||
scoped_test_env env;
|
||||
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path file_out_of_dir = env.create_file("file2", 101);
|
||||
const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
|
||||
const path sym_in_dir = env.create_symlink("file2", "dir/sym2");
|
||||
|
||||
const perms old_perms = status(dir).permissions();
|
||||
|
||||
// test a file which doesn't exist
|
||||
{
|
||||
directory_entry ent;
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(StaticEnv::DNE, ec);
|
||||
TEST_REQUIRE(ent.path() == StaticEnv::DNE);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ExceptionChecker Checker(StaticEnv::DNE,
|
||||
std::errc::no_such_file_or_directory,
|
||||
"directory_entry::file_size");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
|
||||
}
|
||||
// test a dead symlink
|
||||
{
|
||||
directory_entry ent;
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
uintmax_t expect_bad = file_size(StaticEnv::BadSymlink, ec);
|
||||
TEST_CHECK(expect_bad == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ec = GetTestEC();
|
||||
ent.assign(StaticEnv::BadSymlink, ec);
|
||||
TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == expect_bad);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ExceptionChecker Checker(StaticEnv::BadSymlink,
|
||||
std::errc::no_such_file_or_directory,
|
||||
"directory_entry::file_size");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
|
||||
}
|
||||
// test a file w/o appropriate permissions.
|
||||
{
|
||||
directory_entry ent;
|
||||
uintmax_t expect_good = file_size(file);
|
||||
permissions(dir, perms::none);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(file, ec);
|
||||
TEST_REQUIRE(ent.path() == file);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ExceptionChecker Checker(file, std::errc::permission_denied, "file_size");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
|
||||
|
||||
permissions(dir, old_perms);
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == expect_good);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK_NO_THROW(ent.file_size());
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
// test a symlink w/o appropriate permissions.
|
||||
{
|
||||
directory_entry ent;
|
||||
uintmax_t expect_good = file_size(sym_in_dir);
|
||||
permissions(dir, perms::none);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(sym_in_dir, ec);
|
||||
TEST_REQUIRE(ent.path() == sym_in_dir);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
|
||||
"file_size");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
|
||||
|
||||
permissions(dir, old_perms);
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == expect_good);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK_NO_THROW(ent.file_size());
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
// test a symlink to a file w/o appropriate permissions
|
||||
{
|
||||
directory_entry ent;
|
||||
uintmax_t expect_good = file_size(sym_out_of_dir);
|
||||
permissions(dir, perms::none);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(sym_out_of_dir, ec);
|
||||
TEST_REQUIRE(ent.path() == sym_out_of_dir);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied,
|
||||
"file_size");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size());
|
||||
|
||||
permissions(dir, old_perms);
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.file_size(ec) == expect_good);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK_NO_THROW(ent.file_size());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,257 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// file_status status() const;
|
||||
// file_status status(error_code const&) const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_obs_testsuite)
|
||||
|
||||
TEST_CASE(file_dne) {
|
||||
using namespace fs;
|
||||
directory_entry p("dne");
|
||||
}
|
||||
|
||||
TEST_CASE(signatures) {
|
||||
using namespace fs;
|
||||
const directory_entry e = {};
|
||||
std::error_code ec;
|
||||
#define TEST_FUNC(name) \
|
||||
static_assert(std::is_same<decltype(e.name()), bool>::value, \
|
||||
"wrong return type"); \
|
||||
static_assert(noexcept(e.name()) == false, "should not be noexcept"); \
|
||||
static_assert(std::is_same<decltype(e.name(ec)), bool>::value, \
|
||||
"wrong return type"); \
|
||||
static_assert(noexcept(e.name(ec)) == true, "should be noexcept")
|
||||
|
||||
TEST_FUNC(exists);
|
||||
TEST_FUNC(is_block_file);
|
||||
TEST_FUNC(is_character_file);
|
||||
TEST_FUNC(is_directory);
|
||||
TEST_FUNC(is_fifo);
|
||||
TEST_FUNC(is_other);
|
||||
TEST_FUNC(is_regular_file);
|
||||
TEST_FUNC(is_socket);
|
||||
TEST_FUNC(is_symlink);
|
||||
|
||||
#undef TEST_FUNC
|
||||
}
|
||||
|
||||
TEST_CASE(test_without_ec) {
|
||||
using namespace fs;
|
||||
using fs::directory_entry;
|
||||
using fs::file_status;
|
||||
using fs::path;
|
||||
|
||||
scoped_test_env env;
|
||||
path f = env.create_file("foo", 42);
|
||||
path d = env.create_dir("dir");
|
||||
path fifo = env.create_fifo("fifo");
|
||||
path hl = env.create_hardlink("foo", "hl");
|
||||
for (auto p : {hl, f, d, fifo}) {
|
||||
directory_entry e(p);
|
||||
file_status st = status(p);
|
||||
file_status sym_st = symlink_status(p);
|
||||
fs::remove(p);
|
||||
TEST_REQUIRE(e.exists());
|
||||
TEST_REQUIRE(!exists(p));
|
||||
TEST_CHECK(e.exists() == exists(st));
|
||||
TEST_CHECK(e.is_block_file() == is_block_file(st));
|
||||
TEST_CHECK(e.is_character_file() == is_character_file(st));
|
||||
TEST_CHECK(e.is_directory() == is_directory(st));
|
||||
TEST_CHECK(e.is_fifo() == is_fifo(st));
|
||||
TEST_CHECK(e.is_other() == is_other(st));
|
||||
TEST_CHECK(e.is_regular_file() == is_regular_file(st));
|
||||
TEST_CHECK(e.is_socket() == is_socket(st));
|
||||
TEST_CHECK(e.is_symlink() == is_symlink(sym_st));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_with_ec) {
|
||||
using namespace fs;
|
||||
using fs::directory_entry;
|
||||
using fs::file_status;
|
||||
using fs::path;
|
||||
|
||||
scoped_test_env env;
|
||||
path f = env.create_file("foo", 42);
|
||||
path d = env.create_dir("dir");
|
||||
path fifo = env.create_fifo("fifo");
|
||||
path hl = env.create_hardlink("foo", "hl");
|
||||
for (auto p : {hl, f, d, fifo}) {
|
||||
directory_entry e(p);
|
||||
std::error_code status_ec = GetTestEC();
|
||||
std::error_code sym_status_ec = GetTestEC(1);
|
||||
file_status st = status(p, status_ec);
|
||||
file_status sym_st = symlink_status(p, sym_status_ec);
|
||||
fs::remove(p);
|
||||
std::error_code ec = GetTestEC(2);
|
||||
auto CheckEC = [&](std::error_code const& other_ec) {
|
||||
bool res = ec == other_ec;
|
||||
ec = GetTestEC(2);
|
||||
return res;
|
||||
};
|
||||
|
||||
TEST_REQUIRE(e.exists(ec));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
TEST_REQUIRE(!exists(p));
|
||||
|
||||
TEST_CHECK(e.exists(ec) == exists(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_block_file(ec) == is_block_file(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_character_file(ec) == is_character_file(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_directory(ec) == is_directory(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_fifo(ec) == is_fifo(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_other(ec) == is_other(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_socket(ec) == is_socket(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st));
|
||||
TEST_CHECK(CheckEC(sym_status_ec));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_with_ec_dne) {
|
||||
using namespace fs;
|
||||
using fs::directory_entry;
|
||||
using fs::file_status;
|
||||
using fs::path;
|
||||
|
||||
for (auto p : {StaticEnv::DNE, StaticEnv::BadSymlink}) {
|
||||
|
||||
directory_entry e(p);
|
||||
std::error_code status_ec = GetTestEC();
|
||||
std::error_code sym_status_ec = GetTestEC(1);
|
||||
file_status st = status(p, status_ec);
|
||||
file_status sym_st = symlink_status(p, sym_status_ec);
|
||||
std::error_code ec = GetTestEC(2);
|
||||
auto CheckEC = [&](std::error_code const& other_ec) {
|
||||
bool res = ec == other_ec;
|
||||
ec = GetTestEC(2);
|
||||
return res;
|
||||
};
|
||||
|
||||
TEST_CHECK(e.exists(ec) == exists(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_block_file(ec) == is_block_file(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_character_file(ec) == is_character_file(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_directory(ec) == is_directory(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_fifo(ec) == is_fifo(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_other(ec) == is_other(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_socket(ec) == is_socket(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st));
|
||||
TEST_CHECK(CheckEC(sym_status_ec));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_with_ec_cannot_resolve) {
|
||||
using namespace fs;
|
||||
using fs::directory_entry;
|
||||
using fs::file_status;
|
||||
using fs::path;
|
||||
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path file_out_of_dir = env.create_file("file2", 99);
|
||||
const path sym = env.create_symlink("file2", "dir/sym");
|
||||
|
||||
perms old_perms = fs::status(dir).permissions();
|
||||
|
||||
for (auto p : {file, sym}) {
|
||||
permissions(dir, old_perms);
|
||||
directory_entry e(p);
|
||||
|
||||
permissions(dir, perms::none);
|
||||
std::error_code dummy_ec;
|
||||
e.refresh(dummy_ec);
|
||||
TEST_REQUIRE(dummy_ec);
|
||||
|
||||
std::error_code status_ec = GetTestEC();
|
||||
std::error_code sym_status_ec = GetTestEC(1);
|
||||
file_status st = status(p, status_ec);
|
||||
file_status sym_st = symlink_status(p, sym_status_ec);
|
||||
std::error_code ec = GetTestEC(2);
|
||||
auto CheckEC = [&](std::error_code const& other_ec) {
|
||||
bool res = ec == other_ec;
|
||||
ec = GetTestEC(2);
|
||||
return res;
|
||||
};
|
||||
|
||||
TEST_CHECK(e.exists(ec) == exists(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_block_file(ec) == is_block_file(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_character_file(ec) == is_character_file(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_directory(ec) == is_directory(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_fifo(ec) == is_fifo(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_other(ec) == is_other(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_socket(ec) == is_socket(st));
|
||||
TEST_CHECK(CheckEC(status_ec));
|
||||
|
||||
TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st));
|
||||
TEST_CHECK(CheckEC(sym_status_ec));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,241 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// uintmax_t hard_link_count() const;
|
||||
// uintmax_t hard_link_count(error_code const&) const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_obs_testsuite)
|
||||
|
||||
TEST_CASE(signatures) {
|
||||
using namespace fs;
|
||||
{
|
||||
const directory_entry e = {};
|
||||
std::error_code ec;
|
||||
static_assert(std::is_same<decltype(e.hard_link_count()), uintmax_t>::value, "");
|
||||
static_assert(std::is_same<decltype(e.hard_link_count(ec)), uintmax_t>::value,
|
||||
"");
|
||||
static_assert(noexcept(e.hard_link_count()) == false, "");
|
||||
static_assert(noexcept(e.hard_link_count(ec)) == true, "");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(basic) {
|
||||
using namespace fs;
|
||||
|
||||
scoped_test_env env;
|
||||
const path file = env.create_file("file", 42);
|
||||
const path dir = env.create_dir("dir");
|
||||
const path sym = env.create_symlink("file", "sym");
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
uintmax_t expect = hard_link_count(ent);
|
||||
|
||||
// Remove the file to show that the results were already in the cache.
|
||||
LIBCPP_ONLY(remove(file));
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == expect);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
{
|
||||
directory_entry ent(dir);
|
||||
uintmax_t expect = hard_link_count(ent);
|
||||
|
||||
LIBCPP_ONLY(remove(dir));
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == expect);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
env.create_file("file", 99);
|
||||
env.create_hardlink("file", "hl");
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
std::error_code ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == 2);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(not_regular_file) {
|
||||
using namespace fs;
|
||||
|
||||
scoped_test_env env;
|
||||
const path dir = env.create_dir("dir");
|
||||
const path dir2 = env.create_dir("dir/dir2");
|
||||
const path fifo = env.create_fifo("dir/fifo");
|
||||
const path sym_to_fifo = env.create_symlink("dir/fifo", "dir/sym");
|
||||
|
||||
const perms old_perms = status(dir).permissions();
|
||||
|
||||
for (auto p : {dir2, fifo, sym_to_fifo}) {
|
||||
permissions(dir, old_perms);
|
||||
std::error_code dummy_ec = GetTestEC();
|
||||
directory_entry ent(p, dummy_ec);
|
||||
TEST_CHECK(!dummy_ec);
|
||||
|
||||
uintmax_t expect = hard_link_count(p);
|
||||
|
||||
LIBCPP_ONLY(permissions(dir, perms::none));
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == expect);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK_NO_THROW(ent.hard_link_count());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(error_reporting) {
|
||||
using namespace fs;
|
||||
|
||||
scoped_test_env env;
|
||||
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path file_out_of_dir = env.create_file("file2", 101);
|
||||
const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
|
||||
const path sym_in_dir = env.create_symlink("file2", "dir/sym2");
|
||||
|
||||
const perms old_perms = status(dir).permissions();
|
||||
|
||||
// test a file which doesn't exist
|
||||
{
|
||||
directory_entry ent;
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(StaticEnv::DNE, ec);
|
||||
TEST_CHECK(ec);
|
||||
TEST_REQUIRE(ent.path() == StaticEnv::DNE);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ExceptionChecker Checker(StaticEnv::DNE,
|
||||
std::errc::no_such_file_or_directory,
|
||||
"directory_entry::hard_link_count");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
|
||||
}
|
||||
// test a dead symlink
|
||||
{
|
||||
directory_entry ent;
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
uintmax_t expect_bad = hard_link_count(StaticEnv::BadSymlink, ec);
|
||||
TEST_CHECK(expect_bad == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ec = GetTestEC();
|
||||
ent.assign(StaticEnv::BadSymlink, ec);
|
||||
TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == expect_bad);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ExceptionChecker Checker(StaticEnv::BadSymlink,
|
||||
std::errc::no_such_file_or_directory,
|
||||
"directory_entry::hard_link_count");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
|
||||
}
|
||||
// test a file w/o appropriate permissions.
|
||||
{
|
||||
directory_entry ent;
|
||||
uintmax_t expect_good = hard_link_count(file);
|
||||
permissions(dir, perms::none);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(file, ec);
|
||||
TEST_REQUIRE(ent.path() == file);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ExceptionChecker Checker(file, std::errc::permission_denied,
|
||||
"hard_link_count");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
|
||||
|
||||
permissions(dir, old_perms);
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == expect_good);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK_NO_THROW(ent.hard_link_count());
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
// test a symlink w/o appropriate permissions.
|
||||
{
|
||||
directory_entry ent;
|
||||
uintmax_t expect_good = hard_link_count(sym_in_dir);
|
||||
permissions(dir, perms::none);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(sym_in_dir, ec);
|
||||
TEST_REQUIRE(ent.path() == sym_in_dir);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
|
||||
"hard_link_count");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
|
||||
|
||||
permissions(dir, old_perms);
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == expect_good);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK_NO_THROW(ent.hard_link_count());
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
// test a symlink to a file w/o appropriate permissions
|
||||
{
|
||||
directory_entry ent;
|
||||
uintmax_t expect_good = hard_link_count(sym_out_of_dir);
|
||||
permissions(dir, perms::none);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(sym_out_of_dir, ec);
|
||||
TEST_REQUIRE(ent.path() == sym_out_of_dir);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1));
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied,
|
||||
"hard_link_count");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count());
|
||||
|
||||
permissions(dir, old_perms);
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.hard_link_count(ec) == expect_good);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK_NO_THROW(ent.hard_link_count());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,214 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// file_time_type last_write_time() const;
|
||||
// file_time_type last_write_time(error_code const&) const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_obs_testsuite)
|
||||
|
||||
TEST_CASE(signatures) {
|
||||
using namespace fs;
|
||||
{
|
||||
const fs::directory_entry e = {};
|
||||
std::error_code ec;
|
||||
static_assert(std::is_same<decltype(e.last_write_time()), file_time_type>::value,
|
||||
"");
|
||||
static_assert(std::is_same<decltype(e.last_write_time(ec)), file_time_type>::value,
|
||||
"");
|
||||
static_assert(noexcept(e.last_write_time()) == false, "");
|
||||
static_assert(noexcept(e.last_write_time(ec)) == true, "");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(basic) {
|
||||
using namespace fs;
|
||||
|
||||
scoped_test_env env;
|
||||
const path file = env.create_file("file", 42);
|
||||
const path dir = env.create_dir("dir");
|
||||
const path sym = env.create_symlink("file", "sym");
|
||||
|
||||
{
|
||||
directory_entry ent(file);
|
||||
file_time_type expect = last_write_time(ent);
|
||||
|
||||
// Remove the file to show that the results were already in the cache.
|
||||
LIBCPP_ONLY(remove(file));
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == expect);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
{
|
||||
directory_entry ent(dir);
|
||||
file_time_type expect = last_write_time(ent);
|
||||
|
||||
LIBCPP_ONLY(remove(dir));
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == expect);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
env.create_file("file", 99);
|
||||
{
|
||||
directory_entry ent(sym);
|
||||
file_time_type expect = last_write_time(sym);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == expect);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(error_reporting) {
|
||||
using namespace fs;
|
||||
|
||||
scoped_test_env env;
|
||||
|
||||
const path dir = env.create_dir("dir");
|
||||
const path file = env.create_file("dir/file", 42);
|
||||
const path file_out_of_dir = env.create_file("file2", 101);
|
||||
const path sym_out_of_dir = env.create_symlink("dir/file", "sym");
|
||||
const path sym_in_dir = env.create_symlink("file2", "dir/sym2");
|
||||
|
||||
const perms old_perms = status(dir).permissions();
|
||||
|
||||
// test a file which doesn't exist
|
||||
{
|
||||
directory_entry ent;
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(StaticEnv::DNE, ec);
|
||||
TEST_REQUIRE(ent.path() == StaticEnv::DNE);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ExceptionChecker Checker(StaticEnv::DNE,
|
||||
std::errc::no_such_file_or_directory,
|
||||
"directory_entry::last_write_time");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
|
||||
}
|
||||
// test a dead symlink
|
||||
{
|
||||
directory_entry ent;
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
file_time_type expect_bad = last_write_time(StaticEnv::BadSymlink, ec);
|
||||
TEST_CHECK(expect_bad == file_time_type::min());
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ec = GetTestEC();
|
||||
ent.assign(StaticEnv::BadSymlink, ec);
|
||||
TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == expect_bad);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory));
|
||||
|
||||
ExceptionChecker Checker(StaticEnv::BadSymlink,
|
||||
std::errc::no_such_file_or_directory,
|
||||
"directory_entry::last_write_time");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
|
||||
}
|
||||
// test a file w/o appropriate permissions.
|
||||
{
|
||||
directory_entry ent;
|
||||
file_time_type expect_good = last_write_time(file);
|
||||
permissions(dir, perms::none);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(file, ec);
|
||||
TEST_REQUIRE(ent.path() == file);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ExceptionChecker Checker(file, std::errc::permission_denied,
|
||||
"last_write_time");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
|
||||
|
||||
permissions(dir, old_perms);
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == expect_good);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK_NO_THROW(ent.last_write_time());
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
// test a symlink w/o appropriate permissions.
|
||||
{
|
||||
directory_entry ent;
|
||||
file_time_type expect_good = last_write_time(sym_in_dir);
|
||||
permissions(dir, perms::none);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(sym_in_dir, ec);
|
||||
TEST_REQUIRE(ent.path() == sym_in_dir);
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied,
|
||||
"last_write_time");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
|
||||
|
||||
permissions(dir, old_perms);
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == expect_good);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK_NO_THROW(ent.last_write_time());
|
||||
}
|
||||
permissions(dir, old_perms);
|
||||
// test a symlink to a file w/o appropriate permissions
|
||||
{
|
||||
directory_entry ent;
|
||||
file_time_type expect_good = last_write_time(sym_out_of_dir);
|
||||
permissions(dir, perms::none);
|
||||
|
||||
std::error_code ec = GetTestEC();
|
||||
ent.assign(sym_out_of_dir, ec);
|
||||
TEST_REQUIRE(ent.path() == sym_out_of_dir);
|
||||
TEST_CHECK(!ec);
|
||||
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == file_time_type::min());
|
||||
TEST_CHECK(ErrorIs(ec, std::errc::permission_denied));
|
||||
|
||||
ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied,
|
||||
"last_write_time");
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time());
|
||||
|
||||
permissions(dir, old_perms);
|
||||
ec = GetTestEC();
|
||||
TEST_CHECK(ent.last_write_time(ec) == expect_good);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK_NO_THROW(ent.last_write_time());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,89 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// const path& path() const noexcept;
|
||||
// operator const path&() const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
void test_path_method() {
|
||||
using namespace fs;
|
||||
const path p("foo/bar/baz.exe");
|
||||
const path p2("abc");
|
||||
{
|
||||
directory_entry nce;
|
||||
const directory_entry e("");
|
||||
static_assert(std::is_same<decltype(e.path()), const path&>::value, "");
|
||||
static_assert(std::is_same<decltype(nce.path()), const path&>::value, "");
|
||||
static_assert(noexcept(e.path()) && noexcept(nce.path()), "");
|
||||
}
|
||||
{
|
||||
directory_entry e(p);
|
||||
path const& pref = e.path();
|
||||
assert(pref == p);
|
||||
assert(&pref == &e.path());
|
||||
e.assign(p2);
|
||||
assert(pref == p2);
|
||||
assert(&pref == &e.path());
|
||||
}
|
||||
}
|
||||
|
||||
void test_path_conversion() {
|
||||
using namespace fs;
|
||||
const path p("foo/bar/baz.exe");
|
||||
const path p2("abc");
|
||||
{
|
||||
directory_entry nce;
|
||||
const directory_entry e("");
|
||||
// Check conversions exist
|
||||
static_assert(std::is_convertible<directory_entry&, path const&>::value, "");
|
||||
static_assert(std::is_convertible<directory_entry const&, path const&>::value, "");
|
||||
static_assert(std::is_convertible<directory_entry &&, path const&>::value, "");
|
||||
static_assert(std::is_convertible<directory_entry const&&, path const&>::value, "");
|
||||
// Not convertible to non-const
|
||||
static_assert(!std::is_convertible<directory_entry&, path&>::value, "");
|
||||
static_assert(!std::is_convertible<directory_entry const&, path&>::value, "");
|
||||
static_assert(!std::is_convertible<directory_entry &&, path&>::value, "");
|
||||
static_assert(!std::is_convertible<directory_entry const&&, path&>::value, "");
|
||||
// conversions are noexcept
|
||||
static_assert(noexcept(e.operator fs::path const&()) &&
|
||||
noexcept(e.operator fs::path const&()), "");
|
||||
}
|
||||
// const
|
||||
{
|
||||
directory_entry const e(p);
|
||||
path const& pref = e;
|
||||
assert(&pref == &e.path());
|
||||
}
|
||||
// non-const
|
||||
{
|
||||
directory_entry e(p);
|
||||
path const& pref = e;
|
||||
assert(&pref == &e.path());
|
||||
|
||||
e.assign(p2);
|
||||
assert(pref == p2);
|
||||
assert(&pref == &e.path());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test_path_method();
|
||||
test_path_conversion();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// file_status status() const;
|
||||
// file_status status(error_code const&) const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_status_testsuite)
|
||||
|
||||
TEST_CASE(test_basic) {
|
||||
using namespace fs;
|
||||
{
|
||||
const fs::directory_entry e("foo");
|
||||
std::error_code ec;
|
||||
static_assert(std::is_same<decltype(e.status()), fs::file_status>::value, "");
|
||||
static_assert(std::is_same<decltype(e.status(ec)), fs::file_status>::value, "");
|
||||
static_assert(noexcept(e.status()) == false, "");
|
||||
static_assert(noexcept(e.status(ec)) == true, "");
|
||||
}
|
||||
path TestCases[] = {StaticEnv::File, StaticEnv::Dir, StaticEnv::SymlinkToFile,
|
||||
StaticEnv::DNE};
|
||||
for (const auto& p : TestCases) {
|
||||
const directory_entry e(p);
|
||||
std::error_code pec = GetTestEC(), eec = GetTestEC(1);
|
||||
file_status ps = fs::status(p, pec);
|
||||
file_status es = e.status(eec);
|
||||
TEST_CHECK(ps.type() == es.type());
|
||||
TEST_CHECK(ps.permissions() == es.permissions());
|
||||
TEST_CHECK(pec == eec);
|
||||
}
|
||||
for (const auto& p : TestCases) {
|
||||
const directory_entry e(p);
|
||||
file_status ps = fs::status(p);
|
||||
file_status es = e.status();
|
||||
TEST_CHECK(ps.type() == es.type());
|
||||
TEST_CHECK(ps.permissions() == es.permissions());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,57 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_entry
|
||||
|
||||
// file_status symlink_status() const;
|
||||
// file_status symlink_status(error_code&) const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
|
||||
TEST_SUITE(directory_entry_obs_suite)
|
||||
|
||||
TEST_CASE(test_signature) {
|
||||
using namespace fs;
|
||||
{
|
||||
const directory_entry e("foo");
|
||||
std::error_code ec;
|
||||
static_assert(std::is_same<decltype(e.symlink_status()), file_status>::value, "");
|
||||
static_assert(std::is_same<decltype(e.symlink_status(ec)), file_status>::value, "");
|
||||
static_assert(noexcept(e.symlink_status()) == false, "");
|
||||
static_assert(noexcept(e.symlink_status(ec)) == true, "");
|
||||
}
|
||||
path TestCases[] = {StaticEnv::File, StaticEnv::Dir, StaticEnv::SymlinkToFile,
|
||||
StaticEnv::DNE};
|
||||
for (const auto& p : TestCases) {
|
||||
const directory_entry e(p);
|
||||
std::error_code pec = GetTestEC(), eec = GetTestEC(1);
|
||||
file_status ps = fs::symlink_status(p, pec);
|
||||
file_status es = e.symlink_status(eec);
|
||||
TEST_CHECK(ps.type() == es.type());
|
||||
TEST_CHECK(ps.permissions() == es.permissions());
|
||||
TEST_CHECK(pec == eec);
|
||||
}
|
||||
for (const auto& p : TestCases) {
|
||||
const directory_entry e(p);
|
||||
file_status ps = fs::symlink_status(p);
|
||||
file_status es = e.symlink_status();
|
||||
TEST_CHECK(ps.type() == es.type());
|
||||
TEST_CHECK(ps.permissions() == es.permissions());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,58 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_iterator
|
||||
|
||||
// directory_iterator(directory_iterator const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(directory_iterator_copy_construct_tests)
|
||||
|
||||
TEST_CASE(test_constructor_signature)
|
||||
{
|
||||
using D = directory_iterator;
|
||||
static_assert(std::is_copy_constructible<D>::value, "");
|
||||
}
|
||||
|
||||
TEST_CASE(test_copy_end_iterator)
|
||||
{
|
||||
const directory_iterator endIt;
|
||||
directory_iterator it(endIt);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
TEST_CASE(test_copy_valid_iterator)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const directory_iterator endIt{};
|
||||
|
||||
const directory_iterator it(testDir);
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
|
||||
const directory_iterator it2(it);
|
||||
TEST_REQUIRE(it2 == it);
|
||||
TEST_CHECK(*it2 == entry);
|
||||
TEST_CHECK(*it == entry);
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,97 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_iterator
|
||||
|
||||
// directory_iterator& operator=(directory_iterator const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(directory_iterator_copy_assign_tests)
|
||||
|
||||
TEST_CASE(test_assignment_signature)
|
||||
{
|
||||
using D = directory_iterator;
|
||||
static_assert(std::is_copy_assignable<D>::value, "");
|
||||
}
|
||||
|
||||
TEST_CASE(test_copy_to_end_iterator)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
|
||||
const directory_iterator from(testDir);
|
||||
TEST_REQUIRE(from != directory_iterator{});
|
||||
const path entry = *from;
|
||||
|
||||
directory_iterator to{};
|
||||
to = from;
|
||||
TEST_REQUIRE(to == from);
|
||||
TEST_CHECK(*to == entry);
|
||||
TEST_CHECK(*from == entry);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(test_copy_from_end_iterator)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
|
||||
const directory_iterator from{};
|
||||
|
||||
directory_iterator to(testDir);
|
||||
TEST_REQUIRE(to != directory_iterator{});
|
||||
|
||||
to = from;
|
||||
TEST_REQUIRE(to == from);
|
||||
TEST_CHECK(to == directory_iterator{});
|
||||
}
|
||||
|
||||
TEST_CASE(test_copy_valid_iterator)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const directory_iterator endIt{};
|
||||
|
||||
directory_iterator it_obj(testDir);
|
||||
const directory_iterator& it = it_obj;
|
||||
TEST_REQUIRE(it != endIt);
|
||||
++it_obj;
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
|
||||
directory_iterator it2(testDir);
|
||||
TEST_REQUIRE(it2 != it);
|
||||
const path entry2 = *it2;
|
||||
TEST_CHECK(entry2 != entry);
|
||||
|
||||
it2 = it;
|
||||
TEST_REQUIRE(it2 == it);
|
||||
TEST_CHECK(*it2 == entry);
|
||||
}
|
||||
|
||||
TEST_CASE(test_returns_reference_to_self)
|
||||
{
|
||||
const directory_iterator it;
|
||||
directory_iterator it2;
|
||||
directory_iterator& ref = (it2 = it);
|
||||
TEST_CHECK(&ref == &it2);
|
||||
}
|
||||
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,253 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_iterator
|
||||
|
||||
// explicit directory_iterator(const path& p);
|
||||
// directory_iterator(const path& p, directory_options options);
|
||||
// directory_iterator(const path& p, error_code& ec);
|
||||
// directory_iterator(const path& p, directory_options options, error_code& ec);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(directory_iterator_constructor_tests)
|
||||
|
||||
TEST_CASE(test_constructor_signatures)
|
||||
{
|
||||
using D = directory_iterator;
|
||||
|
||||
// explicit directory_iterator(path const&);
|
||||
static_assert(!std::is_convertible<path, D>::value, "");
|
||||
static_assert(std::is_constructible<D, path>::value, "");
|
||||
static_assert(!std::is_nothrow_constructible<D, path>::value, "");
|
||||
|
||||
// directory_iterator(path const&, error_code&)
|
||||
static_assert(std::is_constructible<D, path,
|
||||
std::error_code&>::value, "");
|
||||
static_assert(!std::is_nothrow_constructible<D, path,
|
||||
std::error_code&>::value, "");
|
||||
|
||||
// directory_iterator(path const&, directory_options);
|
||||
static_assert(std::is_constructible<D, path, directory_options>::value, "");
|
||||
static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, "");
|
||||
|
||||
// directory_iterator(path const&, directory_options, error_code&)
|
||||
static_assert(std::is_constructible<D, path, directory_options,
|
||||
std::error_code&>::value, "");
|
||||
static_assert(!std::is_nothrow_constructible<D, path, directory_options,
|
||||
std::error_code&>::value, "");
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE(test_construction_from_bad_path)
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_options opts = directory_options::none;
|
||||
const directory_iterator endIt;
|
||||
|
||||
const path testPaths[] = { StaticEnv::DNE, StaticEnv::BadSymlink };
|
||||
for (path const& testPath : testPaths)
|
||||
{
|
||||
{
|
||||
directory_iterator it(testPath, ec);
|
||||
TEST_CHECK(ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
{
|
||||
directory_iterator it(testPath, opts, ec);
|
||||
TEST_CHECK(ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
{
|
||||
TEST_CHECK_THROW(filesystem_error, directory_iterator(testPath));
|
||||
TEST_CHECK_THROW(filesystem_error, directory_iterator(testPath, opts));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(access_denied_test_case)
|
||||
{
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
path const testDir = env.make_env_path("dir1");
|
||||
path const testFile = testDir / "testFile";
|
||||
env.create_dir(testDir);
|
||||
env.create_file(testFile, 42);
|
||||
|
||||
// Test that we can iterator over the directory before changing the perms
|
||||
{
|
||||
directory_iterator it(testDir);
|
||||
TEST_REQUIRE(it != directory_iterator{});
|
||||
}
|
||||
// Change the permissions so we can no longer iterate
|
||||
permissions(testDir, perms::none);
|
||||
|
||||
// Check that the construction fails when skip_permissions_denied is
|
||||
// not given.
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_iterator it(testDir, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_CHECK(it == directory_iterator{});
|
||||
}
|
||||
// Check that construction does not report an error when
|
||||
// 'skip_permissions_denied' is given.
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_iterator it(testDir, directory_options::skip_permission_denied, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(it == directory_iterator{});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(access_denied_to_file_test_case)
|
||||
{
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
path const testFile = env.make_env_path("file1");
|
||||
env.create_file(testFile, 42);
|
||||
|
||||
// Change the permissions so we can no longer iterate
|
||||
permissions(testFile, perms::none);
|
||||
|
||||
// Check that the construction fails when skip_permissions_denied is
|
||||
// not given.
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_iterator it(testFile, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_CHECK(it == directory_iterator{});
|
||||
}
|
||||
// Check that construction still fails when 'skip_permissions_denied' is given
|
||||
// because we tried to open a file and not a directory.
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_iterator it(testFile, directory_options::skip_permission_denied, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_CHECK(it == directory_iterator{});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_open_on_empty_directory_equals_end)
|
||||
{
|
||||
scoped_test_env env;
|
||||
const path testDir = env.make_env_path("dir1");
|
||||
env.create_dir(testDir);
|
||||
|
||||
const directory_iterator endIt;
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_iterator it(testDir, ec);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
{
|
||||
directory_iterator it(testDir);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_open_on_directory_succeeds)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
|
||||
std::end( StaticEnv::DirIterationList));
|
||||
const directory_iterator endIt{};
|
||||
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_iterator it(testDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(it != endIt);
|
||||
TEST_CHECK(dir_contents.count(*it));
|
||||
}
|
||||
{
|
||||
directory_iterator it(testDir);
|
||||
TEST_CHECK(it != endIt);
|
||||
TEST_CHECK(dir_contents.count(*it));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_open_on_file_fails)
|
||||
{
|
||||
const path testFile = StaticEnv::File;
|
||||
const directory_iterator endIt{};
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_iterator it(testFile, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
{
|
||||
TEST_CHECK_THROW(filesystem_error, directory_iterator(testFile));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_open_on_empty_string)
|
||||
{
|
||||
const path testPath = "";
|
||||
const directory_iterator endIt{};
|
||||
|
||||
std::error_code ec;
|
||||
directory_iterator it(testPath, ec);
|
||||
TEST_CHECK(ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
TEST_CASE(test_open_on_dot_dir)
|
||||
{
|
||||
const path testPath = ".";
|
||||
|
||||
std::error_code ec;
|
||||
directory_iterator it(testPath, ec);
|
||||
TEST_CHECK(!ec);
|
||||
}
|
||||
|
||||
TEST_CASE(test_open_on_symlink)
|
||||
{
|
||||
const path symlinkToDir = StaticEnv::SymlinkToDir;
|
||||
std::set<path> dir_contents;
|
||||
for (path const& p : StaticEnv::DirIterationList) {
|
||||
dir_contents.insert(p.filename());
|
||||
}
|
||||
const directory_iterator endIt{};
|
||||
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_iterator it(symlinkToDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(it != endIt);
|
||||
path const& entry = *it;
|
||||
TEST_CHECK(dir_contents.count(entry.filename()));
|
||||
}
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_iterator it(symlinkToDir,
|
||||
directory_options::follow_directory_symlink, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(it != endIt);
|
||||
path const& entry = *it;
|
||||
TEST_CHECK(dir_contents.count(entry.filename()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,36 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_iterator
|
||||
|
||||
// directory_iterator::directory_iterator() noexcept
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
{
|
||||
static_assert(std::is_nothrow_default_constructible<fs::directory_iterator>::value, "");
|
||||
}
|
||||
{
|
||||
fs::directory_iterator d1;
|
||||
const fs::directory_iterator d2;
|
||||
assert(d1 == d2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_iterator
|
||||
|
||||
// directory_iterator& operator++();
|
||||
// directory_iterator& increment(error_code& ec);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(directory_iterator_increment_tests)
|
||||
|
||||
TEST_CASE(test_increment_signatures)
|
||||
{
|
||||
directory_iterator d; ((void)d);
|
||||
std::error_code ec; ((void)ec);
|
||||
|
||||
ASSERT_SAME_TYPE(decltype(++d), directory_iterator&);
|
||||
ASSERT_NOT_NOEXCEPT(++d);
|
||||
|
||||
ASSERT_SAME_TYPE(decltype(d.increment(ec)), directory_iterator&);
|
||||
ASSERT_NOT_NOEXCEPT(d.increment(ec));
|
||||
}
|
||||
|
||||
TEST_CASE(test_prefix_increment)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
|
||||
std::end( StaticEnv::DirIterationList));
|
||||
const directory_iterator endIt{};
|
||||
|
||||
std::error_code ec;
|
||||
directory_iterator it(testDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
|
||||
std::set<path> unseen_entries = dir_contents;
|
||||
while (!unseen_entries.empty()) {
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
TEST_REQUIRE(unseen_entries.erase(entry) == 1);
|
||||
directory_iterator& it_ref = ++it;
|
||||
TEST_CHECK(&it_ref == &it);
|
||||
}
|
||||
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
TEST_CASE(test_postfix_increment)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
|
||||
std::end( StaticEnv::DirIterationList));
|
||||
const directory_iterator endIt{};
|
||||
|
||||
std::error_code ec;
|
||||
directory_iterator it(testDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
|
||||
std::set<path> unseen_entries = dir_contents;
|
||||
while (!unseen_entries.empty()) {
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
TEST_REQUIRE(unseen_entries.erase(entry) == 1);
|
||||
const path entry2 = *it++;
|
||||
TEST_CHECK(entry2 == entry);
|
||||
}
|
||||
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(test_increment_method)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
|
||||
std::end( StaticEnv::DirIterationList));
|
||||
const directory_iterator endIt{};
|
||||
|
||||
std::error_code ec;
|
||||
directory_iterator it(testDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
|
||||
std::set<path> unseen_entries = dir_contents;
|
||||
while (!unseen_entries.empty()) {
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
TEST_REQUIRE(unseen_entries.erase(entry) == 1);
|
||||
directory_iterator& it_ref = it.increment(ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(&it_ref == &it);
|
||||
}
|
||||
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,61 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_iterator
|
||||
|
||||
// directory_iterator(directory_iterator&&) noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(directory_iterator_move_construct_tests)
|
||||
|
||||
TEST_CASE(test_constructor_signature)
|
||||
{
|
||||
using D = directory_iterator;
|
||||
static_assert(std::is_nothrow_move_constructible<D>::value, "");
|
||||
}
|
||||
|
||||
TEST_CASE(test_move_end_iterator)
|
||||
{
|
||||
const directory_iterator endIt;
|
||||
directory_iterator endIt2{};
|
||||
|
||||
directory_iterator it(std::move(endIt2));
|
||||
TEST_CHECK(it == endIt);
|
||||
TEST_CHECK(endIt2 == endIt);
|
||||
}
|
||||
|
||||
TEST_CASE(test_move_valid_iterator)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const directory_iterator endIt{};
|
||||
|
||||
directory_iterator it(testDir);
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
|
||||
const directory_iterator it2(std::move(it));
|
||||
TEST_CHECK(*it2 == entry);
|
||||
|
||||
TEST_CHECK(it == it2 || it == endIt);
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,115 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_iterator
|
||||
|
||||
// directory_iterator& operator=(directory_iterator const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
// The filesystem specification explicitly allows for self-move on
|
||||
// the directory iterators. Turn off this warning so we can test it.
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wself-move"
|
||||
#endif
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(directory_iterator_move_assign_tests)
|
||||
|
||||
TEST_CASE(test_assignment_signature)
|
||||
{
|
||||
using D = directory_iterator;
|
||||
static_assert(std::is_nothrow_move_assignable<D>::value, "");
|
||||
}
|
||||
|
||||
TEST_CASE(test_move_to_end_iterator)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
|
||||
directory_iterator from(testDir);
|
||||
TEST_REQUIRE(from != directory_iterator{});
|
||||
const path entry = *from;
|
||||
|
||||
directory_iterator to{};
|
||||
to = std::move(from);
|
||||
TEST_REQUIRE(to != directory_iterator{});
|
||||
TEST_CHECK(*to == entry);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(test_move_from_end_iterator)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
|
||||
directory_iterator from{};
|
||||
|
||||
directory_iterator to(testDir);
|
||||
TEST_REQUIRE(to != from);
|
||||
|
||||
to = std::move(from);
|
||||
TEST_REQUIRE(to == directory_iterator{});
|
||||
TEST_REQUIRE(from == directory_iterator{});
|
||||
}
|
||||
|
||||
TEST_CASE(test_move_valid_iterator)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const directory_iterator endIt{};
|
||||
|
||||
directory_iterator it(testDir);
|
||||
TEST_REQUIRE(it != endIt);
|
||||
++it;
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
|
||||
directory_iterator it2(testDir);
|
||||
TEST_REQUIRE(it2 != it);
|
||||
const path entry2 = *it2;
|
||||
TEST_CHECK(entry2 != entry);
|
||||
|
||||
it2 = std::move(it);
|
||||
TEST_REQUIRE(it2 != directory_iterator{});
|
||||
TEST_CHECK(*it2 == entry);
|
||||
}
|
||||
|
||||
TEST_CASE(test_returns_reference_to_self)
|
||||
{
|
||||
directory_iterator it;
|
||||
directory_iterator it2;
|
||||
directory_iterator& ref = (it2 = it);
|
||||
TEST_CHECK(&ref == &it2);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(test_self_move)
|
||||
{
|
||||
// Create two non-equal iterators that have exactly the same state.
|
||||
directory_iterator it(StaticEnv::Dir);
|
||||
directory_iterator it2(StaticEnv::Dir);
|
||||
++it; ++it2;
|
||||
TEST_CHECK(it != it2);
|
||||
TEST_CHECK(*it2 == *it);
|
||||
|
||||
it = std::move(it);
|
||||
TEST_CHECK(*it2 == *it);
|
||||
}
|
||||
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,59 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_iterator
|
||||
|
||||
// directory_iterator begin(directory_iterator iter) noexcept;
|
||||
// directory_iterator end(directory_iterator iter) noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(directory_iterator_begin_end_tests)
|
||||
|
||||
TEST_CASE(test_function_signatures)
|
||||
{
|
||||
directory_iterator d; ((void)d);
|
||||
|
||||
ASSERT_SAME_TYPE(decltype(begin(d)), directory_iterator);
|
||||
ASSERT_NOEXCEPT(begin(std::move(d)));
|
||||
|
||||
ASSERT_SAME_TYPE(decltype(end(d)), directory_iterator);
|
||||
ASSERT_NOEXCEPT(end(std::move(d)));
|
||||
}
|
||||
|
||||
TEST_CASE(test_ranged_for_loop)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
|
||||
std::end( StaticEnv::DirIterationList));
|
||||
|
||||
std::error_code ec;
|
||||
directory_iterator it(testDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
|
||||
for (auto& elem : it) {
|
||||
TEST_CHECK(dir_contents.erase(elem) == 1);
|
||||
}
|
||||
TEST_CHECK(dir_contents.empty());
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,38 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_iterator
|
||||
|
||||
// typedef ... value_type;
|
||||
// typedef ... difference_type;
|
||||
// typedef ... pointer;
|
||||
// typedef ... reference;
|
||||
// typedef ... iterator_category
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
using D = directory_iterator;
|
||||
ASSERT_SAME_TYPE(D::value_type, directory_entry);
|
||||
ASSERT_SAME_TYPE(D::difference_type, std::ptrdiff_t);
|
||||
ASSERT_SAME_TYPE(D::pointer, const directory_entry*);
|
||||
ASSERT_SAME_TYPE(D::reference, const directory_entry&);
|
||||
ASSERT_SAME_TYPE(D::iterator_category, std::input_iterator_tag);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class file_status
|
||||
|
||||
// explicit file_status() noexcept;
|
||||
// explicit file_status(file_type, perms prms = perms::unknown) noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_convertible.hpp"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
// Default ctor
|
||||
{
|
||||
static_assert(std::is_nothrow_default_constructible<file_status>::value,
|
||||
"The default constructor must be noexcept");
|
||||
static_assert(test_convertible<file_status>(),
|
||||
"The default constructor must not be explicit");
|
||||
const file_status f;
|
||||
assert(f.type() == file_type::none);
|
||||
assert(f.permissions() == perms::unknown);
|
||||
}
|
||||
|
||||
// Unary ctor
|
||||
{
|
||||
static_assert(std::is_nothrow_constructible<file_status, file_type>::value,
|
||||
"This constructor must be noexcept");
|
||||
static_assert(!test_convertible<file_status, file_type>(),
|
||||
"This constructor must be explicit");
|
||||
|
||||
const file_status f(file_type::not_found);
|
||||
assert(f.type() == file_type::not_found);
|
||||
assert(f.permissions() == perms::unknown);
|
||||
}
|
||||
// Binary ctor
|
||||
{
|
||||
static_assert(std::is_nothrow_constructible<file_status, file_type, perms>::value,
|
||||
"This constructor must be noexcept");
|
||||
static_assert(!test_convertible<file_status, file_type, perms>(),
|
||||
"This constructor must b explicit");
|
||||
const file_status f(file_type::regular, perms::owner_read);
|
||||
assert(f.type() == file_type::regular);
|
||||
assert(f.permissions() == perms::owner_read);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class file_status
|
||||
|
||||
// void type(file_type) noexcept;
|
||||
// void permissions(perms) noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
|
||||
file_status st;
|
||||
|
||||
// type test
|
||||
{
|
||||
static_assert(noexcept(st.type(file_type::regular)),
|
||||
"operation must be noexcept");
|
||||
static_assert(std::is_same<decltype(st.type(file_type::regular)), void>::value,
|
||||
"operation must return void");
|
||||
assert(st.type() != file_type::regular);
|
||||
st.type(file_type::regular);
|
||||
assert(st.type() == file_type::regular);
|
||||
}
|
||||
// permissions test
|
||||
{
|
||||
static_assert(noexcept(st.permissions(perms::owner_read)),
|
||||
"operation must be noexcept");
|
||||
static_assert(std::is_same<decltype(st.permissions(perms::owner_read)), void>::value,
|
||||
"operation must return void");
|
||||
assert(st.permissions() != perms::owner_read);
|
||||
st.permissions(perms::owner_read);
|
||||
assert(st.permissions() == perms::owner_read);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class file_status
|
||||
|
||||
// file_type type() const noexcept;
|
||||
// perms permissions(p) const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
|
||||
const file_status st(file_type::regular, perms::owner_read);
|
||||
|
||||
// type test
|
||||
{
|
||||
static_assert(noexcept(st.type()),
|
||||
"operation must be noexcept");
|
||||
static_assert(std::is_same<decltype(st.type()), file_type>::value,
|
||||
"operation must return file_type");
|
||||
assert(st.type() == file_type::regular);
|
||||
}
|
||||
// permissions test
|
||||
{
|
||||
static_assert(noexcept(st.permissions()),
|
||||
"operation must be noexcept");
|
||||
static_assert(std::is_same<decltype(st.permissions()), perms>::value,
|
||||
"operation must return perms");
|
||||
assert(st.permissions() == perms::owner_read);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class filesystem_error
|
||||
|
||||
// filesystem_error(const string& what_arg, error_code ec);
|
||||
// filesystem_error(const string& what_arg, const path& p1, error_code ec);
|
||||
// filesystem_error(const string& what_arg, const path& p1, const path& p2, error_code ec);
|
||||
// const std::error_code& code() const;
|
||||
// const char* what() const noexcept;
|
||||
// const path& path1() const noexcept;
|
||||
// const path& path2() const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
||||
void test_constructors() {
|
||||
using namespace fs;
|
||||
|
||||
// The string returned by "filesystem_error::what() must contain runtime_error::what()
|
||||
const std::string what_arg = "Hello World";
|
||||
const std::string what_contains = std::runtime_error(what_arg).what();
|
||||
assert(what_contains.find(what_arg) != std::string::npos);
|
||||
auto CheckWhat = [what_contains](filesystem_error const& e) {
|
||||
std::string s = e.what();
|
||||
assert(s.find(what_contains) != std::string::npos);
|
||||
};
|
||||
|
||||
std::error_code ec = std::make_error_code(std::errc::file_exists);
|
||||
const path p1("foo");
|
||||
const path p2("bar");
|
||||
|
||||
// filesystem_error(const string& what_arg, error_code ec);
|
||||
{
|
||||
ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, ec));
|
||||
filesystem_error e(what_arg, ec);
|
||||
CheckWhat(e);
|
||||
assert(e.code() == ec);
|
||||
assert(e.path1().empty() && e.path2().empty());
|
||||
}
|
||||
// filesystem_error(const string& what_arg, const path&, error_code ec);
|
||||
{
|
||||
ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, p1, ec));
|
||||
filesystem_error e(what_arg, p1, ec);
|
||||
CheckWhat(e);
|
||||
assert(e.code() == ec);
|
||||
assert(e.path1() == p1);
|
||||
assert(e.path2().empty());
|
||||
}
|
||||
// filesystem_error(const string& what_arg, const path&, const path&, error_code ec);
|
||||
{
|
||||
ASSERT_NOT_NOEXCEPT(filesystem_error(what_arg, p1, p2, ec));
|
||||
filesystem_error e(what_arg, p1, p2, ec);
|
||||
CheckWhat(e);
|
||||
assert(e.code() == ec);
|
||||
assert(e.path1() == p1);
|
||||
assert(e.path2() == p2);
|
||||
}
|
||||
}
|
||||
|
||||
void test_signatures()
|
||||
{
|
||||
using namespace fs;
|
||||
const path p;
|
||||
std::error_code ec;
|
||||
const filesystem_error e("lala", ec);
|
||||
// const path& path1() const noexcept;
|
||||
{
|
||||
ASSERT_SAME_TYPE(path const&, decltype(e.path1()));
|
||||
ASSERT_NOEXCEPT(e.path1());
|
||||
}
|
||||
// const path& path2() const noexcept
|
||||
{
|
||||
ASSERT_SAME_TYPE(path const&, decltype(e.path2()));
|
||||
ASSERT_NOEXCEPT(e.path2());
|
||||
}
|
||||
// const char* what() const noexcept
|
||||
{
|
||||
ASSERT_SAME_TYPE(const char*, decltype(e.what()));
|
||||
ASSERT_NOEXCEPT(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
static_assert(std::is_base_of<std::system_error, fs::filesystem_error>::value, "");
|
||||
test_constructors();
|
||||
test_signatures();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// template <class Source>
|
||||
// path(const Source& source);
|
||||
// template <class InputIterator>
|
||||
// path(InputIterator first, InputIterator last);
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
|
||||
template <class It>
|
||||
std::reverse_iterator<It> mkRev(It it) {
|
||||
return std::reverse_iterator<It>(it);
|
||||
}
|
||||
|
||||
void checkIteratorConcepts() {
|
||||
using namespace fs;
|
||||
using It = path::iterator;
|
||||
using Traits = std::iterator_traits<It>;
|
||||
ASSERT_SAME_TYPE(Traits::iterator_category, std::bidirectional_iterator_tag);
|
||||
ASSERT_SAME_TYPE(Traits::value_type, path);
|
||||
ASSERT_SAME_TYPE(Traits::pointer, path const*);
|
||||
ASSERT_SAME_TYPE(Traits::reference, path const&);
|
||||
{
|
||||
It it;
|
||||
ASSERT_SAME_TYPE(It&, decltype(++it));
|
||||
ASSERT_SAME_TYPE(It, decltype(it++));
|
||||
ASSERT_SAME_TYPE(It&, decltype(--it));
|
||||
ASSERT_SAME_TYPE(It, decltype(it--));
|
||||
ASSERT_SAME_TYPE(Traits::reference, decltype(*it));
|
||||
ASSERT_SAME_TYPE(Traits::pointer, decltype(it.operator->()));
|
||||
ASSERT_SAME_TYPE(std::string const&, decltype(it->native()));
|
||||
ASSERT_SAME_TYPE(bool, decltype(it == it));
|
||||
ASSERT_SAME_TYPE(bool, decltype(it != it));
|
||||
}
|
||||
{
|
||||
path const p;
|
||||
ASSERT_SAME_TYPE(It, decltype(p.begin()));
|
||||
ASSERT_SAME_TYPE(It, decltype(p.end()));
|
||||
assert(p.begin() == p.end());
|
||||
}
|
||||
}
|
||||
|
||||
void checkBeginEndBasic() {
|
||||
using namespace fs;
|
||||
using It = path::iterator;
|
||||
{
|
||||
path const p;
|
||||
ASSERT_SAME_TYPE(It, decltype(p.begin()));
|
||||
ASSERT_SAME_TYPE(It, decltype(p.end()));
|
||||
assert(p.begin() == p.end());
|
||||
}
|
||||
{
|
||||
path const p("foo");
|
||||
It default_constructed;
|
||||
default_constructed = p.begin();
|
||||
assert(default_constructed == p.begin());
|
||||
assert(default_constructed != p.end());
|
||||
default_constructed = p.end();
|
||||
assert(default_constructed == p.end());
|
||||
assert(default_constructed != p.begin());
|
||||
}
|
||||
{
|
||||
path p("//root_name//first_dir////second_dir");
|
||||
const path expect[] = {"/", "root_name", "first_dir", "second_dir"};
|
||||
assert(checkCollectionsEqual(p.begin(), p.end(), std::begin(expect), std::end(expect)));
|
||||
assert(checkCollectionsEqualBackwards(p.begin(), p.end(), std::begin(expect), std::end(expect)));
|
||||
|
||||
}
|
||||
{
|
||||
path p("////foo/bar/baz///");
|
||||
const path expect[] = {"/", "foo", "bar", "baz", ""};
|
||||
assert(checkCollectionsEqual(p.begin(), p.end(), std::begin(expect), std::end(expect)));
|
||||
assert(checkCollectionsEqualBackwards(p.begin(), p.end(), std::begin(expect), std::end(expect)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
checkIteratorConcepts();
|
||||
checkBeginEndBasic(); // See path.decompose.pass.cpp for more tests.
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,340 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path& operator/=(path const&)
|
||||
// template <class Source>
|
||||
// path& operator/=(Source const&);
|
||||
// template <class Source>
|
||||
// path& append(Source const&);
|
||||
// template <class InputIterator>
|
||||
// path& append(InputIterator first, InputIterator last);
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <string_view>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "verbose_assert.h"
|
||||
|
||||
|
||||
struct AppendOperatorTestcase {
|
||||
MultiStringType lhs;
|
||||
MultiStringType rhs;
|
||||
MultiStringType expect;
|
||||
};
|
||||
|
||||
#define S(Str) MKSTR(Str)
|
||||
const AppendOperatorTestcase Cases[] =
|
||||
{
|
||||
{S(""), S(""), S("")}
|
||||
, {S("p1"), S("p2"), S("p1/p2")}
|
||||
, {S("p1/"), S("p2"), S("p1/p2")}
|
||||
, {S("p1"), S("/p2"), S("/p2")}
|
||||
, {S("p1/"), S("/p2"), S("/p2")}
|
||||
, {S("p1"), S("\\p2"), S("p1/\\p2")}
|
||||
, {S("p1\\"), S("p2"), S("p1\\/p2")}
|
||||
, {S("p1\\"), S("\\p2"), S("p1\\/\\p2")}
|
||||
, {S(""), S("p2"), S("p2")}
|
||||
, {S("/p1"), S("p2"), S("/p1/p2")}
|
||||
, {S("/p1"), S("/p2"), S("/p2")}
|
||||
, {S("/p1/p3"), S("p2"), S("/p1/p3/p2")}
|
||||
, {S("/p1/p3/"), S("p2"), S("/p1/p3/p2")}
|
||||
, {S("/p1/"), S("p2"), S("/p1/p2")}
|
||||
, {S("/p1/p3/"), S("/p2/p4"), S("/p2/p4")}
|
||||
, {S("/"), S(""), S("/")}
|
||||
, {S("/p1"), S("/p2/"), S("/p2/")}
|
||||
, {S("p1"), S(""), S("p1/")}
|
||||
, {S("p1/"), S(""), S("p1/")}
|
||||
};
|
||||
|
||||
|
||||
const AppendOperatorTestcase LongLHSCases[] =
|
||||
{
|
||||
{S("p1"), S("p2"), S("p1/p2")}
|
||||
, {S("p1/"), S("p2"), S("p1/p2")}
|
||||
, {S("p1"), S("/p2"), S("/p2")}
|
||||
, {S("/p1"), S("p2"), S("/p1/p2")}
|
||||
};
|
||||
#undef S
|
||||
|
||||
|
||||
// The append operator may need to allocate a temporary buffer before a code_cvt
|
||||
// conversion. Test if this allocation occurs by:
|
||||
// 1. Create a path, `LHS`, and reserve enough space to append `RHS`.
|
||||
// This prevents `LHS` from allocating during the actual appending.
|
||||
// 2. Create a `Source` object `RHS`, which represents a "large" string.
|
||||
// (The string must not trigger the SSO)
|
||||
// 3. Append `RHS` to `LHS` and check for the expected allocation behavior.
|
||||
template <class CharT>
|
||||
void doAppendSourceAllocTest(AppendOperatorTestcase const& TC)
|
||||
{
|
||||
using namespace fs;
|
||||
using Ptr = CharT const*;
|
||||
using Str = std::basic_string<CharT>;
|
||||
using StrView = std::basic_string_view<CharT>;
|
||||
using InputIter = input_iterator<Ptr>;
|
||||
|
||||
const Ptr L = TC.lhs;
|
||||
Str RShort = (Ptr)TC.rhs;
|
||||
Str EShort = (Ptr)TC.expect;
|
||||
assert(RShort.size() >= 2);
|
||||
CharT c = RShort.back();
|
||||
RShort.append(100, c);
|
||||
EShort.append(100, c);
|
||||
const Ptr R = RShort.data();
|
||||
const Str& E = EShort;
|
||||
std::size_t ReserveSize = E.size() + 3;
|
||||
// basic_string
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
Str RHS(R);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
LHS /= RHS;
|
||||
}
|
||||
ASSERT_PRED(PathEq, LHS , E);
|
||||
}
|
||||
// basic_string_view
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
StrView RHS(R);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
LHS /= RHS;
|
||||
}
|
||||
assert(PathEq(LHS, E));
|
||||
}
|
||||
// CharT*
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
Ptr RHS(R);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
LHS /= RHS;
|
||||
}
|
||||
assert(PathEq(LHS, E));
|
||||
}
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
Ptr RHS(R);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
LHS.append(RHS, StrEnd(RHS));
|
||||
}
|
||||
assert(PathEq(LHS, E));
|
||||
}
|
||||
// input iterator - For non-native char types, appends needs to copy the
|
||||
// iterator range into a contiguous block of memory before it can perform the
|
||||
// code_cvt conversions.
|
||||
// For "char" no allocations will be performed because no conversion is
|
||||
// required.
|
||||
bool DisableAllocations = std::is_same<CharT, char>::value;
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
InputIter RHS(R);
|
||||
{
|
||||
RequireAllocationGuard g; // requires 1 or more allocations occur by default
|
||||
if (DisableAllocations) g.requireExactly(0);
|
||||
LHS /= RHS;
|
||||
}
|
||||
assert(PathEq(LHS, E));
|
||||
}
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
InputIter RHS(R);
|
||||
InputIter REnd(StrEnd(R));
|
||||
{
|
||||
RequireAllocationGuard g;
|
||||
if (DisableAllocations) g.requireExactly(0);
|
||||
LHS.append(RHS, REnd);
|
||||
}
|
||||
assert(PathEq(LHS, E));
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void doAppendSourceTest(AppendOperatorTestcase const& TC)
|
||||
{
|
||||
using namespace fs;
|
||||
using Ptr = CharT const*;
|
||||
using Str = std::basic_string<CharT>;
|
||||
using StrView = std::basic_string_view<CharT>;
|
||||
using InputIter = input_iterator<Ptr>;
|
||||
const Ptr L = TC.lhs;
|
||||
const Ptr R = TC.rhs;
|
||||
const Ptr E = TC.expect;
|
||||
// basic_string
|
||||
{
|
||||
path Result(L);
|
||||
Str RHS(R);
|
||||
path& Ref = (Result /= RHS);
|
||||
ASSERT_EQ(Result, E)
|
||||
<< DISPLAY(L) << DISPLAY(R);
|
||||
assert(&Ref == &Result);
|
||||
}
|
||||
{
|
||||
path LHS(L);
|
||||
Str RHS(R);
|
||||
path& Ref = LHS.append(RHS);
|
||||
assert(PathEq(LHS, E));
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
// basic_string_view
|
||||
{
|
||||
path LHS(L);
|
||||
StrView RHS(R);
|
||||
path& Ref = (LHS /= RHS);
|
||||
assert(PathEq(LHS, E));
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L);
|
||||
StrView RHS(R);
|
||||
path& Ref = LHS.append(RHS);
|
||||
assert(PathEq(LHS, E));
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
// Char*
|
||||
{
|
||||
path LHS(L);
|
||||
Str RHS(R);
|
||||
path& Ref = (LHS /= RHS);
|
||||
assert(PathEq(LHS, E));
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L);
|
||||
Ptr RHS(R);
|
||||
path& Ref = LHS.append(RHS);
|
||||
assert(PathEq(LHS, E));
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L);
|
||||
Ptr RHS(R);
|
||||
path& Ref = LHS.append(RHS, StrEnd(RHS));
|
||||
ASSERT_PRED(PathEq, LHS, E)
|
||||
<< DISPLAY(L) << DISPLAY(R);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
// iterators
|
||||
{
|
||||
path LHS(L);
|
||||
InputIter RHS(R);
|
||||
path& Ref = (LHS /= RHS);
|
||||
assert(PathEq(LHS, E));
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L); InputIter RHS(R);
|
||||
path& Ref = LHS.append(RHS);
|
||||
assert(PathEq(LHS, E));
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L);
|
||||
InputIter RHS(R);
|
||||
InputIter REnd(StrEnd(R));
|
||||
path& Ref = LHS.append(RHS, REnd);
|
||||
assert(PathEq(LHS, E));
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class It, class = decltype(fs::path{}.append(std::declval<It>()))>
|
||||
constexpr bool has_append(int) { return true; }
|
||||
template <class It>
|
||||
constexpr bool has_append(long) { return false; }
|
||||
|
||||
template <class It, class = decltype(fs::path{}.operator/=(std::declval<It>()))>
|
||||
constexpr bool has_append_op(int) { return true; }
|
||||
template <class It>
|
||||
constexpr bool has_append_op(long) { return false; }
|
||||
|
||||
template <class It>
|
||||
constexpr bool has_append() {
|
||||
static_assert(has_append<It>(0) == has_append_op<It>(0), "must be same");
|
||||
return has_append<It>(0) && has_append_op<It>(0);
|
||||
}
|
||||
|
||||
void test_sfinae()
|
||||
{
|
||||
using namespace fs;
|
||||
{
|
||||
using It = const char* const;
|
||||
static_assert(has_append<It>(), "");
|
||||
}
|
||||
{
|
||||
using It = input_iterator<const char*>;
|
||||
static_assert(has_append<It>(), "");
|
||||
}
|
||||
{
|
||||
struct Traits {
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using value_type = const char;
|
||||
using pointer = const char*;
|
||||
using reference = const char&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
};
|
||||
using It = input_iterator<const char*, Traits>;
|
||||
static_assert(has_append<It>(), "");
|
||||
}
|
||||
{
|
||||
using It = output_iterator<const char*>;
|
||||
static_assert(!has_append<It>(), "");
|
||||
|
||||
}
|
||||
{
|
||||
static_assert(!has_append<int*>(), "");
|
||||
}
|
||||
{
|
||||
static_assert(!has_append<char>(), "");
|
||||
static_assert(!has_append<const char>(), "");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
for (auto const & TC : Cases) {
|
||||
{
|
||||
const char* LHS_In = TC.lhs;
|
||||
const char* RHS_In = TC.rhs;
|
||||
path LHS(LHS_In);
|
||||
path RHS(RHS_In);
|
||||
path& Res = (LHS /= RHS);
|
||||
ASSERT_PRED(PathEq, Res, (const char*)TC.expect)
|
||||
<< DISPLAY(LHS_In) << DISPLAY(RHS_In);
|
||||
assert(&Res == &LHS);
|
||||
}
|
||||
doAppendSourceTest<char> (TC);
|
||||
doAppendSourceTest<wchar_t> (TC);
|
||||
doAppendSourceTest<char16_t>(TC);
|
||||
doAppendSourceTest<char32_t>(TC);
|
||||
}
|
||||
for (auto const & TC : LongLHSCases) {
|
||||
doAppendSourceAllocTest<char>(TC);
|
||||
doAppendSourceAllocTest<wchar_t>(TC);
|
||||
}
|
||||
test_sfinae();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path& operator=(path const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "count_new.hpp"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
path p("abc");
|
||||
p = {};
|
||||
assert(p.native() == "");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path& operator=(path const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
static_assert(std::is_copy_assignable<path>::value, "");
|
||||
static_assert(!std::is_nothrow_copy_assignable<path>::value, "should not be noexcept");
|
||||
const std::string s("foo");
|
||||
const path p(s);
|
||||
path p2;
|
||||
path& pref = (p2 = p);
|
||||
assert(p.native() == s);
|
||||
assert(p2.native() == s);
|
||||
assert(&pref == &p2);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path& operator=(path&&) noexcept
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "count_new.hpp"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
static_assert(std::is_nothrow_move_assignable<path>::value, "");
|
||||
assert(globalMemCounter.checkOutstandingNewEq(0));
|
||||
const std::string s("we really really really really really really really "
|
||||
"really really long string so that we allocate");
|
||||
assert(globalMemCounter.checkOutstandingNewEq(1));
|
||||
path p(s);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
path p2;
|
||||
path& pref = (p2 = std::move(p));
|
||||
assert(p2.native() == s);
|
||||
assert(p.native() != s); // Testing moved from state
|
||||
assert(&pref == &p2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// template <class Source>
|
||||
// path& operator=(Source const&);
|
||||
// path& operator=(string_type&&);
|
||||
// template <class Source>
|
||||
// path& assign(Source const&);
|
||||
// template <class InputIterator>
|
||||
// path& assign(InputIterator first, InputIterator last);
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <string_view>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include <iostream>
|
||||
|
||||
|
||||
template <class CharT>
|
||||
void RunTestCase(MultiStringType const& MS) {
|
||||
using namespace fs;
|
||||
const char* Expect = MS;
|
||||
const CharT* TestPath = MS;
|
||||
const CharT* TestPathEnd = StrEnd(TestPath);
|
||||
const std::size_t Size = TestPathEnd - TestPath;
|
||||
const std::size_t SSize = StrEnd(Expect) - Expect;
|
||||
assert(Size == SSize);
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// basic_string<Char, Traits, Alloc>
|
||||
{
|
||||
const std::basic_string<CharT> S(TestPath);
|
||||
path p; PathReserve(p, S.length() + 1);
|
||||
{
|
||||
// string provides a contiguous iterator. No allocation needed.
|
||||
DisableAllocationGuard g;
|
||||
path& pref = (p = S);
|
||||
assert(&pref == &p);
|
||||
}
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
assert(p.string<CharT>() == S);
|
||||
}
|
||||
{
|
||||
const std::basic_string<CharT> S(TestPath);
|
||||
path p; PathReserve(p, S.length() + 1);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
path& pref = p.assign(S);
|
||||
assert(&pref == &p);
|
||||
}
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
assert(p.string<CharT>() == S);
|
||||
}
|
||||
// basic_string<Char, Traits, Alloc>
|
||||
{
|
||||
const std::basic_string_view<CharT> S(TestPath);
|
||||
path p; PathReserve(p, S.length() + 1);
|
||||
{
|
||||
// string provides a contiguous iterator. No allocation needed.
|
||||
DisableAllocationGuard g;
|
||||
path& pref = (p = S);
|
||||
assert(&pref == &p);
|
||||
}
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
assert(p.string<CharT>() == S);
|
||||
}
|
||||
{
|
||||
const std::basic_string_view<CharT> S(TestPath);
|
||||
path p; PathReserve(p, S.length() + 1);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
path& pref = p.assign(S);
|
||||
assert(&pref == &p);
|
||||
}
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
assert(p.string<CharT>() == S);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Char* pointers
|
||||
{
|
||||
path p; PathReserve(p, Size + 1);
|
||||
{
|
||||
// char* pointers are contiguous and can be used with code_cvt directly.
|
||||
// no allocations needed.
|
||||
DisableAllocationGuard g;
|
||||
path& pref = (p = TestPath);
|
||||
assert(&pref == &p);
|
||||
}
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
}
|
||||
{
|
||||
path p; PathReserve(p, Size + 1);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
path& pref = p.assign(TestPath);
|
||||
assert(&pref == &p);
|
||||
}
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
}
|
||||
{
|
||||
path p; PathReserve(p, Size + 1);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
path& pref = p.assign(TestPath, TestPathEnd);
|
||||
assert(&pref == &p);
|
||||
}
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Iterators
|
||||
{
|
||||
using It = input_iterator<const CharT*>;
|
||||
path p; PathReserve(p, Size + 1);
|
||||
It it(TestPath);
|
||||
{
|
||||
// Iterators cannot be used with code_cvt directly. This assignment
|
||||
// may allocate if it's larger than a "short-string".
|
||||
path& pref = (p = it);
|
||||
assert(&pref == &p);
|
||||
}
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
}
|
||||
{
|
||||
using It = input_iterator<const CharT*>;
|
||||
path p; PathReserve(p, Size + 1);
|
||||
It it(TestPath);
|
||||
{
|
||||
path& pref = p.assign(it);
|
||||
assert(&pref == &p);
|
||||
}
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
}
|
||||
{
|
||||
using It = input_iterator<const CharT*>;
|
||||
path p; PathReserve(p, Size + 1);
|
||||
It it(TestPath);
|
||||
It e(TestPathEnd);
|
||||
{
|
||||
path& pref = p.assign(it, e);
|
||||
assert(&pref == &p);
|
||||
}
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
}
|
||||
}
|
||||
|
||||
template <class It, class = decltype(fs::path{}.assign(std::declval<It>()))>
|
||||
constexpr bool has_assign(int) { return true; }
|
||||
template <class It>
|
||||
constexpr bool has_assign(long) { return false; }
|
||||
template <class It>
|
||||
constexpr bool has_assign() { return has_assign<It>(0); }
|
||||
|
||||
void test_sfinae() {
|
||||
using namespace fs;
|
||||
{
|
||||
using It = const char* const;
|
||||
static_assert(std::is_assignable<path, It>::value, "");
|
||||
static_assert(has_assign<It>(), "");
|
||||
}
|
||||
{
|
||||
using It = input_iterator<const char*>;
|
||||
static_assert(std::is_assignable<path, It>::value, "");
|
||||
static_assert(has_assign<It>(), "");
|
||||
}
|
||||
{
|
||||
struct Traits {
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using value_type = const char;
|
||||
using pointer = const char*;
|
||||
using reference = const char&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
};
|
||||
using It = input_iterator<const char*, Traits>;
|
||||
static_assert(std::is_assignable<path, It>::value, "");
|
||||
static_assert(has_assign<It>(), "");
|
||||
}
|
||||
{
|
||||
using It = output_iterator<const char*>;
|
||||
static_assert(!std::is_assignable<path, It>::value, "");
|
||||
static_assert(!has_assign<It>(), "");
|
||||
|
||||
}
|
||||
{
|
||||
static_assert(!std::is_assignable<path, int*>::value, "");
|
||||
static_assert(!has_assign<int*>(), "");
|
||||
}
|
||||
}
|
||||
|
||||
void RunStringMoveTest(const char* Expect) {
|
||||
using namespace fs;
|
||||
std::string ss(Expect);
|
||||
path p;
|
||||
{
|
||||
DisableAllocationGuard g; ((void)g);
|
||||
path& pr = (p = std::move(ss));
|
||||
assert(&pr == &p);
|
||||
}
|
||||
assert(p == Expect);
|
||||
{
|
||||
// Signature test
|
||||
ASSERT_NOEXCEPT(p = std::move(ss));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
for (auto const& MS : PathList) {
|
||||
RunTestCase<char>(MS);
|
||||
RunTestCase<wchar_t>(MS);
|
||||
RunTestCase<char16_t>(MS);
|
||||
RunTestCase<char32_t>(MS);
|
||||
RunStringMoveTest(MS);
|
||||
}
|
||||
test_sfinae();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// int compare(path const&) const noexcept;
|
||||
// int compare(string_type const&) const;
|
||||
// int compare(value_type const*) const;
|
||||
//
|
||||
// bool operator==(path const&, path const&) noexcept;
|
||||
// bool operator!=(path const&, path const&) noexcept;
|
||||
// bool operator< (path const&, path const&) noexcept;
|
||||
// bool operator<=(path const&, path const&) noexcept;
|
||||
// bool operator> (path const&, path const&) noexcept;
|
||||
// bool operator>=(path const&, path const&) noexcept;
|
||||
//
|
||||
// size_t hash_value(path const&) noexcept;
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "verbose_assert.h"
|
||||
|
||||
struct PathCompareTest {
|
||||
const char* LHS;
|
||||
const char* RHS;
|
||||
int expect;
|
||||
};
|
||||
|
||||
#define LONGA "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
#define LONGB "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
|
||||
#define LONGC "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
|
||||
#define LONGD "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
|
||||
const PathCompareTest CompareTestCases[] =
|
||||
{
|
||||
{"", "", 0},
|
||||
{"a", "", 1},
|
||||
{"", "a", -1},
|
||||
{"a/b/c", "a/b/c", 0},
|
||||
{"b/a/c", "a/b/c", 1},
|
||||
{"a/b/c", "b/a/c", -1},
|
||||
{"a/b", "a/b/c", -1},
|
||||
{"a/b/c", "a/b", 1},
|
||||
{"a/b/", "a/b/.", -1},
|
||||
{"a/b/", "a/b", 1},
|
||||
{"a/b//////", "a/b/////.", -1},
|
||||
{"a/.././b", "a///..//.////b", 0},
|
||||
{"//foo//bar///baz////", "//foo/bar/baz/", 0}, // duplicate separators
|
||||
{"///foo/bar", "/foo/bar", 0}, // "///" is not a root directory
|
||||
{"/foo/bar/", "/foo/bar", 1}, // trailing separator
|
||||
{"foo", "/foo", -1}, // if !this->has_root_directory() and p.has_root_directory(), a value less than 0.
|
||||
{"/foo", "foo", 1}, // if this->has_root_directory() and !p.has_root_directory(), a value greater than 0.
|
||||
{"//" LONGA "////" LONGB "/" LONGC "///" LONGD, "//" LONGA "/" LONGB "/" LONGC "/" LONGD, 0},
|
||||
{ LONGA "/" LONGB "/" LONGC, LONGA "/" LONGB "/" LONGB, 1}
|
||||
|
||||
};
|
||||
#undef LONGA
|
||||
#undef LONGB
|
||||
#undef LONGC
|
||||
#undef LONGD
|
||||
|
||||
static inline int normalize_ret(int ret)
|
||||
{
|
||||
return ret < 0 ? -1 : (ret > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
void test_compare_basic()
|
||||
{
|
||||
using namespace fs;
|
||||
for (auto const & TC : CompareTestCases) {
|
||||
const path p1(TC.LHS);
|
||||
const path p2(TC.RHS);
|
||||
const std::string R(TC.RHS);
|
||||
const std::string_view RV(TC.RHS);
|
||||
const int E = TC.expect;
|
||||
{ // compare(...) functions
|
||||
DisableAllocationGuard g; // none of these operations should allocate
|
||||
|
||||
// check runtime results
|
||||
int ret1 = normalize_ret(p1.compare(p2));
|
||||
int ret2 = normalize_ret(p1.compare(R));
|
||||
int ret3 = normalize_ret(p1.compare(TC.RHS));
|
||||
int ret4 = normalize_ret(p1.compare(RV));
|
||||
|
||||
g.release();
|
||||
ASSERT_EQ(ret1, ret2);
|
||||
ASSERT_EQ(ret1, ret3);
|
||||
ASSERT_EQ(ret1, ret4);
|
||||
ASSERT_EQ(ret1, E)
|
||||
<< DISPLAY(TC.LHS) << DISPLAY(TC.RHS);
|
||||
|
||||
// check signatures
|
||||
ASSERT_NOEXCEPT(p1.compare(p2));
|
||||
}
|
||||
{ // comparison operators
|
||||
DisableAllocationGuard g; // none of these operations should allocate
|
||||
|
||||
// Check runtime result
|
||||
assert((p1 == p2) == (E == 0));
|
||||
assert((p1 != p2) == (E != 0));
|
||||
assert((p1 < p2) == (E < 0));
|
||||
assert((p1 <= p2) == (E <= 0));
|
||||
assert((p1 > p2) == (E > 0));
|
||||
assert((p1 >= p2) == (E >= 0));
|
||||
|
||||
// Check signatures
|
||||
ASSERT_NOEXCEPT(p1 == p2);
|
||||
ASSERT_NOEXCEPT(p1 != p2);
|
||||
ASSERT_NOEXCEPT(p1 < p2);
|
||||
ASSERT_NOEXCEPT(p1 <= p2);
|
||||
ASSERT_NOEXCEPT(p1 > p2);
|
||||
ASSERT_NOEXCEPT(p1 >= p2);
|
||||
}
|
||||
{ // check hash values
|
||||
auto h1 = hash_value(p1);
|
||||
auto h2 = hash_value(p2);
|
||||
assert((h1 == h2) == (p1 == p2));
|
||||
// check signature
|
||||
ASSERT_SAME_TYPE(size_t, decltype(hash_value(p1)));
|
||||
ASSERT_NOEXCEPT(hash_value(p1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CompareElements(std::vector<std::string> const& LHS, std::vector<std::string> const& RHS) {
|
||||
bool IsLess = std::lexicographical_compare(LHS.begin(), LHS.end(), RHS.begin(), RHS.end());
|
||||
if (IsLess)
|
||||
return -1;
|
||||
|
||||
bool IsGreater = std::lexicographical_compare(RHS.begin(), RHS.end(), LHS.begin(), LHS.end());
|
||||
if (IsGreater)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_compare_elements() {
|
||||
struct {
|
||||
std::vector<std::string> LHSElements;
|
||||
std::vector<std::string> RHSElements;
|
||||
int Expect;
|
||||
} TestCases[] = {
|
||||
{{"a"}, {"a"}, 0},
|
||||
{{"a"}, {"b"}, -1},
|
||||
{{"b"}, {"a"}, 1},
|
||||
{{"a", "b", "c"}, {"a", "b", "c"}, 0},
|
||||
{{"a", "b", "c"}, {"a", "b", "d"}, -1},
|
||||
{{"a", "b", "d"}, {"a", "b", "c"}, 1},
|
||||
{{"a", "b"}, {"a", "b", "c"}, -1},
|
||||
{{"a", "b", "c"}, {"a", "b"}, 1},
|
||||
|
||||
};
|
||||
|
||||
auto BuildPath = [](std::vector<std::string> const& Elems) {
|
||||
fs::path p;
|
||||
for (auto &E : Elems)
|
||||
p /= E;
|
||||
return p;
|
||||
};
|
||||
|
||||
for (auto &TC : TestCases) {
|
||||
fs::path LHS = BuildPath(TC.LHSElements);
|
||||
fs::path RHS = BuildPath(TC.RHSElements);
|
||||
const int ExpectCmp = CompareElements(TC.LHSElements, TC.RHSElements);
|
||||
assert(ExpectCmp == TC.Expect);
|
||||
const int GotCmp = normalize_ret(LHS.compare(RHS));
|
||||
assert(GotCmp == TC.Expect);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test_compare_basic();
|
||||
test_compare_elements();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,389 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path& operator+=(const path& x);
|
||||
// path& operator+=(const string_type& x);
|
||||
// path& operator+=(string_view x);
|
||||
// path& operator+=(const value_type* x);
|
||||
// path& operator+=(value_type x);
|
||||
// template <class Source>
|
||||
// path& operator+=(const Source& x);
|
||||
// template <class EcharT>
|
||||
// path& operator+=(EcharT x);
|
||||
// template <class Source>
|
||||
// path& concat(const Source& x);
|
||||
// template <class InputIterator>
|
||||
// path& concat(InputIterator first, InputIterator last);
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
struct ConcatOperatorTestcase {
|
||||
MultiStringType lhs;
|
||||
MultiStringType rhs;
|
||||
MultiStringType expect;
|
||||
};
|
||||
|
||||
#define LONGSTR "LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR_LONGSTR"
|
||||
#define S(Str) MKSTR(Str)
|
||||
const ConcatOperatorTestcase Cases[] =
|
||||
{
|
||||
{S(""), S(""), S("")}
|
||||
, {S("p1"), S("p2"), S("p1p2")}
|
||||
, {S("p1/"), S("/p2"), S("p1//p2")}
|
||||
, {S(""), S("\\foo/bar/baz"), S("\\foo/bar/baz")}
|
||||
, {S("c:\\foo"), S(""), S("c:\\foo")}
|
||||
, {S(LONGSTR), S("foo"), S(LONGSTR "foo")}
|
||||
, {S("abcdefghijklmnopqrstuvwxyz/\\"), S("/\\123456789"), S("abcdefghijklmnopqrstuvwxyz/\\/\\123456789")}
|
||||
};
|
||||
const ConcatOperatorTestcase LongLHSCases[] =
|
||||
{
|
||||
{S(""), S(LONGSTR), S(LONGSTR)}
|
||||
, {S("p1/"), S(LONGSTR), S("p1/" LONGSTR)}
|
||||
};
|
||||
const ConcatOperatorTestcase CharTestCases[] =
|
||||
{
|
||||
{S(""), S("P"), S("P")}
|
||||
, {S("/fooba"), S("r"), S("/foobar")}
|
||||
};
|
||||
#undef S
|
||||
#undef LONGSTR
|
||||
|
||||
// The concat operator may need to allocate a temporary buffer before a code_cvt
|
||||
// conversion. Test if this allocation occurs by:
|
||||
// 1. Create a path, `LHS`, and reserve enough space to append `RHS`.
|
||||
// This prevents `LHS` from allocating during the actual appending.
|
||||
// 2. Create a `Source` object `RHS`, which represents a "large" string.
|
||||
// (The string must not trigger the SSO)
|
||||
// 3. Concat `RHS` to `LHS` and check for the expected allocation behavior.
|
||||
template <class CharT>
|
||||
void doConcatSourceAllocTest(ConcatOperatorTestcase const& TC)
|
||||
{
|
||||
using namespace fs;
|
||||
using Ptr = CharT const*;
|
||||
using Str = std::basic_string<CharT>;
|
||||
using StrView = std::basic_string_view<CharT>;
|
||||
using InputIter = input_iterator<Ptr>;
|
||||
|
||||
const Ptr L = TC.lhs;
|
||||
const Ptr R = TC.rhs;
|
||||
const Ptr E = TC.expect;
|
||||
std::size_t ReserveSize = StrLen(E) + 1;
|
||||
// basic_string
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
Str RHS(R);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
LHS += RHS;
|
||||
}
|
||||
assert(LHS == E);
|
||||
}
|
||||
// basic_string_view
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
StrView RHS(R);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
LHS += RHS;
|
||||
}
|
||||
assert(LHS == E);
|
||||
}
|
||||
// CharT*
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
Ptr RHS(R);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
LHS += RHS;
|
||||
}
|
||||
assert(LHS == E);
|
||||
}
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
Ptr RHS(R);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
LHS.concat(RHS, StrEnd(RHS));
|
||||
}
|
||||
assert(LHS == E);
|
||||
}
|
||||
// input iterator - For non-native char types, appends needs to copy the
|
||||
// iterator range into a contiguous block of memory before it can perform the
|
||||
// code_cvt conversions.
|
||||
// For "char" no allocations will be performed because no conversion is
|
||||
// required.
|
||||
bool DisableAllocations = std::is_same<CharT, char>::value;
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
InputIter RHS(R);
|
||||
{
|
||||
RequireAllocationGuard g; // requires 1 or more allocations occur by default
|
||||
if (DisableAllocations) g.requireExactly(0);
|
||||
LHS += RHS;
|
||||
}
|
||||
assert(LHS == E);
|
||||
}
|
||||
{
|
||||
path LHS(L); PathReserve(LHS, ReserveSize);
|
||||
InputIter RHS(R);
|
||||
InputIter REnd(StrEnd(R));
|
||||
{
|
||||
RequireAllocationGuard g;
|
||||
if (DisableAllocations) g.requireExactly(0);
|
||||
LHS.concat(RHS, REnd);
|
||||
}
|
||||
assert(LHS == E);
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void doConcatSourceTest(ConcatOperatorTestcase const& TC)
|
||||
{
|
||||
using namespace fs;
|
||||
using Ptr = CharT const*;
|
||||
using Str = std::basic_string<CharT>;
|
||||
using StrView = std::basic_string_view<CharT>;
|
||||
using InputIter = input_iterator<Ptr>;
|
||||
const Ptr L = TC.lhs;
|
||||
const Ptr R = TC.rhs;
|
||||
const Ptr E = TC.expect;
|
||||
// basic_string
|
||||
{
|
||||
path LHS(L);
|
||||
Str RHS(R);
|
||||
path& Ref = (LHS += RHS);
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L);
|
||||
Str RHS(R);
|
||||
path& Ref = LHS.concat(RHS);
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
// basic_string_view
|
||||
{
|
||||
path LHS(L);
|
||||
StrView RHS(R);
|
||||
path& Ref = (LHS += RHS);
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L);
|
||||
StrView RHS(R);
|
||||
path& Ref = LHS.concat(RHS);
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
// Char*
|
||||
{
|
||||
path LHS(L);
|
||||
Str RHS(R);
|
||||
path& Ref = (LHS += RHS);
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L);
|
||||
Ptr RHS(R);
|
||||
path& Ref = LHS.concat(RHS);
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L);
|
||||
Ptr RHS(R);
|
||||
path& Ref = LHS.concat(RHS, StrEnd(RHS));
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
// iterators
|
||||
{
|
||||
path LHS(L);
|
||||
InputIter RHS(R);
|
||||
path& Ref = (LHS += RHS);
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L); InputIter RHS(R);
|
||||
path& Ref = LHS.concat(RHS);
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS(L);
|
||||
InputIter RHS(R);
|
||||
InputIter REnd(StrEnd(R));
|
||||
path& Ref = LHS.concat(RHS, REnd);
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void doConcatECharTest(ConcatOperatorTestcase const& TC)
|
||||
{
|
||||
using namespace fs;
|
||||
using Ptr = CharT const*;
|
||||
const Ptr RStr = TC.rhs;
|
||||
assert(StrLen(RStr) == 1);
|
||||
const Ptr L = TC.lhs;
|
||||
const CharT R = RStr[0];
|
||||
const Ptr E = TC.expect;
|
||||
{
|
||||
path LHS(L);
|
||||
path& Ref = (LHS += R);
|
||||
assert(LHS == E);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class It, class = decltype(fs::path{}.concat(std::declval<It>()))>
|
||||
constexpr bool has_concat(int) { return true; }
|
||||
template <class It>
|
||||
constexpr bool has_concat(long) { return false; }
|
||||
|
||||
template <class It, class = decltype(fs::path{}.operator+=(std::declval<It>()))>
|
||||
constexpr bool has_concat_op(int) { return true; }
|
||||
template <class It>
|
||||
constexpr bool has_concat_op(long) { return false; }
|
||||
template <class It>
|
||||
constexpr bool has_concat_op() { return has_concat_op<It>(0); }
|
||||
|
||||
template <class It>
|
||||
constexpr bool has_concat() {
|
||||
static_assert(has_concat<It>(0) == has_concat_op<It>(0), "must be same");
|
||||
return has_concat<It>(0) && has_concat_op<It>(0);
|
||||
}
|
||||
|
||||
void test_sfinae() {
|
||||
using namespace fs;
|
||||
{
|
||||
static_assert(has_concat_op<char>(), "");
|
||||
static_assert(has_concat_op<const char>(), "");
|
||||
static_assert(has_concat_op<char16_t>(), "");
|
||||
static_assert(has_concat_op<const char16_t>(), "");
|
||||
}
|
||||
{
|
||||
using It = const char* const;
|
||||
static_assert(has_concat<It>(), "");
|
||||
}
|
||||
{
|
||||
using It = input_iterator<const char*>;
|
||||
static_assert(has_concat<It>(), "");
|
||||
}
|
||||
{
|
||||
struct Traits {
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using value_type = const char;
|
||||
using pointer = const char*;
|
||||
using reference = const char&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
};
|
||||
using It = input_iterator<const char*, Traits>;
|
||||
static_assert(has_concat<It>(), "");
|
||||
}
|
||||
{
|
||||
using It = output_iterator<const char*>;
|
||||
static_assert(!has_concat<It>(), "");
|
||||
}
|
||||
{
|
||||
static_assert(!has_concat<int>(0), "");
|
||||
// operator+=(int) is well formed since it converts to operator+=(value_type)
|
||||
// but concat(int) isn't valid because there is no concat(value_type).
|
||||
// This should probably be addressed by a LWG issue.
|
||||
static_assert(has_concat_op<int>(), "");
|
||||
}
|
||||
{
|
||||
static_assert(!has_concat<int*>(), "");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
for (auto const & TC : Cases) {
|
||||
{
|
||||
path LHS((const char*)TC.lhs);
|
||||
path RHS((const char*)TC.rhs);
|
||||
path& Ref = (LHS += RHS);
|
||||
assert(LHS == (const char*)TC.expect);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
{
|
||||
path LHS((const char*)TC.lhs);
|
||||
std::string_view RHS((const char*)TC.rhs);
|
||||
path& Ref = (LHS += RHS);
|
||||
assert(LHS == (const char*)TC.expect);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
doConcatSourceTest<char> (TC);
|
||||
doConcatSourceTest<wchar_t> (TC);
|
||||
doConcatSourceTest<char16_t>(TC);
|
||||
doConcatSourceTest<char32_t>(TC);
|
||||
}
|
||||
for (auto const & TC : LongLHSCases) {
|
||||
// Do path test
|
||||
{
|
||||
path LHS((const char*)TC.lhs);
|
||||
path RHS((const char*)TC.rhs);
|
||||
const char* E = TC.expect;
|
||||
PathReserve(LHS, StrLen(E) + 5);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
path& Ref = (LHS += RHS);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
assert(LHS == E);
|
||||
}
|
||||
{
|
||||
path LHS((const char*)TC.lhs);
|
||||
std::string_view RHS((const char*)TC.rhs);
|
||||
const char* E = TC.expect;
|
||||
PathReserve(LHS, StrLen(E) + 5);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
path& Ref = (LHS += RHS);
|
||||
assert(&Ref == &LHS);
|
||||
}
|
||||
assert(LHS == E);
|
||||
}
|
||||
doConcatSourceAllocTest<char>(TC);
|
||||
doConcatSourceAllocTest<wchar_t>(TC);
|
||||
}
|
||||
for (auto const& TC : CharTestCases) {
|
||||
doConcatECharTest<char>(TC);
|
||||
doConcatECharTest<wchar_t>(TC);
|
||||
doConcatECharTest<char16_t>(TC);
|
||||
doConcatECharTest<char32_t>(TC);
|
||||
}
|
||||
test_sfinae();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path(path const&)
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
static_assert(std::is_copy_constructible<path>::value, "");
|
||||
static_assert(!std::is_nothrow_copy_constructible<path>::value, "should not be noexcept");
|
||||
const std::string s("foo");
|
||||
const path p(s);
|
||||
path p2(p);
|
||||
assert(p.native() == s);
|
||||
assert(p2.native() == s);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path() noexcept
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
static_assert(std::is_nothrow_default_constructible<path>::value, "");
|
||||
const path p;
|
||||
assert(p.empty());
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path(path&&) noexcept
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "count_new.hpp"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
static_assert(std::is_nothrow_move_constructible<path>::value, "");
|
||||
assert(globalMemCounter.checkOutstandingNewEq(0));
|
||||
const std::string s("we really really really really really really really "
|
||||
"really really long string so that we allocate");
|
||||
assert(globalMemCounter.checkOutstandingNewEq(1));
|
||||
path p(s);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
path p2(std::move(p));
|
||||
assert(p2.native() == s);
|
||||
assert(p.native() != s); // Testing moved from state
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// template <class Source>
|
||||
// path(const Source& source);
|
||||
// template <class InputIterator>
|
||||
// path(InputIterator first, InputIterator last);
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "min_allocator.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
template <class CharT, class ...Args>
|
||||
void RunTestCaseImpl(MultiStringType const& MS, Args... args) {
|
||||
using namespace fs;
|
||||
const char* Expect = MS;
|
||||
const CharT* TestPath = MS;
|
||||
const CharT* TestPathEnd = StrEnd(TestPath);
|
||||
const std::size_t Size = TestPathEnd - TestPath;
|
||||
const std::size_t SSize = StrEnd(Expect) - Expect;
|
||||
assert(Size == SSize);
|
||||
// StringTypes
|
||||
{
|
||||
const std::basic_string<CharT> S(TestPath);
|
||||
path p(S, args...);
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
assert(p.string<CharT>() == S);
|
||||
}
|
||||
{
|
||||
const std::basic_string_view<CharT> S(TestPath);
|
||||
path p(S, args...);
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
assert(p.string<CharT>() == S);
|
||||
}
|
||||
// Char* pointers
|
||||
{
|
||||
path p(TestPath, args...);
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
}
|
||||
{
|
||||
path p(TestPath, TestPathEnd, args...);
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
}
|
||||
// Iterators
|
||||
{
|
||||
using It = input_iterator<const CharT*>;
|
||||
path p(It{TestPath}, args...);
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
}
|
||||
{
|
||||
using It = input_iterator<const CharT*>;
|
||||
path p(It{TestPath}, It{TestPathEnd}, args...);
|
||||
assert(p.native() == Expect);
|
||||
assert(p.string<CharT>() == TestPath);
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT, class ...Args>
|
||||
void RunTestCase(MultiStringType const& MS) {
|
||||
RunTestCaseImpl<CharT>(MS);
|
||||
RunTestCaseImpl<CharT>(MS, fs::path::format::auto_format);
|
||||
RunTestCaseImpl<CharT>(MS, fs::path::format::native_format);
|
||||
RunTestCaseImpl<CharT>(MS, fs::path::format::generic_format);
|
||||
}
|
||||
|
||||
void test_sfinae() {
|
||||
using namespace fs;
|
||||
{
|
||||
using It = const char* const;
|
||||
static_assert(std::is_constructible<path, It>::value, "");
|
||||
}
|
||||
{
|
||||
using It = input_iterator<const char*>;
|
||||
static_assert(std::is_constructible<path, It>::value, "");
|
||||
}
|
||||
{
|
||||
struct Traits {
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using value_type = const char;
|
||||
using pointer = const char*;
|
||||
using reference = const char&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
};
|
||||
using It = input_iterator<const char*, Traits>;
|
||||
static_assert(std::is_constructible<path, It>::value, "");
|
||||
}
|
||||
{
|
||||
using It = output_iterator<const char*>;
|
||||
static_assert(!std::is_constructible<path, It>::value, "");
|
||||
|
||||
}
|
||||
{
|
||||
static_assert(!std::is_constructible<path, int*>::value, "");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
for (auto const& MS : PathList) {
|
||||
RunTestCase<char>(MS);
|
||||
RunTestCase<wchar_t>(MS);
|
||||
RunTestCase<char16_t>(MS);
|
||||
RunTestCase<char32_t>(MS);
|
||||
}
|
||||
test_sfinae();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// bool empty() const noexcept;
|
||||
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
|
||||
// UNSUPPORTED: clang-3.3, clang-3.4, clang-3.5, clang-3.6, clang-3.7, clang-3.8
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
fs::path c;
|
||||
c.empty(); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// 8.4.9 path decomposition [path.decompose]
|
||||
//------------------------------------------
|
||||
// path root_name() const;
|
||||
// path root_directory() const;
|
||||
// path root_path() const;
|
||||
// path relative_path() const;
|
||||
// path parent_path() const;
|
||||
// path filename() const;
|
||||
// path stem() const;
|
||||
// path extension() const;
|
||||
//-------------------------------
|
||||
// 8.4.10 path query [path.query]
|
||||
//-------------------------------
|
||||
// bool empty() const noexcept;
|
||||
// bool has_root_path() const;
|
||||
// bool has_root_name() const;
|
||||
// bool has_root_directory() const;
|
||||
// bool has_relative_path() const;
|
||||
// bool has_parent_path() const;
|
||||
// bool has_filename() const;
|
||||
// bool has_stem() const;
|
||||
// bool has_extension() const;
|
||||
// bool is_absolute() const;
|
||||
// bool is_relative() const;
|
||||
//-------------------------------
|
||||
// 8.5 path iterators [path.itr]
|
||||
//-------------------------------
|
||||
// iterator begin() const;
|
||||
// iterator end() const;
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "assert_checkpoint.h"
|
||||
#include "verbose_assert.h"
|
||||
|
||||
struct ComparePathExact {
|
||||
bool operator()(std::string const& LHS, std::string const& RHS) const {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
struct PathDecomposeTestcase
|
||||
{
|
||||
std::string raw;
|
||||
std::vector<std::string> elements;
|
||||
std::string root_path;
|
||||
std::string root_name;
|
||||
std::string root_directory;
|
||||
std::string relative_path;
|
||||
std::string parent_path;
|
||||
std::string filename;
|
||||
};
|
||||
|
||||
const PathDecomposeTestcase PathTestCases[] =
|
||||
{
|
||||
{"", {}, "", "", "", "", "", ""}
|
||||
, {".", {"."}, "", "", "", ".", "", "."}
|
||||
, {"..", {".."}, "", "", "", "..", "", ".."}
|
||||
, {"foo", {"foo"}, "", "", "", "foo", "", "foo"}
|
||||
, {"/", {"/"}, "/", "", "/", "", "/", ""}
|
||||
, {"/foo", {"/", "foo"}, "/", "", "/", "foo", "/", "foo"}
|
||||
, {"foo/", {"foo", ""}, "", "", "", "foo/", "foo", ""}
|
||||
, {"/foo/", {"/", "foo", ""}, "/", "", "/", "foo/", "/foo", ""}
|
||||
, {"foo/bar", {"foo","bar"}, "", "", "", "foo/bar", "foo", "bar"}
|
||||
, {"/foo//bar", {"/","foo","bar"}, "/", "", "/", "foo/bar", "/foo", "bar"}
|
||||
, {"//net", {"/", "net"}, "/", "", "/", "net", "/", "net"}
|
||||
, {"//net/foo", {"/", "net", "foo"}, "/", "", "/", "net/foo", "/net", "foo"}
|
||||
, {"///foo///", {"/", "foo", ""}, "/", "", "/", "foo///", "///foo", ""}
|
||||
, {"///foo///bar", {"/", "foo", "bar"}, "/", "", "/", "foo///bar", "///foo", "bar"}
|
||||
, {"/.", {"/", "."}, "/", "", "/", ".", "/", "."}
|
||||
, {"./", {".", ""}, "", "", "", "./", ".", ""}
|
||||
, {"/..", {"/", ".."}, "/", "", "/", "..", "/", ".."}
|
||||
, {"../", {"..", ""}, "", "", "", "../", "..", ""}
|
||||
, {"foo/.", {"foo", "."}, "", "", "", "foo/.", "foo", "."}
|
||||
, {"foo/..", {"foo", ".."}, "", "", "", "foo/..", "foo", ".."}
|
||||
, {"foo/./", {"foo", ".", ""}, "", "", "", "foo/./", "foo/.", ""}
|
||||
, {"foo/./bar", {"foo", ".", "bar"}, "", "", "", "foo/./bar", "foo/.", "bar"}
|
||||
, {"foo/../", {"foo", "..", ""}, "", "", "", "foo/../", "foo/..", ""}
|
||||
, {"foo/../bar", {"foo", "..", "bar"}, "", "", "", "foo/../bar", "foo/..", "bar"}
|
||||
, {"c:", {"c:"}, "", "", "", "c:", "", "c:"}
|
||||
, {"c:/", {"c:", ""}, "", "", "", "c:/", "c:", ""}
|
||||
, {"c:foo", {"c:foo"}, "", "", "", "c:foo", "", "c:foo"}
|
||||
, {"c:/foo", {"c:", "foo"}, "", "", "", "c:/foo", "c:", "foo"}
|
||||
, {"c:foo/", {"c:foo", ""}, "", "", "", "c:foo/", "c:foo", ""}
|
||||
, {"c:/foo/", {"c:", "foo", ""}, "", "", "", "c:/foo/", "c:/foo", ""}
|
||||
, {"c:/foo/bar", {"c:", "foo", "bar"}, "", "", "", "c:/foo/bar", "c:/foo", "bar"}
|
||||
, {"prn:", {"prn:"}, "", "", "", "prn:", "", "prn:"}
|
||||
, {"c:\\", {"c:\\"}, "", "", "", "c:\\", "", "c:\\"}
|
||||
, {"c:\\foo", {"c:\\foo"}, "", "", "", "c:\\foo", "", "c:\\foo"}
|
||||
, {"c:foo\\", {"c:foo\\"}, "", "", "", "c:foo\\", "", "c:foo\\"}
|
||||
, {"c:\\foo\\", {"c:\\foo\\"}, "", "", "", "c:\\foo\\", "", "c:\\foo\\"}
|
||||
, {"c:\\foo/", {"c:\\foo", ""}, "", "", "", "c:\\foo/", "c:\\foo", ""}
|
||||
, {"c:/foo\\bar", {"c:", "foo\\bar"}, "", "", "", "c:/foo\\bar", "c:", "foo\\bar"}
|
||||
, {"//", {"/"}, "/", "", "/", "", "/", ""}
|
||||
};
|
||||
|
||||
void decompPathTest()
|
||||
{
|
||||
using namespace fs;
|
||||
for (auto const & TC : PathTestCases) {
|
||||
CHECKPOINT(TC.raw.c_str());
|
||||
fs::path p(TC.raw);
|
||||
ASSERT(p == TC.raw);
|
||||
|
||||
ASSERT_EQ(p.root_path(), TC.root_path);
|
||||
ASSERT_NEQ(p.has_root_path(), TC.root_path.empty());
|
||||
|
||||
ASSERT(p.root_name().native().empty())
|
||||
<< DISPLAY(p.root_name());
|
||||
ASSERT_EQ(p.root_name(),TC.root_name);
|
||||
ASSERT_NEQ(p.has_root_name(), TC.root_name.empty());
|
||||
|
||||
ASSERT_EQ(p.root_directory(), TC.root_directory);
|
||||
ASSERT_NEQ(p.has_root_directory(), TC.root_directory.empty());
|
||||
|
||||
ASSERT_EQ(p.relative_path(), TC.relative_path);
|
||||
ASSERT_NEQ(p.has_relative_path(), TC.relative_path.empty());
|
||||
|
||||
ASSERT_EQ(p.parent_path(), TC.parent_path);
|
||||
ASSERT_NEQ(p.has_parent_path(), TC.parent_path.empty());
|
||||
|
||||
ASSERT_EQ(p.filename(), TC.filename);
|
||||
ASSERT_NEQ(p.has_filename(), TC.filename.empty());
|
||||
|
||||
ASSERT_EQ(p.is_absolute(), p.has_root_directory());
|
||||
ASSERT_NEQ(p.is_relative(), p.is_absolute());
|
||||
if (p.empty())
|
||||
ASSERT(p.is_relative());
|
||||
|
||||
ASSERT_COLLECTION_EQ_COMP(
|
||||
p.begin(), p.end(),
|
||||
TC.elements.begin(), TC.elements.end(),
|
||||
ComparePathExact()
|
||||
);
|
||||
// check backwards
|
||||
|
||||
std::vector<fs::path> Parts;
|
||||
for (auto it = p.end(); it != p.begin(); )
|
||||
Parts.push_back(*--it);
|
||||
ASSERT_COLLECTION_EQ_COMP(Parts.begin(), Parts.end(),
|
||||
TC.elements.rbegin(), TC.elements.rend(),
|
||||
ComparePathExact());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct FilenameDecompTestcase
|
||||
{
|
||||
std::string raw;
|
||||
std::string filename;
|
||||
std::string stem;
|
||||
std::string extension;
|
||||
};
|
||||
|
||||
const FilenameDecompTestcase FilenameTestCases[] =
|
||||
{
|
||||
{"", "", "", ""}
|
||||
, {".", ".", ".", ""}
|
||||
, {"..", "..", "..", ""}
|
||||
, {"/", "", "", ""}
|
||||
, {"foo", "foo", "foo", ""}
|
||||
, {"/foo/bar.txt", "bar.txt", "bar", ".txt"}
|
||||
, {"foo..txt", "foo..txt", "foo.", ".txt"}
|
||||
, {".profile", ".profile", ".profile", ""}
|
||||
, {".profile.txt", ".profile.txt", ".profile", ".txt"}
|
||||
};
|
||||
|
||||
|
||||
void decompFilenameTest()
|
||||
{
|
||||
using namespace fs;
|
||||
for (auto const & TC : FilenameTestCases) {
|
||||
CHECKPOINT(TC.raw.c_str());
|
||||
fs::path p(TC.raw);
|
||||
ASSERT_EQ(p, TC.raw);
|
||||
ASSERT_NOEXCEPT(p.empty());
|
||||
|
||||
ASSERT_EQ(p.filename(), TC.filename);
|
||||
ASSERT_NEQ(p.has_filename(), TC.filename.empty());
|
||||
|
||||
ASSERT_EQ(p.stem(), TC.stem);
|
||||
ASSERT_NEQ(p.has_stem(), TC.stem.empty());
|
||||
|
||||
ASSERT_EQ(p.extension(), TC.extension);
|
||||
ASSERT_NEQ(p.has_extension(), TC.extension.empty());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
decompPathTest();
|
||||
decompFilenameTest();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path lexically_normal() const;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
// clang-format off
|
||||
struct {
|
||||
std::string input;
|
||||
std::string expect;
|
||||
} TestCases[] = {
|
||||
{"", ""},
|
||||
{"/a/b/c", "/a/b/c"},
|
||||
{"/a/b//c", "/a/b/c"},
|
||||
{"foo/./bar/..", "foo/"},
|
||||
{"foo/.///bar/../", "foo/"},
|
||||
{"/a/b/", "/a/b/"},
|
||||
{"a/b", "a/b"},
|
||||
{"a/b/.", "a/b/"},
|
||||
{"a/b/./", "a/b/"},
|
||||
{"a/..", "."},
|
||||
{".", "."},
|
||||
{"./", "."},
|
||||
{"./.", "."},
|
||||
{"./..", ".."},
|
||||
{"..", ".."},
|
||||
{"../..", "../.."},
|
||||
{"/../", "/"},
|
||||
{"/../..", "/"},
|
||||
{"/../../", "/"},
|
||||
{"..", ".."},
|
||||
{"../", ".."},
|
||||
{"/a/b/c/../", "/a/b/"},
|
||||
{"/a/b/./", "/a/b/"},
|
||||
{"/a/b/c/../d", "/a/b/d"},
|
||||
{"/a/b/c/../d/", "/a/b/d/"},
|
||||
{"//a/", "/a/"},
|
||||
{"//a/b/", "/a/b/"},
|
||||
{"//a/b/.", "/a/b/"},
|
||||
{"//a/..", "/"},
|
||||
///===---------------------------------------------------------------===//
|
||||
/// Tests specifically for the clauses under [fs.path.generic]p6
|
||||
///===---------------------------------------------------------------===//
|
||||
// p1: If the path is empty, stop.
|
||||
{"", ""},
|
||||
// p2: Replace each slash character in the root-name with a preferred
|
||||
// separator.
|
||||
{"NO_ROOT_NAME_ON_LINUX", "NO_ROOT_NAME_ON_LINUX"},
|
||||
// p3: Replace each directory-separator with a preferred-separator.
|
||||
// [ Note: The generic pathname grammar ([fs.path.generic]) defines
|
||||
// directory-separator as one or more slashes and preferred-separators.
|
||||
// — end note ]
|
||||
{"/", "/"},
|
||||
{"//", "/"},
|
||||
{"///", "/"},
|
||||
{"a/b", "a/b"},
|
||||
{"a//b", "a/b"},
|
||||
{"a///b", "a/b"},
|
||||
{"a/b/", "a/b/"},
|
||||
{"a/b//", "a/b/"},
|
||||
{"a/b///", "a/b/"},
|
||||
{"///a////b//////", "/a/b/"},
|
||||
// p4: Remove each dot filename and any immediately following directory
|
||||
// separators
|
||||
{"foo/.", "foo/"},
|
||||
{"foo/./bar/.", "foo/bar/"},
|
||||
{"./foo/././bar/./", "foo/bar/"},
|
||||
{".///foo//.////./bar/.///", "foo/bar/"},
|
||||
// p5: As long as any appear, remove a non-dot-dot filename immediately
|
||||
// followed by a directory-separator and a dot-dot filename, along with
|
||||
// any immediately following directory separator.
|
||||
{"foo/..", "."},
|
||||
{"foo/../", "."},
|
||||
{"foo/bar/..", "foo/"},
|
||||
{"foo/bar/../", "foo/"},
|
||||
{"foo/bar/../..", "."},
|
||||
{"foo/bar/../../", "."},
|
||||
{"foo/bar/baz/../..", "foo/"},
|
||||
{"foo/bar/baz/../../", "foo/"},
|
||||
{"foo/bar/./..", "foo/"},
|
||||
{"foo/bar/./../", "foo/"},
|
||||
// p6: If there is a root-directory, remove all dot-dot filenames and any
|
||||
// directory-separators immediately following them. [ Note: These dot-dot
|
||||
// filenames attempt to refer to nonexistent parent directories. — end note ]
|
||||
{"/..", "/"},
|
||||
{"/../", "/"},
|
||||
{"/foo/../..", "/"},
|
||||
{"/../foo", "/foo"},
|
||||
{"/../foo/../..", "/"},
|
||||
// p7: If the last filename is dot-dot, remove any trailing
|
||||
// directory-separator.
|
||||
{"../", ".."},
|
||||
{"../../", "../.."},
|
||||
{"foo/../bar/../..///", ".."},
|
||||
{"foo/../bar/..//..///../", "../.."},
|
||||
// p8: If the path is empty, add a dot
|
||||
{".", "."},
|
||||
{"./", "."},
|
||||
{"foo/..", "."}
|
||||
};
|
||||
// clang-format on
|
||||
int ID = 0;
|
||||
bool Failed = false;
|
||||
for (auto& TC : TestCases) {
|
||||
++ID;
|
||||
fs::path p(TC.input);
|
||||
const fs::path output = p.lexically_normal();
|
||||
if (!PathEq(output, TC.expect)) {
|
||||
Failed = true;
|
||||
std::cerr << "TEST CASE #" << ID << " FAILED: \n";
|
||||
std::cerr << " Input: '" << TC.input << "'\n";
|
||||
std::cerr << " Expected: '" << TC.expect << "'\n";
|
||||
std::cerr << " Output: '" << output.native() << "'";
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
}
|
||||
return Failed;
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path lexically_relative(const path& p) const;
|
||||
// path lexically_proximate(const path& p) const;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
// clang-format off
|
||||
struct {
|
||||
std::string input;
|
||||
std::string base;
|
||||
std::string expect;
|
||||
} TestCases[] = {
|
||||
{"", "", "."},
|
||||
{"/", "a", ""},
|
||||
{"a", "/", ""},
|
||||
{"//net", "a", ""},
|
||||
{"a", "//net", ""},
|
||||
{"//net/", "//net", "."},
|
||||
{"//net", "//net/", "."},
|
||||
{"//base", "a", ""},
|
||||
{"a", "a", "."},
|
||||
{"a/b", "a/b", "."},
|
||||
{"a/b/c/", "a/b/c/", "."},
|
||||
{"//net", "//net", "."},
|
||||
{"//net/", "//net/", "."},
|
||||
{"//net/a/b", "//net/a/b", "."},
|
||||
{"/a/d", "/a/b/c", "../../d"},
|
||||
{"/a/b/c", "/a/d", "../b/c"},
|
||||
{"a/b/c", "a", "b/c"},
|
||||
{"a/b/c", "a/b/c/x/y", "../.."},
|
||||
{"a/b/c", "a/b/c", "."},
|
||||
{"a/b", "c/d", "../../a/b"}
|
||||
};
|
||||
// clang-format on
|
||||
int ID = 0;
|
||||
bool Failed = false;
|
||||
for (auto& TC : TestCases) {
|
||||
++ID;
|
||||
const fs::path p(TC.input);
|
||||
const fs::path output = p.lexically_relative(TC.base);
|
||||
auto ReportErr = [&](const char* Testing, fs::path const& Output,
|
||||
fs::path const& Expected) {
|
||||
Failed = true;
|
||||
std::cerr << "TEST CASE #" << ID << " FAILED: \n";
|
||||
std::cerr << " Testing: " << Testing << "\n";
|
||||
std::cerr << " Input: '" << TC.input << "'\n";
|
||||
std::cerr << " Base: '" << TC.base << "'\n";
|
||||
std::cerr << " Expected: '" << Expected << "'\n";
|
||||
std::cerr << " Output: '" << Output.native() << "'";
|
||||
std::cerr << std::endl;
|
||||
};
|
||||
if (!PathEq(output, TC.expect))
|
||||
ReportErr("path::lexically_relative", output, TC.expect);
|
||||
const fs::path proximate_output = p.lexically_proximate(TC.base);
|
||||
// [path.gen] lexically_proximate
|
||||
// Returns: If the value of lexically_relative(base) is not an empty path,
|
||||
// return it.Otherwise return *this.
|
||||
const fs::path proximate_expected = output.native().empty() ? p
|
||||
: output;
|
||||
if (!PathEq(proximate_expected, proximate_output))
|
||||
ReportErr("path::lexically_proximate", proximate_output, proximate_expected);
|
||||
}
|
||||
return Failed;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// template <class ECharT, class Traits = char_traits<ECharT>,
|
||||
// class Allocator = allocator<ECharT>>
|
||||
// basic_string<ECharT, Traits, Allocator>
|
||||
// generic_string(const Allocator& a = Allocator()) const;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "min_allocator.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
|
||||
|
||||
// generic_string<C, T, A> forwards to string<C, T, A>. Tests for
|
||||
// string<C, T, A>() are in "path.native.op/string_alloc.pass.cpp".
|
||||
// generic_string is minimally tested here.
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
using CharT = wchar_t;
|
||||
using Traits = std::char_traits<CharT>;
|
||||
using Alloc = malloc_allocator<CharT>;
|
||||
using Str = std::basic_string<CharT, Traits, Alloc>;
|
||||
const wchar_t* expect = longString;
|
||||
const path p((const char*)longString);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
Alloc a;
|
||||
Alloc::disable_default_constructor = true;
|
||||
Str s = p.generic_string<wchar_t, Traits, Alloc>(a);
|
||||
assert(s == expect);
|
||||
assert(Alloc::alloc_count > 0);
|
||||
assert(Alloc::outstanding_alloc() == 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// std::string generic_string() const;
|
||||
// std::wstring generic_wstring() const;
|
||||
// std::u8string generic_u8string() const;
|
||||
// std::u16string generic_u16string() const;
|
||||
// std::u32string generic_u32string() const;
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "min_allocator.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
auto const& MS = longString;
|
||||
const char* value = longString;
|
||||
const path p(value);
|
||||
{
|
||||
std::string s = p.generic_string();
|
||||
assert(s == value);
|
||||
}
|
||||
{
|
||||
std::string s = p.generic_u8string();
|
||||
assert(s == (const char*)MS);
|
||||
}
|
||||
{
|
||||
std::wstring s = p.generic_wstring();
|
||||
assert(s == (const wchar_t*)MS);
|
||||
}
|
||||
{
|
||||
std::u16string s = p.generic_u16string();
|
||||
assert(s == (const char16_t*)MS);
|
||||
}
|
||||
{
|
||||
std::u32string s = p.generic_u32string();
|
||||
assert(s == (const char32_t*)MS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// void clear() noexcept
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
{
|
||||
path p;
|
||||
ASSERT_NOEXCEPT(p.clear());
|
||||
ASSERT_SAME_TYPE(void, decltype(p.clear()));
|
||||
p.clear();
|
||||
assert(p.empty());
|
||||
}
|
||||
{
|
||||
const path p("/foo/bar/baz");
|
||||
path p2(p);
|
||||
assert(p == p2);
|
||||
p2.clear();
|
||||
assert(p2.empty());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path& make_preferred()
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
struct MakePreferredTestcase {
|
||||
const char* value;
|
||||
};
|
||||
|
||||
const MakePreferredTestcase TestCases[] =
|
||||
{
|
||||
{""}
|
||||
, {"hello_world"}
|
||||
, {"/"}
|
||||
, {"/foo/bar/baz/"}
|
||||
, {"\\"}
|
||||
, {"\\foo\\bar\\baz\\"}
|
||||
, {"\\foo\\/bar\\/baz\\"}
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// This operation is an identity operation on linux.
|
||||
using namespace fs;
|
||||
for (auto const & TC : TestCases) {
|
||||
path p(TC.value);
|
||||
assert(p == TC.value);
|
||||
path& Ref = (p.make_preferred());
|
||||
assert(p.native() == TC.value);
|
||||
assert(&Ref == &p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path& remove_filename()
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "verbose_assert.h"
|
||||
|
||||
struct RemoveFilenameTestcase {
|
||||
const char* value;
|
||||
const char* expect;
|
||||
};
|
||||
|
||||
const RemoveFilenameTestcase TestCases[] =
|
||||
{
|
||||
{"", ""}
|
||||
, {"/", "/"}
|
||||
, {"//", "//"}
|
||||
, {"///", "///"}
|
||||
, {"\\", ""}
|
||||
, {".", ""}
|
||||
, {"..", ""}
|
||||
, {"/foo", "/"}
|
||||
, {"foo/bar", "foo/"}
|
||||
, {"foo/", "foo/"}
|
||||
, {"//foo", "//"}
|
||||
, {"//foo/", "//foo/"}
|
||||
, {"//foo///", "//foo///"}
|
||||
, {"///foo", "///"}
|
||||
, {"///foo/", "///foo/"}
|
||||
, {"/foo/", "/foo/"}
|
||||
, {"/foo/.", "/foo/"}
|
||||
, {"/foo/..", "/foo/"}
|
||||
, {"/foo/////", "/foo/////"}
|
||||
, {"/foo\\\\", "/"}
|
||||
, {"/foo//\\/", "/foo//\\/"}
|
||||
, {"///foo", "///"}
|
||||
, {"file.txt", ""}
|
||||
, {"bar/../baz/./file.txt", "bar/../baz/./"}
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
for (auto const & TC : TestCases) {
|
||||
path const p_orig(TC.value);
|
||||
path p(p_orig);
|
||||
assert(p == TC.value);
|
||||
path& Ref = (p.remove_filename());
|
||||
ASSERT_EQ(p, TC.expect) << DISPLAY(p_orig);
|
||||
assert(&Ref == &p);
|
||||
assert(!p.has_filename());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path& replace_extension(path const& p = path())
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
struct ReplaceExtensionTestcase {
|
||||
const char* value;
|
||||
const char* expect;
|
||||
const char* extension;
|
||||
};
|
||||
|
||||
const ReplaceExtensionTestcase TestCases[] =
|
||||
{
|
||||
{"", "", ""}
|
||||
, {"foo.cpp", "foo", ""}
|
||||
, {"foo.cpp", "foo.", "."}
|
||||
, {"foo..cpp", "foo..txt", "txt"}
|
||||
, {"", ".txt", "txt"}
|
||||
, {"", ".txt", ".txt"}
|
||||
, {"/foo", "/foo.txt", ".txt"}
|
||||
, {"/foo", "/foo.txt", "txt"}
|
||||
, {"/foo.cpp", "/foo.txt", ".txt"}
|
||||
, {"/foo.cpp", "/foo.txt", "txt"}
|
||||
};
|
||||
const ReplaceExtensionTestcase NoArgCases[] =
|
||||
{
|
||||
{"", "", ""}
|
||||
, {"foo", "foo", ""}
|
||||
, {"foo.cpp", "foo", ""}
|
||||
, {"foo..cpp", "foo.", ""}
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
for (auto const & TC : TestCases) {
|
||||
path p(TC.value);
|
||||
assert(p == TC.value);
|
||||
path& Ref = (p.replace_extension(TC.extension));
|
||||
assert(p == TC.expect);
|
||||
assert(&Ref == &p);
|
||||
}
|
||||
for (auto const& TC : NoArgCases) {
|
||||
path p(TC.value);
|
||||
assert(p == TC.value);
|
||||
path& Ref = (p.replace_extension());
|
||||
assert(p == TC.expect);
|
||||
assert(&Ref == &p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// path& replace_filename()
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
#include "assert_checkpoint.h"
|
||||
#include "verbose_assert.h"
|
||||
|
||||
struct ReplaceFilenameTestcase {
|
||||
const char* value;
|
||||
const char* expect;
|
||||
const char* filename;
|
||||
};
|
||||
|
||||
const ReplaceFilenameTestcase TestCases[] =
|
||||
{
|
||||
{"/foo", "/bar", "bar"}
|
||||
, {"/foo", "/", ""}
|
||||
, {"foo", "bar", "bar"}
|
||||
, {"/", "/bar", "bar"}
|
||||
, {"\\", "bar", "bar"}
|
||||
, {"///", "///bar", "bar"}
|
||||
, {"\\\\", "bar", "bar"}
|
||||
, {"\\/\\", "\\/bar", "bar"}
|
||||
, {".", "bar", "bar"}
|
||||
, {"..", "bar", "bar"}
|
||||
, {"/foo\\baz/bong/", "/foo\\baz/bong/bar", "bar"}
|
||||
, {"/foo\\baz/bong", "/foo\\baz/bar", "bar"}
|
||||
};
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
for (auto const & TC : TestCases) {
|
||||
path p(TC.value);
|
||||
ASSERT_EQ(p, TC.value);
|
||||
path& Ref = (p.replace_filename(TC.filename));
|
||||
ASSERT_EQ(p, TC.expect)
|
||||
<< DISPLAY(TC.value)
|
||||
<< DISPLAY(TC.filename);
|
||||
assert(&Ref == &p);
|
||||
// Tests Effects "as-if": remove_filename() append(filename)
|
||||
{
|
||||
path p2(TC.value);
|
||||
path replace(TC.filename);
|
||||
p2.remove_filename();
|
||||
p2 /= replace;
|
||||
ASSERT_EQ(p, p2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// void swap(path& rhs) noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
struct SwapTestcase {
|
||||
const char* value1;
|
||||
const char* value2;
|
||||
};
|
||||
|
||||
#define LONG_STR1 "_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG"
|
||||
#define LONG_STR2 "_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2_THIS_IS_LONG2"
|
||||
const SwapTestcase TestCases[] =
|
||||
{
|
||||
{"", ""}
|
||||
, {"shortstr", LONG_STR1}
|
||||
, {LONG_STR1, "shortstr"}
|
||||
, {LONG_STR1, LONG_STR2}
|
||||
};
|
||||
#undef LONG_STR1
|
||||
#undef LONG_STR2
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
{
|
||||
path p;
|
||||
ASSERT_NOEXCEPT(p.swap(p));
|
||||
ASSERT_SAME_TYPE(void, decltype(p.swap(p)));
|
||||
}
|
||||
for (auto const & TC : TestCases) {
|
||||
path p1(TC.value1);
|
||||
path p2(TC.value2);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
p1.swap(p2);
|
||||
}
|
||||
assert(p1 == TC.value2);
|
||||
assert(p2 == TC.value1);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
p1.swap(p2);
|
||||
}
|
||||
assert(p1 == TC.value1);
|
||||
assert(p2 == TC.value2);
|
||||
}
|
||||
// self-swap
|
||||
{
|
||||
const char* Val = "aoeuaoeuaoeuaoeuaoeuaoeuaoeuaoeuaoeu";
|
||||
path p1(Val);
|
||||
assert(p1 == Val);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
p1.swap(p1);
|
||||
}
|
||||
assert(p1 == Val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// const value_type* c_str() const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
const char* const value = "hello world";
|
||||
const std::string str_value = value;
|
||||
{ // Check signature
|
||||
path p(value);
|
||||
ASSERT_SAME_TYPE(path::value_type const*, decltype(p.c_str()));
|
||||
ASSERT_NOEXCEPT(p.c_str());
|
||||
}
|
||||
{
|
||||
path p(value);
|
||||
assert(p.c_str() == str_value);
|
||||
assert(p.native().c_str() == p.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// std::string string() const;
|
||||
// std::wstring wstring() const;
|
||||
// std::u8string u8string() const;
|
||||
// std::u16string u16string() const;
|
||||
// std::u32string u32string() const;
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "min_allocator.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
auto const& MS = longString;
|
||||
const char* value = longString;
|
||||
const path p(value);
|
||||
{
|
||||
std::string s = p.string();
|
||||
assert(s == value);
|
||||
}
|
||||
{
|
||||
std::string s = p.u8string();
|
||||
assert(s == (const char*)MS);
|
||||
}
|
||||
{
|
||||
std::wstring s = p.wstring();
|
||||
assert(s == (const wchar_t*)MS);
|
||||
}
|
||||
{
|
||||
std::u16string s = p.u16string();
|
||||
assert(s == (const char16_t*)MS);
|
||||
}
|
||||
{
|
||||
std::u32string s = p.u32string();
|
||||
assert(s == (const char32_t*)MS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// const string_type& native() const noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
const char* const value = "hello world";
|
||||
{ // Check signature
|
||||
path p(value);
|
||||
ASSERT_SAME_TYPE(path::string_type const&, decltype(p.native()));
|
||||
ASSERT_NOEXCEPT(p.native());
|
||||
}
|
||||
{ // native() is tested elsewhere
|
||||
path p(value);
|
||||
assert(p.native() == value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// operator string_type() const;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
using string_type = path::string_type;
|
||||
const char* const value = "hello world";
|
||||
{ // Check signature
|
||||
path p(value);
|
||||
static_assert(std::is_convertible<path, string_type>::value, "");
|
||||
static_assert(std::is_constructible<string_type, path>::value, "");
|
||||
ASSERT_SAME_TYPE(string_type, decltype(p.operator string_type()));
|
||||
ASSERT_NOT_NOEXCEPT(p.operator string_type());
|
||||
}
|
||||
{
|
||||
path p(value);
|
||||
assert(p.native() == value);
|
||||
string_type s = p;
|
||||
assert(s == value);
|
||||
assert(p == value);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// template <class ECharT, class Traits = char_traits<ECharT>,
|
||||
// class Allocator = allocator<ECharT>>
|
||||
// basic_string<ECharT, Traits, Allocator>
|
||||
// string(const Allocator& a = Allocator()) const;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "min_allocator.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
// the SSO is always triggered for strings of size 2.
|
||||
MultiStringType shortString = MKSTR("a");
|
||||
MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
|
||||
template <class CharT>
|
||||
void doShortStringTest(MultiStringType const& MS) {
|
||||
using namespace fs;
|
||||
using Ptr = CharT const*;
|
||||
using Str = std::basic_string<CharT>;
|
||||
using Alloc = std::allocator<CharT>;
|
||||
Ptr value = MS;
|
||||
const path p((const char*)MS);
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
Str s = p.string<CharT>();
|
||||
assert(s == value);
|
||||
Str s2 = p.string<CharT>(Alloc{});
|
||||
assert(s2 == value);
|
||||
}
|
||||
using MAlloc = malloc_allocator<CharT>;
|
||||
MAlloc::reset();
|
||||
{
|
||||
using Traits = std::char_traits<CharT>;
|
||||
using AStr = std::basic_string<CharT, Traits, MAlloc>;
|
||||
DisableAllocationGuard g;
|
||||
AStr s = p.string<CharT, Traits, MAlloc>();
|
||||
assert(s == value);
|
||||
assert(MAlloc::alloc_count == 0);
|
||||
assert(MAlloc::outstanding_alloc() == 0);
|
||||
}
|
||||
MAlloc::reset();
|
||||
{ // Other allocator - provided copy
|
||||
using Traits = std::char_traits<CharT>;
|
||||
using AStr = std::basic_string<CharT, Traits, MAlloc>;
|
||||
DisableAllocationGuard g;
|
||||
MAlloc a;
|
||||
// don't allow another allocator to be default constructed.
|
||||
MAlloc::disable_default_constructor = true;
|
||||
AStr s = p.string<CharT, Traits, MAlloc>(a);
|
||||
assert(s == value);
|
||||
assert(MAlloc::alloc_count == 0);
|
||||
assert(MAlloc::outstanding_alloc() == 0);
|
||||
}
|
||||
MAlloc::reset();
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void doLongStringTest(MultiStringType const& MS) {
|
||||
using namespace fs;
|
||||
using Ptr = CharT const*;
|
||||
using Str = std::basic_string<CharT>;
|
||||
Ptr value = MS;
|
||||
const path p((const char*)MS);
|
||||
{ // Default allocator
|
||||
using Alloc = std::allocator<CharT>;
|
||||
Str s = p.string<CharT>();
|
||||
assert(s == value);
|
||||
Str s2 = p.string<CharT>(Alloc{});
|
||||
assert(s2 == value);
|
||||
}
|
||||
using MAlloc = malloc_allocator<CharT>;
|
||||
MAlloc::reset();
|
||||
{ // Other allocator - default construct
|
||||
using Traits = std::char_traits<CharT>;
|
||||
using AStr = std::basic_string<CharT, Traits, MAlloc>;
|
||||
DisableAllocationGuard g;
|
||||
AStr s = p.string<CharT, Traits, MAlloc>();
|
||||
assert(s == value);
|
||||
assert(MAlloc::alloc_count > 0);
|
||||
assert(MAlloc::outstanding_alloc() == 1);
|
||||
}
|
||||
MAlloc::reset();
|
||||
{ // Other allocator - provided copy
|
||||
using Traits = std::char_traits<CharT>;
|
||||
using AStr = std::basic_string<CharT, Traits, MAlloc>;
|
||||
DisableAllocationGuard g;
|
||||
MAlloc a;
|
||||
// don't allow another allocator to be default constructed.
|
||||
MAlloc::disable_default_constructor = true;
|
||||
AStr s = p.string<CharT, Traits, MAlloc>(a);
|
||||
assert(s == value);
|
||||
assert(MAlloc::alloc_count > 0);
|
||||
assert(MAlloc::outstanding_alloc() == 1);
|
||||
}
|
||||
MAlloc::reset();
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
{
|
||||
auto const& S = shortString;
|
||||
doShortStringTest<char>(S);
|
||||
doShortStringTest<wchar_t>(S);
|
||||
doShortStringTest<char16_t>(S);
|
||||
doShortStringTest<char32_t>(S);
|
||||
}
|
||||
{
|
||||
auto const& S = longString;
|
||||
doLongStringTest<char>(S);
|
||||
doLongStringTest<wchar_t>(S);
|
||||
doLongStringTest<char16_t>(S);
|
||||
doLongStringTest<char32_t>(S);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
//-------------------------------
|
||||
// 8.4.10 path query [path.query]
|
||||
//-------------------------------
|
||||
// bool empty() const noexcept;
|
||||
// bool has_root_path() const;
|
||||
// bool has_root_name() const;
|
||||
// bool has_root_directory() const;
|
||||
// bool has_relative_path() const;
|
||||
// bool has_parent_path() const;
|
||||
// bool has_filename() const;
|
||||
// bool has_stem() const;
|
||||
// bool has_extension() const;
|
||||
// bool is_absolute() const;
|
||||
// bool is_relative() const;
|
||||
|
||||
// tested in path.decompose
|
||||
int main(int, char**) {
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
struct ConvToPath {
|
||||
operator fs::path() const {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
ConvToPath LHS, RHS;
|
||||
(void)(LHS / RHS); // expected-error {{invalid operands to binary expression}}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// path operator/(path const&, path const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
// This is mainly tested via the member append functions.
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
path p1("abc");
|
||||
path p2("def");
|
||||
path p3 = p1 / p2;
|
||||
assert(p3 == "abc/def");
|
||||
|
||||
path p4 = p1 / "def";
|
||||
assert(p4 == "abc/def");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
struct ConvToPath {
|
||||
operator fs::path() const {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
ConvToPath LHS, RHS;
|
||||
(void)(LHS == RHS); // expected-error {{invalid operands to binary expression}}
|
||||
(void)(LHS != RHS); // expected-error {{invalid operands to binary expression}}
|
||||
(void)(LHS < RHS); // expected-error {{invalid operands to binary expression}}
|
||||
(void)(LHS <= RHS); // expected-error {{invalid operands to binary expression}}
|
||||
(void)(LHS > RHS); // expected-error {{invalid operands to binary expression}}
|
||||
(void)(LHS >= RHS); // expected-error {{invalid operands to binary expression}}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// The comparison operators are tested as part of [path.compare]
|
||||
// in class.path/path.members/path.compare.pass.cpp
|
||||
int main(int, char**) {
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// The "hash_value" function is tested as part of [path.compare]
|
||||
// in class.path/path.members/path.compare.pass.cpp
|
||||
int main(int, char**) {
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// template <class Source>
|
||||
// path u8path(Source const&);
|
||||
// template <class InputIter>
|
||||
// path u8path(InputIter, InputIter);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
const char* In1 = "abcd/efg";
|
||||
const std::string In2(In1);
|
||||
const auto In3 = In2.begin();
|
||||
const auto In3End = In2.end();
|
||||
{
|
||||
path p = fs::u8path(In1);
|
||||
assert(p == In1);
|
||||
}
|
||||
{
|
||||
path p = fs::u8path(In2);
|
||||
assert(p == In1);
|
||||
}
|
||||
{
|
||||
path p = fs::u8path(In3);
|
||||
assert(p == In1);
|
||||
}
|
||||
{
|
||||
path p = fs::u8path(In3, In3End);
|
||||
assert(p == In1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// template <class charT, class traits>
|
||||
// basic_ostream<charT, traits>&
|
||||
// operator<<(basic_ostream<charT, traits>& os, const path& p);
|
||||
//
|
||||
// template <class charT, class traits>
|
||||
// basic_istream<charT, traits>&
|
||||
// operator>>(basic_istream<charT, traits>& is, path& p)
|
||||
//
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
MultiStringType InStr = MKSTR("abcdefg/\"hijklmnop\"/qrstuvwxyz/123456789");
|
||||
MultiStringType OutStr = MKSTR("\"abcdefg/\\\"hijklmnop\\\"/qrstuvwxyz/123456789\"");
|
||||
|
||||
|
||||
|
||||
template <class CharT>
|
||||
void doIOTest() {
|
||||
using namespace fs;
|
||||
using Ptr = const CharT*;
|
||||
using StrStream = std::basic_stringstream<CharT>;
|
||||
const Ptr E = OutStr;
|
||||
const path p((const char*)InStr);
|
||||
StrStream ss;
|
||||
{ // test output
|
||||
auto& ret = (ss << p);
|
||||
assert(ss.str() == E);
|
||||
assert(&ret == &ss);
|
||||
}
|
||||
{ // test input
|
||||
path p_in;
|
||||
auto& ret = ss >> p_in;
|
||||
assert(p_in.native() == (const char*)InStr);
|
||||
assert(&ret == &ss);
|
||||
}
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
using namespace fs;
|
||||
|
||||
template <class Stream, class Tp, class = decltype(std::declval<Stream&>() << std::declval<Tp&>())>
|
||||
std::true_type is_ostreamable_imp(int);
|
||||
|
||||
template <class Stream, class Tp>
|
||||
std::false_type is_ostreamable_imp(long);
|
||||
|
||||
template <class Stream, class Tp, class = decltype(std::declval<Stream&>() >> std::declval<Tp&>())>
|
||||
std::true_type is_istreamable_imp(int);
|
||||
|
||||
template <class Stream, class Tp>
|
||||
std::false_type is_istreamable_imp(long);
|
||||
|
||||
|
||||
} // namespace impl
|
||||
|
||||
template <class Stream, class Tp>
|
||||
struct is_ostreamable : decltype(impl::is_ostreamable_imp<Stream, Tp>(0)) {};
|
||||
template <class Stream, class Tp>
|
||||
struct is_istreamable : decltype(impl::is_istreamable_imp<Stream, Tp>(0)) {};
|
||||
|
||||
void test_LWG2989() {
|
||||
static_assert(!is_ostreamable<decltype(std::cout), std::wstring>::value, "");
|
||||
static_assert(!is_ostreamable<decltype(std::wcout), std::string>::value, "");
|
||||
static_assert(!is_istreamable<decltype(std::cin), std::wstring>::value, "");
|
||||
static_assert(!is_istreamable<decltype(std::wcin), std::string>::value, "");
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
doIOTest<char>();
|
||||
doIOTest<wchar_t>();
|
||||
//doIOTest<char16_t>();
|
||||
//doIOTest<char32_t>();
|
||||
test_LWG2989();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// template <class charT, class traits>
|
||||
// basic_ostream<charT, traits>&
|
||||
// operator<<(basic_ostream<charT, traits>& os, const path& p);
|
||||
//
|
||||
// template <class charT, class traits>
|
||||
// basic_istream<charT, traits>&
|
||||
// operator>>(basic_istream<charT, traits>& is, path& p)
|
||||
//
|
||||
|
||||
// TODO(EricWF) This test fails because "std::quoted" fails to compile
|
||||
// for char16_t and char32_t types. Combine with path.io.pass.cpp when this
|
||||
// passes.
|
||||
// XFAIL: *
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_iterators.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
MultiStringType InStr = MKSTR("abcdefg/\"hijklmnop\"/qrstuvwxyz/123456789");
|
||||
MultiStringType OutStr = MKSTR("\"abcdefg/\\\"hijklmnop\\\"/qrstuvwxyz/123456789\"");
|
||||
|
||||
template <class CharT>
|
||||
void doIOTest() {
|
||||
using namespace fs;
|
||||
using Ptr = const CharT*;
|
||||
using StrStream = std::basic_stringstream<CharT>;
|
||||
const char* const InCStr = InStr;
|
||||
const Ptr E = OutStr;
|
||||
const path p((const char*)InStr);
|
||||
StrStream ss;
|
||||
{ // test output
|
||||
auto& ret = (ss << p);
|
||||
assert(ss.str() == E);
|
||||
assert(&ret == &ss);
|
||||
}
|
||||
{ // test input
|
||||
path p_in;
|
||||
auto& ret = ss >> p_in;
|
||||
assert(p_in.native() == (const char*)InStr);
|
||||
assert(&ret == &ss);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
doIOTest<char16_t>();
|
||||
doIOTest<char32_t>();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// void swap(path& lhs, path& rhs) noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "count_new.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
|
||||
// NOTE: this is tested in path.members/path.modifiers via the member swap.
|
||||
int main(int, char**)
|
||||
{
|
||||
using namespace fs;
|
||||
const char* value1 = "foo/bar/baz";
|
||||
const char* value2 = "_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG_THIS_IS_LONG";
|
||||
path p1(value1);
|
||||
path p2(value2);
|
||||
{
|
||||
using namespace std; using namespace fs;
|
||||
ASSERT_NOEXCEPT(swap(p1, p2));
|
||||
ASSERT_SAME_TYPE(void, decltype(swap(p1, p2)));
|
||||
}
|
||||
{
|
||||
DisableAllocationGuard g;
|
||||
using namespace std;
|
||||
using namespace fs;
|
||||
swap(p1, p2);
|
||||
assert(p1.native() == value2);
|
||||
assert(p2.native() == value1);
|
||||
swap(p1, p2);
|
||||
assert(p1.native() == value1);
|
||||
assert(p2.native() == value2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class path
|
||||
|
||||
// typedef ... value_type;
|
||||
// typedef basic_string<value_type> string_type;
|
||||
// static constexpr value_type preferred_separator = ...;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
|
||||
int main(int, char**) {
|
||||
using namespace fs;
|
||||
ASSERT_SAME_TYPE(path::value_type, char);
|
||||
ASSERT_SAME_TYPE(path::string_type, std::basic_string<path::value_type>);
|
||||
{
|
||||
ASSERT_SAME_TYPE(const path::value_type, decltype(path::preferred_separator));
|
||||
static_assert(path::preferred_separator == '/', "");
|
||||
// Make preferred_separator ODR used by taking its address.
|
||||
const char* dummy = &path::preferred_separator;
|
||||
((void)dummy);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class recursive_directory_iterator
|
||||
|
||||
// recursive_recursive_directory_iterator(recursive_recursive_directory_iterator const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(recursive_directory_iterator_copy_construct_tests)
|
||||
|
||||
TEST_CASE(test_constructor_signature)
|
||||
{
|
||||
using D = recursive_directory_iterator;
|
||||
static_assert(std::is_copy_constructible<D>::value, "");
|
||||
//static_assert(!std::is_nothrow_copy_constructible<D>::value, "");
|
||||
}
|
||||
|
||||
TEST_CASE(test_copy_end_iterator)
|
||||
{
|
||||
const recursive_directory_iterator endIt;
|
||||
recursive_directory_iterator it(endIt);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
TEST_CASE(test_copy_valid_iterator)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const recursive_directory_iterator endIt{};
|
||||
|
||||
// build 'it' up with "interesting" non-default state so we can test
|
||||
// that it gets copied. We want to get 'it' into a state such that:
|
||||
// it.options() != directory_options::none
|
||||
// it.depth() != 0
|
||||
// it.recursion_pending() != true
|
||||
const directory_options opts = directory_options::skip_permission_denied;
|
||||
recursive_directory_iterator it(testDir, opts);
|
||||
TEST_REQUIRE(it != endIt);
|
||||
while (it.depth() == 0) {
|
||||
++it;
|
||||
TEST_REQUIRE(it != endIt);
|
||||
}
|
||||
it.disable_recursion_pending();
|
||||
TEST_CHECK(it.options() == opts);
|
||||
TEST_CHECK(it.depth() == 1);
|
||||
TEST_CHECK(it.recursion_pending() == false);
|
||||
const path entry = *it;
|
||||
|
||||
// OPERATION UNDER TEST //
|
||||
const recursive_directory_iterator it2(it);
|
||||
// ------------------- //
|
||||
|
||||
TEST_REQUIRE(it2 == it);
|
||||
TEST_CHECK(*it2 == entry);
|
||||
TEST_CHECK(it2.depth() == 1);
|
||||
TEST_CHECK(it2.recursion_pending() == false);
|
||||
TEST_CHECK(it != endIt);
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,157 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class recursive_directory_iterator
|
||||
|
||||
// recursive_directory_iterator& operator=(recursive_directory_iterator const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(recursive_directory_iterator_copy_assign_tests)
|
||||
|
||||
recursive_directory_iterator createInterestingIterator()
|
||||
// Create an "interesting" iterator where all fields are
|
||||
// in a non-default state. The returned 'it' is in a
|
||||
// state such that:
|
||||
// it.options() == directory_options::skip_permission_denied
|
||||
// it.depth() == 1
|
||||
// it.recursion_pending() == true
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const recursive_directory_iterator endIt;
|
||||
recursive_directory_iterator it(testDir,
|
||||
directory_options::skip_permission_denied);
|
||||
TEST_ASSERT(it != endIt);
|
||||
while (it.depth() != 1) {
|
||||
++it;
|
||||
TEST_ASSERT(it != endIt);
|
||||
}
|
||||
TEST_ASSERT(it.depth() == 1);
|
||||
it.disable_recursion_pending();
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
recursive_directory_iterator createDifferentInterestingIterator()
|
||||
// Create an "interesting" iterator where all fields are
|
||||
// in a non-default state. The returned 'it' is in a
|
||||
// state such that:
|
||||
// it.options() == directory_options::follow_directory_symlink
|
||||
// it.depth() == 2
|
||||
// it.recursion_pending() == false
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const recursive_directory_iterator endIt;
|
||||
recursive_directory_iterator it(testDir,
|
||||
directory_options::follow_directory_symlink);
|
||||
TEST_ASSERT(it != endIt);
|
||||
while (it.depth() != 2) {
|
||||
++it;
|
||||
TEST_ASSERT(it != endIt);
|
||||
}
|
||||
TEST_ASSERT(it.depth() == 2);
|
||||
return it;
|
||||
}
|
||||
|
||||
TEST_CASE(test_assignment_signature) {
|
||||
using D = recursive_directory_iterator;
|
||||
static_assert(std::is_copy_assignable<D>::value, "");
|
||||
}
|
||||
|
||||
TEST_CASE(test_copy_to_end_iterator)
|
||||
{
|
||||
const recursive_directory_iterator endIt;
|
||||
|
||||
const recursive_directory_iterator from = createInterestingIterator();
|
||||
const path entry = *from;
|
||||
|
||||
recursive_directory_iterator to;
|
||||
to = from;
|
||||
TEST_REQUIRE(to == from);
|
||||
TEST_CHECK(*to == entry);
|
||||
TEST_CHECK(to.options() == from.options());
|
||||
TEST_CHECK(to.depth() == from.depth());
|
||||
TEST_CHECK(to.recursion_pending() == from.recursion_pending());
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(test_copy_from_end_iterator)
|
||||
{
|
||||
const recursive_directory_iterator from;
|
||||
recursive_directory_iterator to = createInterestingIterator();
|
||||
|
||||
to = from;
|
||||
TEST_REQUIRE(to == from);
|
||||
TEST_CHECK(to == recursive_directory_iterator{});
|
||||
}
|
||||
|
||||
TEST_CASE(test_copy_valid_iterator)
|
||||
{
|
||||
const recursive_directory_iterator endIt;
|
||||
|
||||
const recursive_directory_iterator it = createInterestingIterator();
|
||||
const path entry = *it;
|
||||
|
||||
recursive_directory_iterator it2 = createDifferentInterestingIterator();
|
||||
TEST_REQUIRE(it2 != it);
|
||||
TEST_CHECK(it2.options() != it.options());
|
||||
TEST_CHECK(it2.depth() != it.depth());
|
||||
TEST_CHECK(it2.recursion_pending() != it.recursion_pending());
|
||||
TEST_CHECK(*it2 != entry);
|
||||
|
||||
it2 = it;
|
||||
TEST_REQUIRE(it2 == it);
|
||||
TEST_CHECK(it2.options() == it.options());
|
||||
TEST_CHECK(it2.depth() == it.depth());
|
||||
TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
|
||||
TEST_CHECK(*it2 == entry);
|
||||
}
|
||||
|
||||
TEST_CASE(test_returns_reference_to_self)
|
||||
{
|
||||
const recursive_directory_iterator it;
|
||||
recursive_directory_iterator it2;
|
||||
recursive_directory_iterator& ref = (it2 = it);
|
||||
TEST_CHECK(&ref == &it2);
|
||||
}
|
||||
|
||||
TEST_CASE(test_self_copy)
|
||||
{
|
||||
// Create two non-equal iterators that have exactly the same state.
|
||||
recursive_directory_iterator it = createInterestingIterator();
|
||||
recursive_directory_iterator it2 = createInterestingIterator();
|
||||
TEST_CHECK(it != it2);
|
||||
TEST_CHECK(it2.options() == it.options());
|
||||
TEST_CHECK(it2.depth() == it.depth());
|
||||
TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
|
||||
TEST_CHECK(*it2 == *it);
|
||||
|
||||
// perform a self-copy and check that the state still matches the
|
||||
// other unmodified iterator.
|
||||
recursive_directory_iterator const& cit = it;
|
||||
it = cit;
|
||||
TEST_CHECK(it2.options() == it.options());
|
||||
TEST_CHECK(it2.depth() == it.depth());
|
||||
TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
|
||||
TEST_CHECK(*it2 == *it);
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,245 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class directory_iterator
|
||||
|
||||
//
|
||||
// explicit recursive_directory_iterator(const path& p);
|
||||
// recursive_directory_iterator(const path& p, directory_options options);
|
||||
// recursive_directory_iterator(const path& p, error_code& ec);
|
||||
// recursive_directory_iterator(const path& p, directory_options options, error_code& ec);
|
||||
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
using RDI = recursive_directory_iterator;
|
||||
|
||||
TEST_SUITE(recursive_directory_iterator_constructor_tests)
|
||||
|
||||
TEST_CASE(test_constructor_signatures)
|
||||
{
|
||||
using D = recursive_directory_iterator;
|
||||
|
||||
// explicit directory_iterator(path const&);
|
||||
static_assert(!std::is_convertible<path, D>::value, "");
|
||||
static_assert(std::is_constructible<D, path>::value, "");
|
||||
static_assert(!std::is_nothrow_constructible<D, path>::value, "");
|
||||
|
||||
// directory_iterator(path const&, error_code&)
|
||||
static_assert(std::is_constructible<D, path,
|
||||
std::error_code&>::value, "");
|
||||
static_assert(!std::is_nothrow_constructible<D, path,
|
||||
std::error_code&>::value, "");
|
||||
|
||||
// directory_iterator(path const&, directory_options);
|
||||
static_assert(std::is_constructible<D, path, directory_options>::value, "");
|
||||
static_assert(!std::is_nothrow_constructible<D, path, directory_options>::value, "");
|
||||
|
||||
// directory_iterator(path const&, directory_options, error_code&)
|
||||
static_assert(std::is_constructible<D, path, directory_options, std::error_code&>::value, "");
|
||||
static_assert(!std::is_nothrow_constructible<D, path, directory_options, std::error_code&>::value, "");
|
||||
}
|
||||
|
||||
TEST_CASE(test_construction_from_bad_path)
|
||||
{
|
||||
std::error_code ec;
|
||||
directory_options opts = directory_options::none;
|
||||
const RDI endIt;
|
||||
|
||||
const path testPaths[] = { StaticEnv::DNE, StaticEnv::BadSymlink };
|
||||
for (path const& testPath : testPaths)
|
||||
{
|
||||
{
|
||||
RDI it(testPath, ec);
|
||||
TEST_CHECK(ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
{
|
||||
RDI it(testPath, opts, ec);
|
||||
TEST_CHECK(ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
{
|
||||
TEST_CHECK_THROW(filesystem_error, RDI(testPath));
|
||||
TEST_CHECK_THROW(filesystem_error, RDI(testPath, opts));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(access_denied_test_case)
|
||||
{
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
path const testDir = env.make_env_path("dir1");
|
||||
path const testFile = testDir / "testFile";
|
||||
env.create_dir(testDir);
|
||||
env.create_file(testFile, 42);
|
||||
|
||||
// Test that we can iterator over the directory before changing the perms
|
||||
{
|
||||
RDI it(testDir);
|
||||
TEST_REQUIRE(it != RDI{});
|
||||
}
|
||||
|
||||
// Change the permissions so we can no longer iterate
|
||||
permissions(testDir, perms::none);
|
||||
|
||||
// Check that the construction fails when skip_permissions_denied is
|
||||
// not given.
|
||||
{
|
||||
std::error_code ec;
|
||||
RDI it(testDir, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_CHECK(it == RDI{});
|
||||
}
|
||||
// Check that construction does not report an error when
|
||||
// 'skip_permissions_denied' is given.
|
||||
{
|
||||
std::error_code ec;
|
||||
RDI it(testDir, directory_options::skip_permission_denied, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(it == RDI{});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(access_denied_to_file_test_case)
|
||||
{
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
path const testFile = env.make_env_path("file1");
|
||||
env.create_file(testFile, 42);
|
||||
|
||||
// Change the permissions so we can no longer iterate
|
||||
permissions(testFile, perms::none);
|
||||
|
||||
// Check that the construction fails when skip_permissions_denied is
|
||||
// not given.
|
||||
{
|
||||
std::error_code ec;
|
||||
RDI it(testFile, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_CHECK(it == RDI{});
|
||||
}
|
||||
// Check that construction still fails when 'skip_permissions_denied' is given
|
||||
// because we tried to open a file and not a directory.
|
||||
{
|
||||
std::error_code ec;
|
||||
RDI it(testFile, directory_options::skip_permission_denied, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_CHECK(it == RDI{});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_open_on_empty_directory_equals_end)
|
||||
{
|
||||
scoped_test_env env;
|
||||
const path testDir = env.make_env_path("dir1");
|
||||
env.create_dir(testDir);
|
||||
|
||||
const RDI endIt;
|
||||
{
|
||||
std::error_code ec;
|
||||
RDI it(testDir, ec);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
{
|
||||
RDI it(testDir);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_open_on_directory_succeeds)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
std::set<path> dir_contents(std::begin(StaticEnv::DirIterationList),
|
||||
std::end( StaticEnv::DirIterationList));
|
||||
const RDI endIt{};
|
||||
|
||||
{
|
||||
std::error_code ec;
|
||||
RDI it(testDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(it != endIt);
|
||||
TEST_CHECK(dir_contents.count(*it));
|
||||
}
|
||||
{
|
||||
RDI it(testDir);
|
||||
TEST_CHECK(it != endIt);
|
||||
TEST_CHECK(dir_contents.count(*it));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_open_on_file_fails)
|
||||
{
|
||||
const path testFile = StaticEnv::File;
|
||||
const RDI endIt{};
|
||||
{
|
||||
std::error_code ec;
|
||||
RDI it(testFile, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
{
|
||||
TEST_CHECK_THROW(filesystem_error, RDI(testFile));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE(test_options_post_conditions)
|
||||
{
|
||||
const path goodDir = StaticEnv::Dir;
|
||||
const path badDir = StaticEnv::DNE;
|
||||
|
||||
{
|
||||
std::error_code ec;
|
||||
|
||||
RDI it1(goodDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(it1.options() == directory_options::none);
|
||||
|
||||
RDI it2(badDir, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_REQUIRE(it2 == RDI{});
|
||||
}
|
||||
{
|
||||
std::error_code ec;
|
||||
const directory_options opts = directory_options::skip_permission_denied;
|
||||
|
||||
RDI it1(goodDir, opts, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(it1.options() == opts);
|
||||
|
||||
RDI it2(badDir, opts, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_REQUIRE(it2 == RDI{});
|
||||
}
|
||||
{
|
||||
RDI it(goodDir);
|
||||
TEST_CHECK(it.options() == directory_options::none);
|
||||
}
|
||||
{
|
||||
const directory_options opts = directory_options::follow_directory_symlink;
|
||||
RDI it(goodDir, opts);
|
||||
TEST_CHECK(it.options() == opts);
|
||||
}
|
||||
}
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,65 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class recursive_directory_iterator
|
||||
|
||||
// int depth() const
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(recursive_directory_iterator_depth_tests)
|
||||
|
||||
TEST_CASE(test_depth)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const path DirDepth1 = StaticEnv::Dir2;
|
||||
const path DirDepth2 = StaticEnv::Dir3;
|
||||
const recursive_directory_iterator endIt{};
|
||||
|
||||
std::error_code ec;
|
||||
recursive_directory_iterator it(testDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(it.depth() == 0);
|
||||
|
||||
bool seen_d1, seen_d2;
|
||||
seen_d1 = seen_d2 = false;
|
||||
|
||||
while (it != endIt) {
|
||||
const path entry = *it;
|
||||
const path parent = entry.parent_path();
|
||||
if (parent == testDir) {
|
||||
TEST_CHECK(it.depth() == 0);
|
||||
} else if (parent == DirDepth1) {
|
||||
TEST_CHECK(it.depth() == 1);
|
||||
seen_d1 = true;
|
||||
} else if (parent == DirDepth2) {
|
||||
TEST_CHECK(it.depth() == 2);
|
||||
seen_d2 = true;
|
||||
} else {
|
||||
TEST_CHECK(!"Unexpected depth while iterating over static env");
|
||||
}
|
||||
++it;
|
||||
}
|
||||
TEST_REQUIRE(seen_d1 && seen_d2);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,42 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class recursive_directory_iterator
|
||||
|
||||
// void disable_recursion_pending();
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(recursive_directory_iterator_disable_recursion_pending_tests)
|
||||
|
||||
// NOTE: The main semantics of disable_recursion_pending are tested
|
||||
// in the 'recursion_pending()' tests.
|
||||
TEST_CASE(basic_test)
|
||||
{
|
||||
recursive_directory_iterator it(StaticEnv::Dir);
|
||||
TEST_REQUIRE(it.recursion_pending() == true);
|
||||
it.disable_recursion_pending();
|
||||
TEST_CHECK(it.recursion_pending() == false);
|
||||
it.disable_recursion_pending();
|
||||
TEST_CHECK(it.recursion_pending() == false);
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,494 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class recursive_directory_iterator
|
||||
|
||||
// recursive_directory_iterator& operator++();
|
||||
// recursive_directory_iterator& increment(error_code& ec) noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(recursive_directory_iterator_increment_tests)
|
||||
|
||||
TEST_CASE(test_increment_signatures)
|
||||
{
|
||||
recursive_directory_iterator d; ((void)d);
|
||||
std::error_code ec; ((void)ec);
|
||||
|
||||
ASSERT_SAME_TYPE(decltype(++d), recursive_directory_iterator&);
|
||||
ASSERT_NOT_NOEXCEPT(++d);
|
||||
|
||||
ASSERT_SAME_TYPE(decltype(d.increment(ec)), recursive_directory_iterator&);
|
||||
ASSERT_NOT_NOEXCEPT(d.increment(ec));
|
||||
}
|
||||
|
||||
TEST_CASE(test_prefix_increment)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
|
||||
std::end( StaticEnv::RecDirIterationList));
|
||||
const recursive_directory_iterator endIt{};
|
||||
|
||||
std::error_code ec;
|
||||
recursive_directory_iterator it(testDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
|
||||
std::set<path> unseen_entries = dir_contents;
|
||||
while (!unseen_entries.empty()) {
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
TEST_REQUIRE(unseen_entries.erase(entry) == 1);
|
||||
recursive_directory_iterator& it_ref = ++it;
|
||||
TEST_CHECK(&it_ref == &it);
|
||||
}
|
||||
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
TEST_CASE(test_postfix_increment)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
|
||||
std::end( StaticEnv::RecDirIterationList));
|
||||
const recursive_directory_iterator endIt{};
|
||||
|
||||
std::error_code ec;
|
||||
recursive_directory_iterator it(testDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
|
||||
std::set<path> unseen_entries = dir_contents;
|
||||
while (!unseen_entries.empty()) {
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
TEST_REQUIRE(unseen_entries.erase(entry) == 1);
|
||||
const path entry2 = *it++;
|
||||
TEST_CHECK(entry2 == entry);
|
||||
}
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(test_increment_method)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const std::set<path> dir_contents(std::begin(StaticEnv::RecDirIterationList),
|
||||
std::end( StaticEnv::RecDirIterationList));
|
||||
const recursive_directory_iterator endIt{};
|
||||
|
||||
std::error_code ec;
|
||||
recursive_directory_iterator it(testDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
|
||||
std::set<path> unseen_entries = dir_contents;
|
||||
while (!unseen_entries.empty()) {
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
TEST_REQUIRE(unseen_entries.erase(entry) == 1);
|
||||
recursive_directory_iterator& it_ref = it.increment(ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(&it_ref == &it);
|
||||
}
|
||||
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
TEST_CASE(test_follow_symlinks)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
auto const& IterList = StaticEnv::RecDirFollowSymlinksIterationList;
|
||||
|
||||
const std::set<path> dir_contents(std::begin(IterList), std::end(IterList));
|
||||
const recursive_directory_iterator endIt{};
|
||||
|
||||
std::error_code ec;
|
||||
recursive_directory_iterator it(testDir,
|
||||
directory_options::follow_directory_symlink, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
|
||||
std::set<path> unseen_entries = dir_contents;
|
||||
while (!unseen_entries.empty()) {
|
||||
TEST_REQUIRE(it != endIt);
|
||||
const path entry = *it;
|
||||
|
||||
TEST_REQUIRE(unseen_entries.erase(entry) == 1);
|
||||
recursive_directory_iterator& it_ref = it.increment(ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_CHECK(&it_ref == &it);
|
||||
}
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
|
||||
TEST_CASE(access_denied_on_recursion_test_case)
|
||||
{
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path testFiles[] = {
|
||||
env.create_dir("dir1"),
|
||||
env.create_dir("dir1/dir2"),
|
||||
env.create_file("dir1/dir2/file1"),
|
||||
env.create_file("dir1/file2")
|
||||
};
|
||||
const path startDir = testFiles[0];
|
||||
const path permDeniedDir = testFiles[1];
|
||||
const path otherFile = testFiles[3];
|
||||
auto SkipEPerm = directory_options::skip_permission_denied;
|
||||
|
||||
// Change the permissions so we can no longer iterate
|
||||
permissions(permDeniedDir, perms::none);
|
||||
|
||||
const recursive_directory_iterator endIt;
|
||||
|
||||
// Test that recursion resulting in a "EACCESS" error is not ignored
|
||||
// by default.
|
||||
{
|
||||
std::error_code ec = GetTestEC();
|
||||
recursive_directory_iterator it(startDir, ec);
|
||||
TEST_REQUIRE(ec != GetTestEC());
|
||||
TEST_REQUIRE(!ec);
|
||||
while (it != endIt && it->path() != permDeniedDir)
|
||||
++it;
|
||||
TEST_REQUIRE(it != endIt);
|
||||
TEST_REQUIRE(*it == permDeniedDir);
|
||||
|
||||
it.increment(ec);
|
||||
TEST_CHECK(ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
// Same as above but test operator++().
|
||||
{
|
||||
std::error_code ec = GetTestEC();
|
||||
recursive_directory_iterator it(startDir, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
while (it != endIt && it->path() != permDeniedDir)
|
||||
++it;
|
||||
TEST_REQUIRE(it != endIt);
|
||||
TEST_REQUIRE(*it == permDeniedDir);
|
||||
|
||||
TEST_REQUIRE_THROW(filesystem_error, ++it);
|
||||
}
|
||||
// Test that recursion resulting in a "EACCESS" error is ignored when the
|
||||
// correct options are given to the constructor.
|
||||
{
|
||||
std::error_code ec = GetTestEC();
|
||||
recursive_directory_iterator it(startDir, SkipEPerm, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_REQUIRE(it != endIt);
|
||||
|
||||
bool seenOtherFile = false;
|
||||
if (*it == otherFile) {
|
||||
++it;
|
||||
seenOtherFile = true;
|
||||
TEST_REQUIRE (it != endIt);
|
||||
}
|
||||
TEST_REQUIRE(*it == permDeniedDir);
|
||||
|
||||
ec = GetTestEC();
|
||||
it.increment(ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
|
||||
if (seenOtherFile) {
|
||||
TEST_CHECK(it == endIt);
|
||||
} else {
|
||||
TEST_CHECK(it != endIt);
|
||||
TEST_CHECK(*it == otherFile);
|
||||
}
|
||||
}
|
||||
// Test that construction resulting in a "EACCESS" error is not ignored
|
||||
// by default.
|
||||
{
|
||||
std::error_code ec;
|
||||
recursive_directory_iterator it(permDeniedDir, ec);
|
||||
TEST_REQUIRE(ec);
|
||||
TEST_REQUIRE(it == endIt);
|
||||
}
|
||||
// Same as above but testing the throwing constructors
|
||||
{
|
||||
TEST_REQUIRE_THROW(filesystem_error,
|
||||
recursive_directory_iterator(permDeniedDir));
|
||||
}
|
||||
// Test that construction resulting in a "EACCESS" error constructs the
|
||||
// end iterator when the correct options are given.
|
||||
{
|
||||
std::error_code ec = GetTestEC();
|
||||
recursive_directory_iterator it(permDeniedDir, SkipEPerm, ec);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_REQUIRE(it == endIt);
|
||||
}
|
||||
}
|
||||
|
||||
// See llvm.org/PR35078
|
||||
TEST_CASE(test_PR35078)
|
||||
{
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path testFiles[] = {
|
||||
env.create_dir("dir1"),
|
||||
env.create_dir("dir1/dir2"),
|
||||
env.create_dir("dir1/dir2/dir3"),
|
||||
env.create_file("dir1/file1"),
|
||||
env.create_file("dir1/dir2/dir3/file2")
|
||||
};
|
||||
const path startDir = testFiles[0];
|
||||
const path permDeniedDir = testFiles[1];
|
||||
const path nestedDir = testFiles[2];
|
||||
const path nestedFile = testFiles[3];
|
||||
|
||||
// Change the permissions so we can no longer iterate
|
||||
permissions(permDeniedDir,
|
||||
perms::group_exec|perms::owner_exec|perms::others_exec,
|
||||
perm_options::remove);
|
||||
|
||||
const std::error_code eacess_ec =
|
||||
std::make_error_code(std::errc::permission_denied);
|
||||
std::error_code ec = GetTestEC();
|
||||
|
||||
const recursive_directory_iterator endIt;
|
||||
|
||||
auto SetupState = [&](bool AllowEAccess, bool& SeenFile3) {
|
||||
SeenFile3 = false;
|
||||
auto Opts = AllowEAccess ? directory_options::skip_permission_denied
|
||||
: directory_options::none;
|
||||
recursive_directory_iterator it(startDir, Opts, ec);
|
||||
while (!ec && it != endIt && *it != nestedDir) {
|
||||
if (*it == nestedFile)
|
||||
SeenFile3 = true;
|
||||
it.increment(ec);
|
||||
}
|
||||
return it;
|
||||
};
|
||||
|
||||
{
|
||||
bool SeenNestedFile = false;
|
||||
recursive_directory_iterator it = SetupState(false, SeenNestedFile);
|
||||
TEST_REQUIRE(it != endIt);
|
||||
TEST_REQUIRE(*it == nestedDir);
|
||||
ec = GetTestEC();
|
||||
it.increment(ec);
|
||||
TEST_CHECK(ec);
|
||||
TEST_CHECK(ec == eacess_ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
{
|
||||
bool SeenNestedFile = false;
|
||||
recursive_directory_iterator it = SetupState(true, SeenNestedFile);
|
||||
TEST_REQUIRE(it != endIt);
|
||||
TEST_REQUIRE(*it == nestedDir);
|
||||
ec = GetTestEC();
|
||||
it.increment(ec);
|
||||
TEST_CHECK(!ec);
|
||||
if (SeenNestedFile) {
|
||||
TEST_CHECK(it == endIt);
|
||||
} else {
|
||||
TEST_REQUIRE(it != endIt);
|
||||
TEST_CHECK(*it == nestedFile);
|
||||
}
|
||||
}
|
||||
{
|
||||
bool SeenNestedFile = false;
|
||||
recursive_directory_iterator it = SetupState(false, SeenNestedFile);
|
||||
TEST_REQUIRE(it != endIt);
|
||||
TEST_REQUIRE(*it == nestedDir);
|
||||
|
||||
ExceptionChecker Checker(std::errc::permission_denied,
|
||||
"recursive_directory_iterator::operator++()",
|
||||
format_string("attempting recursion into \"%s\"",
|
||||
nestedDir.native()));
|
||||
TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ++it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// See llvm.org/PR35078
|
||||
TEST_CASE(test_PR35078_with_symlink)
|
||||
{
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path testFiles[] = {
|
||||
env.create_dir("dir1"),
|
||||
env.create_file("dir1/file1"),
|
||||
env.create_dir("sym_dir"),
|
||||
env.create_dir("sym_dir/nested_sym_dir"),
|
||||
env.create_symlink("sym_dir/nested_sym_dir", "dir1/dir2"),
|
||||
env.create_dir("sym_dir/dir1"),
|
||||
env.create_dir("sym_dir/dir1/dir2"),
|
||||
|
||||
};
|
||||
// const unsigned TestFilesSize = sizeof(testFiles) / sizeof(testFiles[0]);
|
||||
const path startDir = testFiles[0];
|
||||
const path nestedFile = testFiles[1];
|
||||
const path permDeniedDir = testFiles[2];
|
||||
const path symDir = testFiles[4];
|
||||
|
||||
// Change the permissions so we can no longer iterate
|
||||
permissions(permDeniedDir,
|
||||
perms::group_exec|perms::owner_exec|perms::others_exec,
|
||||
perm_options::remove);
|
||||
|
||||
const std::error_code eacess_ec =
|
||||
std::make_error_code(std::errc::permission_denied);
|
||||
std::error_code ec = GetTestEC();
|
||||
|
||||
const recursive_directory_iterator endIt;
|
||||
|
||||
auto SetupState = [&](bool AllowEAccess, bool FollowSym, bool& SeenFile3) {
|
||||
SeenFile3 = false;
|
||||
auto Opts = AllowEAccess ? directory_options::skip_permission_denied
|
||||
: directory_options::none;
|
||||
if (FollowSym)
|
||||
Opts |= directory_options::follow_directory_symlink;
|
||||
recursive_directory_iterator it(startDir, Opts, ec);
|
||||
while (!ec && it != endIt && *it != symDir) {
|
||||
if (*it == nestedFile)
|
||||
SeenFile3 = true;
|
||||
it.increment(ec);
|
||||
}
|
||||
return it;
|
||||
};
|
||||
|
||||
struct {
|
||||
bool SkipPermDenied;
|
||||
bool FollowSymlinks;
|
||||
bool ExpectSuccess;
|
||||
} TestCases[] = {
|
||||
// Passing cases
|
||||
{false, false, true}, {true, true, true}, {true, false, true},
|
||||
// Failing cases
|
||||
{false, true, false}
|
||||
};
|
||||
for (auto TC : TestCases) {
|
||||
bool SeenNestedFile = false;
|
||||
recursive_directory_iterator it = SetupState(TC.SkipPermDenied,
|
||||
TC.FollowSymlinks,
|
||||
SeenNestedFile);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_REQUIRE(it != endIt);
|
||||
TEST_REQUIRE(*it == symDir);
|
||||
ec = GetTestEC();
|
||||
it.increment(ec);
|
||||
if (TC.ExpectSuccess) {
|
||||
TEST_CHECK(!ec);
|
||||
if (SeenNestedFile) {
|
||||
TEST_CHECK(it == endIt);
|
||||
} else {
|
||||
TEST_REQUIRE(it != endIt);
|
||||
TEST_CHECK(*it == nestedFile);
|
||||
}
|
||||
} else {
|
||||
TEST_CHECK(ec);
|
||||
TEST_CHECK(ec == eacess_ec);
|
||||
TEST_CHECK(it == endIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// See llvm.org/PR35078
|
||||
TEST_CASE(test_PR35078_with_symlink_file)
|
||||
{
|
||||
using namespace fs;
|
||||
scoped_test_env env;
|
||||
const path testFiles[] = {
|
||||
env.create_dir("dir1"),
|
||||
env.create_dir("dir1/dir2"),
|
||||
env.create_file("dir1/file2"),
|
||||
env.create_dir("sym_dir"),
|
||||
env.create_dir("sym_dir/sdir1"),
|
||||
env.create_file("sym_dir/sdir1/sfile1"),
|
||||
env.create_symlink("sym_dir/sdir1/sfile1", "dir1/dir2/file1")
|
||||
};
|
||||
const unsigned TestFilesSize = sizeof(testFiles) / sizeof(testFiles[0]);
|
||||
const path startDir = testFiles[0];
|
||||
const path nestedDir = testFiles[1];
|
||||
const path nestedFile = testFiles[2];
|
||||
const path permDeniedDir = testFiles[3];
|
||||
const path symFile = testFiles[TestFilesSize - 1];
|
||||
|
||||
// Change the permissions so we can no longer iterate
|
||||
permissions(permDeniedDir,
|
||||
perms::group_exec|perms::owner_exec|perms::others_exec,
|
||||
perm_options::remove);
|
||||
|
||||
const std::error_code eacess_ec =
|
||||
std::make_error_code(std::errc::permission_denied);
|
||||
std::error_code ec = GetTestEC();
|
||||
|
||||
const recursive_directory_iterator EndIt;
|
||||
|
||||
auto SetupState = [&](bool AllowEAccess, bool FollowSym, bool& SeenNestedFile) {
|
||||
SeenNestedFile = false;
|
||||
auto Opts = AllowEAccess ? directory_options::skip_permission_denied
|
||||
: directory_options::none;
|
||||
if (FollowSym)
|
||||
Opts |= directory_options::follow_directory_symlink;
|
||||
recursive_directory_iterator it(startDir, Opts, ec);
|
||||
while (!ec && it != EndIt && *it != nestedDir) {
|
||||
if (*it == nestedFile)
|
||||
SeenNestedFile = true;
|
||||
it.increment(ec);
|
||||
}
|
||||
return it;
|
||||
};
|
||||
|
||||
struct {
|
||||
bool SkipPermDenied;
|
||||
bool FollowSymlinks;
|
||||
bool ExpectSuccess;
|
||||
} TestCases[] = {
|
||||
// Passing cases
|
||||
{false, false, true}, {true, true, true}, {true, false, true},
|
||||
// Failing cases
|
||||
{false, true, false}
|
||||
};
|
||||
for (auto TC : TestCases){
|
||||
bool SeenNestedFile = false;
|
||||
recursive_directory_iterator it = SetupState(TC.SkipPermDenied,
|
||||
TC.FollowSymlinks,
|
||||
SeenNestedFile);
|
||||
TEST_REQUIRE(!ec);
|
||||
TEST_REQUIRE(it != EndIt);
|
||||
TEST_REQUIRE(*it == nestedDir);
|
||||
ec = GetTestEC();
|
||||
it.increment(ec);
|
||||
TEST_REQUIRE(it != EndIt);
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK(*it == symFile);
|
||||
ec = GetTestEC();
|
||||
it.increment(ec);
|
||||
if (TC.ExpectSuccess) {
|
||||
if (!SeenNestedFile) {
|
||||
TEST_CHECK(!ec);
|
||||
TEST_REQUIRE(it != EndIt);
|
||||
TEST_CHECK(*it == nestedFile);
|
||||
ec = GetTestEC();
|
||||
it.increment(ec);
|
||||
}
|
||||
TEST_CHECK(!ec);
|
||||
TEST_CHECK(it == EndIt);
|
||||
} else {
|
||||
TEST_CHECK(ec);
|
||||
TEST_CHECK(ec == eacess_ec);
|
||||
TEST_CHECK(it == EndIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,79 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class recursive_directory_iterator
|
||||
|
||||
// recursive_directory_iterator(recursive_directory_iterator&&) noexcept;
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(recursive_directory_iterator_move_construct_tests)
|
||||
|
||||
TEST_CASE(test_constructor_signature)
|
||||
{
|
||||
using D = recursive_directory_iterator;
|
||||
static_assert(std::is_nothrow_move_constructible<D>::value, "");
|
||||
}
|
||||
|
||||
TEST_CASE(test_move_end_iterator)
|
||||
{
|
||||
const recursive_directory_iterator endIt;
|
||||
recursive_directory_iterator endIt2{};
|
||||
|
||||
recursive_directory_iterator it(std::move(endIt2));
|
||||
TEST_CHECK(it == endIt);
|
||||
TEST_CHECK(endIt2 == endIt);
|
||||
}
|
||||
|
||||
TEST_CASE(test_move_valid_iterator)
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const recursive_directory_iterator endIt{};
|
||||
|
||||
// build 'it' up with "interesting" non-default state so we can test
|
||||
// that it gets copied. We want to get 'it' into a state such that:
|
||||
// it.options() != directory_options::none
|
||||
// it.depth() != 0
|
||||
// it.recursion_pending() != true
|
||||
const directory_options opts = directory_options::skip_permission_denied;
|
||||
recursive_directory_iterator it(testDir, opts);
|
||||
TEST_REQUIRE(it != endIt);
|
||||
while (it.depth() == 0) {
|
||||
++it;
|
||||
TEST_REQUIRE(it != endIt);
|
||||
}
|
||||
it.disable_recursion_pending();
|
||||
TEST_CHECK(it.options() == opts);
|
||||
TEST_CHECK(it.depth() == 1);
|
||||
TEST_CHECK(it.recursion_pending() == false);
|
||||
const path entry = *it;
|
||||
|
||||
// OPERATION UNDER TEST //
|
||||
const recursive_directory_iterator it2(std::move(it));
|
||||
// ------------------- //
|
||||
|
||||
TEST_REQUIRE(it2 != endIt);
|
||||
TEST_CHECK(*it2 == entry);
|
||||
TEST_CHECK(it2.depth() == 1);
|
||||
TEST_CHECK(it2.recursion_pending() == false);
|
||||
}
|
||||
|
||||
TEST_SUITE_END()
|
|
@ -0,0 +1,168 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <filesystem>
|
||||
|
||||
// class recursive_directory_iterator
|
||||
|
||||
// recursive_directory_iterator& operator=(recursive_directory_iterator const&);
|
||||
|
||||
#include "filesystem_include.hpp"
|
||||
#include <type_traits>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "rapid-cxx-test.hpp"
|
||||
#include "filesystem_test_helper.hpp"
|
||||
|
||||
// The filesystem specification explicitly allows for self-move on
|
||||
// the directory iterators. Turn off this warning so we can test it.
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wself-move"
|
||||
#endif
|
||||
|
||||
using namespace fs;
|
||||
|
||||
TEST_SUITE(recursive_directory_iterator_move_assign_tests)
|
||||
|
||||
recursive_directory_iterator createInterestingIterator()
|
||||
// Create an "interesting" iterator where all fields are
|
||||
// in a non-default state. The returned 'it' is in a
|
||||
// state such that:
|
||||
// it.options() == directory_options::skip_permission_denied
|
||||
// it.depth() == 1
|
||||
// it.recursion_pending() == true
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const recursive_directory_iterator endIt;
|
||||
recursive_directory_iterator it(testDir,
|
||||
directory_options::skip_permission_denied);
|
||||
TEST_ASSERT(it != endIt);
|
||||
while (it.depth() != 1) {
|
||||
++it;
|
||||
TEST_ASSERT(it != endIt);
|
||||
}
|
||||
TEST_ASSERT(it.depth() == 1);
|
||||
it.disable_recursion_pending();
|
||||
return it;
|
||||
}
|
||||
|
||||
recursive_directory_iterator createDifferentInterestingIterator()
|
||||
// Create an "interesting" iterator where all fields are
|
||||
// in a non-default state. The returned 'it' is in a
|
||||
// state such that:
|
||||
// it.options() == directory_options::follow_directory_symlink
|
||||
// it.depth() == 2
|
||||
// it.recursion_pending() == false
|
||||
{
|
||||
const path testDir = StaticEnv::Dir;
|
||||
const recursive_directory_iterator endIt;
|
||||
recursive_directory_iterator it(testDir,
|
||||
directory_options::follow_directory_symlink);
|
||||
TEST_ASSERT(it != endIt);
|
||||
while (it.depth() != 2) {
|
||||
++it;
|
||||
TEST_ASSERT(it != endIt);
|
||||
}
|
||||
TEST_ASSERT(it.depth() == 2);
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(test_assignment_signature)
|
||||
{
|
||||
using D = recursive_directory_iterator;
|
||||
static_assert(std::is_nothrow_move_assignable<D>::value, "");
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(test_move_to_end_iterator)
|
||||
{
|
||||
const recursive_directory_iterator endIt;
|
||||
|
||||
recursive_directory_iterator from = createInterestingIterator();
|
||||
const recursive_directory_iterator from_copy(from);
|
||||
const path entry = *from;
|
||||
|
||||
recursive_directory_iterator to;
|
||||
to = std::move(from);
|
||||
TEST_REQUIRE(to != endIt);
|
||||
TEST_CHECK(*to == entry);
|
||||
TEST_CHECK(to.options() == from_copy.options());
|
||||
TEST_CHECK(to.depth() == from_copy.depth());
|
||||
TEST_CHECK(to.recursion_pending() == from_copy.recursion_pending());
|
||||
TEST_CHECK(from == endIt || from == to);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(test_move_from_end_iterator)
|
||||
{
|
||||
recursive_directory_iterator from;
|
||||
recursive_directory_iterator to = createInterestingIterator();
|
||||
|
||||
to = std::move(from);
|
||||
TEST_REQUIRE(to == from);
|
||||
TEST_CHECK(to == recursive_directory_iterator{});
|
||||
}
|
||||
|
||||
TEST_CASE(test_move_valid_iterator)
|
||||
{
|
||||
const recursive_directory_iterator endIt;
|
||||
|
||||
recursive_directory_iterator it = createInterestingIterator();
|
||||
const recursive_directory_iterator it_copy(it);
|
||||
const path entry = *it;
|
||||
|
||||
recursive_directory_iterator it2 = createDifferentInterestingIterator();
|
||||
const recursive_directory_iterator it2_copy(it2);
|
||||
TEST_REQUIRE(it2 != it);
|
||||
TEST_CHECK(it2.options() != it.options());
|
||||
TEST_CHECK(it2.depth() != it.depth());
|
||||
TEST_CHECK(it2.recursion_pending() != it.recursion_pending());
|
||||
TEST_CHECK(*it2 != entry);
|
||||
|
||||
it2 = std::move(it);
|
||||
TEST_REQUIRE(it2 != it2_copy && it2 != endIt);
|
||||
TEST_CHECK(it2.options() == it_copy.options());
|
||||
TEST_CHECK(it2.depth() == it_copy.depth());
|
||||
TEST_CHECK(it2.recursion_pending() == it_copy.recursion_pending());
|
||||
TEST_CHECK(*it2 == entry);
|
||||
TEST_CHECK(it == endIt || it == it2);
|
||||
}
|
||||
|
||||
TEST_CASE(test_returns_reference_to_self)
|
||||
{
|
||||
recursive_directory_iterator it;
|
||||
recursive_directory_iterator it2;
|
||||
recursive_directory_iterator& ref = (it2 = std::move(it));
|
||||
TEST_CHECK(&ref == &it2);
|
||||
}
|
||||
|
||||
TEST_CASE(test_self_move)
|
||||
{
|
||||
// Create two non-equal iterators that have exactly the same state.
|
||||
recursive_directory_iterator it = createInterestingIterator();
|
||||
recursive_directory_iterator it2 = createInterestingIterator();
|
||||
TEST_CHECK(it != it2);
|
||||
TEST_CHECK(it2.options() == it.options());
|
||||
TEST_CHECK(it2.depth() == it.depth());
|
||||
TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
|
||||
TEST_CHECK(*it2 == *it);
|
||||
|
||||
it = std::move(it);
|
||||
TEST_CHECK(it2.options() == it.options());
|
||||
TEST_CHECK(it2.depth() == it.depth());
|
||||
TEST_CHECK(it2.recursion_pending() == it.recursion_pending());
|
||||
TEST_CHECK(*it2 == *it);
|
||||
}
|
||||
|
||||
|
||||
TEST_SUITE_END()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue